From e2416caf906a680a27bd89a91f14b2cdcaaa1634 Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Tue, 25 Nov 2014 10:37:57 -0500 Subject: Fix java compilation issues when processing large .proto files Fix issues 579 and 501 on the code.google.com issues list. Specifically, large .proto files lead to too much static code, leading to a compilation error from javac: "code too large". This divides the code used in static initialization into multiple methods to avoid that error. Also, this incorporates the fix in issue 501 on the code.google.com issues list to call registry.add only once per extension. --- .../protobuf/compiler/java/java_extension.cc | 8 +- src/google/protobuf/compiler/java/java_extension.h | 8 +- src/google/protobuf/compiler/java/java_file.cc | 92 +++++++++++++++++++--- src/google/protobuf/compiler/java/java_message.cc | 18 +++-- src/google/protobuf/compiler/java/java_message.h | 6 +- 5 files changed, 107 insertions(+), 25 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 27cf416b..4db7085e 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -181,8 +181,9 @@ void ImmutableExtensionGenerator::Generate(io::Printer* printer) { } } -void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( +int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( io::Printer* printer) { + int bytecode_estimate = 0; if (descriptor_->extension_scope() == NULL && HasDescriptorMethods(descriptor_->file())) { // Only applies to non-nested, non-lite extensions. @@ -190,15 +191,18 @@ void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( "$name$.internalInit(descriptor.getExtensions().get($index$));\n", "name", UnderscoresToCamelCase(descriptor_), "index", SimpleItoa(descriptor_->index())); + bytecode_estimate += 21; } + return bytecode_estimate; } -void ImmutableExtensionGenerator::GenerateRegistrationCode( +int ImmutableExtensionGenerator::GenerateRegistrationCode( io::Printer* printer) { printer->Print( "registry.add($scope$.$name$);\n", "scope", scope_, "name", UnderscoresToCamelCase(descriptor_)); + return 7; } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h index f1701fb5..fac5ba00 100644 --- a/src/google/protobuf/compiler/java/java_extension.h +++ b/src/google/protobuf/compiler/java/java_extension.h @@ -67,8 +67,8 @@ class ExtensionGenerator { virtual ~ExtensionGenerator() {} virtual void Generate(io::Printer* printer) = 0; - virtual void GenerateNonNestedInitializationCode(io::Printer* printer) = 0; - virtual void GenerateRegistrationCode(io::Printer* printer) = 0; + virtual int GenerateNonNestedInitializationCode(io::Printer* printer) = 0; + virtual int GenerateRegistrationCode(io::Printer* printer) = 0; protected: static void InitTemplateVars(const FieldDescriptor* descriptor, @@ -88,8 +88,8 @@ class ImmutableExtensionGenerator : public ExtensionGenerator { virtual ~ImmutableExtensionGenerator(); virtual void Generate(io::Printer* printer); - virtual void GenerateNonNestedInitializationCode(io::Printer* printer); - virtual void GenerateRegistrationCode(io::Printer* printer); + virtual int GenerateNonNestedInitializationCode(io::Printer* printer); + virtual int GenerateRegistrationCode(io::Printer* printer); protected: const FieldDescriptor* descriptor_; diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index f1e3cf67..9f285774 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -35,6 +35,7 @@ #include #include +#include #ifndef _SHARED_PTR_H #include #endif @@ -62,6 +63,19 @@ namespace java { namespace { +struct FieldDescriptorCompare { + bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) { + if(f1== NULL) { + return false; + } + if(f2 == NULL) { + return true; + } + return f1->full_name() < f2->full_name(); + } +}; + +typedef std::set FieldDescriptorSet; // Recursively searches the given message to collect extensions. // Returns true if all the extensions can be recognized. The extensions will be @@ -69,7 +83,7 @@ namespace { // Returns false when there are unknown fields, in which case the data in the // extensions output parameter is not reliable and should be discarded. bool CollectExtensions(const Message& message, - vector* extensions) { + FieldDescriptorSet* extensions) { const Reflection* reflection = message.GetReflection(); // There are unknown fields that could be extensions, thus this call fails. @@ -79,7 +93,7 @@ bool CollectExtensions(const Message& message, reflection->ListFields(message, &fields); for (int i = 0; i < fields.size(); i++) { - if (fields[i]->is_extension()) extensions->push_back(fields[i]); + if (fields[i]->is_extension()) extensions->insert(fields[i]); if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) { if (fields[i]->is_repeated()) { @@ -106,7 +120,7 @@ bool CollectExtensions(const Message& message, // in order to handle this case. void CollectExtensions(const FileDescriptorProto& file_proto, const DescriptorPool& alternate_pool, - vector* extensions, + FieldDescriptorSet* extensions, const string& file_data) { if (!CollectExtensions(file_proto, extensions)) { // There are unknown fields in the file_proto, which are probably @@ -139,6 +153,36 @@ void CollectExtensions(const FileDescriptorProto& file_proto, } } +// Our static initialization methods can become very, very large. +// So large that if we aren't careful we end up blowing the JVM's +// 64K bytes of bytecode/method. Fortunately, since these static +// methods are executed only once near the beginning of a program, +// there's usually plenty of stack space available and we can +// extend our methods by simply chaining them to another method +// with a tail call. This inserts the sequence call-next-method, +// end this one, begin-next-method as needed. +void MaybeRestartJavaMethod(io::Printer* printer, + int *bytecode_estimate, + int *method_num, + const char *chain_statement, + const char *method_decl) { + + // The goal here is to stay under 64K bytes of jvm bytecode/method, + // since otherwise we hit a hardcoded limit in the jvm and javac will + // then fail with the error "code too large". This limit lets our + // estimates be off by a factor of two and still we're okay. + static const int bytesPerMethod = 1<<15; // aka 32K + + if ((*bytecode_estimate) > bytesPerMethod) { + ++(*method_num); + printer->Print(chain_statement, "method_num", SimpleItoa(*method_num)); + printer->Outdent(); + printer->Print("}\n"); + printer->Print(method_decl, "method_num", SimpleItoa(*method_num)); + printer->Indent(); + *bytecode_estimate = 0; + } +} } // namespace @@ -270,9 +314,16 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print( "static {\n"); printer->Indent(); + int bytecode_estimate = 0; + int method_num = 0; for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateStaticVariableInitializers(printer); + bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer); + MaybeRestartJavaMethod( + printer, + &bytecode_estimate, &method_num, + "_clinit_autosplit_$method_num$();\n", + "private static void _clinit_autosplit_$method_num$() {\n"); } printer->Outdent(); @@ -303,12 +354,24 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( SharedCodeGenerator shared_code_generator(file_); shared_code_generator.GenerateDescriptors(printer); + int bytecode_estimate = 0; + int method_num = 0; for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateStaticVariableInitializers(printer); + bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer); + MaybeRestartJavaMethod( + printer, + &bytecode_estimate, &method_num, + "_clinit_autosplit_dinit_$method_num$();\n", + "private static void _clinit_autosplit_dinit_$method_num$() {\n"); } for (int i = 0; i < file_->extension_count(); i++) { - extension_generators_[i]->GenerateNonNestedInitializationCode(printer); + bytecode_estimate += extension_generators_[i]->GenerateNonNestedInitializationCode(printer); + MaybeRestartJavaMethod( + printer, + &bytecode_estimate, &method_num, + "_clinit_autosplit_dinit_$method_num$();\n", + "private static void _clinit_autosplit_dinit_$method_num$() {\n"); } // Proto compiler builds a DescriptorPool, which holds all the descriptors to @@ -330,7 +393,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( file_->CopyTo(&file_proto); string file_data; file_proto.SerializeToString(&file_data); - vector extensions; + FieldDescriptorSet extensions; CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); if (extensions.size() > 0) { @@ -339,10 +402,17 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( printer->Print( "com.google.protobuf.ExtensionRegistry registry =\n" " com.google.protobuf.ExtensionRegistry.newInstance();\n"); - for (int i = 0; i < extensions.size(); i++) { + FieldDescriptorSet::iterator it; + for (it = extensions.begin(); it != extensions.end(); it++) { google::protobuf::scoped_ptr generator( - generator_factory_->NewExtensionGenerator(extensions[i])); - generator->GenerateRegistrationCode(printer); + generator_factory_->NewExtensionGenerator(*it)); + bytecode_estimate += generator->GenerateRegistrationCode(printer); + MaybeRestartJavaMethod( + printer, + &bytecode_estimate, &method_num, + "_clinit_autosplit_dinit_$method_num$(registry);\n", + "private static void _clinit_autosplit_dinit_$method_num$(\n" + " com.google.protobuf.ExtensionRegistry registry) {\n"); } printer->Print( "com.google.protobuf.Descriptors.FileDescriptor\n" @@ -394,7 +464,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* file_->CopyTo(&file_proto); string file_data; file_proto.SerializeToString(&file_data); - vector extensions; + FieldDescriptorSet extensions; CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); if (extensions.size() > 0) { diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 1171b718..ed94d6e4 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -124,7 +124,7 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { // The descriptor for this type. printer->Print(vars, - "$private$static final com.google.protobuf.Descriptors.Descriptor\n" + "$private$static com.google.protobuf.Descriptors.Descriptor\n" " internal_$identifier$_descriptor;\n"); // And the FieldAccessorTable. @@ -139,8 +139,9 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { } } -void ImmutableMessageGenerator::GenerateStaticVariableInitializers( +int ImmutableMessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { + int bytecode_estimate = 0; if (HasDescriptorMethods(descriptor_)) { map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); @@ -156,22 +157,25 @@ void ImmutableMessageGenerator::GenerateStaticVariableInitializers( printer->Print(vars, "internal_$identifier$_descriptor =\n" " getDescriptor().getMessageTypes().get($index$);\n"); + bytecode_estimate += 30; } else { printer->Print(vars, "internal_$identifier$_descriptor =\n" " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); + bytecode_estimate += 30; } // And the FieldAccessorTable. - GenerateFieldAccessorTableInitializer(printer); + bytecode_estimate += GenerateFieldAccessorTableInitializer(printer); } // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - ImmutableMessageGenerator(descriptor_->nested_type(i), context_) + bytecode_estimate += ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateStaticVariableInitializers(printer); } + return bytecode_estimate; } void ImmutableMessageGenerator:: @@ -191,8 +195,9 @@ GenerateFieldAccessorTable(io::Printer* printer) { " internal_$identifier$_fieldAccessorTable;\n"); } -void ImmutableMessageGenerator:: +int ImmutableMessageGenerator:: GenerateFieldAccessorTableInitializer(io::Printer* printer) { + int bytecode_estimate = 10; printer->Print( "internal_$identifier$_fieldAccessorTable = new\n" " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" @@ -203,6 +208,7 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bytecode_estimate += 6; printer->Print( "\"$field_name$\", ", "field_name", info->capitalized_name); @@ -210,11 +216,13 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) { for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { const OneofDescriptor* oneof = descriptor_->oneof_decl(i); const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof); + bytecode_estimate += 6; printer->Print( "\"$oneof_name$\", ", "oneof_name", info->capitalized_name); } printer->Print("});\n"); + return bytecode_estimate; } // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index 91eb2876..91e529cc 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -68,7 +68,7 @@ class MessageGenerator { // Output code which initializes the static variables generated by // GenerateStaticVariables(). - virtual void GenerateStaticVariableInitializers(io::Printer* printer) = 0; + virtual int GenerateStaticVariableInitializers(io::Printer* printer) = 0; // Generate the class itself. virtual void Generate(io::Printer* printer) = 0; @@ -97,7 +97,7 @@ class ImmutableMessageGenerator : public MessageGenerator { virtual void GenerateInterface(io::Printer* printer); virtual void GenerateExtensionRegistrationCode(io::Printer* printer); virtual void GenerateStaticVariables(io::Printer* printer); - virtual void GenerateStaticVariableInitializers(io::Printer* printer); + virtual int GenerateStaticVariableInitializers(io::Printer* printer); private: enum UseMemoization { @@ -106,7 +106,7 @@ class ImmutableMessageGenerator : public MessageGenerator { }; void GenerateFieldAccessorTable(io::Printer* printer); - void GenerateFieldAccessorTableInitializer(io::Printer* printer); + int GenerateFieldAccessorTableInitializer(io::Printer* printer); void GenerateMessageSerializationMethods(io::Printer* printer); void GenerateParseFromMethods(io::Printer* printer); -- cgit v1.2.3 From 7c4bbf07a5eee1fd4f5c2d60be32b95c35b0ed1d Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Wed, 14 Jan 2015 14:56:17 -0800 Subject: Support oneofs in the Ruby code generator. --- .../protobuf/compiler/ruby/ruby_generator.cc | 64 ++++++++++++++++------ 1 file changed, 46 insertions(+), 18 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index c5687903..3101c524 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -100,6 +100,45 @@ std::string TypeName(const google::protobuf::FieldDescriptor* field) { } } +void GenerateField(const google::protobuf::FieldDescriptor* field, + google::protobuf::io::Printer* printer) { + printer->Print( + "$label$ :$name$, ", + "label", LabelForField(field), + "name", field->name()); + printer->Print( + ":$type$, $number$", + "type", TypeName(field), + "number", IntToString(field->number())); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->message_type()->full_name()); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } +} + +void GenerateOneof(const google::protobuf::OneofDescriptor* oneof, + google::protobuf::io::Printer* printer) { + printer->Print( + "oneof :$name$ do\n", + "name", oneof->name()); + printer->Indent(); + + for (int i = 0; i < oneof->field_count(); i++) { + const FieldDescriptor* field = oneof->field(i); + GenerateField(field, printer); + } + + printer->Outdent(); + printer->Print("end\n"); +} + void GenerateMessage(const google::protobuf::Descriptor* message, google::protobuf::io::Printer* printer) { printer->Print( @@ -109,27 +148,16 @@ void GenerateMessage(const google::protobuf::Descriptor* message, for (int i = 0; i < message->field_count(); i++) { const FieldDescriptor* field = message->field(i); - printer->Print( - "$label$ :$name$, ", - "label", LabelForField(field), - "name", field->name()); - printer->Print( - ":$type$, $number$", - "type", TypeName(field), - "number", IntToString(field->number())); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - ", \"$subtype$\"\n", - "subtype", field->message_type()->full_name()); - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { - printer->Print( - ", \"$subtype$\"\n", - "subtype", field->enum_type()->full_name()); - } else { - printer->Print("\n"); + if (!field->containing_oneof()) { + GenerateField(field, printer); } } + for (int i = 0; i < message->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = message->oneof_decl(i); + GenerateOneof(oneof, printer); + } + printer->Outdent(); printer->Print("end\n"); -- cgit v1.2.3 From 3f3820d8f8b5c0b67aadc25ad5a2e728b6a3fe79 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Wed, 14 Jan 2015 15:44:46 -0800 Subject: Two tests for Ruby code generator: - A golden-file test that ensures protoc produces known-valid output. - A Ruby test that loads that golden file and ensures it actually works with the extension. This split strategy allows us to test end-to-end without needing to integrate the Ruby gem build system and the protoc build system. This is desirable because we do not want a gem build/install to depend on building protoc, and we do not want building protoc to depend on building and testing the gem. --- ruby/google-protobuf.gemspec | 4 +- ruby/tests/generated_code.proto | 67 +++++++++++ ruby/tests/generated_code.rb | 124 +++++++++++++++++++++ ruby/tests/generated_code_test.rb | 17 +++ src/Makefile.am | 1 + .../compiler/ruby/ruby_generator_unittest.cc | 116 +++++++++++++++++++ 6 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 ruby/tests/generated_code.proto create mode 100644 ruby/tests/generated_code.rb create mode 100644 ruby/tests/generated_code_test.rb create mode 100644 src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc (limited to 'src/google/protobuf/compiler') diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec index 87033ac4..7bfa533c 100644 --- a/ruby/google-protobuf.gemspec +++ b/ruby/google-protobuf.gemspec @@ -18,5 +18,7 @@ Gem::Specification.new do |s| s.files = ["lib/google/protobuf.rb"] + # extension C source find_c_source("ext/google/protobuf_c") - s.test_files = `git ls-files -- tests`.split + s.test_files = ["tests/basic.rb", + "tests/stress.rb", + "tests/generated_code_test.rb"] end diff --git a/ruby/tests/generated_code.proto b/ruby/tests/generated_code.proto new file mode 100644 index 00000000..b1d63232 --- /dev/null +++ b/ruby/tests/generated_code.proto @@ -0,0 +1,67 @@ +syntax = "proto3"; + +package A.B.C; + +message TestMessage { + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional bool optional_bool = 5; + optional double optional_double = 6; + optional float optional_float = 7; + optional string optional_string = 8; + optional bytes optional_bytes = 9; + optional TestEnum optional_enum = 10; + optional TestMessage optional_msg = 11; + + repeated int32 repeated_int32 = 21; + repeated int64 repeated_int64 = 22; + repeated uint32 repeated_uint32 = 23; + repeated uint64 repeated_uint64 = 24; + repeated bool repeated_bool = 25; + repeated double repeated_double = 26; + repeated float repeated_float = 27; + repeated string repeated_string = 28; + repeated bytes repeated_bytes = 29; + repeated TestEnum repeated_enum = 30; + repeated TestMessage repeated_msg = 31; + + oneof my_oneof { + int32 oneof_int32 = 41; + int64 oneof_int64 = 42; + uint32 oneof_uint32 = 43; + uint64 oneof_uint64 = 44; + bool oneof_bool = 45; + double oneof_double = 46; + float oneof_float = 47; + string oneof_string = 48; + bytes oneof_bytes = 49; + TestEnum oneof_enum = 50; + TestMessage oneof_msg = 51; + } + + map map_int32_string = 61; + map map_int64_string = 62; + map map_uint32_string = 63; + map map_uint64_string = 64; + map map_bool_string = 65; + map map_string_string = 66; + map map_string_msg = 67; + map map_string_enum = 68; + map map_string_int32 = 69; + map map_string_bool = 70; + + message NestedMessage { + optional int32 foo = 1; + } + + optional NestedMessage nested_message = 80; +} + +enum TestEnum { + Default = 0; + A = 1; + B = 2; + C = 3; +} diff --git a/ruby/tests/generated_code.rb b/ruby/tests/generated_code.rb new file mode 100644 index 00000000..db762ad9 --- /dev/null +++ b/ruby/tests/generated_code.rb @@ -0,0 +1,124 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: generated_code.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_message "A.B.C.TestMessage" do + optional :optional_int32, :int32, 1 + optional :optional_int64, :int64, 2 + optional :optional_uint32, :uint32, 3 + optional :optional_uint64, :uint64, 4 + optional :optional_bool, :bool, 5 + optional :optional_double, :double, 6 + optional :optional_float, :float, 7 + optional :optional_string, :string, 8 + optional :optional_bytes, :string, 9 + optional :optional_enum, :enum, 10, "A.B.C.TestEnum" + optional :optional_msg, :message, 11, "A.B.C.TestMessage" + repeated :repeated_int32, :int32, 21 + repeated :repeated_int64, :int64, 22 + repeated :repeated_uint32, :uint32, 23 + repeated :repeated_uint64, :uint64, 24 + repeated :repeated_bool, :bool, 25 + repeated :repeated_double, :double, 26 + repeated :repeated_float, :float, 27 + repeated :repeated_string, :string, 28 + repeated :repeated_bytes, :string, 29 + repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" + repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" + repeated :map_int32_string, :message, 61, "A.B.C.TestMessage.MapInt32StringEntry" + repeated :map_int64_string, :message, 62, "A.B.C.TestMessage.MapInt64StringEntry" + repeated :map_uint32_string, :message, 63, "A.B.C.TestMessage.MapUint32StringEntry" + repeated :map_uint64_string, :message, 64, "A.B.C.TestMessage.MapUint64StringEntry" + repeated :map_bool_string, :message, 65, "A.B.C.TestMessage.MapBoolStringEntry" + repeated :map_string_string, :message, 66, "A.B.C.TestMessage.MapStringStringEntry" + repeated :map_string_msg, :message, 67, "A.B.C.TestMessage.MapStringMsgEntry" + repeated :map_string_enum, :message, 68, "A.B.C.TestMessage.MapStringEnumEntry" + repeated :map_string_int32, :message, 69, "A.B.C.TestMessage.MapStringInt32Entry" + repeated :map_string_bool, :message, 70, "A.B.C.TestMessage.MapStringBoolEntry" + optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" + oneof :my_oneof do + optional :oneof_int32, :int32, 41 + optional :oneof_int64, :int64, 42 + optional :oneof_uint32, :uint32, 43 + optional :oneof_uint64, :uint64, 44 + optional :oneof_bool, :bool, 45 + optional :oneof_double, :double, 46 + optional :oneof_float, :float, 47 + optional :oneof_string, :string, 48 + optional :oneof_bytes, :string, 49 + optional :oneof_enum, :enum, 50, "A.B.C.TestEnum" + optional :oneof_msg, :message, 51, "A.B.C.TestMessage" + end + end + add_message "A.B.C.TestMessage.MapInt32StringEntry" do + optional :key, :int32, 1 + optional :value, :string, 2 + end + add_message "A.B.C.TestMessage.MapInt64StringEntry" do + optional :key, :int64, 1 + optional :value, :string, 2 + end + add_message "A.B.C.TestMessage.MapUint32StringEntry" do + optional :key, :uint32, 1 + optional :value, :string, 2 + end + add_message "A.B.C.TestMessage.MapUint64StringEntry" do + optional :key, :uint64, 1 + optional :value, :string, 2 + end + add_message "A.B.C.TestMessage.MapBoolStringEntry" do + optional :key, :bool, 1 + optional :value, :string, 2 + end + add_message "A.B.C.TestMessage.MapStringStringEntry" do + optional :key, :string, 1 + optional :value, :string, 2 + end + add_message "A.B.C.TestMessage.MapStringMsgEntry" do + optional :key, :string, 1 + optional :value, :message, 2, "A.B.C.TestMessage" + end + add_message "A.B.C.TestMessage.MapStringEnumEntry" do + optional :key, :string, 1 + optional :value, :enum, 2, "A.B.C.TestEnum" + end + add_message "A.B.C.TestMessage.MapStringInt32Entry" do + optional :key, :string, 1 + optional :value, :int32, 2 + end + add_message "A.B.C.TestMessage.MapStringBoolEntry" do + optional :key, :string, 1 + optional :value, :bool, 2 + end + add_message "A.B.C.TestMessage.NestedMessage" do + optional :foo, :int32, 1 + end + add_enum "A.B.C.TestEnum" do + value :Default, 0 + value :A, 1 + value :B, 2 + value :C, 3 + end +end + +module A + module B + module C + TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass + TestMessage::MapInt32StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapInt32StringEntry").msgclass + TestMessage::MapInt64StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapInt64StringEntry").msgclass + TestMessage::MapUint32StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapUint32StringEntry").msgclass + TestMessage::MapUint64StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapUint64StringEntry").msgclass + TestMessage::MapBoolStringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapBoolStringEntry").msgclass + TestMessage::MapStringStringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringStringEntry").msgclass + TestMessage::MapStringMsgEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringMsgEntry").msgclass + TestMessage::MapStringEnumEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringEnumEntry").msgclass + TestMessage::MapStringInt32Entry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringInt32Entry").msgclass + TestMessage::MapStringBoolEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringBoolEntry").msgclass + TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass + TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule + end + end +end diff --git a/ruby/tests/generated_code_test.rb b/ruby/tests/generated_code_test.rb new file mode 100644 index 00000000..daef357a --- /dev/null +++ b/ruby/tests/generated_code_test.rb @@ -0,0 +1,17 @@ +#!/usr/bin/ruby + +# generated_code.rb is in the same directory as this test. +$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) + +require 'generated_code' +require 'test/unit' + +class GeneratedCodeTest < Test::Unit::TestCase + def test_generated_msg + # just test that we can instantiate the message. The purpose of this test + # is to ensure that the output of the code generator is valid Ruby and + # successfully creates message definitions and classes, not to test every + # aspect of the extension (basic.rb is for that). + m = A::B::C::TestMessage.new() + end +end diff --git a/src/Makefile.am b/src/Makefile.am index 3a469fd7..6fd8bd2b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -458,6 +458,7 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/java/java_plugin_unittest.cc \ google/protobuf/compiler/java/java_doc_comment_unittest.cc \ google/protobuf/compiler/python/python_plugin_unittest.cc \ + google/protobuf/compiler/ruby/ruby_generator_unittest.cc \ $(COMMON_TEST_SOURCES) nodist_protobuf_test_SOURCES = $(protoc_outputs) diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc new file mode 100644 index 00000000..971fb739 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -0,0 +1,116 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 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 + +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace python { +namespace { + +class TestGenerator : public CodeGenerator { + public: + TestGenerator() {} + ~TestGenerator() {} + + virtual bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const { + TryInsert("test_pb2.py", "imports", context); + TryInsert("test_pb2.py", "module_scope", context); + TryInsert("test_pb2.py", "class_scope:foo.Bar", context); + TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context); + return true; + } + + void TryInsert(const string& filename, const string& insertion_point, + GeneratorContext* context) const { + google::protobuf::scoped_ptr output( + context->OpenForInsert(filename, insertion_point)); + io::Printer printer(output.get(), '$'); + printer.Print("// inserted $name$\n", "name", insertion_point); + } +}; + +// This test is a simple golden-file test over the output of the Ruby code +// generator. When we make changes to the Ruby extension and alter the Ruby code +// generator to use those changes, we should (i) manually test the output of the +// code generator with the extension, and (ii) update the golden output above. +// Some day, we may integrate build systems between protoc and the language +// extensions to the point where we can do this test in a more automated way. + +TEST(RubyGeneratorTest, GeneratorTest) { + google::protobuf::compiler::CommandLineInterface cli; + cli.SetInputsAreProtoPathRelative(true); + + ruby::Generator ruby_generator; + cli.RegisterGenerator("--ruby_out", &ruby_generator, ""); + + string path_arg = "-I" + TestSourceDir() + "/ruby/tests"; + string ruby_out = "--ruby_out=" + TestTempDir(); + const char* argv[] = { + "protoc", + path_arg.c_str(), + ruby_out.c_str(), + "generated_code.proto", + }; + + EXPECT_EQ(0, cli.Run(4, argv)); + + string output; + GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/generated_code.rb", + &output, + true)); + + string expected_output; + GOOGLE_CHECK_OK(File::GetContents( + TestSourceDir() + "/ruby/tests/generated_code.rb", + &expected_output, + true)); + + EXPECT_EQ(expected_output, output); +} + +} // namespace +} // namespace python +} // namespace compiler +} // namespace protobuf +} // namespace google -- cgit v1.2.3 From b0670ddae761914515850c1a2db90dfb374a75ea Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Wed, 14 Jan 2015 16:45:47 -0800 Subject: Fix golden-file Ruby test to work with out-of-tree builds. --- Makefile.am | 6 +- .../compiler/ruby/ruby_generator_unittest.cc | 69 +++++++++++----------- 2 files changed, 41 insertions(+), 34 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/Makefile.am b/Makefile.am index 566b2850..1e11e371 100644 --- a/Makefile.am +++ b/Makefile.am @@ -245,6 +245,7 @@ ruby_EXTRA_DIST= \ ruby/ext/google/protobuf_c/defs.c \ ruby/ext/google/protobuf_c/encode_decode.c \ ruby/ext/google/protobuf_c/extconf.rb \ + ruby/ext/google/protobuf_c/map.c \ ruby/ext/google/protobuf_c/message.c \ ruby/ext/google/protobuf_c/protobuf.c \ ruby/ext/google/protobuf_c/protobuf.h \ @@ -255,7 +256,10 @@ ruby_EXTRA_DIST= \ ruby/google-protobuf.gemspec \ ruby/lib/google/protobuf.rb \ ruby/tests/basic.rb \ - ruby/tests/stress.rb + ruby/tests/stress.rb \ + ruby/tests/generated_code.proto \ + ruby/tests/generated_code.rb \ + ruby/tests/generated_code_test.rb all_EXTRA_DIST=$(java_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST) diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index 971fb739..e35ca695 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -42,33 +42,22 @@ namespace google { namespace protobuf { namespace compiler { -namespace python { +namespace ruby { namespace { -class TestGenerator : public CodeGenerator { - public: - TestGenerator() {} - ~TestGenerator() {} - - virtual bool Generate(const FileDescriptor* file, - const string& parameter, - GeneratorContext* context, - string* error) const { - TryInsert("test_pb2.py", "imports", context); - TryInsert("test_pb2.py", "module_scope", context); - TryInsert("test_pb2.py", "class_scope:foo.Bar", context); - TryInsert("test_pb2.py", "class_scope:foo.Bar.Baz", context); - return true; - } - - void TryInsert(const string& filename, const string& insertion_point, - GeneratorContext* context) const { - google::protobuf::scoped_ptr output( - context->OpenForInsert(filename, insertion_point)); - io::Printer printer(output.get(), '$'); - printer.Print("// inserted $name$\n", "name", insertion_point); +string FindRubyTestDir() { + // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc. + string prefix = "."; + while (!File::Exists(prefix + "/ruby/tests")) { + if (!File::Exists(prefix)) { + GOOGLE_LOG(FATAL) + << "Could not find Ruby test directory. Please run tests from " + "somewhere within the protobuf source package."; + } + prefix += "/.."; } -}; + return prefix + "/ruby/tests"; +} // This test is a simple golden-file test over the output of the Ruby code // generator. When we make changes to the Ruby extension and alter the Ruby code @@ -78,39 +67,53 @@ class TestGenerator : public CodeGenerator { // extensions to the point where we can do this test in a more automated way. TEST(RubyGeneratorTest, GeneratorTest) { + string ruby_tests = FindRubyTestDir(); + google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); ruby::Generator ruby_generator; cli.RegisterGenerator("--ruby_out", &ruby_generator, ""); - string path_arg = "-I" + TestSourceDir() + "/ruby/tests"; + // Copy generated_code.proto to the temporary test directory. + string test_input; + GOOGLE_CHECK_OK(File::GetContents( + ruby_tests + "/generated_code.proto", + &test_input, + true)); + GOOGLE_CHECK_OK(File::SetContents( + TestTempDir() + "/generated_code.proto", + test_input, + true)); + + // Invoke the proto compiler (we will be inside TestTempDir() at this point). string ruby_out = "--ruby_out=" + TestTempDir(); + string proto_path = "--proto_path=" + TestTempDir(); const char* argv[] = { "protoc", - path_arg.c_str(), ruby_out.c_str(), + proto_path.c_str(), "generated_code.proto", }; EXPECT_EQ(0, cli.Run(4, argv)); + // Load the generated output and compare to the expected result. string output; - GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/generated_code.rb", - &output, - true)); - + GOOGLE_CHECK_OK(File::GetContents( + TestTempDir() + "/generated_code.rb", + &output, + true)); string expected_output; GOOGLE_CHECK_OK(File::GetContents( - TestSourceDir() + "/ruby/tests/generated_code.rb", + ruby_tests + "/generated_code.rb", &expected_output, true)); - EXPECT_EQ(expected_output, output); } } // namespace -} // namespace python +} // namespace ruby } // namespace compiler } // namespace protobuf } // namespace google -- cgit v1.2.3 From 532c94145b6605361513682601f1d8e9f97a2497 Mon Sep 17 00:00:00 2001 From: Richard Geary Date: Fri, 23 Jan 2015 12:35:03 -0500 Subject: Add support for outputting dependency manifest files, used by ninja and make Use --manifest-file=somefile.d to output the dependency manifest. This file will contain a list of files which were read by protoc as part of creating the output files. It doesn't include the plugin inputs if plugins are used, that could be a later extension. The manifest file is in the format : . The manifest file format only allows you to specify one output file, which isn't a problem as it's used to detect input changes in order to detect when to rerun the protoc command. The output file used in the manifest is the manifest filename itself; to use this in ninja you should declare the manifest file as the first output as well as the depfile input. --- .../protobuf/compiler/command_line_interface.cc | 83 ++++++++++++++ .../protobuf/compiler/command_line_interface.h | 9 ++ test-driver | 127 +++++++++++++++++++++ 3 files changed, 219 insertions(+) create mode 100755 test-driver (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 13250702..649aa42d 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -46,6 +46,7 @@ #endif #include #include +#include #include #include @@ -725,6 +726,12 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } + if (!manifest_name_.empty()) { + if (!GenerateDependencyManifestFile(parsed_files, &source_tree)) { + return 1; + } + } + if (mode_ == MODE_ENCODE || mode_ == MODE_DECODE) { if (codec_type_.empty()) { // HACK: Define an EmptyMessage type to use for decoding. @@ -775,6 +782,7 @@ void CommandLineInterface::Clear() { output_directives_.clear(); codec_type_.clear(); descriptor_set_name_.clear(); + manifest_name_.clear(); mode_ = MODE_COMPILE; print_mode_ = PRINT_NONE; @@ -1012,6 +1020,22 @@ CommandLineInterface::InterpretArgument(const string& name, } descriptor_set_name_ = value; + } else if (name == "--manifest-file") { + if (!manifest_name_.empty()) { + cerr << name << " may only be passed once." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (value.empty()) { + cerr << name << " requires a non-empty value." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (mode_ != MODE_COMPILE) { + cerr << "Cannot use --encode or --decode and generate a manifest at the " + "same time." << endl; + return PARSE_ARGUMENT_FAIL; + } + manifest_name_ = value; + } else if (name == "--include_imports") { if (imports_in_descriptor_set_) { cerr << name << " may only be passed once." << endl; @@ -1206,6 +1230,9 @@ void CommandLineInterface::PrintHelpText() { " include information about the original\n" " location of each decl in the source file as\n" " well as surrounding comments.\n" +" --manifest_file=FILE Write a dependency output file in the format\n" +" expected by make. This writes the transitive\n" +" set of input file paths to FILE\n" " --error_format=FORMAT Set the format in which to print errors.\n" " FORMAT may be 'gcc' (the default) or 'msvs'\n" " (Microsoft Visual Studio format).\n" @@ -1282,6 +1309,62 @@ bool CommandLineInterface::GenerateOutput( return true; } +bool CommandLineInterface::GenerateDependencyManifestFile( + const vector parsed_files, + DiskSourceTree * source_tree) { + FileDescriptorSet file_set; + + set already_seen; + for (int i = 0; i < parsed_files.size(); i++) { + GetTransitiveDependencies(parsed_files[i], + false, + &already_seen, file_set.mutable_file()); + } + + int fd; + do { + fd = open(manifest_name_.c_str(), + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); + } while (fd < 0 && errno == EINTR); + + if (fd < 0) { + perror(manifest_name_.c_str()); + return false; + } + + stringstream ss; + string output_filename = manifest_name_; + if (output_filename.compare(0, 2, "./") == 0) { + output_filename = output_filename.substr(2); + } + ss << output_filename << ": "; + for (set::const_iterator it = already_seen.begin(); it != already_seen.end(); ++it ) { + string virtual_file = (*it)->name(); + string disk_file; + if (source_tree && source_tree->VirtualFileToDiskFile(virtual_file, &disk_file) ) { + ss << " " << disk_file << " \\" << endl; + } else { + cerr << "Unable to identify path for file " << virtual_file << endl; + return false; + } + } + + string manifest_contents = ss.str(); + if ( write(fd, manifest_contents.c_str(), manifest_contents.size()) != manifest_contents.size() ) { + cerr << "Error when writing to " << manifest_name_ << endl; + return false; + } + + int rv = ::close(fd); + if ( rv != 0 ) { + cerr << manifest_name_ << ": " << strerror(rv) << endl; + return false; + } + + return true; +} + + bool CommandLineInterface::GeneratePluginOutput( const vector& parsed_files, const string& plugin_name, diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 74a0adb4..59d57fbf 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -247,6 +247,11 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Implements the --descriptor_set_out option. bool WriteDescriptorSet(const vector parsed_files); + // Implements the --manifest-file option + bool GenerateDependencyManifestFile( + const vector parsed_files, + DiskSourceTree * source_tree); + // Get all transitive dependencies of the given file (including the file // itself), adding them to the given list of FileDescriptorProtos. The // protos will be ordered such that every file is listed before any file that @@ -353,6 +358,10 @@ class LIBPROTOC_EXPORT CommandLineInterface { // FileDescriptorSet should be written. Otherwise, empty. string descriptor_set_name_; + // If --manifest_file was given, this is the filename to which the input + // file should be written. Otherwise, empty. + string manifest_name_; + // True if --include_imports was given, meaning that we should // write all transitive dependencies to the DescriptorSet. Otherwise, only // the .proto files listed on the command-line are added. diff --git a/test-driver b/test-driver new file mode 100755 index 00000000..32bf39e8 --- /dev/null +++ b/test-driver @@ -0,0 +1,127 @@ +#! /bin/sh +# test-driver - basic testsuite driver script. + +scriptversion=2012-06-27.10; # UTC + +# Copyright (C) 2011-2013 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# This file is maintained in Automake, please report +# bugs to or send patches to +# . + +# Make unconditional expansion of undefined variables an error. This +# helps a lot in preventing typo-related bugs. +set -u + +usage_error () +{ + echo "$0: $*" >&2 + print_usage >&2 + exit 2 +} + +print_usage () +{ + cat <$log_file 2>&1 +estatus=$? +if test $enable_hard_errors = no && test $estatus -eq 99; then + estatus=1 +fi + +case $estatus:$expect_failure in + 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; + 0:*) col=$grn res=PASS recheck=no gcopy=no;; + 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; + 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; + *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; + *:*) col=$red res=FAIL recheck=yes gcopy=yes;; +esac + +# Report outcome to console. +echo "${col}${res}${std}: $test_name" + +# Register the test result, and other relevant metadata. +echo ":test-result: $res" > $trs_file +echo ":global-test-result: $res" >> $trs_file +echo ":recheck: $recheck" >> $trs_file +echo ":copy-in-global-log: $gcopy" >> $trs_file + +# Local Variables: +# mode: shell-script +# sh-indentation: 2 +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: -- cgit v1.2.3 From f01c1441bc7226bf10cf032b2b699a151020cd14 Mon Sep 17 00:00:00 2001 From: "Niall Douglas (s [underscore] sourceforge {at} nedprod [dot] com)" Date: Tue, 27 Jan 2015 15:44:38 +0000 Subject: Fix illegal C++ use of reinterpret_cast<> to cast between nullptr_t and a pointer. --- src/google/protobuf/compiler/cpp/cpp_service.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/cpp/cpp_service.cc b/src/google/protobuf/compiler/cpp/cpp_service.cc index a8f303da..226c2aa0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.cc +++ b/src/google/protobuf/compiler/cpp/cpp_service.cc @@ -301,7 +301,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, printer->Print(vars_, " default:\n" " GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n" - " return *reinterpret_cast< ::google::protobuf::Message*>(NULL);\n" + " return *static_cast< ::google::protobuf::Message*>(NULL);\n" " }\n" "}\n" "\n"); -- cgit v1.2.3 From d1ef42a8e7986b5b812262dca721ae854758f8ad Mon Sep 17 00:00:00 2001 From: Ming Zhao Date: Thu, 29 Jan 2015 22:51:55 -0800 Subject: Remove unused methods: MessageTypeProtoName, IsVariableLenType --- src/google/protobuf/compiler/cpp/cpp_message.cc | 4 ---- .../compiler/javanano/javanano_primitive_field.cc | 23 +--------------------- 2 files changed, 1 insertion(+), 26 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index e71d35fa..d0fd6c6d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -280,10 +280,6 @@ void OptimizePadding(vector* fields) { } } -string MessageTypeProtoName(const FieldDescriptor* field) { - return field->message_type()->full_name(); -} - // Emits an if-statement with a condition that evaluates to true if |field| is // considered non-default (will be sent over the wire), for message types // without true field presence. Should only be called if diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index a3bc3a84..919a2f89 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -155,28 +155,6 @@ int FixedSize(FieldDescriptor::Type type) { return -1; } -// Return true if the type is a that has variable length -// for instance String's. -bool IsVariableLenType(JavaType type) { - switch (type) { - case JAVATYPE_INT : return false; - case JAVATYPE_LONG : return false; - case JAVATYPE_FLOAT : return false; - case JAVATYPE_DOUBLE : return false; - case JAVATYPE_BOOLEAN: return false; - case JAVATYPE_STRING : return true; - case JAVATYPE_BYTES : return true; - case JAVATYPE_ENUM : return false; - case JAVATYPE_MESSAGE: return true; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - bool AllAscii(const string& text) { for (int i = 0; i < text.size(); i++) { if ((text[i] & 0x80) != 0) { @@ -186,6 +164,7 @@ bool AllAscii(const string& text) { return true; } + void SetPrimitiveVariables(const FieldDescriptor* descriptor, const Params params, map* variables) { (*variables)["name"] = -- cgit v1.2.3 From dce816593d4450a92167c62be44554571e7f6a96 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Fri, 30 Jan 2015 16:14:15 -0800 Subject: Initial checkin for maps support in JavaNano. --- src/Makefile.am | 22 +++--- .../protobuf/compiler/javanano/javanano_helpers.h | 6 ++ .../compiler/javanano/javanano_map_field.cc | 85 ++++++++++++++++++++++ .../compiler/javanano/javanano_map_field.h | 71 ++++++++++++++++++ 4 files changed, 174 insertions(+), 10 deletions(-) create mode 100644 src/google/protobuf/compiler/javanano/javanano_map_field.cc create mode 100644 src/google/protobuf/compiler/javanano/javanano_map_field.h (limited to 'src/google/protobuf/compiler') diff --git a/src/Makefile.am b/src/Makefile.am index 3a469fd7..fc0d70e7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -243,26 +243,28 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_doc_comment.cc \ google/protobuf/compiler/java/java_doc_comment.h \ google/protobuf/compiler/javanano/javanano_enum.cc \ + google/protobuf/compiler/javanano/javanano_enum.h \ + google/protobuf/compiler/javanano/javanano_enum_field.cc \ google/protobuf/compiler/javanano/javanano_enum_field.h \ google/protobuf/compiler/javanano/javanano_extension.cc \ + google/protobuf/compiler/javanano/javanano_extension.h \ google/protobuf/compiler/javanano/javanano_field.cc \ + google/protobuf/compiler/javanano/javanano_field.h \ google/protobuf/compiler/javanano/javanano_file.cc \ + google/protobuf/compiler/javanano/javanano_file.h \ google/protobuf/compiler/javanano/javanano_generator.cc \ + google/protobuf/compiler/javanano/javanano_generator.h \ google/protobuf/compiler/javanano/javanano_helpers.cc \ + google/protobuf/compiler/javanano/javanano_helpers.h \ + google/protobuf/compiler/javanano/javanano_map_field.cc \ + google/protobuf/compiler/javanano/javanano_map_field.h \ google/protobuf/compiler/javanano/javanano_message.cc \ + google/protobuf/compiler/javanano/javanano_message.h \ + google/protobuf/compiler/javanano/javanano_message_field.cc \ google/protobuf/compiler/javanano/javanano_message_field.h \ google/protobuf/compiler/javanano/javanano_params.h \ - google/protobuf/compiler/javanano/javanano_primitive_field.h \ - google/protobuf/compiler/javanano/javanano_enum_field.cc \ - google/protobuf/compiler/javanano/javanano_enum.h \ - google/protobuf/compiler/javanano/javanano_extension.h \ - google/protobuf/compiler/javanano/javanano_field.h \ - google/protobuf/compiler/javanano/javanano_file.h \ - google/protobuf/compiler/javanano/javanano_generator.h \ - google/protobuf/compiler/javanano/javanano_helpers.h \ - google/protobuf/compiler/javanano/javanano_message_field.cc \ - google/protobuf/compiler/javanano/javanano_message.h \ google/protobuf/compiler/javanano/javanano_primitive_field.cc \ + google/protobuf/compiler/javanano/javanano_primitive_field.h \ google/protobuf/compiler/python/python_generator.cc \ google/protobuf/compiler/ruby/ruby_generator.cc diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h index 29310743..5d3532b4 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.h +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h @@ -181,6 +181,12 @@ string GenerateDifferentBit(int bit_index); void SetBitOperationVariables(const string name, int bitIndex, map* variables); +inline bool IsMapEntry(const Descriptor* descriptor) { + // TODO(liujisi): Add an option to turn on maps for proto2 syntax as well. + return descriptor->options().map_entry() && + descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; +} + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc new file mode 100644 index 00000000..5dcc37f4 --- /dev/null +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -0,0 +1,85 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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 +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace javanano { + +namespace { + +void SetMapVariables(const Params& params, + const FieldDescriptor* descriptor, map* variables) { + (*variables)["name"] = + RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); + (*variables)["capitalized_name"] = + RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["type"] = "java.lang.Integer"; + (*variables)["default"] = "null"; + (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); + (*variables)["message_name"] = descriptor->containing_type()->name(); +} +} // namespace + +// =================================================================== +MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, + const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { + SetMapVariables(params, descriptor, &variables_); +} + +MapFieldGenerator::~MapFieldGenerator() {} + +void MapFieldGenerator:: +GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { + printer->Print(variables_, + "public $type$ $name$;\n"); +} + +void MapFieldGenerator:: +GenerateClearCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$ = null;\n"); +} + +} // namespace javanano +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h new file mode 100644 index 00000000..4987945d --- /dev/null +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.h @@ -0,0 +1,71 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace javanano { + +class MapFieldGenerator : public FieldGenerator { + public: + explicit MapFieldGenerator( + const FieldDescriptor* descriptor, const Params& params); + ~MapFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer, bool lazy_init) const; + void GenerateClearCode(io::Printer* printer) const; + // void GenerateMergingCode(io::Printer* printer) const; + // void GenerateSerializationCode(io::Printer* printer) const; + // void GenerateSerializedSizeCode(io::Printer* printer) const; + // void GenerateEqualsCode(io::Printer* printer) const; + // void GenerateHashCodeCode(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + vector canonical_values_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); +}; + +} // namespace javanano +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVANANO_MAP_FIELD_H__ -- cgit v1.2.3 From df4730ca9c093a8551b2a9ee7ba0f3098796aeb8 Mon Sep 17 00:00:00 2001 From: Florian Enner Date: Sat, 31 Jan 2015 19:01:34 -0500 Subject: fixed MSVC compile error is not part of the standard, so I've added a workaround. --- src/google/protobuf/compiler/ruby/ruby_generator.cc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index c5687903..bb88fc16 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -46,6 +46,12 @@ namespace protobuf { namespace compiler { namespace ruby { +#if _MSC_VER >= 1400 // VS 2005 and above + // is not part of the standard, so we need to map + // to MSVC's custom sized integer types instead. + typedef unsigned __int32 uint32_t; +#endif + // Forward decls. std::string IntToString(uint32_t value); std::string StripDotProto(const std::string& proto_file); -- cgit v1.2.3 From e1e86b02a8569f522a867d55c42e5ac5664fc86e Mon Sep 17 00:00:00 2001 From: Florian Enner Date: Sat, 31 Jan 2015 19:22:52 -0500 Subject: replaced type fix with the recommended way --- src/google/protobuf/compiler/ruby/ruby_generator.cc | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index bb88fc16..da2e7e89 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -45,15 +45,9 @@ namespace google { namespace protobuf { namespace compiler { namespace ruby { - -#if _MSC_VER >= 1400 // VS 2005 and above - // is not part of the standard, so we need to map - // to MSVC's custom sized integer types instead. - typedef unsigned __int32 uint32_t; -#endif // Forward decls. -std::string IntToString(uint32_t value); +std::string IntToString(uint32 value); std::string StripDotProto(const std::string& proto_file); std::string LabelForField(google::protobuf::FieldDescriptor* field); std::string TypeName(google::protobuf::FieldDescriptor* field); @@ -70,7 +64,7 @@ void GenerateEnumAssignment( const google::protobuf::EnumDescriptor* en, google::protobuf::io::Printer* printer); -std::string IntToString(uint32_t value) { +std::string IntToString(uint32 value) { std::ostringstream os; os << value; return os.str(); -- cgit v1.2.3 From e544b38815134ea800c1c4d86d207c1b56535afe Mon Sep 17 00:00:00 2001 From: Florian Enner Date: Mon, 2 Feb 2015 15:19:01 -0500 Subject: removed accidental whitespace --- src/google/protobuf/compiler/ruby/ruby_generator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index da2e7e89..22a64de9 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -45,7 +45,7 @@ namespace google { namespace protobuf { namespace compiler { namespace ruby { - + // Forward decls. std::string IntToString(uint32 value); std::string StripDotProto(const std::string& proto_file); -- cgit v1.2.3 From 4a99897c0b31802f78df01bb8afa500184a4aca7 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Mon, 2 Feb 2015 14:51:36 -0800 Subject: Use map generator for maps field; skip entry message. --- src/google/protobuf/compiler/javanano/javanano_field.cc | 7 ++++++- src/google/protobuf/compiler/javanano/javanano_message.cc | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index e3e4cefe..b9be90b1 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -97,7 +98,11 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, if (field->is_repeated()) { switch (java_type) { case JAVATYPE_MESSAGE: - return new RepeatedMessageFieldGenerator(field, params); + if (IsMapEntry(field->message_type())) { + return new MapFieldGenerator(field, params); + } else { + return new RepeatedMessageFieldGenerator(field, params); + } case JAVATYPE_ENUM: return new RepeatedEnumFieldGenerator(field, params); default: diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 7c52ca31..5454d9be 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -90,6 +90,7 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? + if (IsMapEntry(descriptor_->nested_type(i))) continue; MessageGenerator(descriptor_->nested_type(i), params_) .GenerateStaticVariables(printer); } @@ -100,6 +101,7 @@ void MessageGenerator::GenerateStaticVariableInitializers( // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? + if (IsMapEntry(descriptor_->nested_type(i))) continue; MessageGenerator(descriptor_->nested_type(i), params_) .GenerateStaticVariableInitializers(printer); } @@ -159,6 +161,7 @@ void MessageGenerator::Generate(io::Printer* printer) { } for (int i = 0; i < descriptor_->nested_type_count(); i++) { + if (IsMapEntry(descriptor_->nested_type(i))) continue; MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); } -- cgit v1.2.3 From 4d64e65f0974f56310dacd3c6f6a7425ff8e9bf3 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Mon, 2 Feb 2015 21:06:59 -0800 Subject: Parsing for Maps in JavaNano --- .../java/com/google/protobuf/nano/MapUtil.java | 97 +++++++++++++++++++++ .../compiler/javanano/javanano_map_field.cc | 98 +++++++++++++++++++--- .../compiler/javanano/javanano_map_field.h | 11 ++- 3 files changed, 190 insertions(+), 16 deletions(-) create mode 100644 javanano/src/main/java/com/google/protobuf/nano/MapUtil.java (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java b/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java new file mode 100644 index 00000000..8e7647dd --- /dev/null +++ b/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java @@ -0,0 +1,97 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2013 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. + +package com.google.protobuf.nano; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * Utility class for maps support. + */ +public final class MapUtil { + public static interface MapFactory { + Map forMap(Map oldMap); + } + public static void setMapFactory(MapFactory newMapFactory) { + mapFactory = newMapFactory; + } + + private static class DefaultMapFactory implements MapFactory { + public Map forMap(Map oldMap) { + if (oldMap == null) { + return new HashMap(); + } + return oldMap; + } + } + private static volatile MapFactory mapFactory = new DefaultMapFactory(); + + @SuppressWarnings("unchecked") + public static final Map mergeEntry( + Map target, CodedInputByteBufferNano input, + int keyType, int valueType, V value, + int keyTag, int valueTag) + throws IOException { + target = mapFactory.forMap(target); + final int length = input.readRawVarint32(); + final int oldLimit = input.pushLimit(length); + K key = null; + while (true) { + int tag = input.readTag(); + if (tag == 0) { + break; + } + if (tag == keyTag) { + key = (K) input.readData(keyType); + } else if (tag == valueTag) { + if (valueType == InternalNano.TYPE_MESSAGE) { + input.readMessage((MessageNano) value); + } else { + value = (V) input.readData(valueType); + } + } else { + if (!input.skipField(tag)) { + break; + } + } + } + input.checkLastTagWas(0); + input.popLimit(oldLimit); + + if (key != null) { + target.put(key, value); + } + return target; + } + + private MapUtil() {} +} diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc index 5dcc37f4..4453cdfa 100644 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -42,19 +42,69 @@ namespace javanano { namespace { +string TypeName(const Params& params, const FieldDescriptor* field, + bool boxed) { + JavaType java_type = GetJavaType(field); + switch (java_type) { + case JAVATYPE_MESSAGE: + return ClassName(params, field->message_type()); + case JAVATYPE_INT: + case JAVATYPE_LONG: + case JAVATYPE_FLOAT: + case JAVATYPE_DOUBLE: + case JAVATYPE_BOOLEAN: + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + case JAVATYPE_ENUM: + if (boxed) { + return BoxedPrimitiveTypeName(java_type); + } else { + return PrimitiveTypeName(java_type); + } + // No default because we want the compiler to complain if any new JavaTypes + // are added.. + } + + GOOGLE_LOG(FATAL) << "should not reach here."; + return ""; +} + +const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) { + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + const Descriptor* message = descriptor->message_type(); + GOOGLE_CHECK(message->options().map_entry()); + return message->FindFieldByName("key"); +} + +const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) { + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + const Descriptor* message = descriptor->message_type(); + GOOGLE_CHECK(message->options().map_entry()); + return message->FindFieldByName("value"); +} + void SetMapVariables(const Params& params, const FieldDescriptor* descriptor, map* variables) { + const FieldDescriptor* key = KeyField(descriptor); + const FieldDescriptor* value = ValueField(descriptor); (*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); - (*variables)["capitalized_name"] = - RenameJavaKeywords(UnderscoresToCapitalizedCamelCase(descriptor)); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = "java.lang.Integer"; - (*variables)["default"] = "null"; - (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); - (*variables)["tag_size"] = SimpleItoa( - internal::WireFormat::TagSize(descriptor->number(), descriptor->type())); - (*variables)["message_name"] = descriptor->containing_type()->name(); + (*variables)["key_type"] = TypeName(params, key, false); + (*variables)["boxed_key_type"] = TypeName(params,key, true); + (*variables)["key_desc_type"] = + "TYPE_" + ToUpper(FieldDescriptor::TypeName(key->type())); + (*variables)["key_tag"] = SimpleItoa(internal::WireFormat::MakeTag(key)); + (*variables)["value_type"] = TypeName(params, value, false); + (*variables)["boxed_value_type"] = TypeName(params, value, true); + (*variables)["value_desc_type"] = + "TYPE_" + ToUpper(FieldDescriptor::TypeName(value->type())); + (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value)); + (*variables)["type_parameters"] = + (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; + (*variables)["value_default"] = + value->type() == FieldDescriptor::TYPE_MESSAGE + ? "new " + (*variables)["value_type"] + "()" + : "null"; } } // namespace @@ -70,7 +120,7 @@ MapFieldGenerator::~MapFieldGenerator() {} void MapFieldGenerator:: GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { printer->Print(variables_, - "public $type$ $name$;\n"); + "public java.util.Map<$type_parameters$> $name$;\n"); } void MapFieldGenerator:: @@ -79,6 +129,34 @@ GenerateClearCode(io::Printer* printer) const { "$name$ = null;\n"); } +void MapFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$ = com.google.protobuf.nano.MapUtil.mergeEntry(\n" + " $name$, input,\n" + " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" + " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n" + " $value_default$,\n" + " $key_tag$, $value_tag$);\n" + "\n"); +} + +void MapFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { +} + +void MapFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { +} + +void MapFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { +} + +void MapFieldGenerator:: +GenerateHashCodeCode(io::Printer* printer) const { +} + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.h b/src/google/protobuf/compiler/javanano/javanano_map_field.h index 4987945d..c01bde38 100644 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.h @@ -50,16 +50,15 @@ class MapFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GenerateMembers(io::Printer* printer, bool lazy_init) const; void GenerateClearCode(io::Printer* printer) const; - // void GenerateMergingCode(io::Printer* printer) const; - // void GenerateSerializationCode(io::Printer* printer) const; - // void GenerateSerializedSizeCode(io::Printer* printer) const; - // void GenerateEqualsCode(io::Printer* printer) const; - // void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCodeCode(io::Printer* printer) const; private: const FieldDescriptor* descriptor_; map variables_; - vector canonical_values_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator); }; -- cgit v1.2.3 From d5839d2b4d45a6af02fe5852ace768ab3d40b5ff Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Tue, 3 Feb 2015 18:15:12 -0800 Subject: parsing and serialzation for maps in JavaNano. --- .../protobuf/nano/CodedOutputByteBufferNano.java | 124 +++++++++++++ .../java/com/google/protobuf/nano/MapUtil.java | 193 ++++++++++++++++++--- .../java/com/google/protobuf/nano/NanoTest.java | 29 +--- .../compiler/javanano/javanano_map_field.cc | 25 ++- 4 files changed, 316 insertions(+), 55 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java index 37982b57..2777f34c 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java @@ -876,4 +876,128 @@ public final class CodedOutputByteBufferNano { // Note: the right-shift must be arithmetic return (n << 1) ^ (n >> 63); } + + static int computeFieldSize(int number, int type, Object object) { + switch (type) { + case InternalNano.TYPE_BOOL: + return computeBoolSize(number, (Boolean) object); + case InternalNano.TYPE_BYTES: + return computeBytesSize(number, (byte[]) object); + case InternalNano.TYPE_STRING: + return computeStringSize(number, (String) object); + case InternalNano.TYPE_FLOAT: + return computeFloatSize(number, (Float) object); + case InternalNano.TYPE_DOUBLE: + return computeDoubleSize(number, (Double) object); + case InternalNano.TYPE_ENUM: + return computeEnumSize(number, (Integer) object); + case InternalNano.TYPE_FIXED32: + return computeFixed32Size(number, (Integer) object); + case InternalNano.TYPE_INT32: + return computeInt32Size(number, (Integer) object); + case InternalNano.TYPE_UINT32: + return computeUInt32Size(number, (Integer) object); + case InternalNano.TYPE_SINT32: + return computeSInt32Size(number, (Integer) object); + case InternalNano.TYPE_SFIXED32: + return computeSFixed32Size(number, (Integer) object); + case InternalNano.TYPE_INT64: + return computeInt64Size(number, (Long) object); + case InternalNano.TYPE_UINT64: + return computeUInt64Size(number, (Long) object); + case InternalNano.TYPE_SINT64: + return computeSInt64Size(number, (Long) object); + case InternalNano.TYPE_FIXED64: + return computeFixed64Size(number, (Long) object); + case InternalNano.TYPE_SFIXED64: + return computeSFixed64Size(number, (Long) object); + case InternalNano.TYPE_MESSAGE: + return computeMessageSize(number, (MessageNano) object); + case InternalNano.TYPE_GROUP: + return computeGroupSize(number, (MessageNano) object); + default: + throw new IllegalArgumentException("Unknown type: " + type); + } + } + + void writeField(int number, int type, Object value) + throws IOException { + switch (type) { + case InternalNano.TYPE_DOUBLE: + Double doubleValue = (Double) value; + writeDouble(number, doubleValue); + break; + case InternalNano.TYPE_FLOAT: + Float floatValue = (Float) value; + writeFloat(number, floatValue); + break; + case InternalNano.TYPE_INT64: + Long int64Value = (Long) value; + writeInt64(number, int64Value); + break; + case InternalNano.TYPE_UINT64: + Long uint64Value = (Long) value; + writeUInt64(number, uint64Value); + break; + case InternalNano.TYPE_INT32: + Integer int32Value = (Integer) value; + writeInt32(number, int32Value); + break; + case InternalNano.TYPE_FIXED64: + Long fixed64Value = (Long) value; + writeFixed64(number, fixed64Value); + break; + case InternalNano.TYPE_FIXED32: + Integer fixed32Value = (Integer) value; + writeFixed32(number, fixed32Value); + break; + case InternalNano.TYPE_BOOL: + Boolean boolValue = (Boolean) value; + writeBool(number, boolValue); + break; + case InternalNano.TYPE_STRING: + String stringValue = (String) value; + writeString(number, stringValue); + break; + case InternalNano.TYPE_BYTES: + byte[] bytesValue = (byte[]) value; + writeBytes(number, bytesValue); + break; + case InternalNano.TYPE_UINT32: + Integer uint32Value = (Integer) value; + writeUInt32(number, uint32Value); + break; + case InternalNano.TYPE_ENUM: + Integer enumValue = (Integer) value; + writeEnum(number, enumValue); + break; + case InternalNano.TYPE_SFIXED32: + Integer sfixed32Value = (Integer) value; + writeSFixed32(number, sfixed32Value); + break; + case InternalNano.TYPE_SFIXED64: + Long sfixed64Value = (Long) value; + writeSFixed64(number, sfixed64Value); + break; + case InternalNano.TYPE_SINT32: + Integer sint32Value = (Integer) value; + writeSInt32(number, sint32Value); + break; + case InternalNano.TYPE_SINT64: + Long sint64Value = (Long) value; + writeSInt64(number, sint64Value); + break; + case InternalNano.TYPE_MESSAGE: + MessageNano messageValue = (MessageNano) value; + writeMessage(number, messageValue); + break; + case InternalNano.TYPE_GROUP: + MessageNano groupValue = (MessageNano) value; + writeGroup(number, groupValue); + break; + default: + throw new IOException("Unknown type: " + type); + } + } + } diff --git a/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java b/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java index 8e7647dd..bc544081 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java +++ b/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java @@ -33,6 +33,7 @@ package com.google.protobuf.nano; import java.io.IOException; import java.util.HashMap; import java.util.Map; +import java.util.Map.Entry; /** * Utility class for maps support. @@ -55,42 +56,178 @@ public final class MapUtil { } private static volatile MapFactory mapFactory = new DefaultMapFactory(); - @SuppressWarnings("unchecked") - public static final Map mergeEntry( - Map target, CodedInputByteBufferNano input, - int keyType, int valueType, V value, - int keyTag, int valueTag) - throws IOException { - target = mapFactory.forMap(target); - final int length = input.readRawVarint32(); - final int oldLimit = input.pushLimit(length); - K key = null; - while (true) { - int tag = input.readTag(); - if (tag == 0) { - break; + /** + * Internal utilities to implement maps for generated messages. + * Do NOT use it explicitly. + */ + public static class Internal { + private static final byte[] emptyBytes = new byte[0]; + private static Object primitiveDefaultValue(int type) { + switch (type) { + case InternalNano.TYPE_BOOL: + return Boolean.FALSE; + case InternalNano.TYPE_BYTES: + return emptyBytes; + case InternalNano.TYPE_STRING: + return ""; + case InternalNano.TYPE_FLOAT: + return Float.valueOf(0); + case InternalNano.TYPE_DOUBLE: + return Double.valueOf(0); + case InternalNano.TYPE_ENUM: + case InternalNano.TYPE_FIXED32: + case InternalNano.TYPE_INT32: + case InternalNano.TYPE_UINT32: + case InternalNano.TYPE_SINT32: + case InternalNano.TYPE_SFIXED32: + return Integer.valueOf(0); + case InternalNano.TYPE_INT64: + case InternalNano.TYPE_UINT64: + case InternalNano.TYPE_SINT64: + case InternalNano.TYPE_FIXED64: + case InternalNano.TYPE_SFIXED64: + return Long.valueOf(0L); + case InternalNano.TYPE_MESSAGE: + case InternalNano.TYPE_GROUP: + default: + throw new IllegalArgumentException( + "Type: " + type + " is not a primitive type."); } - if (tag == keyTag) { - key = (K) input.readData(keyType); - } else if (tag == valueTag) { - if (valueType == InternalNano.TYPE_MESSAGE) { - input.readMessage((MessageNano) value); + } + + /** + * Merges the map entry into the map field. Note this is only supposed to + * be called by generated messages. + * + * @param map the map field; may be null, in which case a map will be + * instantiated using the {@link MapUtil.MapFactory} + * @param input the input byte buffer + * @param keyType key type, as defined in InternalNano.TYPE_* + * @param valueType value type, as defined in InternalNano.TYPE_* + * @param valueClazz class of the value field if the valueType is + * TYPE_MESSAGE; otherwise the parameter is ignored and can be null. + * @param keyTag wire tag for the key + * @param valueTag wire tag for the value + * @return the map field + * @throws IOException + */ + @SuppressWarnings("unchecked") + public static final Map mergeEntry( + CodedInputByteBufferNano input, + Map map, + int keyType, + int valueType, + Class valueClazz, + int keyTag, + int valueTag) throws IOException { + map = mapFactory.forMap(map); + final int length = input.readRawVarint32(); + final int oldLimit = input.pushLimit(length); + byte[] payload = null; + K key = null; + V value = null; + while (true) { + int tag = input.readTag(); + if (tag == 0) { + break; + } + if (tag == keyTag) { + key = (K) input.readData(keyType); + } else if (tag == valueTag) { + if (valueType == InternalNano.TYPE_MESSAGE) { + payload = input.readBytes(); + } else { + value = (V) input.readData(valueType); + } } else { - value = (V) input.readData(valueType); + if (!input.skipField(tag)) { + break; + } } - } else { - if (!input.skipField(tag)) { - break; + } + input.checkLastTagWas(0); + input.popLimit(oldLimit); + + if (key == null) { + key = (K) primitiveDefaultValue(keyType); + } + + // Special case: merge the value when the value is a message. + if (valueType == InternalNano.TYPE_MESSAGE) { + MessageNano oldMessageValue = (MessageNano) map.get(key); + if (oldMessageValue != null) { + if (payload != null) { + MessageNano.mergeFrom(oldMessageValue, payload); + } + return map; + } + // Otherwise, create a new value message. + try { + value = valueClazz.newInstance(); + } catch (InstantiationException e) { + throw new IOException( + "Unable to create value message " + valueClazz.getName() + + " in maps."); + } catch (IllegalAccessException e) { + throw new IOException( + "Unable to create value message " + valueClazz.getName() + + " in maps."); + } + if (payload != null) { + MessageNano.mergeFrom((MessageNano) value, payload); } } + + if (value == null) { + value = (V) primitiveDefaultValue(valueType); + } + + map.put(key, value); + return map; + } + + public static void serializeMapField( + CodedOutputByteBufferNano output, + Map map, int number, int keyType, int valueType) + throws IOException { + for (Entry entry: map.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + if (key == null || value == null) { + throw new IllegalStateException( + "keys and values in maps cannot be null"); + } + int entrySize = + CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + + CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); + output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); + output.writeRawVarint32(entrySize); + output.writeField(1, keyType, key); + output.writeField(2, valueType, value); + } } - input.checkLastTagWas(0); - input.popLimit(oldLimit); - if (key != null) { - target.put(key, value); + public static int computeMapFieldSize( + Map map, int number, int keyType, int valueType) { + int size = 0; + int tagSize = CodedOutputByteBufferNano.computeTagSize(number); + for (Entry entry: map.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + if (key == null || value == null) { + throw new IllegalStateException( + "keys and values in maps cannot be null"); + } + int entrySize = + CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + + CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); + size += tagSize + entrySize + + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize); + } + return size; } - return target; + + private Internal() {} } private MapUtil() {} diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java index 442f0b74..d9428432 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java +++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java @@ -30,31 +30,9 @@ package com.google.protobuf.nano; -import com.google.protobuf.nano.CodedInputByteBufferNano; -import com.google.protobuf.nano.EnumClassNanoMultiple; -import com.google.protobuf.nano.EnumClassNanos; -import com.google.protobuf.nano.EnumValidity; -import com.google.protobuf.nano.EnumValidityAccessors; -import com.google.protobuf.nano.FileScopeEnumMultiple; -import com.google.protobuf.nano.FileScopeEnumRefNano; -import com.google.protobuf.nano.InternalNano; -import com.google.protobuf.nano.InvalidProtocolBufferNanoException; -import com.google.protobuf.nano.MessageNano; -import com.google.protobuf.nano.MessageScopeEnumRefNano; -import com.google.protobuf.nano.MultipleImportingNonMultipleNano1; -import com.google.protobuf.nano.MultipleImportingNonMultipleNano2; -import com.google.protobuf.nano.MultipleNameClashNano; import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors; import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas; -import com.google.protobuf.nano.NanoOuterClass; import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano; -import com.google.protobuf.nano.NanoReferenceTypes; -import com.google.protobuf.nano.NanoRepeatedPackables; -import com.google.protobuf.nano.PackedExtensions; -import com.google.protobuf.nano.RepeatedExtensions; -import com.google.protobuf.nano.SingularExtensions; -import com.google.protobuf.nano.TestRepeatedMergeNano; -import com.google.protobuf.nano.UnittestMultipleNano; import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano; import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano; import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano; @@ -3754,6 +3732,13 @@ public class NanoTest extends TestCase { assertTrue(Arrays.equals(new boolean[] {false, true, false, true}, nonPacked.bools)); } + public void testMapsSerializeAndParse() throws Exception { + // TODO(liujisi): Test basic serialization/parsing roundtrip. + // TODO(liujisi): Test null values in serialization. + // TODO(liujisi): Test merging message type values. + // TODO(liujisi): Test missing key/value in parsing. + } + private void assertRepeatedPackablesEqual( NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) { // Not using MessageNano.equals() -- that belongs to a separate test. diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc index 4453cdfa..dead3685 100644 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -89,6 +89,7 @@ void SetMapVariables(const Params& params, const FieldDescriptor* value = ValueField(descriptor); (*variables)["name"] = RenameJavaKeywords(UnderscoresToCamelCase(descriptor)); + (*variables)["number"] = SimpleItoa(descriptor->number()); (*variables)["key_type"] = TypeName(params, key, false); (*variables)["boxed_key_type"] = TypeName(params,key, true); (*variables)["key_desc_type"] = @@ -101,9 +102,9 @@ void SetMapVariables(const Params& params, (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value)); (*variables)["type_parameters"] = (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; - (*variables)["value_default"] = + (*variables)["value_class"] = value->type() == FieldDescriptor::TYPE_MESSAGE - ? "new " + (*variables)["value_type"] + "()" + ? (*variables)["value_type"] + ".class" : "null"; } } // namespace @@ -132,21 +133,35 @@ GenerateClearCode(io::Printer* printer) const { void MapFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print(variables_, - "$name$ = com.google.protobuf.nano.MapUtil.mergeEntry(\n" - " $name$, input,\n" + "this.$name$ = com.google.protobuf.nano.MapUtil.Internal.mergeEntry(\n" + " input, this.$name$,\n" " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n" - " $value_default$,\n" + " $value_class$,\n" " $key_tag$, $value_tag$);\n" "\n"); } void MapFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null) {\n" + " com.google.protobuf.nano.MapUtil.Internal.serializeMapField(\n" + " output, this.$name$, $number$,\n" + " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" + " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n" + "}\n"); } void MapFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null) {\n" + " size += com.google.protobuf.nano.MapUtil.Internal.computeMapFieldSize(\n" + " this.$name$, $number$,\n" + " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" + " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n" + "}\n"); } void MapFieldGenerator:: -- cgit v1.2.3 From 5914ce7a160a82db1490e99c45c95c69417b20ea Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Tue, 3 Feb 2015 21:35:50 -0800 Subject: Implement a feature to generate a dependency file. By giving protoc the flag "--dependency_manifest_out=FILE", protoc will write dependencies of input proto files into FILE. In FILE, the format will be : \\\n ... This cl is based on https://github.com/google/protobuf/pull/178 --- .../protobuf/compiler/command_line_interface.cc | 55 +++++++++--------- .../protobuf/compiler/command_line_interface.h | 2 +- .../compiler/command_line_interface_unittest.cc | 65 ++++++++++++++++++++++ src/google/protobuf/testing/file.cc | 4 ++ src/google/protobuf/testing/file.h | 3 + test-driver | 20 +++++-- 6 files changed, 115 insertions(+), 34 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 649aa42d..1a182f73 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -726,7 +726,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - if (!manifest_name_.empty()) { + if (!dependency_manifest_name_.empty()) { if (!GenerateDependencyManifestFile(parsed_files, &source_tree)) { return 1; } @@ -782,7 +782,7 @@ void CommandLineInterface::Clear() { output_directives_.clear(); codec_type_.clear(); descriptor_set_name_.clear(); - manifest_name_.clear(); + dependency_manifest_name_.clear(); mode_ = MODE_COMPILE; print_mode_ = PRINT_NONE; @@ -1020,8 +1020,8 @@ CommandLineInterface::InterpretArgument(const string& name, } descriptor_set_name_ = value; - } else if (name == "--manifest-file") { - if (!manifest_name_.empty()) { + } else if (name == "--dependency_manifest_out") { + if (!dependency_manifest_name_.empty()) { cerr << name << " may only be passed once." << endl; return PARSE_ARGUMENT_FAIL; } @@ -1034,7 +1034,7 @@ CommandLineInterface::InterpretArgument(const string& name, "same time." << endl; return PARSE_ARGUMENT_FAIL; } - manifest_name_ = value; + dependency_manifest_name_ = value; } else if (name == "--include_imports") { if (imports_in_descriptor_set_) { @@ -1323,48 +1323,45 @@ bool CommandLineInterface::GenerateDependencyManifestFile( int fd; do { - fd = open(manifest_name_.c_str(), + fd = open(dependency_manifest_name_.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); } while (fd < 0 && errno == EINTR); if (fd < 0) { - perror(manifest_name_.c_str()); + perror(dependency_manifest_name_.c_str()); return false; } - stringstream ss; - string output_filename = manifest_name_; - if (output_filename.compare(0, 2, "./") == 0) { - output_filename = output_filename.substr(2); + io::FileOutputStream out(fd); + io::Printer printer(&out, '$'); + + string output_filename = dependency_manifest_name_; + if (output_filename.compare(0, 1, "/") != 0) { + // Convert relative path to absolute path before print. + printer.Print("$working_directory$/$output_filename$:", + "working_directory", get_current_dir_name(), + "output_filename",output_filename); + } else { + printer.Print("$output_filename$:", + "output_filename",output_filename); } - ss << output_filename << ": "; - for (set::const_iterator it = already_seen.begin(); it != already_seen.end(); ++it ) { - string virtual_file = (*it)->name(); + for (int i = 0; i < file_set.file_size(); i++) { + const FileDescriptorProto& file = file_set.file(i); + string virtual_file = file.name(); string disk_file; - if (source_tree && source_tree->VirtualFileToDiskFile(virtual_file, &disk_file) ) { - ss << " " << disk_file << " \\" << endl; + if (source_tree && + source_tree->VirtualFileToDiskFile(virtual_file, &disk_file)) { + printer.Print(" $disk_file$", "disk_file", disk_file); + if (i < file_set.file_size() - 1) printer.Print("\\\n"); } else { cerr << "Unable to identify path for file " << virtual_file << endl; return false; } } - - string manifest_contents = ss.str(); - if ( write(fd, manifest_contents.c_str(), manifest_contents.size()) != manifest_contents.size() ) { - cerr << "Error when writing to " << manifest_name_ << endl; - return false; - } - - int rv = ::close(fd); - if ( rv != 0 ) { - cerr << manifest_name_ << ": " << strerror(rv) << endl; - return false; - } return true; } - bool CommandLineInterface::GeneratePluginOutput( const vector& parsed_files, const string& plugin_name, diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 59d57fbf..1b657f5e 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -360,7 +360,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // If --manifest_file was given, this is the filename to which the input // file should be written. Otherwise, empty. - string manifest_name_; + string dependency_manifest_name_; // True if --include_imports was given, meaning that we should // write all transitive dependencies to the DescriptorSet. Otherwise, only diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index dbaaa405..e7cfff6b 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -116,6 +116,10 @@ class CommandLineInterfaceTest : public testing::Test { cli_.SetInputsAreProtoPathRelative(enable); } + string GetTempDirectory() { + return temp_directory_; + } + // ----------------------------------------------------------------- // Methods to check the test results (called after Run()). @@ -176,6 +180,9 @@ class CommandLineInterfaceTest : public testing::Test { void ReadDescriptorSet(const string& filename, FileDescriptorSet* descriptor_set); + void ExpectFileContent(const string& filename, + const string& content); + private: // The object we are testing. CommandLineInterface cli_; @@ -456,6 +463,17 @@ void CommandLineInterfaceTest::ExpectCapturedStdout( EXPECT_EQ(expected_text, captured_stdout_); } + +void CommandLineInterfaceTest::ExpectFileContent( + const string& filename, const string& content) { + string path = temp_directory_ + "/" + filename; + string file_contents; + GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); + + EXPECT_EQ(StringReplace(content, "$tmpdir", temp_directory_, true), + file_contents); +} + // =================================================================== TEST_F(CommandLineInterfaceTest, BasicOutput) { @@ -940,6 +958,53 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); } +TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --dependency_manifest_out=$tmpdir/manifest " + "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + ExpectFileContent("manifest", + "$tmpdir/manifest: $tmpdir/foo.proto\\\n" + " $tmpdir/bar.proto"); +} + +TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + string current_working_directory = get_current_dir_name(); + File::ChangeWorkingDirectory(GetTempDirectory()); + + Run("protocol_compiler --dependency_manifest_out=manifest " + "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); + + ExpectNoErrors(); + + ExpectFileContent("manifest", + "$tmpdir/manifest: $tmpdir/foo.proto\\\n" + " $tmpdir/bar.proto"); + + File::ChangeWorkingDirectory(current_working_directory); +} + // ------------------------------------------------------------------- TEST_F(CommandLineInterfaceTest, ParseErrors) { diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index 5344ec15..3d07b127 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -192,5 +192,9 @@ void File::DeleteRecursively(const string& name, #endif } +bool File::ChangeWorkingDirectory(const string& new_working_directory) { + return chdir(new_working_directory.c_str()) == 0; +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h index d2aeabf2..2f63f80e 100644 --- a/src/google/protobuf/testing/file.h +++ b/src/google/protobuf/testing/file.h @@ -77,6 +77,9 @@ class File { static void DeleteRecursively(const string& name, void* dummy1, void* dummy2); + // Change working directory to given directory. + static bool ChangeWorkingDirectory(const string& new_working_directory); + static bool GetContents( const string& name, string* output, bool /*is_default*/) { return ReadFileToString(name, output); diff --git a/test-driver b/test-driver index 32bf39e8..d3060566 100755 --- a/test-driver +++ b/test-driver @@ -1,7 +1,7 @@ #! /bin/sh # test-driver - basic testsuite driver script. -scriptversion=2012-06-27.10; # UTC +scriptversion=2013-07-13.22; # UTC # Copyright (C) 2011-2013 Free Software Foundation, Inc. # @@ -44,13 +44,12 @@ print_usage () Usage: test-driver --test-name=NAME --log-file=PATH --trs-file=PATH [--expect-failure={yes|no}] [--color-tests={yes|no}] - [--enable-hard-errors={yes|no}] [--] TEST-SCRIPT + [--enable-hard-errors={yes|no}] [--] + TEST-SCRIPT [TEST-SCRIPT-ARGUMENTS] The '--test-name', '--log-file' and '--trs-file' options are mandatory. END } -# TODO: better error handling in option parsing (in particular, ensure -# TODO: $log_file, $trs_file and $test_name are defined). test_name= # Used for reporting. log_file= # Where to save the output of the test script. trs_file= # Where to save the metadata of the test run. @@ -69,10 +68,23 @@ while test $# -gt 0; do --enable-hard-errors) enable_hard_errors=$2; shift;; --) shift; break;; -*) usage_error "invalid option: '$1'";; + *) break;; esac shift done +missing_opts= +test x"$test_name" = x && missing_opts="$missing_opts --test-name" +test x"$log_file" = x && missing_opts="$missing_opts --log-file" +test x"$trs_file" = x && missing_opts="$missing_opts --trs-file" +if test x"$missing_opts" != x; then + usage_error "the following mandatory options are missing:$missing_opts" +fi + +if test $# -eq 0; then + usage_error "missing argument" +fi + if test $color_tests = yes; then # Keep this in sync with 'lib/am/check.am:$(am__tty_colors)'. red='' # Red. -- cgit v1.2.3 From 5fa3956edef4648fa14da81958330b6df59cdb6d Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Tue, 3 Feb 2015 21:51:29 -0800 Subject: Fix comments. --- src/google/protobuf/compiler/command_line_interface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 1b657f5e..0c951a71 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -358,8 +358,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { // FileDescriptorSet should be written. Otherwise, empty. string descriptor_set_name_; - // If --manifest_file was given, this is the filename to which the input - // file should be written. Otherwise, empty. + // If --dependency_manifest_out was given, this is the filename to which the + // input file should be written. Otherwise, empty. string dependency_manifest_name_; // True if --include_imports was given, meaning that we should -- cgit v1.2.3 From a1b351c55bee819fc69861b3d0d88dab7dce0c4f Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Wed, 4 Feb 2015 10:20:20 -0800 Subject: Change flag for generating dependency file to "dependency_out". Delete test-driver --- .../protobuf/compiler/command_line_interface.cc | 4 +- .../protobuf/compiler/command_line_interface.h | 4 +- .../compiler/command_line_interface_unittest.cc | 15 +-- test-driver | 139 --------------------- 4 files changed, 12 insertions(+), 150 deletions(-) delete mode 100755 test-driver (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 1a182f73..4b28cf6b 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -1020,7 +1020,7 @@ CommandLineInterface::InterpretArgument(const string& name, } descriptor_set_name_ = value; - } else if (name == "--dependency_manifest_out") { + } else if (name == "--dependency_out") { if (!dependency_manifest_name_.empty()) { cerr << name << " may only be passed once." << endl; return PARSE_ARGUMENT_FAIL; @@ -1230,7 +1230,7 @@ void CommandLineInterface::PrintHelpText() { " include information about the original\n" " location of each decl in the source file as\n" " well as surrounding comments.\n" -" --manifest_file=FILE Write a dependency output file in the format\n" +" --dependency_out=FILE Write a dependency output file in the format\n" " expected by make. This writes the transitive\n" " set of input file paths to FILE\n" " --error_format=FORMAT Set the format in which to print errors.\n" diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 0c951a71..13e93c54 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -358,8 +358,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { // FileDescriptorSet should be written. Otherwise, empty. string descriptor_set_name_; - // If --dependency_manifest_out was given, this is the filename to which the - // input file should be written. Otherwise, empty. + // If --dependency_out was given, this is the filename to which the input file + // should be written. Otherwise, empty. string dependency_manifest_name_; // True if --include_imports was given, meaning that we should diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index e7cfff6b..f298be75 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -112,12 +112,13 @@ class CommandLineInterfaceTest : public testing::Test { // Create a subdirectory within temp_directory_. void CreateTempDir(const string& name); - void SetInputsAreProtoPathRelative(bool enable) { - cli_.SetInputsAreProtoPathRelative(enable); + // Change working directory to temp directory. + void SwitchToTempDirectory() { + File::ChangeWorkingDirectory(temp_directory_); } - string GetTempDirectory() { - return temp_directory_; + void SetInputsAreProtoPathRelative(bool enable) { + cli_.SetInputsAreProtoPathRelative(enable); } // ----------------------------------------------------------------- @@ -969,7 +970,7 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { " optional Foo foo = 1;\n" "}\n"); - Run("protocol_compiler --dependency_manifest_out=$tmpdir/manifest " + Run("protocol_compiler --dependency_out=$tmpdir/manifest " "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); ExpectNoErrors(); @@ -991,9 +992,9 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { "}\n"); string current_working_directory = get_current_dir_name(); - File::ChangeWorkingDirectory(GetTempDirectory()); + SwitchToTempDirectory(); - Run("protocol_compiler --dependency_manifest_out=manifest " + Run("protocol_compiler --dependency_out=manifest " "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); ExpectNoErrors(); diff --git a/test-driver b/test-driver deleted file mode 100755 index d3060566..00000000 --- a/test-driver +++ /dev/null @@ -1,139 +0,0 @@ -#! /bin/sh -# test-driver - basic testsuite driver script. - -scriptversion=2013-07-13.22; # UTC - -# Copyright (C) 2011-2013 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# This file is maintained in Automake, please report -# bugs to or send patches to -# . - -# Make unconditional expansion of undefined variables an error. This -# helps a lot in preventing typo-related bugs. -set -u - -usage_error () -{ - echo "$0: $*" >&2 - print_usage >&2 - exit 2 -} - -print_usage () -{ - cat <$log_file 2>&1 -estatus=$? -if test $enable_hard_errors = no && test $estatus -eq 99; then - estatus=1 -fi - -case $estatus:$expect_failure in - 0:yes) col=$red res=XPASS recheck=yes gcopy=yes;; - 0:*) col=$grn res=PASS recheck=no gcopy=no;; - 77:*) col=$blu res=SKIP recheck=no gcopy=yes;; - 99:*) col=$mgn res=ERROR recheck=yes gcopy=yes;; - *:yes) col=$lgn res=XFAIL recheck=no gcopy=yes;; - *:*) col=$red res=FAIL recheck=yes gcopy=yes;; -esac - -# Report outcome to console. -echo "${col}${res}${std}: $test_name" - -# Register the test result, and other relevant metadata. -echo ":test-result: $res" > $trs_file -echo ":global-test-result: $res" >> $trs_file -echo ":recheck: $recheck" >> $trs_file -echo ":copy-in-global-log: $gcopy" >> $trs_file - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-time-zone: "UTC" -# time-stamp-end: "; # UTC" -# End: -- cgit v1.2.3 From 2e32b8b569f316acc405a36dfad2c742438cb41f Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Wed, 4 Feb 2015 10:27:52 -0800 Subject: Remove "include sstream" from command_line_interface.cc --- src/google/protobuf/compiler/command_line_interface.cc | 1 - 1 file changed, 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 4b28cf6b..06aedd22 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -46,7 +46,6 @@ #endif #include #include -#include #include #include -- cgit v1.2.3 From 3edcbaf57a3dc3bc60a9c8e80e9edac813d86b1d Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Wed, 4 Feb 2015 13:42:16 -0800 Subject: Clean code --- .../protobuf/compiler/command_line_interface.cc | 32 +++++++++++----------- .../protobuf/compiler/command_line_interface.h | 8 +++--- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 06aedd22..c8e60bc4 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -725,7 +725,7 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - if (!dependency_manifest_name_.empty()) { + if (!dependency_out_name_.empty()) { if (!GenerateDependencyManifestFile(parsed_files, &source_tree)) { return 1; } @@ -781,7 +781,7 @@ void CommandLineInterface::Clear() { output_directives_.clear(); codec_type_.clear(); descriptor_set_name_.clear(); - dependency_manifest_name_.clear(); + dependency_out_name_.clear(); mode_ = MODE_COMPILE; print_mode_ = PRINT_NONE; @@ -1020,7 +1020,7 @@ CommandLineInterface::InterpretArgument(const string& name, descriptor_set_name_ = value; } else if (name == "--dependency_out") { - if (!dependency_manifest_name_.empty()) { + if (!dependency_out_name_.empty()) { cerr << name << " may only be passed once." << endl; return PARSE_ARGUMENT_FAIL; } @@ -1029,11 +1029,11 @@ CommandLineInterface::InterpretArgument(const string& name, return PARSE_ARGUMENT_FAIL; } if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode or --decode and generate a manifest at the " - "same time." << endl; + cerr << "Cannot use --encode or --decode and --dependency_out=FILE at " + "the same time." << endl; return PARSE_ARGUMENT_FAIL; } - dependency_manifest_name_ = value; + dependency_out_name_ = value; } else if (name == "--include_imports") { if (imports_in_descriptor_set_) { @@ -1309,44 +1309,44 @@ bool CommandLineInterface::GenerateOutput( } bool CommandLineInterface::GenerateDependencyManifestFile( - const vector parsed_files, - DiskSourceTree * source_tree) { + const vector& parsed_files, + DiskSourceTree* source_tree) { FileDescriptorSet file_set; set already_seen; for (int i = 0; i < parsed_files.size(); i++) { GetTransitiveDependencies(parsed_files[i], false, - &already_seen, file_set.mutable_file()); + &already_seen, + file_set.mutable_file()); } int fd; do { - fd = open(dependency_manifest_name_.c_str(), + fd = open(dependency_out_name_.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); } while (fd < 0 && errno == EINTR); if (fd < 0) { - perror(dependency_manifest_name_.c_str()); + perror(dependency_out_name_.c_str()); return false; } io::FileOutputStream out(fd); io::Printer printer(&out, '$'); - string output_filename = dependency_manifest_name_; - if (output_filename.compare(0, 1, "/") != 0) { + if (dependency_out_name_.compare(0, 1, "/") != 0) { // Convert relative path to absolute path before print. printer.Print("$working_directory$/$output_filename$:", "working_directory", get_current_dir_name(), - "output_filename",output_filename); + "output_filename", dependency_out_name_); } else { printer.Print("$output_filename$:", - "output_filename",output_filename); + "output_filename", dependency_out_name_); } for (int i = 0; i < file_set.file_size(); i++) { const FileDescriptorProto& file = file_set.file(i); - string virtual_file = file.name(); + const string& virtual_file = file.name(); string disk_file; if (source_tree && source_tree->VirtualFileToDiskFile(virtual_file, &disk_file)) { diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 13e93c54..92c578c8 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -247,10 +247,10 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Implements the --descriptor_set_out option. bool WriteDescriptorSet(const vector parsed_files); - // Implements the --manifest-file option + // Implements the --dependency_out option bool GenerateDependencyManifestFile( - const vector parsed_files, - DiskSourceTree * source_tree); + const vector& parsed_files, + DiskSourceTree* source_tree); // Get all transitive dependencies of the given file (including the file // itself), adding them to the given list of FileDescriptorProtos. The @@ -360,7 +360,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // If --dependency_out was given, this is the filename to which the input file // should be written. Otherwise, empty. - string dependency_manifest_name_; + string dependency_out_name_; // True if --include_imports was given, meaning that we should // write all transitive dependencies to the DescriptorSet. Otherwise, only -- cgit v1.2.3 From 3c0355ef3768d45843aaf8437f8ecf63f3706e5d Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Wed, 4 Feb 2015 13:54:58 -0800 Subject: Moving internal code to InternalNano and rename MapUtil to MapFactories. --- .../com/google/protobuf/nano/InternalNano.java | 167 +++++++++++++++ .../com/google/protobuf/nano/MapFactories.java | 63 ++++++ .../java/com/google/protobuf/nano/MapUtil.java | 234 --------------------- .../compiler/javanano/javanano_map_field.cc | 6 +- 4 files changed, 233 insertions(+), 237 deletions(-) create mode 100644 javanano/src/main/java/com/google/protobuf/nano/MapFactories.java delete mode 100644 javanano/src/main/java/com/google/protobuf/nano/MapUtil.java (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java index 6d30c0f8..0705b0c0 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java @@ -30,8 +30,11 @@ package com.google.protobuf.nano; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Arrays; +import java.util.Map; +import java.util.Map.Entry; /** * The classes contained within are used internally by the Protocol Buffer @@ -349,5 +352,169 @@ public final class InternalNano { } return result; } + private static final byte[] emptyBytes = new byte[0]; + private static Object primitiveDefaultValue(int type) { + switch (type) { + case TYPE_BOOL: + return Boolean.FALSE; + case TYPE_BYTES: + return emptyBytes; + case TYPE_STRING: + return ""; + case TYPE_FLOAT: + return Float.valueOf(0); + case TYPE_DOUBLE: + return Double.valueOf(0); + case TYPE_ENUM: + case TYPE_FIXED32: + case TYPE_INT32: + case TYPE_UINT32: + case TYPE_SINT32: + case TYPE_SFIXED32: + return Integer.valueOf(0); + case TYPE_INT64: + case TYPE_UINT64: + case TYPE_SINT64: + case TYPE_FIXED64: + case TYPE_SFIXED64: + return Long.valueOf(0L); + case TYPE_MESSAGE: + case TYPE_GROUP: + default: + throw new IllegalArgumentException( + "Type: " + type + " is not a primitive type."); + } + } + + /** + * Merges the map entry into the map field. Note this is only supposed to + * be called by generated messages. + * + * @param map the map field; may be null, in which case a map will be + * instantiated using the {@link MapUtil.MapFactory} + * @param input the input byte buffer + * @param keyType key type, as defined in InternalNano.TYPE_* + * @param valueType value type, as defined in InternalNano.TYPE_* + * @param valueClazz class of the value field if the valueType is + * TYPE_MESSAGE; otherwise the parameter is ignored and can be null. + * @param keyTag wire tag for the key + * @param valueTag wire tag for the value + * @return the map field + * @throws IOException + */ + @SuppressWarnings("unchecked") + public static final Map mergeMapEntry( + CodedInputByteBufferNano input, + Map map, + int keyType, + int valueType, + Class valueClazz, + int keyTag, + int valueTag) throws IOException { + map = MapFactories.getMapFactory().forMap(map); + final int length = input.readRawVarint32(); + final int oldLimit = input.pushLimit(length); + byte[] payload = null; + K key = null; + V value = null; + while (true) { + int tag = input.readTag(); + if (tag == 0) { + break; + } + if (tag == keyTag) { + key = (K) input.readData(keyType); + } else if (tag == valueTag) { + if (valueType == TYPE_MESSAGE) { + payload = input.readBytes(); + } else { + value = (V) input.readData(valueType); + } + } else { + if (!input.skipField(tag)) { + break; + } + } + } + input.checkLastTagWas(0); + input.popLimit(oldLimit); + + if (key == null) { + key = (K) primitiveDefaultValue(keyType); + } + // Special case: merge the value when the value is a message. + if (valueType == TYPE_MESSAGE) { + MessageNano oldMessageValue = (MessageNano) map.get(key); + if (oldMessageValue != null) { + if (payload != null) { + MessageNano.mergeFrom(oldMessageValue, payload); + } + return map; + } + // Otherwise, create a new value message. + try { + value = valueClazz.newInstance(); + } catch (InstantiationException e) { + throw new IOException( + "Unable to create value message " + valueClazz.getName() + + " in maps."); + } catch (IllegalAccessException e) { + throw new IOException( + "Unable to create value message " + valueClazz.getName() + + " in maps."); + } + if (payload != null) { + MessageNano.mergeFrom((MessageNano) value, payload); + } + } + + if (value == null) { + value = (V) primitiveDefaultValue(valueType); + } + + map.put(key, value); + return map; + } + + public static void serializeMapField( + CodedOutputByteBufferNano output, + Map map, int number, int keyType, int valueType) + throws IOException { + for (Entry entry: map.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + if (key == null || value == null) { + throw new IllegalStateException( + "keys and values in maps cannot be null"); + } + int entrySize = + CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + + CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); + output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); + output.writeRawVarint32(entrySize); + output.writeField(1, keyType, key); + output.writeField(2, valueType, value); + } + } + + public static int computeMapFieldSize( + Map map, int number, int keyType, int valueType) { + int size = 0; + int tagSize = CodedOutputByteBufferNano.computeTagSize(number); + for (Entry entry: map.entrySet()) { + K key = entry.getKey(); + V value = entry.getValue(); + if (key == null || value == null) { + throw new IllegalStateException( + "keys and values in maps cannot be null"); + } + int entrySize = + CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + + CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); + size += tagSize + entrySize + + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize); + } + return size; + } } diff --git a/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java b/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java new file mode 100644 index 00000000..57d00b49 --- /dev/null +++ b/javanano/src/main/java/com/google/protobuf/nano/MapFactories.java @@ -0,0 +1,63 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2013 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. + +package com.google.protobuf.nano; + +import java.util.HashMap; +import java.util.Map; + +/** + * Utility class for maps support. + */ +public final class MapFactories { + public static interface MapFactory { + Map forMap(Map oldMap); + } + + public static void setMapFactory(MapFactory newMapFactory) { + mapFactory = newMapFactory; + } + + public static MapFactory getMapFactory() { + return mapFactory; + } + + private static class DefaultMapFactory implements MapFactory { + public Map forMap(Map oldMap) { + if (oldMap == null) { + return new HashMap(); + } + return oldMap; + } + } + private static volatile MapFactory mapFactory = new DefaultMapFactory(); + + private MapFactories() {} +} diff --git a/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java b/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java deleted file mode 100644 index bc544081..00000000 --- a/javanano/src/main/java/com/google/protobuf/nano/MapUtil.java +++ /dev/null @@ -1,234 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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. - -package com.google.protobuf.nano; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -/** - * Utility class for maps support. - */ -public final class MapUtil { - public static interface MapFactory { - Map forMap(Map oldMap); - } - public static void setMapFactory(MapFactory newMapFactory) { - mapFactory = newMapFactory; - } - - private static class DefaultMapFactory implements MapFactory { - public Map forMap(Map oldMap) { - if (oldMap == null) { - return new HashMap(); - } - return oldMap; - } - } - private static volatile MapFactory mapFactory = new DefaultMapFactory(); - - /** - * Internal utilities to implement maps for generated messages. - * Do NOT use it explicitly. - */ - public static class Internal { - private static final byte[] emptyBytes = new byte[0]; - private static Object primitiveDefaultValue(int type) { - switch (type) { - case InternalNano.TYPE_BOOL: - return Boolean.FALSE; - case InternalNano.TYPE_BYTES: - return emptyBytes; - case InternalNano.TYPE_STRING: - return ""; - case InternalNano.TYPE_FLOAT: - return Float.valueOf(0); - case InternalNano.TYPE_DOUBLE: - return Double.valueOf(0); - case InternalNano.TYPE_ENUM: - case InternalNano.TYPE_FIXED32: - case InternalNano.TYPE_INT32: - case InternalNano.TYPE_UINT32: - case InternalNano.TYPE_SINT32: - case InternalNano.TYPE_SFIXED32: - return Integer.valueOf(0); - case InternalNano.TYPE_INT64: - case InternalNano.TYPE_UINT64: - case InternalNano.TYPE_SINT64: - case InternalNano.TYPE_FIXED64: - case InternalNano.TYPE_SFIXED64: - return Long.valueOf(0L); - case InternalNano.TYPE_MESSAGE: - case InternalNano.TYPE_GROUP: - default: - throw new IllegalArgumentException( - "Type: " + type + " is not a primitive type."); - } - } - - /** - * Merges the map entry into the map field. Note this is only supposed to - * be called by generated messages. - * - * @param map the map field; may be null, in which case a map will be - * instantiated using the {@link MapUtil.MapFactory} - * @param input the input byte buffer - * @param keyType key type, as defined in InternalNano.TYPE_* - * @param valueType value type, as defined in InternalNano.TYPE_* - * @param valueClazz class of the value field if the valueType is - * TYPE_MESSAGE; otherwise the parameter is ignored and can be null. - * @param keyTag wire tag for the key - * @param valueTag wire tag for the value - * @return the map field - * @throws IOException - */ - @SuppressWarnings("unchecked") - public static final Map mergeEntry( - CodedInputByteBufferNano input, - Map map, - int keyType, - int valueType, - Class valueClazz, - int keyTag, - int valueTag) throws IOException { - map = mapFactory.forMap(map); - final int length = input.readRawVarint32(); - final int oldLimit = input.pushLimit(length); - byte[] payload = null; - K key = null; - V value = null; - while (true) { - int tag = input.readTag(); - if (tag == 0) { - break; - } - if (tag == keyTag) { - key = (K) input.readData(keyType); - } else if (tag == valueTag) { - if (valueType == InternalNano.TYPE_MESSAGE) { - payload = input.readBytes(); - } else { - value = (V) input.readData(valueType); - } - } else { - if (!input.skipField(tag)) { - break; - } - } - } - input.checkLastTagWas(0); - input.popLimit(oldLimit); - - if (key == null) { - key = (K) primitiveDefaultValue(keyType); - } - - // Special case: merge the value when the value is a message. - if (valueType == InternalNano.TYPE_MESSAGE) { - MessageNano oldMessageValue = (MessageNano) map.get(key); - if (oldMessageValue != null) { - if (payload != null) { - MessageNano.mergeFrom(oldMessageValue, payload); - } - return map; - } - // Otherwise, create a new value message. - try { - value = valueClazz.newInstance(); - } catch (InstantiationException e) { - throw new IOException( - "Unable to create value message " + valueClazz.getName() - + " in maps."); - } catch (IllegalAccessException e) { - throw new IOException( - "Unable to create value message " + valueClazz.getName() - + " in maps."); - } - if (payload != null) { - MessageNano.mergeFrom((MessageNano) value, payload); - } - } - - if (value == null) { - value = (V) primitiveDefaultValue(valueType); - } - - map.put(key, value); - return map; - } - - public static void serializeMapField( - CodedOutputByteBufferNano output, - Map map, int number, int keyType, int valueType) - throws IOException { - for (Entry entry: map.entrySet()) { - K key = entry.getKey(); - V value = entry.getValue(); - if (key == null || value == null) { - throw new IllegalStateException( - "keys and values in maps cannot be null"); - } - int entrySize = - CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + - CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); - output.writeTag(number, WireFormatNano.WIRETYPE_LENGTH_DELIMITED); - output.writeRawVarint32(entrySize); - output.writeField(1, keyType, key); - output.writeField(2, valueType, value); - } - } - - public static int computeMapFieldSize( - Map map, int number, int keyType, int valueType) { - int size = 0; - int tagSize = CodedOutputByteBufferNano.computeTagSize(number); - for (Entry entry: map.entrySet()) { - K key = entry.getKey(); - V value = entry.getValue(); - if (key == null || value == null) { - throw new IllegalStateException( - "keys and values in maps cannot be null"); - } - int entrySize = - CodedOutputByteBufferNano.computeFieldSize(1, keyType, key) + - CodedOutputByteBufferNano.computeFieldSize(2, valueType, value); - size += tagSize + entrySize - + CodedOutputByteBufferNano.computeRawVarint32Size(entrySize); - } - return size; - } - - private Internal() {} - } - - private MapUtil() {} -} diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc index dead3685..7b14db5d 100644 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -133,7 +133,7 @@ GenerateClearCode(io::Printer* printer) const { void MapFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print(variables_, - "this.$name$ = com.google.protobuf.nano.MapUtil.Internal.mergeEntry(\n" + "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n" " input, this.$name$,\n" " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n" @@ -146,7 +146,7 @@ void MapFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, "if (this.$name$ != null) {\n" - " com.google.protobuf.nano.MapUtil.Internal.serializeMapField(\n" + " com.google.protobuf.nano.InternalNano.serializeMapField(\n" " output, this.$name$, $number$,\n" " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n" @@ -157,7 +157,7 @@ void MapFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "if (this.$name$ != null) {\n" - " size += com.google.protobuf.nano.MapUtil.Internal.computeMapFieldSize(\n" + " size += com.google.protobuf.nano.InternalNano.computeMapFieldSize(\n" " this.$name$, $number$,\n" " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" " com.google.protobuf.nano.InternalNano.$value_desc_type$);\n" -- cgit v1.2.3 From 1d627f85c3aef00b24a6a19e5bc2a46ef889f16f Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Wed, 4 Feb 2015 15:48:06 -0800 Subject: Fix comment --- src/google/protobuf/compiler/command_line_interface.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 92c578c8..1df53c4a 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -358,8 +358,8 @@ class LIBPROTOC_EXPORT CommandLineInterface { // FileDescriptorSet should be written. Otherwise, empty. string descriptor_set_name_; - // If --dependency_out was given, this is the filename to which the input file - // should be written. Otherwise, empty. + // If --dependency_out was given, this is the path to the file where the + // dependency file will be written. Otherwise, empty. string dependency_out_name_; // True if --include_imports was given, meaning that we should -- cgit v1.2.3 From bd3573cb096cb8f0ec4bf29f0e11744a06a9e5a6 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Thu, 5 Feb 2015 14:52:17 -0800 Subject: Fix the behavior when merging conflicting keys, the new value always override the existing one even for message types. --- .../com/google/protobuf/nano/InternalNano.java | 40 ++++------------------ .../java/com/google/protobuf/nano/NanoTest.java | 28 ++++++++++++++- .../java/com/google/protobuf/nano/map_test.proto | 1 + .../compiler/javanano/javanano_map_field.cc | 6 ++-- 4 files changed, 38 insertions(+), 37 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java index 0705b0c0..fc0a36cd 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java @@ -391,12 +391,12 @@ public final class InternalNano { * be called by generated messages. * * @param map the map field; may be null, in which case a map will be - * instantiated using the {@link MapUtil.MapFactory} + * instantiated using the {@link MapFactories.MapFactory} * @param input the input byte buffer * @param keyType key type, as defined in InternalNano.TYPE_* * @param valueType value type, as defined in InternalNano.TYPE_* - * @param valueClazz class of the value field if the valueType is - * TYPE_MESSAGE; otherwise the parameter is ignored and can be null. + * @param value an new instance of the value, if the value is a TYPE_MESSAGE; + * otherwise this parameter can be null and will be ignored. * @param keyTag wire tag for the key * @param valueTag wire tag for the value * @return the map field @@ -408,15 +408,13 @@ public final class InternalNano { Map map, int keyType, int valueType, - Class valueClazz, + V value, int keyTag, int valueTag) throws IOException { map = MapFactories.getMapFactory().forMap(map); final int length = input.readRawVarint32(); final int oldLimit = input.pushLimit(length); - byte[] payload = null; K key = null; - V value = null; while (true) { int tag = input.readTag(); if (tag == 0) { @@ -426,7 +424,7 @@ public final class InternalNano { key = (K) input.readData(keyType); } else if (tag == valueTag) { if (valueType == TYPE_MESSAGE) { - payload = input.readBytes(); + input.readMessage((MessageNano) value); } else { value = (V) input.readData(valueType); } @@ -440,36 +438,12 @@ public final class InternalNano { input.popLimit(oldLimit); if (key == null) { + // key can only be primitive types. key = (K) primitiveDefaultValue(keyType); } - // Special case: merge the value when the value is a message. - if (valueType == TYPE_MESSAGE) { - MessageNano oldMessageValue = (MessageNano) map.get(key); - if (oldMessageValue != null) { - if (payload != null) { - MessageNano.mergeFrom(oldMessageValue, payload); - } - return map; - } - // Otherwise, create a new value message. - try { - value = valueClazz.newInstance(); - } catch (InstantiationException e) { - throw new IOException( - "Unable to create value message " + valueClazz.getName() - + " in maps."); - } catch (IllegalAccessException e) { - throw new IOException( - "Unable to create value message " + valueClazz.getName() - + " in maps."); - } - if (payload != null) { - MessageNano.mergeFrom((MessageNano) value, payload); - } - } - if (value == null) { + // message type value = (V) primitiveDefaultValue(valueType); } diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java index a7383cb4..bf8a391a 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java +++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java @@ -3742,7 +3742,6 @@ public class NanoTest extends TestCase { byte[] output = MessageNano.toByteArray(origin); TestMap parsed = new TestMap(); MessageNano.mergeFrom(parsed, output); - // TODO(liujisi): Test merging message type values. // TODO(liujisi): Test missing key/value in parsing. } @@ -3769,6 +3768,33 @@ public class NanoTest extends TestCase { } } + /** + * Tests that merging bytes containing conflicting keys with override the + * message value instead of merging the message value into the existing entry. + */ + public void testMapMergeOverrideMessageValues() throws Exception { + TestMap.MessageValue origValue = new TestMap.MessageValue(); + origValue.value = 1; + origValue.value2 = 2; + TestMap.MessageValue newValue = new TestMap.MessageValue(); + newValue.value = 3; + + TestMap origMessage = new TestMap(); + origMessage.int32ToMessageField = + new HashMap(); + origMessage.int32ToMessageField.put(1, origValue); + + TestMap newMessage = new TestMap(); + newMessage.int32ToMessageField = + new HashMap(); + newMessage.int32ToMessageField.put(1, newValue); + MessageNano.mergeFrom(origMessage, + MessageNano.toByteArray(newMessage)); + TestMap.MessageValue mergedValue = origMessage.int32ToMessageField.get(1); + assertEquals(3, mergedValue.value); + assertEquals(0, mergedValue.value2); + } + private static final Integer[] int32Values = new Integer[] { 0, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE, }; diff --git a/javanano/src/test/java/com/google/protobuf/nano/map_test.proto b/javanano/src/test/java/com/google/protobuf/nano/map_test.proto index 5ea86717..f72833ad 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/map_test.proto +++ b/javanano/src/test/java/com/google/protobuf/nano/map_test.proto @@ -38,6 +38,7 @@ option java_outer_classname = "MapTestProto"; message TestMap { message MessageValue { int32 value = 1; + int32 value2 = 2; } enum EnumValue { FOO = 0; diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc index 7b14db5d..082573dd 100644 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -102,9 +102,9 @@ void SetMapVariables(const Params& params, (*variables)["value_tag"] = SimpleItoa(internal::WireFormat::MakeTag(value)); (*variables)["type_parameters"] = (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; - (*variables)["value_class"] = + (*variables)["value_default"] = value->type() == FieldDescriptor::TYPE_MESSAGE - ? (*variables)["value_type"] + ".class" + ? "new " + (*variables)["value_type"] + "()" : "null"; } } // namespace @@ -137,7 +137,7 @@ GenerateMergingCode(io::Printer* printer) const { " input, this.$name$,\n" " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n" - " $value_class$,\n" + " $value_default$,\n" " $key_tag$, $value_tag$);\n" "\n"); } -- cgit v1.2.3 From 1536e93349b0f8e703060e5efddb91169c93786d Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Fri, 6 Feb 2015 15:30:48 -0800 Subject: Implement Equals for nano. --- .../com/google/protobuf/nano/InternalNano.java | 40 +++++++ .../java/com/google/protobuf/nano/NanoTest.java | 123 ++++++++++++++++++++- .../compiler/javanano/javanano_map_field.cc | 5 + 3 files changed, 166 insertions(+), 2 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java index a9a459dd..044c30dd 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java @@ -491,4 +491,44 @@ public final class InternalNano { } return size; } + + /** + * Checks whether two {@link Map} are equal. We don't use the default equals + * method of {@link Map} because it compares by identity not by content for + * byte arrays. + */ + public static boolean equals(Map a, Map b) { + if (a == b) { + return true; + } + if (a == null) { + return b.size() == 0; + } + if (b == null) { + return a.size() == 0; + } + if (a.size() != b.size()) { + return false; + } + for (Entry entry : a.entrySet()) { + if (!b.containsKey(entry.getKey())) { + return false; + } + if (!equalsMapValue(entry.getValue(), b.get(entry.getKey()))) { + return false; + } + } + return true; + } + + private static boolean equalsMapValue(Object a, Object b) { + if (a == null || b == null) { + throw new IllegalStateException( + "keys and values in maps cannot be null"); + } + if (a instanceof byte[] && b instanceof byte[]) { + return Arrays.equals((byte[]) a, (byte[]) b); + } + return a.equals(b); + } } diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java index 4159e662..aa279da2 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java +++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java @@ -31,6 +31,7 @@ package com.google.protobuf.nano; import com.google.protobuf.nano.MapTestProto.TestMap; +import com.google.protobuf.nano.MapTestProto.TestMap.MessageValue; import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors; import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas; import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano; @@ -47,6 +48,7 @@ import junit.framework.TestCase; import java.util.Arrays; import java.util.HashMap; import java.util.Map; +import java.util.TreeMap; /** * Test nano runtime. @@ -3824,15 +3826,107 @@ public class NanoTest extends TestCase { assertEquals(0, messageValue.value2); } + public void testMapEquals() throws Exception { + TestMap a = new TestMap(); + TestMap b = new TestMap(); + + // empty and null map fields are equal. + assertTestMapEqual(a, b); + a.int32ToBytesField = new HashMap(); + assertTestMapEqual(a, b); + + a.int32ToInt32Field = new HashMap(); + b.int32ToInt32Field = new HashMap(); + setMap(a.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values)); + setMap(b.int32ToInt32Field, deepCopy(int32Values), deepCopy(int32Values)); + assertTestMapEqual(a, b); + + a.int32ToMessageField = + new HashMap(); + b.int32ToMessageField = + new HashMap(); + setMap(a.int32ToMessageField, + deepCopy(int32Values), deepCopy(messageValues)); + setMap(b.int32ToMessageField, + deepCopy(int32Values), deepCopy(messageValues)); + assertTestMapEqual(a, b); + + a.stringToInt32Field = new HashMap(); + b.stringToInt32Field = new HashMap(); + setMap(a.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values)); + setMap(b.stringToInt32Field, deepCopy(stringValues), deepCopy(int32Values)); + assertTestMapEqual(a, b); + + a.int32ToBytesField = new HashMap(); + b.int32ToBytesField = new HashMap(); + setMap(a.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues)); + setMap(b.int32ToBytesField, deepCopy(int32Values), deepCopy(bytesValues)); + assertTestMapEqual(a, b); + + // Make sure the map implementation does not matter. + a.int32ToStringField = new TreeMap(); + b.int32ToStringField = new HashMap(); + setMap(a.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues)); + setMap(b.int32ToStringField, deepCopy(int32Values), deepCopy(stringValues)); + assertTestMapEqual(a, b); + + a.clear(); + b.clear(); + + // unequal cases: different value + a.int32ToInt32Field = new HashMap(); + b.int32ToInt32Field = new HashMap(); + a.int32ToInt32Field.put(1, 1); + b.int32ToInt32Field.put(1, 2); + assertTestMapUnequal(a, b); + // unequal case: additional entry + b.int32ToInt32Field.put(1, 1); + b.int32ToInt32Field.put(2, 1); + assertTestMapUnequal(a, b); + a.int32ToInt32Field.put(2, 1); + assertTestMapEqual(a, b); + + // unequal case: different message value. + a.int32ToMessageField = + new HashMap(); + b.int32ToMessageField = + new HashMap(); + MessageValue va = new MessageValue(); + va.value = 1; + MessageValue vb = new MessageValue(); + vb.value = 1; + a.int32ToMessageField.put(1, va); + b.int32ToMessageField.put(1, vb); + assertTestMapEqual(a, b); + vb.value = 2; + assertTestMapUnequal(a, b); + } + + private static void assertTestMapEqual(TestMap a, TestMap b) + throws Exception { + assertEquals(a.hashCode(), b.hashCode()); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + } + + private static void assertTestMapUnequal(TestMap a, TestMap b) + throws Exception { + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + } + private static final Integer[] int32Values = new Integer[] { 0, 1, -1, Integer.MAX_VALUE, Integer.MIN_VALUE, }; + private static final Long[] int64Values = new Long[] { 0L, 1L, -1L, Long.MAX_VALUE, Long.MIN_VALUE, }; + private static final String[] stringValues = new String[] { "", "hello", "world", "foo", "bar", }; + private static final byte[][] bytesValues = new byte[][] { new byte[] {}, new byte[] {0}, @@ -3840,13 +3934,16 @@ public class NanoTest extends TestCase { new byte[] {127, -128}, new byte[] {'a', 'b', '0', '1'}, }; + private static final Boolean[] boolValues = new Boolean[] { false, true, }; + private static final Integer[] enumValues = new Integer[] { TestMap.FOO, TestMap.BAR, TestMap.BAZ, TestMap.QUX, Integer.MAX_VALUE /* unknown */, }; + private static final TestMap.MessageValue[] messageValues = new TestMap.MessageValue[] { newMapValueMessage(0), @@ -3855,15 +3952,37 @@ public class NanoTest extends TestCase { newMapValueMessage(Integer.MAX_VALUE), newMapValueMessage(Integer.MIN_VALUE), }; + private static TestMap.MessageValue newMapValueMessage(int value) { TestMap.MessageValue result = new TestMap.MessageValue(); result.value = value; return result; } + @SuppressWarnings("unchecked") + private static T[] deepCopy(T[] orig) throws Exception { + if (orig instanceof MessageValue[]) { + MessageValue[] result = new MessageValue[orig.length]; + for (int i = 0; i < orig.length; i++) { + result[i] = new MessageValue(); + MessageNano.mergeFrom( + result[i], MessageNano.toByteArray((MessageValue) orig[i])); + } + return (T[]) result; + } + if (orig instanceof byte[][]) { + byte[][] result = new byte[orig.length][]; + for (int i = 0; i < orig.length; i++) { + byte[] origBytes = (byte[]) orig[i]; + result[i] = Arrays.copyOf(origBytes, origBytes.length); + } + } + return Arrays.copyOf(orig, orig.length); + } + private void setMap(Map map, K[] keys, V[] values) { assert(keys.length == values.length); - for (int i = 0; i < keys.length; ++i) { + for (int i = 0; i < keys.length; i++) { map.put(keys[i], values[i]); } } @@ -3871,7 +3990,7 @@ public class NanoTest extends TestCase { private void assertMapSet( Map map, K[] keys, V[] values) throws Exception { assert(keys.length == values.length); - for (int i = 0; i < values.length; ++i) { + for (int i = 0; i < values.length; i++) { assertEquals(values[i], map.get(keys[i])); } assertEquals(keys.length, map.size()); diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc index 082573dd..c816fb3d 100644 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -166,6 +166,11 @@ GenerateSerializedSizeCode(io::Printer* printer) const { void MapFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!com.google.protobuf.nano.InternalNano.equals(\n" + " this.$name$, other.$name$)) {\n" + " return false;\n" + "}\n"); } void MapFieldGenerator:: -- cgit v1.2.3 From d9a6f27bc333587fad88b3bc1f53b370a016ccd0 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Fri, 6 Feb 2015 15:55:04 -0800 Subject: implement hashCode() for JavaNano maps. --- .../java/com/google/protobuf/nano/InternalNano.java | 19 +++++++++++++++++++ .../protobuf/compiler/javanano/javanano_map_field.cc | 3 +++ 2 files changed, 22 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java index 044c30dd..f3144652 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java @@ -531,4 +531,23 @@ public final class InternalNano { } return a.equals(b); } + + public static int hashCode(Map map) { + if (map == null) { + return 0; + } + int result = 0; + for (Entry entry : map.entrySet()) { + result += hashCodeForMap(entry.getKey()) + ^ hashCodeForMap(entry.getValue()); + } + return result; + } + + private static int hashCodeForMap(Object o) { + if (o instanceof byte[]) { + return Arrays.hashCode((byte[]) o); + } + return o.hashCode(); + } } diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc index c816fb3d..117c4f5c 100644 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -175,6 +175,9 @@ GenerateEqualsCode(io::Printer* printer) const { void MapFieldGenerator:: GenerateHashCodeCode(io::Printer* printer) const { + printer->Print(variables_, + "result = 31 * result +\n" + " com.google.protobuf.nano.InternalNano.hashCode(this.$name$);\n"); } } // namespace javanano -- cgit v1.2.3 From 12d8a514c84ee8d60e5d8b8b84aa09dad15197f2 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Sat, 7 Feb 2015 12:51:36 -0800 Subject: Get the map factory per mergeFrom() call for JavaNano. --- .../src/main/java/com/google/protobuf/nano/InternalNano.java | 5 ++++- src/google/protobuf/compiler/javanano/javanano_helpers.cc | 11 +++++++++++ src/google/protobuf/compiler/javanano/javanano_helpers.h | 2 ++ src/google/protobuf/compiler/javanano/javanano_map_field.cc | 2 +- src/google/protobuf/compiler/javanano/javanano_message.cc | 5 +++++ 5 files changed, 23 insertions(+), 2 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java index f3144652..c92ec417 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java @@ -30,6 +30,8 @@ package com.google.protobuf.nano; +import com.google.protobuf.nano.MapFactories.MapFactory; + import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Arrays; @@ -406,12 +408,13 @@ public final class InternalNano { public static final Map mergeMapEntry( CodedInputByteBufferNano input, Map map, + MapFactory mapFactory, int keyType, int valueType, V value, int keyTag, int valueTag) throws IOException { - map = MapFactories.getMapFactory().forMap(map); + map = mapFactory.forMap(map); final int length = input.readRawVarint32(); final int oldLimit = input.pushLimit(length); K key = null; diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 2149418a..7b23d9f4 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -560,6 +560,17 @@ void SetBitOperationVariables(const string name, (*variables)["different_" + name] = GenerateDifferentBit(bitIndex); } +bool HasMapField(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = descriptor->field(i); + if (field->type() == FieldDescriptor::TYPE_MESSAGE && + IsMapEntry(field->message_type())) { + return true; + } + } + return false; +} + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h index 5d3532b4..b4fee649 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.h +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h @@ -187,6 +187,8 @@ inline bool IsMapEntry(const Descriptor* descriptor) { descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3; } +bool HasMapField(const Descriptor* descriptor); + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_map_field.cc b/src/google/protobuf/compiler/javanano/javanano_map_field.cc index 117c4f5c..83b2b0ce 100644 --- a/src/google/protobuf/compiler/javanano/javanano_map_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_map_field.cc @@ -134,7 +134,7 @@ void MapFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print(variables_, "this.$name$ = com.google.protobuf.nano.InternalNano.mergeMapEntry(\n" - " input, this.$name$,\n" + " input, this.$name$, mapFactory,\n" " com.google.protobuf.nano.InternalNano.$key_desc_type$,\n" " com.google.protobuf.nano.InternalNano.$value_desc_type$,\n" " $value_default$,\n" diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 5454d9be..da7c656f 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -345,6 +345,11 @@ void MessageGenerator::GenerateMergeFromMethods(io::Printer* printer) { "classname", descriptor_->name()); printer->Indent(); + if (HasMapField(descriptor_)) { + printer->Print( + "com.google.protobuf.nano.MapFactories.MapFactory mapFactory =\n" + " com.google.protobuf.nano.MapFactories.getMapFactory();\n"); + } printer->Print( "while (true) {\n"); -- cgit v1.2.3 From e2555e235f867f3d7a0378e95a45109c8fd2dfbe Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Sat, 7 Feb 2015 15:28:54 -0800 Subject: Change target to output filenames --- .../protobuf/compiler/command_line_interface.cc | 69 +++++++++++++++------- .../protobuf/compiler/command_line_interface.h | 3 + .../compiler/command_line_interface_unittest.cc | 26 ++++++-- 3 files changed, 73 insertions(+), 25 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index c8e60bc4..ddd58e2d 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -48,7 +48,6 @@ #include #include -#include #include #ifndef _SHARED_PTR_H #include @@ -254,6 +253,9 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { // format, unless one has already been written. void AddJarManifest(); + // Get name of all output files. + void GetOutputFilenames(vector* output_filenames); + // implements GeneratorContext -------------------------------------- io::ZeroCopyOutputStream* Open(const string& filename); io::ZeroCopyOutputStream* OpenForAppend(const string& filename); @@ -441,6 +443,14 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { } } +void CommandLineInterface::GeneratorContextImpl::GetOutputFilenames( + vector* output_filenames) { + for (map::iterator iter = files_.begin(); + iter != files_.end(); ++iter) { + output_filenames->push_back(iter->first); + } +} + io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( const string& filename) { return new MemoryOutputStream(this, filename, false); @@ -670,7 +680,6 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { // We construct a separate GeneratorContext for each output location. Note // that two code generators may output to the same location, in which case // they should share a single GeneratorContext so that OpenForInsert() works. - typedef hash_map GeneratorContextMap; GeneratorContextMap output_directories; // Generate output. @@ -717,16 +726,17 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } - STLDeleteValues(&output_directories); - - if (!descriptor_set_name_.empty()) { - if (!WriteDescriptorSet(parsed_files)) { + if (!dependency_out_name_.empty()) { + if (!GenerateDependencyManifestFile(parsed_files, output_directories, + &source_tree)) { return 1; } } - if (!dependency_out_name_.empty()) { - if (!GenerateDependencyManifestFile(parsed_files, &source_tree)) { + STLDeleteValues(&output_directories); + + if (!descriptor_set_name_.empty()) { + if (!WriteDescriptorSet(parsed_files)) { return 1; } } @@ -878,6 +888,15 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { cerr << "Missing output directives." << endl; return PARSE_ARGUMENT_FAIL; } + if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) { + cerr << "Can only use --dependency_out=FILE when generating code." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (!dependency_out_name_.empty() && input_files_.size() > 1) { + cerr << "Can only process one input file when using --dependency_out=FILE." + << endl; + return PARSE_ARGUMENT_FAIL; + } if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { cerr << "--include_imports only makes sense when combined with " "--descriptor_set_out." << endl; @@ -1028,11 +1047,6 @@ CommandLineInterface::InterpretArgument(const string& name, cerr << name << " requires a non-empty value." << endl; return PARSE_ARGUMENT_FAIL; } - if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode or --decode and --dependency_out=FILE at " - "the same time." << endl; - return PARSE_ARGUMENT_FAIL; - } dependency_out_name_ = value; } else if (name == "--include_imports") { @@ -1310,6 +1324,7 @@ bool CommandLineInterface::GenerateOutput( bool CommandLineInterface::GenerateDependencyManifestFile( const vector& parsed_files, + const GeneratorContextMap& output_directories, DiskSourceTree* source_tree) { FileDescriptorSet file_set; @@ -1321,6 +1336,18 @@ bool CommandLineInterface::GenerateDependencyManifestFile( file_set.mutable_file()); } + vector output_filenames; + for (GeneratorContextMap::const_iterator iter = output_directories.begin(); + iter != output_directories.end(); ++iter) { + const string& location = iter->first; + GeneratorContextImpl* directory = iter->second; + vector relative_output_filenames; + directory->GetOutputFilenames(&relative_output_filenames); + for (int i = 0; i < relative_output_filenames.size(); i++) { + output_filenames.push_back(location + relative_output_filenames[i]); + } + } + int fd; do { fd = open(dependency_out_name_.c_str(), @@ -1335,15 +1362,15 @@ bool CommandLineInterface::GenerateDependencyManifestFile( io::FileOutputStream out(fd); io::Printer printer(&out, '$'); - if (dependency_out_name_.compare(0, 1, "/") != 0) { - // Convert relative path to absolute path before print. - printer.Print("$working_directory$/$output_filename$:", - "working_directory", get_current_dir_name(), - "output_filename", dependency_out_name_); - } else { - printer.Print("$output_filename$:", - "output_filename", dependency_out_name_); + for (int i = 0; i < output_filenames.size(); i++) { + printer.Print(output_filenames[i].c_str()); + if (i == output_filenames.size() - 1) { + printer.Print(":"); + } else { + printer.Print(" \\\n"); + } } + for (int i = 0; i < file_set.file_size(); i++) { const FileDescriptorProto& file = file_set.file(i); const string& virtual_file = file.name(); diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 1df53c4a..7e611c44 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -39,6 +39,7 @@ #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__ #include +#include #include #include #include @@ -190,6 +191,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { class ErrorPrinter; class GeneratorContextImpl; class MemoryOutputStream; + typedef hash_map GeneratorContextMap; // Clear state from previous Run(). void Clear(); @@ -250,6 +252,7 @@ class LIBPROTOC_EXPORT CommandLineInterface { // Implements the --dependency_out option bool GenerateDependencyManifestFile( const vector& parsed_files, + const GeneratorContextMap& output_directories, DiskSourceTree* source_tree); // Get all transitive dependencies of the given file (including the file diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index f298be75..9e02f729 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -959,6 +959,24 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); } +TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { + CreateTempFile("foo.proto", + "syntax = \"proto2\";\n" + "message Foo {}\n"); + CreateTempFile("bar.proto", + "syntax = \"proto2\";\n" + "import \"foo.proto\";\n" + "message Bar {\n" + " optional Foo foo = 1;\n" + "}\n"); + + Run("protocol_compiler --dependency_out=$tmpdir/manifest " + "--test_out=$tmpdir --proto_path=$tmpdir bar.proto foo.proto"); + + ExpectErrorText( + "Can only process one input file when using --dependency_out=FILE.\n"); +} + TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" @@ -976,8 +994,8 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { ExpectNoErrors(); ExpectFileContent("manifest", - "$tmpdir/manifest: $tmpdir/foo.proto\\\n" - " $tmpdir/bar.proto"); + "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " + "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); } TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { @@ -1000,8 +1018,8 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { ExpectNoErrors(); ExpectFileContent("manifest", - "$tmpdir/manifest: $tmpdir/foo.proto\\\n" - " $tmpdir/bar.proto"); + "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " + "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); File::ChangeWorkingDirectory(current_working_directory); } -- cgit v1.2.3 From de525ec219338d37eee976c00783cd1edee8054d Mon Sep 17 00:00:00 2001 From: Nobuaki Sukegawa Date: Sat, 7 Feb 2015 13:41:00 +0900 Subject: Add missing LIBPROTOC_EXPORT to ruby generator --- src/google/protobuf/compiler/ruby/ruby_generator.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h index 48dbefd1..75555c31 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.h +++ b/src/google/protobuf/compiler/ruby/ruby_generator.h @@ -40,7 +40,8 @@ namespace protobuf { namespace compiler { namespace ruby { -class Generator : public google::protobuf::compiler::CodeGenerator { +class LIBPROTOC_EXPORT Generator + : public google::protobuf::compiler::CodeGenerator { virtual bool Generate( const FileDescriptor* file, const string& parameter, -- cgit v1.2.3 From eb2ce0293138532680fdd3647c01db7587b9367b Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Mon, 9 Feb 2015 11:57:41 -0800 Subject: Fix absolute/relative path in output --- .../protobuf/compiler/command_line_interface.cc | 6 +++++- .../compiler/command_line_interface_unittest.cc | 22 +++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index ddd58e2d..4095b3c9 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -1344,7 +1344,11 @@ bool CommandLineInterface::GenerateDependencyManifestFile( vector relative_output_filenames; directory->GetOutputFilenames(&relative_output_filenames); for (int i = 0; i < relative_output_filenames.size(); i++) { - output_filenames.push_back(location + relative_output_filenames[i]); + string output_filename = location + relative_output_filenames[i]; + if (output_filename.compare(0, 2, "./") == 0) { + output_filename = output_filename.substr(2); + } + output_filenames.push_back(output_filename); } } diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 9e02f729..2aba68b9 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -988,17 +988,22 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { " optional Foo foo = 1;\n" "}\n"); - Run("protocol_compiler --dependency_out=$tmpdir/manifest " - "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); + string current_working_directory = get_current_dir_name(); + SwitchToTempDirectory(); + + Run("protocol_compiler --dependency_out=manifest --test_out=. " + "bar.proto"); ExpectNoErrors(); ExpectFileContent("manifest", - "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " - "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); + "bar.proto.MockCodeGenerator.test_generator: " + "foo.proto\\\n bar.proto"); + + File::ChangeWorkingDirectory(current_working_directory); } -TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { +TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" "message Foo {}\n"); @@ -1009,10 +1014,7 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { " optional Foo foo = 1;\n" "}\n"); - string current_working_directory = get_current_dir_name(); - SwitchToTempDirectory(); - - Run("protocol_compiler --dependency_out=manifest " + Run("protocol_compiler --dependency_out=$tmpdir/manifest " "--test_out=$tmpdir --proto_path=$tmpdir bar.proto"); ExpectNoErrors(); @@ -1020,8 +1022,6 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForRelativePath) { ExpectFileContent("manifest", "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); - - File::ChangeWorkingDirectory(current_working_directory); } // ------------------------------------------------------------------- -- cgit v1.2.3 From a2bea0a0012b4adbc50c47246d968a85cb88cec2 Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Thu, 12 Feb 2015 16:08:01 -0800 Subject: Properly support maps in Ruby protoc and another bugfix. Previously, we supported map fields in the Ruby DSL. However, we never connected the final link in the chain and generated `map` DSL commands for map fields in `.proto` files. My apologies -- I had been testing with the DSL directly so I missed this. Also fixed a handlerdata-setup-infinite-loop when a map value field's type is its containing message. --- ruby/ext/google/protobuf_c/encode_decode.c | 23 +++---- ruby/tests/generated_code.rb | 70 +++----------------- .../protobuf/compiler/ruby/ruby_generator.cc | 75 +++++++++++++++++----- 3 files changed, 79 insertions(+), 89 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/ruby/ext/google/protobuf_c/encode_decode.c b/ruby/ext/google/protobuf_c/encode_decode.c index 0630f567..256fc829 100644 --- a/ruby/ext/google/protobuf_c/encode_decode.c +++ b/ruby/ext/google/protobuf_c/encode_decode.c @@ -208,7 +208,7 @@ typedef struct { size_t ofs; upb_fieldtype_t key_field_type; upb_fieldtype_t value_field_type; - VALUE value_field_typeclass; + const upb_def* value_field_subdef; } map_handlerdata_t; // Temporary frame for map parsing: at the beginning of a map entry message, a @@ -248,8 +248,15 @@ static bool endmap_handler(void *closure, const void *hd, upb_status* s) { VALUE key = native_slot_get( mapdata->key_field_type, Qnil, &frame->key_storage); + + VALUE value_field_typeclass = Qnil; + if (mapdata->value_field_type == UPB_TYPE_MESSAGE || + mapdata->value_field_type == UPB_TYPE_ENUM) { + value_field_typeclass = get_def_obj(mapdata->value_field_subdef); + } + VALUE value = native_slot_get( - mapdata->value_field_type, mapdata->value_field_typeclass, + mapdata->value_field_type, value_field_typeclass, &frame->value_storage); Map_index_set(frame->map, key, value); @@ -280,17 +287,7 @@ static map_handlerdata_t* new_map_handlerdata( MAP_VALUE_FIELD); assert(value_field != NULL); hd->value_field_type = upb_fielddef_type(value_field); - hd->value_field_typeclass = field_type_class(value_field); - - // Ensure that value_field_typeclass is properly GC-rooted. We must do this - // because we hold a reference to the Ruby class in the handlerdata, which is - // owned by the handlers. The handlers are owned by *this* message's Ruby - // object, but each Ruby object is rooted independently at the def -> Ruby - // object map. So we have to ensure that the Ruby objects we depend on will - // stick around as long as we're around. - if (hd->value_field_typeclass != Qnil) { - rb_ary_push(desc->typeclass_references, hd->value_field_typeclass); - } + hd->value_field_subdef = upb_fielddef_subdef(value_field); return hd; } diff --git a/ruby/tests/generated_code.rb b/ruby/tests/generated_code.rb index db762ad9..5a685433 100644 --- a/ruby/tests/generated_code.rb +++ b/ruby/tests/generated_code.rb @@ -27,16 +27,16 @@ Google::Protobuf::DescriptorPool.generated_pool.build do repeated :repeated_bytes, :string, 29 repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" - repeated :map_int32_string, :message, 61, "A.B.C.TestMessage.MapInt32StringEntry" - repeated :map_int64_string, :message, 62, "A.B.C.TestMessage.MapInt64StringEntry" - repeated :map_uint32_string, :message, 63, "A.B.C.TestMessage.MapUint32StringEntry" - repeated :map_uint64_string, :message, 64, "A.B.C.TestMessage.MapUint64StringEntry" - repeated :map_bool_string, :message, 65, "A.B.C.TestMessage.MapBoolStringEntry" - repeated :map_string_string, :message, 66, "A.B.C.TestMessage.MapStringStringEntry" - repeated :map_string_msg, :message, 67, "A.B.C.TestMessage.MapStringMsgEntry" - repeated :map_string_enum, :message, 68, "A.B.C.TestMessage.MapStringEnumEntry" - repeated :map_string_int32, :message, 69, "A.B.C.TestMessage.MapStringInt32Entry" - repeated :map_string_bool, :message, 70, "A.B.C.TestMessage.MapStringBoolEntry" + map :map_int32_string, :int32, :string, 61 + map :map_int64_string, :int64, :string, 62 + map :map_uint32_string, :uint32, :string, 63 + map :map_uint64_string, :uint64, :string, 64 + map :map_bool_string, :bool, :string, 65 + map :map_string_string, :string, :string, 66 + map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage" + map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum" + map :map_string_int32, :string, :int32, 69 + map :map_string_bool, :string, :bool, 70 optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" oneof :my_oneof do optional :oneof_int32, :int32, 41 @@ -52,46 +52,6 @@ Google::Protobuf::DescriptorPool.generated_pool.build do optional :oneof_msg, :message, 51, "A.B.C.TestMessage" end end - add_message "A.B.C.TestMessage.MapInt32StringEntry" do - optional :key, :int32, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapInt64StringEntry" do - optional :key, :int64, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapUint32StringEntry" do - optional :key, :uint32, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapUint64StringEntry" do - optional :key, :uint64, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapBoolStringEntry" do - optional :key, :bool, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapStringStringEntry" do - optional :key, :string, 1 - optional :value, :string, 2 - end - add_message "A.B.C.TestMessage.MapStringMsgEntry" do - optional :key, :string, 1 - optional :value, :message, 2, "A.B.C.TestMessage" - end - add_message "A.B.C.TestMessage.MapStringEnumEntry" do - optional :key, :string, 1 - optional :value, :enum, 2, "A.B.C.TestEnum" - end - add_message "A.B.C.TestMessage.MapStringInt32Entry" do - optional :key, :string, 1 - optional :value, :int32, 2 - end - add_message "A.B.C.TestMessage.MapStringBoolEntry" do - optional :key, :string, 1 - optional :value, :bool, 2 - end add_message "A.B.C.TestMessage.NestedMessage" do optional :foo, :int32, 1 end @@ -107,16 +67,6 @@ module A module B module C TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass - TestMessage::MapInt32StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapInt32StringEntry").msgclass - TestMessage::MapInt64StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapInt64StringEntry").msgclass - TestMessage::MapUint32StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapUint32StringEntry").msgclass - TestMessage::MapUint64StringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapUint64StringEntry").msgclass - TestMessage::MapBoolStringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapBoolStringEntry").msgclass - TestMessage::MapStringStringEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringStringEntry").msgclass - TestMessage::MapStringMsgEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringMsgEntry").msgclass - TestMessage::MapStringEnumEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringEnumEntry").msgclass - TestMessage::MapStringInt32Entry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringInt32Entry").msgclass - TestMessage::MapStringBoolEntry = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.MapStringBoolEntry").msgclass TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule end diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index be59fafd..88292891 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -102,24 +102,53 @@ std::string TypeName(const google::protobuf::FieldDescriptor* field) { void GenerateField(const google::protobuf::FieldDescriptor* field, google::protobuf::io::Printer* printer) { - printer->Print( - "$label$ :$name$, ", - "label", LabelForField(field), - "name", field->name()); - printer->Print( - ":$type$, $number$", - "type", TypeName(field), - "number", IntToString(field->number())); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print( - ", \"$subtype$\"\n", - "subtype", field->message_type()->full_name()); - } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + + if (field->is_map()) { + const FieldDescriptor* key_field = + field->message_type()->FindFieldByNumber(1); + const FieldDescriptor* value_field = + field->message_type()->FindFieldByNumber(2); + printer->Print( - ", \"$subtype$\"\n", - "subtype", field->enum_type()->full_name()); + "map :$name$, :$key_type$, :$value_type$, $number$", + "name", field->name(), + "key_type", TypeName(key_field), + "value_type", TypeName(value_field), + "number", IntToString(field->number())); + + if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", value_field->message_type()->full_name()); + } else if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", value_field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } } else { - printer->Print("\n"); + + printer->Print( + "$label$ :$name$, ", + "label", LabelForField(field), + "name", field->name()); + printer->Print( + ":$type$, $number$", + "type", TypeName(field), + "number", IntToString(field->number())); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->message_type()->full_name()); + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + printer->Print( + ", \"$subtype$\"\n", + "subtype", field->enum_type()->full_name()); + } else { + printer->Print("\n"); + } } } @@ -141,6 +170,13 @@ void GenerateOneof(const google::protobuf::OneofDescriptor* oneof, void GenerateMessage(const google::protobuf::Descriptor* message, google::protobuf::io::Printer* printer) { + + // Don't generate MapEntry messages -- we use the Ruby extension's native + // support for map fields instead. + if (message->options().map_entry()) { + return; + } + printer->Print( "add_message \"$name$\" do\n", "name", message->full_name()); @@ -213,6 +249,13 @@ void GenerateMessageAssignment( const std::string& prefix, const google::protobuf::Descriptor* message, google::protobuf::io::Printer* printer) { + + // Don't generate MapEntry messages -- we use the Ruby extension's native + // support for map fields instead. + if (message->options().map_entry()) { + return; + } + printer->Print( "$prefix$$name$ = ", "prefix", prefix, -- cgit v1.2.3 From cb3caf1e61126fd18fa63e2a0e91bf71ab4ac3c9 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Tue, 17 Feb 2015 18:23:41 -0800 Subject: Integrate changes from Google open-source branch. --- autogen.sh | 10 ++++---- configure.ac | 2 +- src/Makefile.am | 1 + src/google/protobuf/arena.h | 2 ++ src/google/protobuf/compiler/parser_unittest.cc | 28 ++++++++++++++++------ .../protobuf/compiler/python/python_generator.cc | 5 ++-- .../protobuf/compiler/python/python_generator.h | 3 ++- .../protobuf/compiler/ruby/ruby_generator.cc | 7 +++--- src/google/protobuf/map_entry.h | 3 ++- 9 files changed, 42 insertions(+), 19 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/autogen.sh b/autogen.sh index c18474bf..1e97a72a 100755 --- a/autogen.sh +++ b/autogen.sh @@ -15,6 +15,12 @@ __EOF__ exit 1 fi +if test -e .git; then + # pull down git submodules. + git submodule init + git submodule update +fi + # Check that gtest is present. Usually it is already there since the # directory is set up as an SVN external. if test ! -e gtest; then @@ -39,9 +45,5 @@ sed -i -e 's/RuntimeLibrary="5"/RuntimeLibrary="3"/g; # TODO(kenton): Remove the ",no-obsolete" part and fix the resulting warnings. autoreconf -f -i -Wall,no-obsolete -# pull down git submodules. -git submodule init -git submodule update - rm -rf autom4te.cache config.h.in~ exit 0 diff --git a/configure.ac b/configure.ac index d1fde9d5..b68468e4 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ AC_PROG_CC AC_PROG_CXX AC_LANG([C++]) ACX_USE_SYSTEM_EXTENSIONS -AM_PROG_AR +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) AM_CONDITIONAL(GCC, test "$GCC" = yes) # let the Makefile know if we're gcc # test_util.cc takes forever to compile with GCC and optimization turned on. diff --git a/src/Makefile.am b/src/Makefile.am index 46190713..e1a2e169 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -106,6 +106,7 @@ nobase_include_HEADERS = \ google/protobuf/compiler/plugin.pb.h \ google/protobuf/compiler/cpp/cpp_generator.h \ google/protobuf/compiler/java/java_generator.h \ + google/protobuf/compiler/java/java_names.h \ google/protobuf/compiler/python/python_generator.h lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index d0cb163c..4f9e39e1 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -313,6 +313,8 @@ class LIBPROTOBUF_EXPORT Arena { static const size_t kHeaderSize = sizeof(Block); static google::protobuf::internal::SequenceNumber lifecycle_id_generator_; #ifdef PROTOBUF_USE_DLLS + // Thread local variables cannot be exposed through DLL interface but we can + // wrap them in static functions. static ThreadCache& thread_cache(); #else static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index 638a83b9..fe0719f8 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -401,13 +401,27 @@ TEST_F(ParseMessageTest, FieldDefaults) { " field { type:TYPE_BOOL default_value:\"true\" " ETC " }" " field { type_name:\"Foo\" default_value:\"FOO\" " ETC " }" - " field { type:TYPE_INT32 default_value:\"2147483647\" " ETC " }" - " field { type:TYPE_INT32 default_value:\"-2147483648\" " ETC " }" - " field { type:TYPE_UINT32 default_value:\"4294967295\" " ETC " }" - " field { type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC " }" - " field { type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC " }" - " field { type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC " }" - " field { type:TYPE_DOUBLE default_value:\"43981\" " ETC " }" + " field {" + " type:TYPE_INT32 default_value:\"2147483647\" " ETC + " }" + " field {" + " type:TYPE_INT32 default_value:\"-2147483648\" " ETC + " }" + " field {" + " type:TYPE_UINT32 default_value:\"4294967295\" " ETC + " }" + " field {" + " type:TYPE_INT64 default_value:\"9223372036854775807\" " ETC + " }" + " field {" + " type:TYPE_INT64 default_value:\"-9223372036854775808\" " ETC + " }" + " field {" + " type:TYPE_UINT64 default_value:\"18446744073709551615\" " ETC + " }" + " field {" + " type:TYPE_DOUBLE default_value:\"43981\" " ETC + " }" "}"); #undef ETC } diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index b30d1972..0c65b993 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -581,14 +581,15 @@ void Generator::PrintServiceDescriptor( } -void Generator::PrintDescriptorKeyAndModuleName(const ServiceDescriptor& descriptor) const { +void Generator::PrintDescriptorKeyAndModuleName( + const ServiceDescriptor& descriptor) const { printer_->Print( "$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); printer_->Print( "__module__ = '$module_name$'\n", - "module_name", ModuleName(file_->name())); + "module_name", ModuleName(file_->name())); } void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index ee68ad72..2ddac601 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -127,7 +127,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const; void PrintServiceClass(const ServiceDescriptor& descriptor) const; void PrintServiceStub(const ServiceDescriptor& descriptor) const; - void PrintDescriptorKeyAndModuleName(const ServiceDescriptor& descriptor) const ; + void PrintDescriptorKeyAndModuleName( + const ServiceDescriptor& descriptor) const ; void PrintEnumValueDescriptor(const EnumValueDescriptor& descriptor) const; string OptionsValue(const string& class_name, diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index 82ccd72b..6fed1d46 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -47,7 +47,7 @@ namespace compiler { namespace ruby { // Forward decls. -std::string IntToString(uint32_t value); +std::string IntToString(uint32 value); std::string StripDotProto(const std::string& proto_file); std::string LabelForField(google::protobuf::FieldDescriptor* field); std::string TypeName(google::protobuf::FieldDescriptor* field); @@ -64,7 +64,7 @@ void GenerateEnumAssignment( const google::protobuf::EnumDescriptor* en, google::protobuf::io::Printer* printer); -std::string IntToString(uint32_t value) { +std::string IntToString(uint32 value) { std::ostringstream os; os << value; return os.str(); @@ -299,7 +299,8 @@ bool Generator::Generate( string* error) const { std::string filename = StripDotProto(file->name()) + ".rb"; - scoped_ptr output(generator_context->Open(filename)); + scoped_ptr output( + generator_context->Open(filename)); io::Printer printer(output.get(), '$'); GenerateFile(file, &printer); diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index 217b15f6..30302a09 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -45,7 +45,8 @@ namespace internal { // Register all MapEntry default instances so we can delete them in // ShutdownProtobufLibrary(). -void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance(MessageLite* default_instance); +void LIBPROTOBUF_EXPORT RegisterMapEntryDefaultInstance( + MessageLite* default_instance); // This is the common base class for MapEntry. It is used by MapFieldBase in // reflection api, in which the static type of key and value is unknown. -- cgit v1.2.3 From 33222b5a024821df499eaf9060206ea70ebe4574 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Tue, 17 Feb 2015 18:03:59 -0800 Subject: Initial check in for primitive oneof fields. --- .../com/google/protobuf/nano/unittest_nano.proto | 8 +++ .../protobuf/compiler/javanano/javanano_field.cc | 23 +++++++ .../protobuf/compiler/javanano/javanano_field.h | 4 ++ .../protobuf/compiler/javanano/javanano_helpers.cc | 8 +++ .../protobuf/compiler/javanano/javanano_helpers.h | 5 ++ .../protobuf/compiler/javanano/javanano_message.cc | 14 ++++ .../compiler/javanano/javanano_primitive_field.cc | 76 +++++++++++++++++++++- .../compiler/javanano/javanano_primitive_field.h | 27 +++++++- 8 files changed, 161 insertions(+), 4 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto index 4519533c..cc3717d3 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto +++ b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto @@ -167,6 +167,14 @@ message TestAllTypesNano { // Try to fail with java reserved keywords optional int32 synchronized = 96; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + // NestedMessage oneof_nested_message = 112; + // string oneof_string = 123; + // bytes oneof_bytes = 124; + fixed64 oneof_fixed64 = 115; + } } message ForeignMessageNano { diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index b9be90b1..635916bf 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -108,6 +108,13 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, default: return new RepeatedPrimitiveFieldGenerator(field, params); } + } else if (field->containing_oneof()) { + switch (java_type) { + case JAVATYPE_MESSAGE: + case JAVATYPE_ENUM: + default: + return new PrimitiveOneofFieldGenerator(field, params); + } } else if (params.optional_field_accessors() && field->is_optional() && java_type != JAVATYPE_MESSAGE) { // We need a has-bit for each primitive/enum field because their default @@ -142,6 +149,22 @@ const FieldGenerator& FieldGeneratorMap::get( return *field_generators_[field->index()]; } +void SetCommonOneofVariables(const FieldDescriptor* descriptor, + map* variables) { + (*variables)["oneof_name"] = + UnderscoresToCamelCase(descriptor->containing_oneof()); + (*variables)["oneof_capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor->containing_oneof()); + (*variables)["oneof_index"] = + SimpleItoa(descriptor->containing_oneof()->index()); + (*variables)["set_oneof_case"] = + (*variables)["oneof_name"] + "Case_ = " + SimpleItoa(descriptor->number()); + (*variables)["clear_oneof_case"] = + (*variables)["oneof_name"] + "Case_ = 0"; + (*variables)["has_oneof_case"] = + (*variables)["oneof_name"] + "Case_ == " + SimpleItoa(descriptor->number()); +} + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h index 6170c2c0..fae79ce4 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_field.h @@ -35,6 +35,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVANANO_FIELD_H__ +#include #include #include #include @@ -111,6 +112,9 @@ class FieldGeneratorMap { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; +void SetCommonOneofVariables(const FieldDescriptor* descriptor, + map* variables); + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.cc b/src/google/protobuf/compiler/javanano/javanano_helpers.cc index 7b23d9f4..0d2ae9db 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.cc +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.cc @@ -154,6 +154,14 @@ string UnderscoresToCamelCase(const MethodDescriptor* method) { return UnderscoresToCamelCaseImpl(method->name(), false); } +string UnderscoresToCamelCase(const OneofDescriptor* oneof) { + return UnderscoresToCamelCaseImpl(oneof->name(), false); +} + +string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof) { + return UnderscoresToCamelCaseImpl(oneof->name(), true); +} + string RenameJavaKeywords(const string& input) { return sRenameKeywords.RenameJavaKeywordsImpl(input); } diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h index b4fee649..b47ee4a4 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.h +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h @@ -54,7 +54,9 @@ extern const char kThinSeparator[]; // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes // "fooBarBaz" or "FooBarBaz", respectively. string UnderscoresToCamelCase(const FieldDescriptor* field); +string UnderscoresToCamelCase(const OneofDescriptor* oneof); string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); +string UnderscoresToCapitalizedCamelCase(const OneofDescriptor* oneof); // Appends an "_" to the end of a field where the name is a reserved java // keyword. For example int32 public = 1 will generate int public_. @@ -189,6 +191,9 @@ inline bool IsMapEntry(const Descriptor* descriptor) { bool HasMapField(const Descriptor* descriptor); +void SetCommonOneofVariables(const FieldDescriptor* field, + map* variables); + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index da7c656f..75e2573b 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -165,6 +165,20 @@ void MessageGenerator::Generate(io::Printer* printer) { MessageGenerator(descriptor_->nested_type(i), params_).Generate(printer); } + // oneof + map vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)); + vars["oneof_capitalized_name"] = + UnderscoresToCapitalizedCamelCase(descriptor_->oneof_decl(i)); + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // OneofCase enum + } + // Lazy initialization of otherwise static final fields can help prevent the // class initializer from being generated. We want to prevent it because it // stops ProGuard from inlining any methods in this class into call sites and diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index a3bc3a84..99cb89ec 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -706,8 +706,80 @@ GenerateHashCodeCode(io::Printer* printer) const { // =================================================================== -RepeatedPrimitiveFieldGenerator:: -RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params) +PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { + SetPrimitiveVariables(descriptor, params, &variables_); + SetCommonOneofVariables(descriptor, &variables_); +} + +PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} + +void PrimitiveOneofFieldGenerator::GenerateMembers( + io::Printer* printer, bool /*unused lazy_init*/) const { + printer->Print(variables_, + "public boolean has$capitalized_name$() {\n" + " return $has_oneof_case$;\n" + "}\n" + "public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case$) {\n" + " return ($type$) ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n" + "public $message_name$ set$capitalized_name$($type$ value) {\n" + " $set_oneof_case$;\n" + " $oneof_name$_ = value;\n" + " return this;\n" + "}\n" + "public $message_name$ clear$capitalized_name$() {\n" + " $clear_oneof_case$;\n" + " $oneof_name$_ = null;\n" + " return this;\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateClearCode( + io::Printer* printer) const { + // No clear method for oneof fields. +} + +void PrimitiveOneofFieldGenerator::GenerateMergingCode( + io::Printer* printer) const { + printer->Print(variables_, + "$oneof_name$_ = input.read$capitalized_type$();\n" + "$set_oneof_case$;\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateSerializationCode( + io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case$) {\n" + " output.write$capitalized_type$(\n" + " $number$, ($boxed_type$) $oneof_name$_);\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode( + io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case$) {\n" + " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" + " .compute$capitalized_type$Size(\n" + " $number$, ($boxed_type$) $oneof_name$_);\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateEqualsCode(io::Printer* printer) const { +} + +void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const { +} + +// =================================================================== + +RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) : FieldGenerator(params), descriptor_(descriptor) { SetPrimitiveVariables(descriptor, params, &variables_); } diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h index c04a19b7..ca7116ff 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h @@ -47,7 +47,7 @@ namespace javanano { class PrimitiveFieldGenerator : public FieldGenerator { public: explicit PrimitiveFieldGenerator( - const FieldDescriptor* descriptor, const Params ¶ms); + const FieldDescriptor* descriptor, const Params& params); ~PrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- @@ -94,9 +94,32 @@ class AccessorPrimitiveFieldGenerator : public FieldGenerator { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AccessorPrimitiveFieldGenerator); }; +class PrimitiveOneofFieldGenerator : public FieldGenerator { + public: + explicit PrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, const Params& params); + ~PrimitiveOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer, bool lazy_init) const; + void GenerateClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCodeCode(io::Printer* printer) const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); +}; + class RepeatedPrimitiveFieldGenerator : public FieldGenerator { public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Params& params); + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, + const Params& params); ~RepeatedPrimitiveFieldGenerator(); // implements FieldGenerator --------------------------------------- -- cgit v1.2.3 From 7794a98ff43776491d4f3434ea3ec32c8146970a Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Tue, 17 Feb 2015 19:31:10 -0800 Subject: Initial check-in for message oneof. --- src/google/protobuf/compiler/javanano/javanano_field.cc | 1 + .../protobuf/compiler/javanano/javanano_message_field.cc | 16 +++++++++++++--- .../protobuf/compiler/javanano/javanano_message_field.h | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 3 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index 635916bf..2c7261f9 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -111,6 +111,7 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, } else if (field->containing_oneof()) { switch (java_type) { case JAVATYPE_MESSAGE: + return new MessageOneofFieldGenerator(field, params); case JAVATYPE_ENUM: default: return new PrimitiveOneofFieldGenerator(field, params); diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index a46081d0..425f7ae3 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -146,12 +146,22 @@ GenerateHashCodeCode(io::Printer* printer) const { "result = 31 * result +\n" " (this.$name$ == null ? 0 : this.$name$.hashCode());\n"); } +// =================================================================== + +MessageOneofFieldGenerator::MessageOneofFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { + SetMessageVariables(params, descriptor, &variables_); + SetCommonOneofVariables(descriptor, &variables_); +} + +MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} // =================================================================== -RepeatedMessageFieldGenerator:: -RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Params& params) - : FieldGenerator(params), descriptor_(descriptor) { +RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( + const FieldDescriptor* descriptor, const Params& params) + : FieldGenerator(params), descriptor_(descriptor) { SetMessageVariables(params, descriptor, &variables_); } diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h index 5d35fd24..7c3b7399 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h @@ -66,6 +66,20 @@ class MessageFieldGenerator : public FieldGenerator { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; +class MessageOneofFieldGenerator : public FieldGenerator { + public: + explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + const Params& params); + ~MessageOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + private: + const FieldDescriptor* descriptor_; + map variables_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); +}; + class RepeatedMessageFieldGenerator : public FieldGenerator { public: explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, -- cgit v1.2.3 From c72d3d51ff70944d7f9f5f8b1173920ca246d5b3 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Tue, 17 Feb 2015 21:15:20 -0800 Subject: Oneof message level elements (consts, case getter/clear) and messsage type field oneof support. --- .../com/google/protobuf/nano/unittest_nano.proto | 2 +- .../protobuf/compiler/javanano/javanano_field.cc | 8 +-- .../protobuf/compiler/javanano/javanano_message.cc | 28 ++++++++-- .../compiler/javanano/javanano_message_field.cc | 63 ++++++++++++++++++++++ .../compiler/javanano/javanano_message_field.h | 8 +++ .../compiler/javanano/javanano_primitive_field.cc | 15 ++---- 6 files changed, 106 insertions(+), 18 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto index cc3717d3..842959a7 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto +++ b/javanano/src/test/java/com/google/protobuf/nano/unittest_nano.proto @@ -170,7 +170,7 @@ message TestAllTypesNano { oneof oneof_field { uint32 oneof_uint32 = 111; - // NestedMessage oneof_nested_message = 112; + NestedMessage oneof_nested_message = 112; // string oneof_string = 123; // bytes oneof_bytes = 124; fixed64 oneof_fixed64 = 115; diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index 2c7261f9..5565781c 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -159,11 +159,13 @@ void SetCommonOneofVariables(const FieldDescriptor* descriptor, (*variables)["oneof_index"] = SimpleItoa(descriptor->containing_oneof()->index()); (*variables)["set_oneof_case"] = - (*variables)["oneof_name"] + "Case_ = " + SimpleItoa(descriptor->number()); + "this." + (*variables)["oneof_name"] + + "Case_ = " + SimpleItoa(descriptor->number()); (*variables)["clear_oneof_case"] = - (*variables)["oneof_name"] + "Case_ = 0"; + "this." + (*variables)["oneof_name"] + "Case_ = 0"; (*variables)["has_oneof_case"] = - (*variables)["oneof_name"] + "Case_ == " + SimpleItoa(descriptor->number()); + "this." + (*variables)["oneof_name"] + "Case_ == " + + SimpleItoa(descriptor->number()); } } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 75e2573b..6b31c3bf 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -167,16 +167,36 @@ void MessageGenerator::Generate(io::Printer* printer) { // oneof map vars; + vars["message_name"] = descriptor_->name(); for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["oneof_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)); + const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); + vars["oneof_name"] = UnderscoresToCamelCase(oneof_desc); vars["oneof_capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor_->oneof_decl(i)); - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + UnderscoresToCapitalizedCamelCase(oneof_desc); + vars["oneof_index"] = SimpleItoa(oneof_desc->index()); + // Oneof Constants + for (int j = 0; j < oneof_desc->field_count(); j++) { + const FieldDescriptor* field = oneof_desc->field(j); + vars["number"] = SimpleItoa(field->number()); + vars["cap_field_name"] = ToUpper(field->name()); + printer->Print(vars, + "public static final int $cap_field_name$_FIELD_NUMBER = $number$;\n"); + } // oneofCase_ and oneof_ printer->Print(vars, "private int $oneof_name$Case_ = 0;\n" "private java.lang.Object $oneof_name$_;\n"); - // OneofCase enum + printer->Print(vars, + "public int get$oneof_capitalized_name$Case() {\n" + " return this.$oneof_name$Case_;\n" + "}\n"); + // Oneof clear + printer->Print(vars, + "public $message_name$ clear$oneof_capitalized_name$() {\n" + " this.$oneof_name$Case_ = 0;\n" + " this.$oneof_name$_ = null;\n" + " return this;\n" + "}\n"); } // Lazy initialization of otherwise static final fields can help prevent the diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index 425f7ae3..63bc7195 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -157,6 +157,69 @@ MessageOneofFieldGenerator::MessageOneofFieldGenerator( MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} +void MessageOneofFieldGenerator:: +GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { + printer->Print(variables_, + "public boolean has$capitalized_name$() {\n" + " return $has_oneof_case$;\n" + "}\n" + "public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case$) {\n" + " return ($type$) this.$oneof_name$_;\n" + " }\n" + " return null;\n" + "}\n" + "public $message_name$ set$capitalized_name$($type$ value) {\n" + " if (value == null) { throw new java.lang.NullPointerException(); }\n" + " $set_oneof_case$;\n" + " this.$oneof_name$_ = value;\n" + " return this;\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateClearCode(io::Printer* printer) const { + // No clear method for oneof fields. +} + +void MessageOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!($has_oneof_case$)) {\n" + " this.$oneof_name$_ = new $type$();\n" + "}\n" + "input.readMessage(\n" + " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" + "$set_oneof_case$;\n"); +} + +void MessageOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case$) {\n" + " output.writeMessage($number$,\n" + " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case$) {\n" + " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" + " .computeMessageSize($number$,\n" + " (com.google.protobuf.nano.MessageNano) this.$oneof_name$_);\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateEqualsCode(io::Printer* printer) const { +} + +void MessageOneofFieldGenerator:: +GenerateHashCodeCode(io::Printer* printer) const { +} + // =================================================================== RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h index 7c3b7399..6c615f5e 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h @@ -73,6 +73,14 @@ class MessageOneofFieldGenerator : public FieldGenerator { ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer, bool lazy_init) const; + void GenerateClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCodeCode(io::Printer* printer) const; + private: const FieldDescriptor* descriptor_; map variables_; diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index 99cb89ec..4bbaec82 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -723,18 +723,13 @@ void PrimitiveOneofFieldGenerator::GenerateMembers( "}\n" "public $type$ get$capitalized_name$() {\n" " if ($has_oneof_case$) {\n" - " return ($type$) ($boxed_type$) $oneof_name$_;\n" + " return ($type$) ($boxed_type$) this.$oneof_name$_;\n" " }\n" " return $default$;\n" "}\n" "public $message_name$ set$capitalized_name$($type$ value) {\n" " $set_oneof_case$;\n" - " $oneof_name$_ = value;\n" - " return this;\n" - "}\n" - "public $message_name$ clear$capitalized_name$() {\n" - " $clear_oneof_case$;\n" - " $oneof_name$_ = null;\n" + " this.$oneof_name$_ = value;\n" " return this;\n" "}\n"); } @@ -747,7 +742,7 @@ void PrimitiveOneofFieldGenerator::GenerateClearCode( void PrimitiveOneofFieldGenerator::GenerateMergingCode( io::Printer* printer) const { printer->Print(variables_, - "$oneof_name$_ = input.read$capitalized_type$();\n" + "this.$oneof_name$_ = input.read$capitalized_type$();\n" "$set_oneof_case$;\n"); } @@ -756,7 +751,7 @@ void PrimitiveOneofFieldGenerator::GenerateSerializationCode( printer->Print(variables_, "if ($has_oneof_case$) {\n" " output.write$capitalized_type$(\n" - " $number$, ($boxed_type$) $oneof_name$_);\n" + " $number$, ($boxed_type$) this.$oneof_name$_);\n" "}\n"); } @@ -766,7 +761,7 @@ void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode( "if ($has_oneof_case$) {\n" " size += com.google.protobuf.nano.CodedOutputByteBufferNano\n" " .compute$capitalized_type$Size(\n" - " $number$, ($boxed_type$) $oneof_name$_);\n" + " $number$, ($boxed_type$) this.$oneof_name$_);\n" "}\n"); } -- cgit v1.2.3 From 06a2e29855efbd67c86171ee822ec2e217f6fe29 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Tue, 17 Feb 2015 21:27:44 -0800 Subject: Equals for message oneof field in nano. --- .../protobuf/compiler/javanano/javanano_message_field.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index 63bc7195..527121e6 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -214,6 +214,16 @@ GenerateSerializedSizeCode(io::Printer* printer) const { void MessageOneofFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.has$capitalized_name$()) {\n" + " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" + " return false;\n" + " }\n" + "} else {\n" + " if (other.has$capitalized_name$()) {\n" + " return false;\n" + " }\n" + "}\n"); } void MessageOneofFieldGenerator:: -- cgit v1.2.3 From f173cdeb02618c117947bbed2646609f6101390e Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Wed, 18 Feb 2015 13:47:22 -0800 Subject: hashcode and equals for oneofs in nano. --- .../protobuf/compiler/javanano/javanano_field.cc | 22 ++++++++++++++++++++++ .../protobuf/compiler/javanano/javanano_field.h | 4 ++++ .../compiler/javanano/javanano_message_field.cc | 12 ++---------- .../compiler/javanano/javanano_primitive_field.cc | 8 ++++++-- 4 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index 5565781c..07517567 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -168,6 +168,28 @@ void SetCommonOneofVariables(const FieldDescriptor* descriptor, SimpleItoa(descriptor->number()); } +void GenerateOneofFieldEquals(const map& variables, + io::Printer* printer) { + printer->Print(variables, + "if (this.has$capitalized_name$()) {\n" + " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" + " return false;\n" + " }\n" + "} else {\n" + " if (other.has$capitalized_name$()) {\n" + " return false;\n" + " }\n" + "}\n"); + +} + +void GenerateOneofFieldHashCode(const map& variables, + io::Printer* printer) { + printer->Print(variables, + "result = 31 * result +\n" + " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n"); +} + } // namespace javanano } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h index fae79ce4..b31b517b 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_field.h @@ -114,6 +114,10 @@ class FieldGeneratorMap { void SetCommonOneofVariables(const FieldDescriptor* descriptor, map* variables); +void GenerateOneofFieldEquals(const map& variables, + io::Printer* printer); +void GenerateOneofFieldHashCode(const map& variables, + io::Printer* printer); } // namespace javanano } // namespace compiler diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index 527121e6..6e12bf63 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -214,20 +214,12 @@ GenerateSerializedSizeCode(io::Printer* printer) const { void MessageOneofFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { - printer->Print(variables_, - "if (this.has$capitalized_name$()) {\n" - " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" - " return false;\n" - " }\n" - "} else {\n" - " if (other.has$capitalized_name$()) {\n" - " return false;\n" - " }\n" - "}\n"); + GenerateOneofFieldEquals(variables_, printer); } void MessageOneofFieldGenerator:: GenerateHashCodeCode(io::Printer* printer) const { + GenerateOneofFieldHashCode(variables_, printer); } // =================================================================== diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index 4bbaec82..038db6e2 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -765,10 +765,14 @@ void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode( "}\n"); } -void PrimitiveOneofFieldGenerator::GenerateEqualsCode(io::Printer* printer) const { +void PrimitiveOneofFieldGenerator::GenerateEqualsCode( + io::Printer* printer) const { + GenerateOneofFieldEquals(variables_, printer); } -void PrimitiveOneofFieldGenerator::GenerateHashCodeCode(io::Printer* printer) const { +void PrimitiveOneofFieldGenerator::GenerateHashCodeCode( + io::Printer* printer) const { + GenerateOneofFieldHashCode(variables_, printer); } // =================================================================== -- cgit v1.2.3 From 3accf81ea9c83980ced2c1901c58f4bed44003f4 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Wed, 18 Feb 2015 13:52:37 -0800 Subject: Clear oneofs. --- src/google/protobuf/compiler/javanano/javanano_message.cc | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 6b31c3bf..ac591bbb 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -508,6 +508,14 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { field_generators_.get(field).GenerateClearCode(printer); } + // Clear oneofs. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "clear$oneof_capitalized_name$();\n", + "oneof_capitalized_name", UnderscoresToCapitalizedCamelCase( + descriptor_->oneof_decl(i))); + } + // Clear unknown fields. if (params_.store_unknown_fields()) { printer->Print("unknownFieldData = null;\n"); -- cgit v1.2.3 From 7b72a24a2038dcb3409bb91d90f5a06abac3959c Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Wed, 18 Feb 2015 16:39:01 -0800 Subject: fix equal and hash for bytes field for javanano oneof --- .../protobuf/compiler/javanano/javanano_field.cc | 54 +++++++++++++++------- .../protobuf/compiler/javanano/javanano_field.h | 6 ++- .../compiler/javanano/javanano_message_field.cc | 4 +- .../compiler/javanano/javanano_primitive_field.cc | 4 +- 4 files changed, 46 insertions(+), 22 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index 07517567..e40db620 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -168,26 +168,48 @@ void SetCommonOneofVariables(const FieldDescriptor* descriptor, SimpleItoa(descriptor->number()); } -void GenerateOneofFieldEquals(const map& variables, +void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, + const map& variables, io::Printer* printer) { - printer->Print(variables, - "if (this.has$capitalized_name$()) {\n" - " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" - " return false;\n" - " }\n" - "} else {\n" - " if (other.has$capitalized_name$()) {\n" - " return false;\n" - " }\n" - "}\n"); - + if (GetJavaType(descriptor) == JAVATYPE_BYTES) { + printer->Print(variables, + "if (this.has$capitalized_name$()) {\n" + " if (!other.has$capitalized_name$() ||\n" + " !java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n" + " (byte[]) other.$oneof_name$_)) {\n" + " return false;\n" + " }\n" + "} else {\n" + " if (other.has$capitalized_name$()) {\n" + " return false;\n" + " }\n" + "}\n"); + } else { + printer->Print(variables, + "if (this.has$capitalized_name$()) {\n" + " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" + " return false;\n" + " }\n" + "} else {\n" + " if (other.has$capitalized_name$()) {\n" + " return false;\n" + " }\n" + "}\n"); + } } -void GenerateOneofFieldHashCode(const map& variables, +void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor, + const map& variables, io::Printer* printer) { - printer->Print(variables, - "result = 31 * result +\n" - " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n"); + if (GetJavaType(descriptor) == JAVATYPE_BYTES) { + printer->Print(variables, + "result = 31 * result + ($has_oneof_case$\n" + " ? java.util.Arrays.hashCode((byte[]) this.$oneof_name$_) : 0);\n"); + } else { + printer->Print(variables, + "result = 31 * result +\n" + " ($has_oneof_case$ ? this.$oneof_name$_.hashCode() : 0);\n"); + } } } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h index b31b517b..c2cf091c 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_field.h @@ -114,9 +114,11 @@ class FieldGeneratorMap { void SetCommonOneofVariables(const FieldDescriptor* descriptor, map* variables); -void GenerateOneofFieldEquals(const map& variables, +void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, + const map& variables, io::Printer* printer); -void GenerateOneofFieldHashCode(const map& variables, +void GenerateOneofFieldHashCode(const FieldDescriptor* descriptor, + const map& variables, io::Printer* printer); } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index 6e12bf63..181c4060 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -214,12 +214,12 @@ GenerateSerializedSizeCode(io::Printer* printer) const { void MessageOneofFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { - GenerateOneofFieldEquals(variables_, printer); + GenerateOneofFieldEquals(descriptor_, variables_, printer); } void MessageOneofFieldGenerator:: GenerateHashCodeCode(io::Printer* printer) const { - GenerateOneofFieldHashCode(variables_, printer); + GenerateOneofFieldHashCode(descriptor_, variables_, printer); } // =================================================================== diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index 038db6e2..106a7506 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -767,12 +767,12 @@ void PrimitiveOneofFieldGenerator::GenerateSerializedSizeCode( void PrimitiveOneofFieldGenerator::GenerateEqualsCode( io::Printer* printer) const { - GenerateOneofFieldEquals(variables_, printer); + GenerateOneofFieldEquals(descriptor_, variables_, printer); } void PrimitiveOneofFieldGenerator::GenerateHashCodeCode( io::Printer* printer) const { - GenerateOneofFieldHashCode(variables_, printer); + GenerateOneofFieldHashCode(descriptor_, variables_, printer); } // =================================================================== -- cgit v1.2.3 From f2cf6cdcb2cd80458fb872e29e6936f4377c0e48 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Thu, 19 Feb 2015 11:26:08 -0800 Subject: Remove the unused set common oneof variables in helper --- src/google/protobuf/compiler/javanano/javanano_helpers.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_helpers.h b/src/google/protobuf/compiler/javanano/javanano_helpers.h index b47ee4a4..014c85ae 100644 --- a/src/google/protobuf/compiler/javanano/javanano_helpers.h +++ b/src/google/protobuf/compiler/javanano/javanano_helpers.h @@ -191,9 +191,6 @@ inline bool IsMapEntry(const Descriptor* descriptor) { bool HasMapField(const Descriptor* descriptor); -void SetCommonOneofVariables(const FieldDescriptor* field, - map* variables); - } // namespace javanano } // namespace compiler } // namespace protobuf -- cgit v1.2.3 From a6fc5da0fc3285399da7974671a96a5fcbcd83f9 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Thu, 19 Feb 2015 17:16:26 -0800 Subject: Fix review comments. Change-Id: Iafd4a3aa9d55e31478bf070311eeadfe95ece4d7 --- javanano/src/test/java/com/google/protobuf/nano/NanoTest.java | 2 +- src/google/protobuf/compiler/javanano/javanano_field.cc | 11 +---------- src/google/protobuf/compiler/javanano/javanano_message.cc | 10 ++++++++++ 3 files changed, 12 insertions(+), 11 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java index f3ba2de5..2c9e2d84 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java +++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java @@ -3741,7 +3741,7 @@ public class NanoTest extends TestCase { checkOneofCase(m, 0); } - public void testOneofMarshling() throws Exception { + public void testOneofMarshaling() throws Exception { TestAllTypesNano m = new TestAllTypesNano(); TestAllTypesNano parsed = new TestAllTypesNano(); { diff --git a/src/google/protobuf/compiler/javanano/javanano_field.cc b/src/google/protobuf/compiler/javanano/javanano_field.cc index e40db620..85257f3f 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_field.cc @@ -174,15 +174,10 @@ void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, if (GetJavaType(descriptor) == JAVATYPE_BYTES) { printer->Print(variables, "if (this.has$capitalized_name$()) {\n" - " if (!other.has$capitalized_name$() ||\n" - " !java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n" + " if (!java.util.Arrays.equals((byte[]) this.$oneof_name$_,\n" " (byte[]) other.$oneof_name$_)) {\n" " return false;\n" " }\n" - "} else {\n" - " if (other.has$capitalized_name$()) {\n" - " return false;\n" - " }\n" "}\n"); } else { printer->Print(variables, @@ -190,10 +185,6 @@ void GenerateOneofFieldEquals(const FieldDescriptor* descriptor, " if (!this.$oneof_name$_.equals(other.$oneof_name$_)) {\n" " return false;\n" " }\n" - "} else {\n" - " if (other.has$capitalized_name$()) {\n" - " return false;\n" - " }\n" "}\n"); } } diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index ac591bbb..707f6b84 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -551,6 +551,16 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) { "$classname$ other = ($classname$) o;\n", "classname", descriptor_->name()); + // Checking oneof case before checking each oneof field. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof_desc = descriptor_->oneof_decl(i); + printer->Print( + "if (this.$oneof_name$Case_ != other.$oneof_name$Case_) {\n" + " return false;\n" + "}\n", + "oneof_name", UnderscoresToCamelCase(oneof_desc)); + } + for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); field_generators_.get(field).GenerateEqualsCode(printer); -- cgit v1.2.3 From 7a00a1e42495495cef8bc20821b9554c6afb3ab5 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Sat, 21 Feb 2015 17:28:51 -0800 Subject: Add shutdown code for several newly introduced leaks; Disable commandline interface test for heap check tests. Change-Id: I02aa2ad9704e3c70dcecae8b3b3557b18607d455 --- .../compiler/command_line_interface_unittest.cc | 6 ++++++ .../protobuf/generated_message_reflection.cc | 6 ++++++ src/google/protobuf/message.cc | 24 ++++++++++++++++++++++ src/google/protobuf/stubs/singleton.h | 6 +++++- 4 files changed, 41 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index dbaaa405..64e877a3 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -64,6 +64,10 @@ #include +// Disable the whole test when we use tcmalloc for "draconian" heap checks, in +// which case tcmalloc will print warnings that fail the plugin tests. +#if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN + namespace google { namespace protobuf { namespace compiler { @@ -1663,3 +1667,5 @@ TEST_F(EncodeDecodeTest, ProtoParseError) { } // namespace compiler } // namespace protobuf } // namespace google + +#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index b500b9c5..34826801 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -247,8 +247,14 @@ namespace { UnknownFieldSet* empty_unknown_field_set_ = NULL; GOOGLE_PROTOBUF_DECLARE_ONCE(empty_unknown_field_set_once_); +void DeleteEmptyUnknownFieldSet() { + delete empty_unknown_field_set_; + empty_unknown_field_set_ = NULL; +} + void InitEmptyUnknownFieldSet() { empty_unknown_field_set_ = new UnknownFieldSet; + internal::OnShutdown(&DeleteEmptyUnknownFieldSet); } const UnknownFieldSet& GetEmptyUnknownFieldSet() { diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index afe95461..28955b35 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -440,6 +440,30 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( return NULL; } +namespace internal { +namespace { +void ShutdownRepeatedFieldAccessor() { + Singleton >::ShutDown(); + Singleton >::ShutDown(); + Singleton >::ShutDown(); + Singleton >::ShutDown(); + Singleton >::ShutDown(); + Singleton >::ShutDown(); + Singleton >::ShutDown(); + Singleton::ShutDown(); + Singleton::ShutDown(); + Singleton::ShutDown(); +}; + +struct ShutdownRepeatedFieldRegister { + ShutdownRepeatedFieldRegister() { + OnShutdown(&ShutdownRepeatedFieldAccessor); + } +} shutdown_; + +} // namesapce +} // namespace internal + namespace internal { // Macro defined in repeated_field.h. We can only define the Message-specific // GenericTypeHandler specializations here because we depend on Message, which diff --git a/src/google/protobuf/stubs/singleton.h b/src/google/protobuf/stubs/singleton.h index e123e4fe..9301f549 100644 --- a/src/google/protobuf/stubs/singleton.h +++ b/src/google/protobuf/stubs/singleton.h @@ -44,6 +44,10 @@ class Singleton { GoogleOnceInit(&once_, &Singleton::Init); return instance_; } + static void ShutDown() { + delete instance_; + instance_ = NULL; + } private: static void Init() { instance_ = new T(); @@ -56,7 +60,7 @@ template ProtobufOnceType Singleton::once_; template -T* Singleton::instance_; +T* Singleton::instance_ = NULL; } // namespace internal } // namespace protobuf } // namespace google -- cgit v1.2.3 From e70329c6c0a2a9ebbbd1038f076d823e730512a7 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Mon, 23 Feb 2015 17:24:36 -0800 Subject: Propogate onChange() event when getFooBuilder() is on an oneof message field. Change-Id: Idb5b53da5accd24038a895aba49b684eeee95814 --- .../java/com/google/protobuf/GeneratedMessageTest.java | 14 +++++++++++++- src/google/protobuf/compiler/java/java_message_field.cc | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java index 41ed7bd0..2d101ba7 100644 --- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -56,9 +56,10 @@ import protobuf_unittest.UnittestProto; import protobuf_unittest.UnittestProto.ForeignEnum; import protobuf_unittest.UnittestProto.ForeignMessage; import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder; +import protobuf_unittest.UnittestProto.NestedTestAllTypes; import protobuf_unittest.UnittestProto.TestAllExtensions; -import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; +import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; import protobuf_unittest.UnittestProto.TestExtremeDefaultValues; import protobuf_unittest.UnittestProto.TestOneof2; @@ -1510,6 +1511,17 @@ public class GeneratedMessageTest extends TestCase { } } + public void testOneofNestedBuilderOnChangePropagation() { + NestedTestAllTypes.Builder parentBuilder = NestedTestAllTypes.newBuilder(); + TestAllTypes.Builder builder = parentBuilder.getPayloadBuilder(); + builder.getOneofNestedMessageBuilder(); + assertTrue(builder.hasOneofNestedMessage()); + assertTrue(parentBuilder.hasPayload()); + NestedTestAllTypes message = parentBuilder.build(); + assertTrue(message.hasPayload()); + assertTrue(message.getPayload().hasOneofNestedMessage()); + } + public void testGetRepeatedFieldBuilder() { Descriptor descriptor = TestAllTypes.getDescriptor(); diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index 538f1248..a2d12a38 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -718,6 +718,7 @@ GenerateBuilderMembers(io::Printer* printer) const { " $oneof_name$_ = null;\n" " }\n" " $set_oneof_case_message$;\n" + " $on_changed$;\n" " return $name$Builder_;\n" "}\n"); } -- cgit v1.2.3 From ada65567852b96fdb4d070c0c3f86ca7b77824f9 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Wed, 25 Feb 2015 16:39:11 -0800 Subject: Down integrate from Google internal. Change-Id: I34d301133eea9c6f3a822c47d1f91e136fd33145 --- python/README.txt | 5 +- python/google/protobuf/descriptor.py | 158 +- python/google/protobuf/descriptor_pool.py | 114 +- .../google/protobuf/internal/api_implementation.cc | 14 +- .../google/protobuf/internal/api_implementation.py | 38 +- .../internal/api_implementation_default_test.py | 63 - python/google/protobuf/internal/containers.py | 37 +- python/google/protobuf/internal/decoder.py | 3 - python/google/protobuf/internal/descriptor_test.py | 176 ++- python/google/protobuf/internal/message_test.py | 782 +++++++--- python/google/protobuf/internal/python_message.py | 81 +- python/google/protobuf/internal/reflection_test.py | 21 + python/google/protobuf/internal/test_util.py | 170 ++- .../google/protobuf/internal/text_format_test.py | 557 +++---- python/google/protobuf/internal/type_checkers.py | 8 +- .../protobuf/internal/unknown_fields_test.py | 120 +- python/google/protobuf/pyext/descriptor.cc | 1538 +++++++++++++++---- python/google/protobuf/pyext/descriptor.h | 122 +- .../google/protobuf/pyext/descriptor_containers.cc | 1564 ++++++++++++++++++++ .../google/protobuf/pyext/descriptor_containers.h | 95 ++ .../google/protobuf/pyext/descriptor_cpp2_test.py | 58 - python/google/protobuf/pyext/descriptor_pool.cc | 370 +++++ python/google/protobuf/pyext/descriptor_pool.h | 152 ++ python/google/protobuf/pyext/extension_dict.cc | 25 +- python/google/protobuf/pyext/extension_dict.h | 3 +- python/google/protobuf/pyext/message.cc | 1044 ++++++------- python/google/protobuf/pyext/message.h | 50 +- .../protobuf/pyext/message_factory_cpp2_test.py | 56 - .../pyext/reflection_cpp2_generated_test.py | 94 -- .../protobuf/pyext/repeated_composite_container.cc | 53 +- .../protobuf/pyext/repeated_composite_container.h | 8 +- .../protobuf/pyext/repeated_scalar_container.cc | 183 ++- .../protobuf/pyext/repeated_scalar_container.h | 4 +- python/google/protobuf/reflection.py | 18 +- python/google/protobuf/text_format.py | 5 + python/setup.py | 22 +- .../protobuf/compiler/python/python_generator.cc | 25 +- src/google/protobuf/testdata/golden_message_proto3 | Bin 0 -> 398 bytes src/google/protobuf/unittest_proto3_arena.proto | 54 +- 39 files changed, 5781 insertions(+), 2109 deletions(-) delete mode 100644 python/google/protobuf/internal/api_implementation_default_test.py create mode 100644 python/google/protobuf/pyext/descriptor_containers.cc create mode 100644 python/google/protobuf/pyext/descriptor_containers.h delete mode 100644 python/google/protobuf/pyext/descriptor_cpp2_test.py create mode 100644 python/google/protobuf/pyext/descriptor_pool.cc create mode 100644 python/google/protobuf/pyext/descriptor_pool.h delete mode 100644 python/google/protobuf/pyext/message_factory_cpp2_test.py delete mode 100755 python/google/protobuf/pyext/reflection_cpp2_generated_test.py create mode 100644 src/google/protobuf/testdata/golden_message_proto3 (limited to 'src/google/protobuf/compiler') diff --git a/python/README.txt b/python/README.txt index 7d852458..04cb1767 100644 --- a/python/README.txt +++ b/python/README.txt @@ -48,8 +48,9 @@ Installation $ python setup.py build $ python setup.py google_test - If you want to test c++ implementation, run: - $ python setup.py test --cpp_implementation + If you want to build/test c++ implementation, run: + $ python setup.py build --cpp_implementation + $ python setup.py google_test --cpp_implementation If some tests fail, this library may not work correctly on your system. Continue at your own risk. diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py index af571b7c..f7a58ca0 100755 --- a/python/google/protobuf/descriptor.py +++ b/python/google/protobuf/descriptor.py @@ -41,15 +41,13 @@ __author__ = 'robinson@google.com (Will Robinson)' from google.protobuf.internal import api_implementation +_USE_C_DESCRIPTORS = False if api_implementation.Type() == 'cpp': # Used by MakeDescriptor in cpp mode import os import uuid - - if api_implementation.Version() == 2: - from google.protobuf.pyext import _message - else: - from google.protobuf.internal import cpp_message + from google.protobuf.pyext import _message + _USE_C_DESCRIPTORS = getattr(_message, '_USE_C_DESCRIPTORS', False) class Error(Exception): @@ -60,12 +58,29 @@ class TypeTransformationError(Error): """Error transforming between python proto type and corresponding C++ type.""" +if _USE_C_DESCRIPTORS: + # This metaclass allows to override the behavior of code like + # isinstance(my_descriptor, FieldDescriptor) + # and make it return True when the descriptor is an instance of the extension + # type written in C++. + class DescriptorMetaclass(type): + def __instancecheck__(cls, obj): + if super(DescriptorMetaclass, cls).__instancecheck__(obj): + return True + if isinstance(obj, cls._C_DESCRIPTOR_CLASS): + return True + return False +else: + # The standard metaclass; nothing changes. + DescriptorMetaclass = type + + class DescriptorBase(object): """Descriptors base class. This class is the base of all descriptor classes. It provides common options - related functionaility. + related functionality. Attributes: has_options: True if the descriptor has non-default options. Usually it @@ -75,6 +90,12 @@ class DescriptorBase(object): avoid some bootstrapping issues. """ + __metaclass__ = DescriptorMetaclass + if _USE_C_DESCRIPTORS: + # The class, or tuple of classes, that are considered as "virtual + # subclasses" of this descriptor class. + _C_DESCRIPTOR_CLASS = () + def __init__(self, options, options_class_name): """Initialize the descriptor given its options message and the name of the class of the options message. The name of the class is required in case @@ -235,13 +256,25 @@ class Descriptor(_NestedDescriptorBase): file: (FileDescriptor) Reference to file descriptor. """ + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.Descriptor + + def __new__(cls, name, full_name, filename, containing_type, fields, + nested_types, enum_types, extensions, options=None, + is_extendable=True, extension_ranges=None, oneofs=None, + file=None, serialized_start=None, serialized_end=None, + syntax=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.Message._GetMessageDescriptor(full_name) + # NOTE(tmarek): The file argument redefining a builtin is nothing we can # fix right now since we don't know how many clients already rely on the # name of the argument. def __init__(self, name, full_name, filename, containing_type, fields, nested_types, enum_types, extensions, options=None, is_extendable=True, extension_ranges=None, oneofs=None, - file=None, serialized_start=None, serialized_end=None): # pylint:disable=redefined-builtin + file=None, serialized_start=None, serialized_end=None, + syntax=None): # pylint:disable=redefined-builtin """Arguments to __init__() are as described in the description of Descriptor fields above. @@ -286,6 +319,7 @@ class Descriptor(_NestedDescriptorBase): self.oneofs_by_name = dict((o.name, o) for o in self.oneofs) for oneof in self.oneofs: oneof.containing_type = self + self.syntax = syntax or "proto2" def EnumValueName(self, enum, value): """Returns the string name of an enum value. @@ -452,6 +486,19 @@ class FieldDescriptor(DescriptorBase): FIRST_RESERVED_FIELD_NUMBER = 19000 LAST_RESERVED_FIELD_NUMBER = 19999 + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.FieldDescriptor + + def __new__(cls, name, full_name, index, number, type, cpp_type, label, + default_value, message_type, enum_type, containing_type, + is_extension, extension_scope, options=None, + has_default_value=True, containing_oneof=None): + _message.Message._CheckCalledFromGeneratedFile() + if is_extension: + return _message.Message._GetExtensionDescriptor(full_name) + else: + return _message.Message._GetFieldDescriptor(full_name) + def __init__(self, name, full_name, index, number, type, cpp_type, label, default_value, message_type, enum_type, containing_type, is_extension, extension_scope, options=None, @@ -481,20 +528,14 @@ class FieldDescriptor(DescriptorBase): self.containing_oneof = containing_oneof if api_implementation.Type() == 'cpp': if is_extension: - if api_implementation.Version() == 2: - # pylint: disable=protected-access - self._cdescriptor = ( - _message.Message._GetExtensionDescriptor(full_name)) - # pylint: enable=protected-access - else: - self._cdescriptor = cpp_message.GetExtensionDescriptor(full_name) + # pylint: disable=protected-access + self._cdescriptor = ( + _message.Message._GetExtensionDescriptor(full_name)) + # pylint: enable=protected-access else: - if api_implementation.Version() == 2: - # pylint: disable=protected-access - self._cdescriptor = _message.Message._GetFieldDescriptor(full_name) - # pylint: enable=protected-access - else: - self._cdescriptor = cpp_message.GetFieldDescriptor(full_name) + # pylint: disable=protected-access + self._cdescriptor = _message.Message._GetFieldDescriptor(full_name) + # pylint: enable=protected-access else: self._cdescriptor = None @@ -544,6 +585,15 @@ class EnumDescriptor(_NestedDescriptorBase): None to use default enum options. """ + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.EnumDescriptor + + def __new__(cls, name, full_name, filename, values, + containing_type=None, options=None, file=None, + serialized_start=None, serialized_end=None): + _message.Message._CheckCalledFromGeneratedFile() + return _message.Message._GetEnumDescriptor(full_name) + def __init__(self, name, full_name, filename, values, containing_type=None, options=None, file=None, serialized_start=None, serialized_end=None): @@ -588,6 +638,17 @@ class EnumValueDescriptor(DescriptorBase): None to use default enum value options options. """ + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.EnumValueDescriptor + + def __new__(cls, name, index, number, type=None, options=None): + _message.Message._CheckCalledFromGeneratedFile() + # There is no way we can build a complete EnumValueDescriptor with the + # given parameters (the name of the Enum is not known, for example). + # Fortunately generated files just pass it to the EnumDescriptor() + # constructor, which will ignore it, so returning None is good enough. + return None + def __init__(self, name, index, number, type=None, options=None): """Arguments are as described in the attribute description above.""" super(EnumValueDescriptor, self).__init__(options, 'EnumValueOptions') @@ -611,6 +672,13 @@ class OneofDescriptor(object): oneof can contain. """ + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.OneofDescriptor + + def __new__(cls, name, full_name, index, containing_type, fields): + _message.Message._CheckCalledFromGeneratedFile() + return _message.Message._GetOneofDescriptor(full_name) + def __init__(self, name, full_name, index, containing_type, fields): """Arguments are as described in the attribute description above.""" self.name = name @@ -704,6 +772,7 @@ class FileDescriptor(DescriptorBase): name: name of file, relative to root of source tree. package: name of the package + syntax: string indicating syntax of the file (can be "proto2" or "proto3") serialized_pb: (str) Byte string of serialized descriptor_pb2.FileDescriptorProto. dependencies: List of other FileDescriptors this FileDescriptor depends on. @@ -712,14 +781,31 @@ class FileDescriptor(DescriptorBase): extensions_by_name: Dict of extension names and their descriptors. """ + if _USE_C_DESCRIPTORS: + _C_DESCRIPTOR_CLASS = _message.FileDescriptor + + def __new__(cls, name, package, options=None, serialized_pb=None, + dependencies=None, syntax=None): + # FileDescriptor() is called from various places, not only from generated + # files, to register dynamic proto files and messages. + # TODO(amauryfa): Expose BuildFile() as a public function and make this + # constructor an implementation detail. + if serialized_pb: + # pylint: disable=protected-access2 + return _message.Message._BuildFile(serialized_pb) + # pylint: enable=protected-access + else: + return super(FileDescriptor, cls).__new__(cls) + def __init__(self, name, package, options=None, serialized_pb=None, - dependencies=None): + dependencies=None, syntax=None): """Constructor.""" super(FileDescriptor, self).__init__(options, 'FileOptions') self.message_types_by_name = {} self.name = name self.package = package + self.syntax = syntax or "proto2" self.serialized_pb = serialized_pb self.enum_types_by_name = {} @@ -728,12 +814,9 @@ class FileDescriptor(DescriptorBase): if (api_implementation.Type() == 'cpp' and self.serialized_pb is not None): - if api_implementation.Version() == 2: - # pylint: disable=protected-access - _message.Message._BuildFile(self.serialized_pb) - # pylint: enable=protected-access - else: - cpp_message.BuildFile(self.serialized_pb) + # pylint: disable=protected-access + _message.Message._BuildFile(self.serialized_pb) + # pylint: enable=protected-access def CopyToProto(self, proto): """Copies this to a descriptor_pb2.FileDescriptorProto. @@ -754,7 +837,8 @@ def _ParseOptions(message, string): return message -def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True): +def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, + syntax=None): """Make a protobuf Descriptor given a DescriptorProto protobuf. Handles nested descriptors. Note that this is limited to the scope of defining @@ -766,6 +850,8 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True): package: Optional package name for the new message Descriptor (string). build_file_if_cpp: Update the C++ descriptor pool if api matches. Set to False on recursion, so no duplicates are created. + syntax: The syntax/semantics that should be used. Set to "proto3" to get + proto3 field presence semantics. Returns: A Descriptor for protobuf messages. """ @@ -791,12 +877,13 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True): else: file_descriptor_proto.name = proto_name + '.proto' - if api_implementation.Version() == 2: - # pylint: disable=protected-access - _message.Message._BuildFile(file_descriptor_proto.SerializeToString()) - # pylint: enable=protected-access - else: - cpp_message.BuildFile(file_descriptor_proto.SerializeToString()) + # pylint: disable=protected-access + result = _message.Message._BuildFile( + file_descriptor_proto.SerializeToString()) + # pylint: enable=protected-access + + if _USE_C_DESCRIPTORS: + return result.message_types_by_name[desc_proto.name] full_message_name = [desc_proto.name] if package: full_message_name.insert(0, package) @@ -819,7 +906,8 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True): # used by fields in the message, so no loops are possible here. nested_desc = MakeDescriptor(nested_proto, package='.'.join(full_message_name), - build_file_if_cpp=False) + build_file_if_cpp=False, + syntax=syntax) nested_types[full_name] = nested_desc fields = [] diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py index bcac513a..7e7701f8 100644 --- a/python/google/protobuf/descriptor_pool.py +++ b/python/google/protobuf/descriptor_pool.py @@ -64,6 +64,9 @@ from google.protobuf import descriptor_database from google.protobuf import text_encoding +_USE_C_DESCRIPTORS = descriptor._USE_C_DESCRIPTORS + + def _NormalizeFullyQualifiedName(name): """Remove leading period from fully-qualified type name. @@ -271,58 +274,81 @@ class DescriptorPool(object): file_descriptor = descriptor.FileDescriptor( name=file_proto.name, package=file_proto.package, + syntax=file_proto.syntax, options=file_proto.options, serialized_pb=file_proto.SerializeToString(), dependencies=direct_deps) - scope = {} - - # This loop extracts all the message and enum types from all the - # dependencoes of the file_proto. This is necessary to create the - # scope of available message types when defining the passed in - # file proto. - for dependency in built_deps: - scope.update(self._ExtractSymbols( - dependency.message_types_by_name.values())) - scope.update((_PrefixWithDot(enum.full_name), enum) - for enum in dependency.enum_types_by_name.values()) - - for message_type in file_proto.message_type: - message_desc = self._ConvertMessageDescriptor( - message_type, file_proto.package, file_descriptor, scope) - file_descriptor.message_types_by_name[message_desc.name] = message_desc - - for enum_type in file_proto.enum_type: - file_descriptor.enum_types_by_name[enum_type.name] = ( - self._ConvertEnumDescriptor(enum_type, file_proto.package, - file_descriptor, None, scope)) - - for index, extension_proto in enumerate(file_proto.extension): - extension_desc = self.MakeFieldDescriptor( - extension_proto, file_proto.package, index, is_extension=True) - extension_desc.containing_type = self._GetTypeFromScope( - file_descriptor.package, extension_proto.extendee, scope) - self.SetFieldType(extension_proto, extension_desc, - file_descriptor.package, scope) - file_descriptor.extensions_by_name[extension_desc.name] = extension_desc - - for desc_proto in file_proto.message_type: - self.SetAllFieldTypes(file_proto.package, desc_proto, scope) - - if file_proto.package: - desc_proto_prefix = _PrefixWithDot(file_proto.package) + if _USE_C_DESCRIPTORS: + # When using C++ descriptors, all objects defined in the file were added + # to the C++ database when the FileDescriptor was built above. + # Just add them to this descriptor pool. + def _AddMessageDescriptor(message_desc): + self._descriptors[message_desc.full_name] = message_desc + for nested in message_desc.nested_types: + _AddMessageDescriptor(nested) + for enum_type in message_desc.enum_types: + _AddEnumDescriptor(enum_type) + def _AddEnumDescriptor(enum_desc): + self._enum_descriptors[enum_desc.full_name] = enum_desc + for message_type in file_descriptor.message_types_by_name.values(): + _AddMessageDescriptor(message_type) + for enum_type in file_descriptor.enum_types_by_name.values(): + _AddEnumDescriptor(enum_type) else: - desc_proto_prefix = '' + scope = {} + + # This loop extracts all the message and enum types from all the + # dependencies of the file_proto. This is necessary to create the + # scope of available message types when defining the passed in + # file proto. + for dependency in built_deps: + scope.update(self._ExtractSymbols( + dependency.message_types_by_name.values())) + scope.update((_PrefixWithDot(enum.full_name), enum) + for enum in dependency.enum_types_by_name.values()) + + for message_type in file_proto.message_type: + message_desc = self._ConvertMessageDescriptor( + message_type, file_proto.package, file_descriptor, scope, + file_proto.syntax) + file_descriptor.message_types_by_name[message_desc.name] = ( + message_desc) + + for enum_type in file_proto.enum_type: + file_descriptor.enum_types_by_name[enum_type.name] = ( + self._ConvertEnumDescriptor(enum_type, file_proto.package, + file_descriptor, None, scope)) + + for index, extension_proto in enumerate(file_proto.extension): + extension_desc = self.MakeFieldDescriptor( + extension_proto, file_proto.package, index, is_extension=True) + extension_desc.containing_type = self._GetTypeFromScope( + file_descriptor.package, extension_proto.extendee, scope) + self.SetFieldType(extension_proto, extension_desc, + file_descriptor.package, scope) + file_descriptor.extensions_by_name[extension_desc.name] = ( + extension_desc) + + for desc_proto in file_proto.message_type: + self.SetAllFieldTypes(file_proto.package, desc_proto, scope) + + if file_proto.package: + desc_proto_prefix = _PrefixWithDot(file_proto.package) + else: + desc_proto_prefix = '' + + for desc_proto in file_proto.message_type: + desc = self._GetTypeFromScope( + desc_proto_prefix, desc_proto.name, scope) + file_descriptor.message_types_by_name[desc_proto.name] = desc - for desc_proto in file_proto.message_type: - desc = self._GetTypeFromScope(desc_proto_prefix, desc_proto.name, scope) - file_descriptor.message_types_by_name[desc_proto.name] = desc self.Add(file_proto) self._file_descriptors[file_proto.name] = file_descriptor return self._file_descriptors[file_proto.name] def _ConvertMessageDescriptor(self, desc_proto, package=None, file_desc=None, - scope=None): + scope=None, syntax=None): """Adds the proto to the pool in the specified package. Args: @@ -349,7 +375,8 @@ class DescriptorPool(object): scope = {} nested = [ - self._ConvertMessageDescriptor(nested, desc_name, file_desc, scope) + self._ConvertMessageDescriptor( + nested, desc_name, file_desc, scope, syntax) for nested in desc_proto.nested_type] enums = [ self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope) @@ -383,7 +410,8 @@ class DescriptorPool(object): extension_ranges=extension_ranges, file=file_desc, serialized_start=None, - serialized_end=None) + serialized_end=None, + syntax=syntax) for nested in desc.nested_types: nested.containing_type = desc for enum in desc.enum_types: diff --git a/python/google/protobuf/internal/api_implementation.cc b/python/google/protobuf/internal/api_implementation.cc index 83db40b1..6db12e8d 100644 --- a/python/google/protobuf/internal/api_implementation.cc +++ b/python/google/protobuf/internal/api_implementation.cc @@ -50,10 +50,7 @@ namespace python { // and // PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION=2 #ifdef PYTHON_PROTO2_CPP_IMPL_V1 -#if PY_MAJOR_VERSION >= 3 -#error "PYTHON_PROTO2_CPP_IMPL_V1 is not supported under Python 3." -#endif -static int kImplVersion = 1; +#error "PYTHON_PROTO2_CPP_IMPL_V1 is no longer supported." #else #ifdef PYTHON_PROTO2_CPP_IMPL_V2 static int kImplVersion = 2; @@ -62,14 +59,7 @@ static int kImplVersion = 2; static int kImplVersion = 0; #else -// The defaults are set here. Python 3 uses the fast C++ APIv2 by default. -// Python 2 still uses the Python version by default until some compatibility -// issues can be worked around. -#if PY_MAJOR_VERSION >= 3 -static int kImplVersion = 2; -#else -static int kImplVersion = 0; -#endif +static int kImplVersion = -1; // -1 means "Unspecified by compiler flags". #endif // PYTHON_PROTO2_PYTHON_IMPL #endif // PYTHON_PROTO2_CPP_IMPL_V2 diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py index f7926c16..8ba4357c 100755 --- a/python/google/protobuf/internal/api_implementation.py +++ b/python/google/protobuf/internal/api_implementation.py @@ -40,14 +40,33 @@ try: # The compile-time constants in the _api_implementation module can be used to # switch to a certain implementation of the Python API at build time. _api_version = _api_implementation.api_version - del _api_implementation + _proto_extension_modules_exist_in_build = True except ImportError: - _api_version = 0 + _api_version = -1 # Unspecified by compiler flags. + _proto_extension_modules_exist_in_build = False + +if _api_version == 1: + raise ValueError('api_version=1 is no longer supported.') +if _api_version < 0: # Still unspecified? + try: + # The presence of this module in a build allows the proto implementation to + # be upgraded merely via build deps rather than a compiler flag or the + # runtime environment variable. + # pylint: disable=g-import-not-at-top + from google.protobuf import _use_fast_cpp_protos + # Work around a known issue in the classic bootstrap .par import hook. + if not _use_fast_cpp_protos: + raise ImportError('_use_fast_cpp_protos import succeeded but was None') + del _use_fast_cpp_protos + _api_version = 2 + except ImportError: + if _proto_extension_modules_exist_in_build: + if sys.version_info[0] >= 3: # Python 3 defaults to C++ impl v2. + _api_version = 2 + # TODO(b/17427486): Make Python 2 default to C++ impl v2. _default_implementation_type = ( - 'python' if _api_version == 0 else 'cpp') -_default_version_str = ( - '1' if _api_version <= 1 else '2') + 'python' if _api_version <= 0 else 'cpp') # This environment variable can be used to switch to a certain implementation # of the Python API, overriding the compile-time constants in the @@ -64,13 +83,12 @@ if _implementation_type != 'python': # _api_implementation module. Right now only 1 and 2 are valid values. Any other # value will be ignored. _implementation_version_str = os.getenv( - 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', - _default_version_str) + 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', '2') -if _implementation_version_str not in ('1', '2'): +if _implementation_version_str != '2': raise ValueError( - "unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: '" + - _implementation_version_str + "' (supported versions: 1, 2)" + 'unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: "' + + _implementation_version_str + '" (supported versions: 2)' ) _implementation_version = int(_implementation_version_str) diff --git a/python/google/protobuf/internal/api_implementation_default_test.py b/python/google/protobuf/internal/api_implementation_default_test.py deleted file mode 100644 index 78d5cf23..00000000 --- a/python/google/protobuf/internal/api_implementation_default_test.py +++ /dev/null @@ -1,63 +0,0 @@ -#! /usr/bin/python -# -# 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. - -"""Test that the api_implementation defaults are what we expect.""" - -import os -import sys -# Clear environment implementation settings before the google3 imports. -os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', None) -os.environ.pop('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', None) - -# pylint: disable=g-import-not-at-top -from google.apputils import basetest -from google.protobuf.internal import api_implementation - - -class ApiImplementationDefaultTest(basetest.TestCase): - - if sys.version_info.major <= 2: - - def testThatPythonIsTheDefault(self): - """If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail.""" - self.assertEqual('python', api_implementation.Type()) - - else: - - def testThatCppApiV2IsTheDefault(self): - """If -DPYTHON_PROTO_*IMPL* was given at build time, this may fail.""" - self.assertEqual('cpp', api_implementation.Type()) - self.assertEqual(2, api_implementation.Version()) - - -if __name__ == '__main__': - basetest.main() diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py index 20bfa857..d976f9e1 100755 --- a/python/google/protobuf/internal/containers.py +++ b/python/google/protobuf/internal/containers.py @@ -41,7 +41,6 @@ are: __author__ = 'petar@google.com (Petar Petrov)' - class BaseContainer(object): """Base container class.""" @@ -119,15 +118,23 @@ class RepeatedScalarFieldContainer(BaseContainer): self._message_listener.Modified() def extend(self, elem_seq): - """Extends by appending the given sequence. Similar to list.extend().""" - if not elem_seq: - return + """Extends by appending the given iterable. Similar to list.extend().""" - new_values = [] - for elem in elem_seq: - new_values.append(self._type_checker.CheckValue(elem)) - self._values.extend(new_values) - self._message_listener.Modified() + if elem_seq is None: + return + try: + elem_seq_iter = iter(elem_seq) + except TypeError: + if not elem_seq: + # silently ignore falsy inputs :-/. + # TODO(ptucker): Deprecate this behavior. b/18413862 + return + raise + + new_values = [self._type_checker.CheckValue(elem) for elem in elem_seq_iter] + if new_values: + self._values.extend(new_values) + self._message_listener.Modified() def MergeFrom(self, other): """Appends the contents of another repeated field of the same type to this @@ -141,6 +148,12 @@ class RepeatedScalarFieldContainer(BaseContainer): self._values.remove(elem) self._message_listener.Modified() + def pop(self, key=-1): + """Removes and returns an item at a given index. Similar to list.pop().""" + value = self._values[key] + self.__delitem__(key) + return value + def __setitem__(self, key, value): """Sets the item on the specified position.""" if isinstance(key, slice): # PY3 @@ -245,6 +258,12 @@ class RepeatedCompositeFieldContainer(BaseContainer): self._values.remove(elem) self._message_listener.Modified() + def pop(self, key=-1): + """Removes and returns an item at a given index. Similar to list.pop().""" + value = self._values[key] + self.__delitem__(key) + return value + def __getslice__(self, start, stop): """Retrieves the subset of items from between the specified indices.""" return self._values[start:stop] diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py index a4b90608..0f500606 100755 --- a/python/google/protobuf/internal/decoder.py +++ b/python/google/protobuf/internal/decoder.py @@ -621,9 +621,6 @@ def MessageDecoder(field_number, is_repeated, is_packed, key, new_default): if value is None: value = field_dict.setdefault(key, new_default(message)) while 1: - value = field_dict.get(key) - if value is None: - value = field_dict.setdefault(key, new_default(message)) # Read length. (size, pos) = local_DecodeVarint(buffer, pos) new_pos = pos + size diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index 3924f21a..50c4dbba 100755 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -34,12 +34,16 @@ __author__ = 'robinson@google.com (Will Robinson)' +import sys + from google.apputils import basetest from google.protobuf import unittest_custom_options_pb2 from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_pb2 from google.protobuf import descriptor_pb2 +from google.protobuf.internal import api_implementation from google.protobuf import descriptor +from google.protobuf import symbol_database from google.protobuf import text_format @@ -51,41 +55,28 @@ name: 'TestEmptyMessage' class DescriptorTest(basetest.TestCase): def setUp(self): - self.my_file = descriptor.FileDescriptor( + file_proto = descriptor_pb2.FileDescriptorProto( name='some/filename/some.proto', - package='protobuf_unittest' - ) - self.my_enum = descriptor.EnumDescriptor( - name='ForeignEnum', - full_name='protobuf_unittest.ForeignEnum', - filename=None, - file=self.my_file, - values=[ - descriptor.EnumValueDescriptor(name='FOREIGN_FOO', index=0, number=4), - descriptor.EnumValueDescriptor(name='FOREIGN_BAR', index=1, number=5), - descriptor.EnumValueDescriptor(name='FOREIGN_BAZ', index=2, number=6), - ]) - self.my_message = descriptor.Descriptor( - name='NestedMessage', - full_name='protobuf_unittest.TestAllTypes.NestedMessage', - filename=None, - file=self.my_file, - containing_type=None, - fields=[ - descriptor.FieldDescriptor( - name='bb', - full_name='protobuf_unittest.TestAllTypes.NestedMessage.bb', - index=0, number=1, - type=5, cpp_type=1, label=1, - has_default_value=False, default_value=0, - message_type=None, enum_type=None, containing_type=None, - is_extension=False, extension_scope=None), - ], - nested_types=[], - enum_types=[ - self.my_enum, - ], - extensions=[]) + package='protobuf_unittest') + message_proto = file_proto.message_type.add( + name='NestedMessage') + message_proto.field.add( + name='bb', + number=1, + type=descriptor_pb2.FieldDescriptorProto.TYPE_INT32, + label=descriptor_pb2.FieldDescriptorProto.LABEL_OPTIONAL) + enum_proto = message_proto.enum_type.add( + name='ForeignEnum') + enum_proto.value.add(name='FOREIGN_FOO', number=4) + enum_proto.value.add(name='FOREIGN_BAR', number=5) + enum_proto.value.add(name='FOREIGN_BAZ', number=6) + + descriptor_pool = symbol_database.Default().pool + descriptor_pool.Add(file_proto) + self.my_file = descriptor_pool.FindFileByName(file_proto.name) + self.my_message = self.my_file.message_types_by_name[message_proto.name] + self.my_enum = self.my_message.enum_types_by_name[enum_proto.name] + self.my_method = descriptor.MethodDescriptor( name='Bar', full_name='protobuf_unittest.TestService.Bar', @@ -173,6 +164,11 @@ class DescriptorTest(basetest.TestCase): self.assertEqual(unittest_custom_options_pb2.METHODOPT1_VAL2, method_options.Extensions[method_opt1]) + message_descriptor = ( + unittest_custom_options_pb2.DummyMessageContainingEnum.DESCRIPTOR) + self.assertTrue(file_descriptor.has_options) + self.assertFalse(message_descriptor.has_options) + def testDifferentCustomOptionTypes(self): kint32min = -2**31 kint64min = -2**63 @@ -394,6 +390,108 @@ class DescriptorTest(basetest.TestCase): self.assertEqual(self.my_file.name, 'some/filename/some.proto') self.assertEqual(self.my_file.package, 'protobuf_unittest') + @basetest.unittest.skipIf( + api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, + 'Immutability of descriptors is only enforced in v2 implementation') + def testImmutableCppDescriptor(self): + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + with self.assertRaises(AttributeError): + message_descriptor.fields_by_name = None + with self.assertRaises(TypeError): + message_descriptor.fields_by_name['Another'] = None + with self.assertRaises(TypeError): + message_descriptor.fields.append(None) + + +class GeneratedDescriptorTest(basetest.TestCase): + """Tests for the properties of descriptors in generated code.""" + + def CheckMessageDescriptor(self, message_descriptor): + # Basic properties + self.assertEqual(message_descriptor.name, 'TestAllTypes') + self.assertEqual(message_descriptor.full_name, + 'protobuf_unittest.TestAllTypes') + # Test equality and hashability + self.assertEqual(message_descriptor, message_descriptor) + self.assertEqual(message_descriptor.fields[0].containing_type, + message_descriptor) + self.assertIn(message_descriptor, [message_descriptor]) + self.assertIn(message_descriptor, {message_descriptor: None}) + # Test field containers + self.CheckDescriptorSequence(message_descriptor.fields) + self.CheckDescriptorMapping(message_descriptor.fields_by_name) + self.CheckDescriptorMapping(message_descriptor.fields_by_number) + + def CheckFieldDescriptor(self, field_descriptor): + # Basic properties + self.assertEqual(field_descriptor.name, 'optional_int32') + self.assertEqual(field_descriptor.full_name, + 'protobuf_unittest.TestAllTypes.optional_int32') + self.assertEqual(field_descriptor.containing_type.name, 'TestAllTypes') + # Test equality and hashability + self.assertEqual(field_descriptor, field_descriptor) + self.assertEqual( + field_descriptor.containing_type.fields_by_name['optional_int32'], + field_descriptor) + self.assertIn(field_descriptor, [field_descriptor]) + self.assertIn(field_descriptor, {field_descriptor: None}) + + def CheckDescriptorSequence(self, sequence): + # Verifies that a property like 'messageDescriptor.fields' has all the + # properties of an immutable abc.Sequence. + self.assertGreater(len(sequence), 0) # Sized + self.assertEqual(len(sequence), len(list(sequence))) # Iterable + item = sequence[0] + self.assertEqual(item, sequence[0]) + self.assertIn(item, sequence) # Container + self.assertEqual(sequence.index(item), 0) + self.assertEqual(sequence.count(item), 1) + reversed_iterator = reversed(sequence) + self.assertEqual(list(reversed_iterator), list(sequence)[::-1]) + self.assertRaises(StopIteration, next, reversed_iterator) + + def CheckDescriptorMapping(self, mapping): + # Verifies that a property like 'messageDescriptor.fields' has all the + # properties of an immutable abc.Mapping. + self.assertGreater(len(mapping), 0) # Sized + self.assertEqual(len(mapping), len(list(mapping))) # Iterable + if sys.version_info.major >= 3: + key, item = next(iter(mapping.items())) + else: + key, item = mapping.items()[0] + self.assertIn(key, mapping) # Container + self.assertEqual(mapping.get(key), item) + # keys(), iterkeys() &co + item = (next(iter(mapping.keys())), next(iter(mapping.values()))) + self.assertEqual(item, next(iter(mapping.items()))) + if sys.version_info.major < 3: + def CheckItems(seq, iterator): + self.assertEqual(next(iterator), seq[0]) + self.assertEqual(list(iterator), seq[1:]) + CheckItems(mapping.keys(), mapping.iterkeys()) + CheckItems(mapping.values(), mapping.itervalues()) + CheckItems(mapping.items(), mapping.iteritems()) + + def testDescriptor(self): + message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.CheckMessageDescriptor(message_descriptor) + field_descriptor = message_descriptor.fields_by_name['optional_int32'] + self.CheckFieldDescriptor(field_descriptor) + + def testCppDescriptorContainer(self): + # Check that the collection is still valid even if the parent disappeared. + enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] + values = enum.values + del enum + self.assertEqual('FOO', values[0].name) + + def testCppDescriptorContainer_Iterator(self): + # Same test with the iterator + enum = unittest_pb2.TestAllTypes.DESCRIPTOR.enum_types_by_name['NestedEnum'] + values_iter = iter(enum.values) + del enum + self.assertEqual('FOO', next(values_iter).name) + class DescriptorCopyToProtoTest(basetest.TestCase): """Tests for CopyTo functions of Descriptor.""" @@ -588,10 +686,12 @@ class DescriptorCopyToProtoTest(basetest.TestCase): output_type: '.protobuf_unittest.BarResponse' > """ - self._InternalTestCopyToProto( - unittest_pb2.TestService.DESCRIPTOR, - descriptor_pb2.ServiceDescriptorProto, - TEST_SERVICE_ASCII) + # TODO(rocking): enable this test after the proto descriptor change is + # checked in. + #self._InternalTestCopyToProto( + # unittest_pb2.TestService.DESCRIPTOR, + # descriptor_pb2.ServiceDescriptorProto, + # TEST_SERVICE_ASCII) class MakeDescriptorTest(basetest.TestCase): diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index 42e2ad7e..7ab814cf 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -48,9 +48,12 @@ import math import operator import pickle import sys +import unittest from google.apputils import basetest +from google.apputils.pybase import parameterized from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 from google.protobuf.internal import api_implementation from google.protobuf.internal import test_util from google.protobuf import message @@ -69,88 +72,65 @@ def IsNegInf(val): return isinf(val) and (val < 0) +@parameterized.Parameters( + (unittest_pb2), + (unittest_proto3_arena_pb2)) class MessageTest(basetest.TestCase): - def testBadUtf8String(self): + def testBadUtf8String(self, message_module): if api_implementation.Type() != 'python': self.skipTest("Skipping testBadUtf8String, currently only the python " "api implementation raises UnicodeDecodeError when a " "string field contains bad utf-8.") bad_utf8_data = test_util.GoldenFileData('bad_utf8_string') with self.assertRaises(UnicodeDecodeError) as context: - unittest_pb2.TestAllTypes.FromString(bad_utf8_data) - self.assertIn('field: protobuf_unittest.TestAllTypes.optional_string', - str(context.exception)) - - def testGoldenMessage(self): - golden_data = test_util.GoldenFileData( - 'golden_message_oneof_implemented') - golden_message = unittest_pb2.TestAllTypes() - golden_message.ParseFromString(golden_data) - test_util.ExpectAllFieldsSet(self, golden_message) - self.assertEqual(golden_data, golden_message.SerializeToString()) - golden_copy = copy.deepcopy(golden_message) - self.assertEqual(golden_data, golden_copy.SerializeToString()) + message_module.TestAllTypes.FromString(bad_utf8_data) + self.assertIn('TestAllTypes.optional_string', str(context.exception)) + + def testGoldenMessage(self, message_module): + # Proto3 doesn't have the "default_foo" members or foreign enums, + # and doesn't preserve unknown fields, so for proto3 we use a golden + # message that doesn't have these fields set. + if message_module is unittest_pb2: + golden_data = test_util.GoldenFileData( + 'golden_message_oneof_implemented') + else: + golden_data = test_util.GoldenFileData('golden_message_proto3') - def testGoldenExtensions(self): - golden_data = test_util.GoldenFileData('golden_message') - golden_message = unittest_pb2.TestAllExtensions() + golden_message = message_module.TestAllTypes() golden_message.ParseFromString(golden_data) - all_set = unittest_pb2.TestAllExtensions() - test_util.SetAllExtensions(all_set) - self.assertEquals(all_set, golden_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, golden_message) self.assertEqual(golden_data, golden_message.SerializeToString()) golden_copy = copy.deepcopy(golden_message) self.assertEqual(golden_data, golden_copy.SerializeToString()) - def testGoldenPackedMessage(self): + def testGoldenPackedMessage(self, message_module): golden_data = test_util.GoldenFileData('golden_packed_fields_message') - golden_message = unittest_pb2.TestPackedTypes() + golden_message = message_module.TestPackedTypes() golden_message.ParseFromString(golden_data) - all_set = unittest_pb2.TestPackedTypes() + all_set = message_module.TestPackedTypes() test_util.SetAllPackedFields(all_set) - self.assertEquals(all_set, golden_message) + self.assertEqual(all_set, golden_message) self.assertEqual(golden_data, all_set.SerializeToString()) golden_copy = copy.deepcopy(golden_message) self.assertEqual(golden_data, golden_copy.SerializeToString()) - def testGoldenPackedExtensions(self): - golden_data = test_util.GoldenFileData('golden_packed_fields_message') - golden_message = unittest_pb2.TestPackedExtensions() - golden_message.ParseFromString(golden_data) - all_set = unittest_pb2.TestPackedExtensions() - test_util.SetAllPackedExtensions(all_set) - self.assertEquals(all_set, golden_message) - self.assertEqual(golden_data, all_set.SerializeToString()) - golden_copy = copy.deepcopy(golden_message) - self.assertEqual(golden_data, golden_copy.SerializeToString()) - - def testPickleSupport(self): + def testPickleSupport(self, message_module): golden_data = test_util.GoldenFileData('golden_message') - golden_message = unittest_pb2.TestAllTypes() + golden_message = message_module.TestAllTypes() golden_message.ParseFromString(golden_data) pickled_message = pickle.dumps(golden_message) unpickled_message = pickle.loads(pickled_message) - self.assertEquals(unpickled_message, golden_message) - - - def testPickleIncompleteProto(self): - golden_message = unittest_pb2.TestRequired(a=1) - pickled_message = pickle.dumps(golden_message) - - unpickled_message = pickle.loads(pickled_message) - self.assertEquals(unpickled_message, golden_message) - self.assertEquals(unpickled_message.a, 1) - # This is still an incomplete proto - so serializing should fail - self.assertRaises(message.EncodeError, unpickled_message.SerializeToString) + self.assertEqual(unpickled_message, golden_message) - def testPositiveInfinity(self): + def testPositiveInfinity(self, message_module): golden_data = (b'\x5D\x00\x00\x80\x7F' b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' b'\xCD\x02\x00\x00\x80\x7F' b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F') - golden_message = unittest_pb2.TestAllTypes() + golden_message = message_module.TestAllTypes() golden_message.ParseFromString(golden_data) self.assertTrue(IsPosInf(golden_message.optional_float)) self.assertTrue(IsPosInf(golden_message.optional_double)) @@ -158,12 +138,12 @@ class MessageTest(basetest.TestCase): self.assertTrue(IsPosInf(golden_message.repeated_double[0])) self.assertEqual(golden_data, golden_message.SerializeToString()) - def testNegativeInfinity(self): + def testNegativeInfinity(self, message_module): golden_data = (b'\x5D\x00\x00\x80\xFF' b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' b'\xCD\x02\x00\x00\x80\xFF' b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF') - golden_message = unittest_pb2.TestAllTypes() + golden_message = message_module.TestAllTypes() golden_message.ParseFromString(golden_data) self.assertTrue(IsNegInf(golden_message.optional_float)) self.assertTrue(IsNegInf(golden_message.optional_double)) @@ -171,12 +151,12 @@ class MessageTest(basetest.TestCase): self.assertTrue(IsNegInf(golden_message.repeated_double[0])) self.assertEqual(golden_data, golden_message.SerializeToString()) - def testNotANumber(self): + def testNotANumber(self, message_module): golden_data = (b'\x5D\x00\x00\xC0\x7F' b'\x61\x00\x00\x00\x00\x00\x00\xF8\x7F' b'\xCD\x02\x00\x00\xC0\x7F' b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF8\x7F') - golden_message = unittest_pb2.TestAllTypes() + golden_message = message_module.TestAllTypes() golden_message.ParseFromString(golden_data) self.assertTrue(isnan(golden_message.optional_float)) self.assertTrue(isnan(golden_message.optional_double)) @@ -188,47 +168,47 @@ class MessageTest(basetest.TestCase): # verify the serialized string can be converted into a correctly # behaving protocol buffer. serialized = golden_message.SerializeToString() - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() message.ParseFromString(serialized) self.assertTrue(isnan(message.optional_float)) self.assertTrue(isnan(message.optional_double)) self.assertTrue(isnan(message.repeated_float[0])) self.assertTrue(isnan(message.repeated_double[0])) - def testPositiveInfinityPacked(self): + def testPositiveInfinityPacked(self, message_module): golden_data = (b'\xA2\x06\x04\x00\x00\x80\x7F' b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') - golden_message = unittest_pb2.TestPackedTypes() + golden_message = message_module.TestPackedTypes() golden_message.ParseFromString(golden_data) self.assertTrue(IsPosInf(golden_message.packed_float[0])) self.assertTrue(IsPosInf(golden_message.packed_double[0])) self.assertEqual(golden_data, golden_message.SerializeToString()) - def testNegativeInfinityPacked(self): + def testNegativeInfinityPacked(self, message_module): golden_data = (b'\xA2\x06\x04\x00\x00\x80\xFF' b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') - golden_message = unittest_pb2.TestPackedTypes() + golden_message = message_module.TestPackedTypes() golden_message.ParseFromString(golden_data) self.assertTrue(IsNegInf(golden_message.packed_float[0])) self.assertTrue(IsNegInf(golden_message.packed_double[0])) self.assertEqual(golden_data, golden_message.SerializeToString()) - def testNotANumberPacked(self): + def testNotANumberPacked(self, message_module): golden_data = (b'\xA2\x06\x04\x00\x00\xC0\x7F' b'\xAA\x06\x08\x00\x00\x00\x00\x00\x00\xF8\x7F') - golden_message = unittest_pb2.TestPackedTypes() + golden_message = message_module.TestPackedTypes() golden_message.ParseFromString(golden_data) self.assertTrue(isnan(golden_message.packed_float[0])) self.assertTrue(isnan(golden_message.packed_double[0])) serialized = golden_message.SerializeToString() - message = unittest_pb2.TestPackedTypes() + message = message_module.TestPackedTypes() message.ParseFromString(serialized) self.assertTrue(isnan(message.packed_float[0])) self.assertTrue(isnan(message.packed_double[0])) - def testExtremeFloatValues(self): - message = unittest_pb2.TestAllTypes() + def testExtremeFloatValues(self, message_module): + message = message_module.TestAllTypes() # Most positive exponent, no significand bits set. kMostPosExponentNoSigBits = math.pow(2, 127) @@ -272,8 +252,8 @@ class MessageTest(basetest.TestCase): message.ParseFromString(message.SerializeToString()) self.assertTrue(message.optional_float == -kMostNegExponentOneSigBit) - def testExtremeDoubleValues(self): - message = unittest_pb2.TestAllTypes() + def testExtremeDoubleValues(self, message_module): + message = message_module.TestAllTypes() # Most positive exponent, no significand bits set. kMostPosExponentNoSigBits = math.pow(2, 1023) @@ -317,43 +297,43 @@ class MessageTest(basetest.TestCase): message.ParseFromString(message.SerializeToString()) self.assertTrue(message.optional_double == -kMostNegExponentOneSigBit) - def testFloatPrinting(self): - message = unittest_pb2.TestAllTypes() + def testFloatPrinting(self, message_module): + message = message_module.TestAllTypes() message.optional_float = 2.0 self.assertEqual(str(message), 'optional_float: 2.0\n') - def testHighPrecisionFloatPrinting(self): - message = unittest_pb2.TestAllTypes() + def testHighPrecisionFloatPrinting(self, message_module): + message = message_module.TestAllTypes() message.optional_double = 0.12345678912345678 if sys.version_info.major >= 3: self.assertEqual(str(message), 'optional_double: 0.12345678912345678\n') else: self.assertEqual(str(message), 'optional_double: 0.123456789123\n') - def testUnknownFieldPrinting(self): - populated = unittest_pb2.TestAllTypes() + def testUnknownFieldPrinting(self, message_module): + populated = message_module.TestAllTypes() test_util.SetAllNonLazyFields(populated) - empty = unittest_pb2.TestEmptyMessage() + empty = message_module.TestEmptyMessage() empty.ParseFromString(populated.SerializeToString()) self.assertEqual(str(empty), '') - def testRepeatedNestedFieldIteration(self): - msg = unittest_pb2.TestAllTypes() + def testRepeatedNestedFieldIteration(self, message_module): + msg = message_module.TestAllTypes() msg.repeated_nested_message.add(bb=1) msg.repeated_nested_message.add(bb=2) msg.repeated_nested_message.add(bb=3) msg.repeated_nested_message.add(bb=4) - self.assertEquals([1, 2, 3, 4], - [m.bb for m in msg.repeated_nested_message]) - self.assertEquals([4, 3, 2, 1], - [m.bb for m in reversed(msg.repeated_nested_message)]) - self.assertEquals([4, 3, 2, 1], - [m.bb for m in msg.repeated_nested_message[::-1]]) + self.assertEqual([1, 2, 3, 4], + [m.bb for m in msg.repeated_nested_message]) + self.assertEqual([4, 3, 2, 1], + [m.bb for m in reversed(msg.repeated_nested_message)]) + self.assertEqual([4, 3, 2, 1], + [m.bb for m in msg.repeated_nested_message[::-1]]) - def testSortingRepeatedScalarFieldsDefaultComparator(self): + def testSortingRepeatedScalarFieldsDefaultComparator(self, message_module): """Check some different types with the default comparator.""" - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() # TODO(mattp): would testing more scalar types strengthen test? message.repeated_int32.append(1) @@ -388,9 +368,9 @@ class MessageTest(basetest.TestCase): self.assertEqual(message.repeated_bytes[1], b'b') self.assertEqual(message.repeated_bytes[2], b'c') - def testSortingRepeatedScalarFieldsCustomComparator(self): + def testSortingRepeatedScalarFieldsCustomComparator(self, message_module): """Check some different types with custom comparator.""" - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() message.repeated_int32.append(-3) message.repeated_int32.append(-2) @@ -408,9 +388,9 @@ class MessageTest(basetest.TestCase): self.assertEqual(message.repeated_string[1], 'bb') self.assertEqual(message.repeated_string[2], 'aaa') - def testSortingRepeatedCompositeFieldsCustomComparator(self): + def testSortingRepeatedCompositeFieldsCustomComparator(self, message_module): """Check passing a custom comparator to sort a repeated composite field.""" - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() message.repeated_nested_message.add().bb = 1 message.repeated_nested_message.add().bb = 3 @@ -426,9 +406,9 @@ class MessageTest(basetest.TestCase): self.assertEqual(message.repeated_nested_message[4].bb, 5) self.assertEqual(message.repeated_nested_message[5].bb, 6) - def testRepeatedCompositeFieldSortArguments(self): + def testRepeatedCompositeFieldSortArguments(self, message_module): """Check sorting a repeated composite field using list.sort() arguments.""" - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() get_bb = operator.attrgetter('bb') cmp_bb = lambda a, b: cmp(a.bb, b.bb) @@ -452,9 +432,9 @@ class MessageTest(basetest.TestCase): self.assertEqual([k.bb for k in message.repeated_nested_message], [6, 5, 4, 3, 2, 1]) - def testRepeatedScalarFieldSortArguments(self): + def testRepeatedScalarFieldSortArguments(self, message_module): """Check sorting a scalar field using list.sort() arguments.""" - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() message.repeated_int32.append(-3) message.repeated_int32.append(-2) @@ -484,9 +464,9 @@ class MessageTest(basetest.TestCase): message.repeated_string.sort(cmp=len_cmp, reverse=True) self.assertEqual(list(message.repeated_string), ['aaa', 'bb', 'c']) - def testRepeatedFieldsComparable(self): - m1 = unittest_pb2.TestAllTypes() - m2 = unittest_pb2.TestAllTypes() + def testRepeatedFieldsComparable(self, message_module): + m1 = message_module.TestAllTypes() + m2 = message_module.TestAllTypes() m1.repeated_int32.append(0) m1.repeated_int32.append(1) m1.repeated_int32.append(2) @@ -519,55 +499,6 @@ class MessageTest(basetest.TestCase): # TODO(anuraag): Implement extensiondict comparison in C++ and then add test - def testParsingMerge(self): - """Check the merge behavior when a required or optional field appears - multiple times in the input.""" - messages = [ - unittest_pb2.TestAllTypes(), - unittest_pb2.TestAllTypes(), - unittest_pb2.TestAllTypes() ] - messages[0].optional_int32 = 1 - messages[1].optional_int64 = 2 - messages[2].optional_int32 = 3 - messages[2].optional_string = 'hello' - - merged_message = unittest_pb2.TestAllTypes() - merged_message.optional_int32 = 3 - merged_message.optional_int64 = 2 - merged_message.optional_string = 'hello' - - generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator() - generator.field1.extend(messages) - generator.field2.extend(messages) - generator.field3.extend(messages) - generator.ext1.extend(messages) - generator.ext2.extend(messages) - generator.group1.add().field1.MergeFrom(messages[0]) - generator.group1.add().field1.MergeFrom(messages[1]) - generator.group1.add().field1.MergeFrom(messages[2]) - generator.group2.add().field1.MergeFrom(messages[0]) - generator.group2.add().field1.MergeFrom(messages[1]) - generator.group2.add().field1.MergeFrom(messages[2]) - - data = generator.SerializeToString() - parsing_merge = unittest_pb2.TestParsingMerge() - parsing_merge.ParseFromString(data) - - # Required and optional fields should be merged. - self.assertEqual(parsing_merge.required_all_types, merged_message) - self.assertEqual(parsing_merge.optional_all_types, merged_message) - self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types, - merged_message) - self.assertEqual(parsing_merge.Extensions[ - unittest_pb2.TestParsingMerge.optional_ext], - merged_message) - - # Repeated fields should not be merged. - self.assertEqual(len(parsing_merge.repeated_all_types), 3) - self.assertEqual(len(parsing_merge.repeatedgroup), 3) - self.assertEqual(len(parsing_merge.Extensions[ - unittest_pb2.TestParsingMerge.repeated_ext]), 3) - def ensureNestedMessageExists(self, msg, attribute): """Make sure that a nested message object exists. @@ -577,12 +508,28 @@ class MessageTest(basetest.TestCase): getattr(msg, attribute) self.assertFalse(msg.HasField(attribute)) - def testOneofGetCaseNonexistingField(self): - m = unittest_pb2.TestAllTypes() + def testOneofGetCaseNonexistingField(self, message_module): + m = message_module.TestAllTypes() self.assertRaises(ValueError, m.WhichOneof, 'no_such_oneof_field') - def testOneofSemantics(self): - m = unittest_pb2.TestAllTypes() + def testOneofDefaultValues(self, message_module): + m = message_module.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + self.assertFalse(m.HasField('oneof_uint32')) + + # Oneof is set even when setting it to a default value. + m.oneof_uint32 = 0 + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_uint32')) + self.assertFalse(m.HasField('oneof_string')) + + m.oneof_string = "" + self.assertEqual('oneof_string', m.WhichOneof('oneof_field')) + self.assertTrue(m.HasField('oneof_string')) + self.assertFalse(m.HasField('oneof_uint32')) + + def testOneofSemantics(self, message_module): + m = message_module.TestAllTypes() self.assertIs(None, m.WhichOneof('oneof_field')) m.oneof_uint32 = 11 @@ -604,96 +551,569 @@ class MessageTest(basetest.TestCase): self.assertFalse(m.HasField('oneof_nested_message')) self.assertTrue(m.HasField('oneof_bytes')) - def testOneofCompositeFieldReadAccess(self): - m = unittest_pb2.TestAllTypes() + def testOneofCompositeFieldReadAccess(self, message_module): + m = message_module.TestAllTypes() m.oneof_uint32 = 11 self.ensureNestedMessageExists(m, 'oneof_nested_message') self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) self.assertEqual(11, m.oneof_uint32) - def testOneofHasField(self): - m = unittest_pb2.TestAllTypes() - self.assertFalse(m.HasField('oneof_field')) + def testOneofWhichOneof(self, message_module): + m = message_module.TestAllTypes() + self.assertIs(None, m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) + m.oneof_uint32 = 11 - self.assertTrue(m.HasField('oneof_field')) + self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertTrue(m.HasField('oneof_field')) + m.oneof_bytes = b'bb' - self.assertTrue(m.HasField('oneof_field')) + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + m.ClearField('oneof_bytes') - self.assertFalse(m.HasField('oneof_field')) + self.assertIs(None, m.WhichOneof('oneof_field')) + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) - def testOneofClearField(self): - m = unittest_pb2.TestAllTypes() + def testOneofClearField(self, message_module): + m = message_module.TestAllTypes() m.oneof_uint32 = 11 m.ClearField('oneof_field') - self.assertFalse(m.HasField('oneof_field')) + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) self.assertFalse(m.HasField('oneof_uint32')) self.assertIs(None, m.WhichOneof('oneof_field')) - def testOneofClearSetField(self): - m = unittest_pb2.TestAllTypes() + def testOneofClearSetField(self, message_module): + m = message_module.TestAllTypes() m.oneof_uint32 = 11 m.ClearField('oneof_uint32') - self.assertFalse(m.HasField('oneof_field')) + if message_module is unittest_pb2: + self.assertFalse(m.HasField('oneof_field')) self.assertFalse(m.HasField('oneof_uint32')) self.assertIs(None, m.WhichOneof('oneof_field')) - def testOneofClearUnsetField(self): - m = unittest_pb2.TestAllTypes() + def testOneofClearUnsetField(self, message_module): + m = message_module.TestAllTypes() m.oneof_uint32 = 11 self.ensureNestedMessageExists(m, 'oneof_nested_message') m.ClearField('oneof_nested_message') self.assertEqual(11, m.oneof_uint32) - self.assertTrue(m.HasField('oneof_field')) + if message_module is unittest_pb2: + self.assertTrue(m.HasField('oneof_field')) self.assertTrue(m.HasField('oneof_uint32')) self.assertEqual('oneof_uint32', m.WhichOneof('oneof_field')) - def testOneofDeserialize(self): - m = unittest_pb2.TestAllTypes() + def testOneofDeserialize(self, message_module): + m = message_module.TestAllTypes() m.oneof_uint32 = 11 - m2 = unittest_pb2.TestAllTypes() + m2 = message_module.TestAllTypes() m2.ParseFromString(m.SerializeToString()) self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) - def testOneofCopyFrom(self): - m = unittest_pb2.TestAllTypes() + def testOneofCopyFrom(self, message_module): + m = message_module.TestAllTypes() m.oneof_uint32 = 11 - m2 = unittest_pb2.TestAllTypes() + m2 = message_module.TestAllTypes() m2.CopyFrom(m) self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) - def testOneofNestedMergeFrom(self): - m = unittest_pb2.NestedTestAllTypes() + def testOneofNestedMergeFrom(self, message_module): + m = message_module.NestedTestAllTypes() m.payload.oneof_uint32 = 11 - m2 = unittest_pb2.NestedTestAllTypes() + m2 = message_module.NestedTestAllTypes() m2.payload.oneof_bytes = b'bb' m2.child.payload.oneof_bytes = b'bb' m2.MergeFrom(m) self.assertEqual('oneof_uint32', m2.payload.WhichOneof('oneof_field')) self.assertEqual('oneof_bytes', m2.child.payload.WhichOneof('oneof_field')) - def testOneofClear(self): - m = unittest_pb2.TestAllTypes() + def testOneofMessageMergeFrom(self, message_module): + m = message_module.NestedTestAllTypes() + m.payload.oneof_nested_message.bb = 11 + m.child.payload.oneof_nested_message.bb = 12 + m2 = message_module.NestedTestAllTypes() + m2.payload.oneof_uint32 = 13 + m2.MergeFrom(m) + self.assertEqual('oneof_nested_message', + m2.payload.WhichOneof('oneof_field')) + self.assertEqual('oneof_nested_message', + m2.child.payload.WhichOneof('oneof_field')) + + def testOneofNestedMessageInit(self, message_module): + m = message_module.TestAllTypes( + oneof_nested_message=message_module.TestAllTypes.NestedMessage()) + self.assertEqual('oneof_nested_message', m.WhichOneof('oneof_field')) + + def testOneofClear(self, message_module): + m = message_module.TestAllTypes() m.oneof_uint32 = 11 m.Clear() self.assertIsNone(m.WhichOneof('oneof_field')) m.oneof_bytes = b'bb' - self.assertTrue(m.HasField('oneof_field')) + self.assertEqual('oneof_bytes', m.WhichOneof('oneof_field')) + + def testAssignByteStringToUnicodeField(self, message_module): + """Assigning a byte string to a string field should result + in the value being converted to a Unicode string.""" + m = message_module.TestAllTypes() + m.optional_string = str('') + self.assertTrue(isinstance(m.optional_string, unicode)) +# TODO(haberman): why are these tests Google-internal only? - def testSortEmptyRepeatedCompositeContainer(self): + def testLongValuedSlice(self, message_module): + """It should be possible to use long-valued indicies in slices + + This didn't used to work in the v2 C++ implementation. + """ + m = message_module.TestAllTypes() + + # Repeated scalar + m.repeated_int32.append(1) + sl = m.repeated_int32[long(0):long(len(m.repeated_int32))] + self.assertEqual(len(m.repeated_int32), len(sl)) + + # Repeated composite + m.repeated_nested_message.add().bb = 3 + sl = m.repeated_nested_message[long(0):long(len(m.repeated_nested_message))] + self.assertEqual(len(m.repeated_nested_message), len(sl)) + + def testExtendShouldNotSwallowExceptions(self, message_module): + """This didn't use to work in the v2 C++ implementation.""" + m = message_module.TestAllTypes() + with self.assertRaises(NameError) as _: + m.repeated_int32.extend(a for i in range(10)) # pylint: disable=undefined-variable + with self.assertRaises(NameError) as _: + m.repeated_nested_enum.extend( + a for i in range(10)) # pylint: disable=undefined-variable + + FALSY_VALUES = [None, False, 0, 0.0, b'', u'', bytearray(), [], {}, set()] + + def testExtendInt32WithNothing(self, message_module): + """Test no-ops extending repeated int32 fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_int32.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_int32) + + m.repeated_int32.extend([]) + self.assertSequenceEqual([], m.repeated_int32) + + def testExtendFloatWithNothing(self, message_module): + """Test no-ops extending repeated float fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_float.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_float) + + m.repeated_float.extend([]) + self.assertSequenceEqual([], m.repeated_float) + + def testExtendStringWithNothing(self, message_module): + """Test no-ops extending repeated string fields.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + + # TODO(ptucker): Deprecate this behavior. b/18413862 + for falsy_value in MessageTest.FALSY_VALUES: + m.repeated_string.extend(falsy_value) + self.assertSequenceEqual([], m.repeated_string) + + m.repeated_string.extend([]) + self.assertSequenceEqual([], m.repeated_string) + + def testExtendInt32WithPythonList(self, message_module): + """Test extending repeated int32 fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend([0]) + self.assertSequenceEqual([0], m.repeated_int32) + m.repeated_int32.extend([1, 2]) + self.assertSequenceEqual([0, 1, 2], m.repeated_int32) + m.repeated_int32.extend([3, 4]) + self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32) + + def testExtendFloatWithPythonList(self, message_module): + """Test extending repeated float fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend([0.0]) + self.assertSequenceEqual([0.0], m.repeated_float) + m.repeated_float.extend([1.0, 2.0]) + self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float) + m.repeated_float.extend([3.0, 4.0]) + self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float) + + def testExtendStringWithPythonList(self, message_module): + """Test extending repeated string fields with python lists.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(['']) + self.assertSequenceEqual([''], m.repeated_string) + m.repeated_string.extend(['11', '22']) + self.assertSequenceEqual(['', '11', '22'], m.repeated_string) + m.repeated_string.extend(['33', '44']) + self.assertSequenceEqual(['', '11', '22', '33', '44'], m.repeated_string) + + def testExtendStringWithString(self, message_module): + """Test extending repeated string fields with characters from a string.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend('abc') + self.assertSequenceEqual(['a', 'b', 'c'], m.repeated_string) + + class TestIterable(object): + """This iterable object mimics the behavior of numpy.array. + + __nonzero__ fails for length > 1, and returns bool(item[0]) for length == 1. + + """ + + def __init__(self, values=None): + self._list = values or [] + + def __nonzero__(self): + size = len(self._list) + if size == 0: + return False + if size == 1: + return bool(self._list[0]) + raise ValueError('Truth value is ambiguous.') + + def __len__(self): + return len(self._list) + + def __iter__(self): + return self._list.__iter__() + + def testExtendInt32WithIterable(self, message_module): + """Test extending repeated int32 fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([0])) + self.assertSequenceEqual([0], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([1, 2])) + self.assertSequenceEqual([0, 1, 2], m.repeated_int32) + m.repeated_int32.extend(MessageTest.TestIterable([3, 4])) + self.assertSequenceEqual([0, 1, 2, 3, 4], m.repeated_int32) + + def testExtendFloatWithIterable(self, message_module): + """Test extending repeated float fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([0.0])) + self.assertSequenceEqual([0.0], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([1.0, 2.0])) + self.assertSequenceEqual([0.0, 1.0, 2.0], m.repeated_float) + m.repeated_float.extend(MessageTest.TestIterable([3.0, 4.0])) + self.assertSequenceEqual([0.0, 1.0, 2.0, 3.0, 4.0], m.repeated_float) + + def testExtendStringWithIterable(self, message_module): + """Test extending repeated string fields with iterable.""" + m = message_module.TestAllTypes() + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable([])) + self.assertSequenceEqual([], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable([''])) + self.assertSequenceEqual([''], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable(['1', '2'])) + self.assertSequenceEqual(['', '1', '2'], m.repeated_string) + m.repeated_string.extend(MessageTest.TestIterable(['3', '4'])) + self.assertSequenceEqual(['', '1', '2', '3', '4'], m.repeated_string) + + def testPickleRepeatedScalarContainer(self, message_module): + # TODO(tibell): The pure-Python implementation support pickling of + # scalar containers in *some* cases. For now the cpp2 version + # throws an exception to avoid a segfault. Investigate if we + # want to support pickling of these fields. + # + # For more information see: https://b2.corp.google.com/u/0/issues/18677897 + if (api_implementation.Type() != 'cpp' or + api_implementation.Version() == 2): + return + m = message_module.TestAllTypes() + with self.assertRaises(pickle.PickleError) as _: + pickle.dumps(m.repeated_int32, pickle.HIGHEST_PROTOCOL) + + + def testSortEmptyRepeatedCompositeContainer(self, message_module): """Exercise a scenario that has led to segfaults in the past. """ - m = unittest_pb2.TestAllTypes() + m = message_module.TestAllTypes() m.repeated_nested_message.sort() - def testHasFieldOnRepeatedField(self): + def testHasFieldOnRepeatedField(self, message_module): """Using HasField on a repeated field should raise an exception. """ - m = unittest_pb2.TestAllTypes() + m = message_module.TestAllTypes() with self.assertRaises(ValueError) as _: m.HasField('repeated_int32') + def testRepeatedScalarFieldPop(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(IndexError) as _: + m.repeated_int32.pop() + m.repeated_int32.extend(range(5)) + self.assertEqual(4, m.repeated_int32.pop()) + self.assertEqual(0, m.repeated_int32.pop(0)) + self.assertEqual(2, m.repeated_int32.pop(1)) + self.assertEqual([1, 3], m.repeated_int32) + + def testRepeatedCompositeFieldPop(self, message_module): + m = message_module.TestAllTypes() + with self.assertRaises(IndexError) as _: + m.repeated_nested_message.pop() + for i in range(5): + n = m.repeated_nested_message.add() + n.bb = i + self.assertEqual(4, m.repeated_nested_message.pop().bb) + self.assertEqual(0, m.repeated_nested_message.pop(0).bb) + self.assertEqual(2, m.repeated_nested_message.pop(1).bb) + self.assertEqual([1, 3], [n.bb for n in m.repeated_nested_message]) + + +# Class to test proto2-only features (required, extensions, etc.) +class Proto2Test(basetest.TestCase): + + def testFieldPresence(self): + message = unittest_pb2.TestAllTypes() + + self.assertFalse(message.HasField("optional_int32")) + self.assertFalse(message.HasField("optional_bool")) + self.assertFalse(message.HasField("optional_nested_message")) + + with self.assertRaises(ValueError): + message.HasField("field_doesnt_exist") + + with self.assertRaises(ValueError): + message.HasField("repeated_int32") + with self.assertRaises(ValueError): + message.HasField("repeated_nested_message") + + self.assertEqual(0, message.optional_int32) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + # Fields are set even when setting the values to default values. + message.optional_int32 = 0 + message.optional_bool = False + message.optional_nested_message.bb = 0 + self.assertTrue(message.HasField("optional_int32")) + self.assertTrue(message.HasField("optional_bool")) + self.assertTrue(message.HasField("optional_nested_message")) + + # Set the fields to non-default values. + message.optional_int32 = 5 + message.optional_bool = True + message.optional_nested_message.bb = 15 + + self.assertTrue(message.HasField("optional_int32")) + self.assertTrue(message.HasField("optional_bool")) + self.assertTrue(message.HasField("optional_nested_message")) + + # Clearing the fields unsets them and resets their value to default. + message.ClearField("optional_int32") + message.ClearField("optional_bool") + message.ClearField("optional_nested_message") + + self.assertFalse(message.HasField("optional_int32")) + self.assertFalse(message.HasField("optional_bool")) + self.assertFalse(message.HasField("optional_nested_message")) + self.assertEqual(0, message.optional_int32) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + # TODO(tibell): The C++ implementations actually allows assignment + # of unknown enum values to *scalar* fields (but not repeated + # fields). Once checked enum fields becomes the default in the + # Python implementation, the C++ implementation should follow suit. + def testAssignInvalidEnum(self): + """It should not be possible to assign an invalid enum number to an + enum field.""" + m = unittest_pb2.TestAllTypes() + + with self.assertRaises(ValueError) as _: + m.optional_nested_enum = 1234567 + self.assertRaises(ValueError, m.repeated_nested_enum.append, 1234567) + + def testGoldenExtensions(self): + golden_data = test_util.GoldenFileData('golden_message') + golden_message = unittest_pb2.TestAllExtensions() + golden_message.ParseFromString(golden_data) + all_set = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(all_set) + self.assertEqual(all_set, golden_message) + self.assertEqual(golden_data, golden_message.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testGoldenPackedExtensions(self): + golden_data = test_util.GoldenFileData('golden_packed_fields_message') + golden_message = unittest_pb2.TestPackedExtensions() + golden_message.ParseFromString(golden_data) + all_set = unittest_pb2.TestPackedExtensions() + test_util.SetAllPackedExtensions(all_set) + self.assertEqual(all_set, golden_message) + self.assertEqual(golden_data, all_set.SerializeToString()) + golden_copy = copy.deepcopy(golden_message) + self.assertEqual(golden_data, golden_copy.SerializeToString()) + + def testPickleIncompleteProto(self): + golden_message = unittest_pb2.TestRequired(a=1) + pickled_message = pickle.dumps(golden_message) + + unpickled_message = pickle.loads(pickled_message) + self.assertEqual(unpickled_message, golden_message) + self.assertEqual(unpickled_message.a, 1) + # This is still an incomplete proto - so serializing should fail + self.assertRaises(message.EncodeError, unpickled_message.SerializeToString) + + + # TODO(haberman): this isn't really a proto2-specific test except that this + # message has a required field in it. Should probably be factored out so + # that we can test the other parts with proto3. + def testParsingMerge(self): + """Check the merge behavior when a required or optional field appears + multiple times in the input.""" + messages = [ + unittest_pb2.TestAllTypes(), + unittest_pb2.TestAllTypes(), + unittest_pb2.TestAllTypes() ] + messages[0].optional_int32 = 1 + messages[1].optional_int64 = 2 + messages[2].optional_int32 = 3 + messages[2].optional_string = 'hello' + + merged_message = unittest_pb2.TestAllTypes() + merged_message.optional_int32 = 3 + merged_message.optional_int64 = 2 + merged_message.optional_string = 'hello' + + generator = unittest_pb2.TestParsingMerge.RepeatedFieldsGenerator() + generator.field1.extend(messages) + generator.field2.extend(messages) + generator.field3.extend(messages) + generator.ext1.extend(messages) + generator.ext2.extend(messages) + generator.group1.add().field1.MergeFrom(messages[0]) + generator.group1.add().field1.MergeFrom(messages[1]) + generator.group1.add().field1.MergeFrom(messages[2]) + generator.group2.add().field1.MergeFrom(messages[0]) + generator.group2.add().field1.MergeFrom(messages[1]) + generator.group2.add().field1.MergeFrom(messages[2]) + + data = generator.SerializeToString() + parsing_merge = unittest_pb2.TestParsingMerge() + parsing_merge.ParseFromString(data) + + # Required and optional fields should be merged. + self.assertEqual(parsing_merge.required_all_types, merged_message) + self.assertEqual(parsing_merge.optional_all_types, merged_message) + self.assertEqual(parsing_merge.optionalgroup.optional_group_all_types, + merged_message) + self.assertEqual(parsing_merge.Extensions[ + unittest_pb2.TestParsingMerge.optional_ext], + merged_message) + + # Repeated fields should not be merged. + self.assertEqual(len(parsing_merge.repeated_all_types), 3) + self.assertEqual(len(parsing_merge.repeatedgroup), 3) + self.assertEqual(len(parsing_merge.Extensions[ + unittest_pb2.TestParsingMerge.repeated_ext]), 3) + + +# Class to test proto3-only features/behavior (updated field presence & enums) +class Proto3Test(basetest.TestCase): + + def testFieldPresence(self): + message = unittest_proto3_arena_pb2.TestAllTypes() + + # We can't test presence of non-repeated, non-submessage fields. + with self.assertRaises(ValueError): + message.HasField("optional_int32") + with self.assertRaises(ValueError): + message.HasField("optional_float") + with self.assertRaises(ValueError): + message.HasField("optional_string") + with self.assertRaises(ValueError): + message.HasField("optional_bool") + + # But we can still test presence of submessage fields. + self.assertFalse(message.HasField("optional_nested_message")) + + # As with proto2, we can't test presence of fields that don't exist, or + # repeated fields. + with self.assertRaises(ValueError): + message.HasField("field_doesnt_exist") + + with self.assertRaises(ValueError): + message.HasField("repeated_int32") + with self.assertRaises(ValueError): + message.HasField("repeated_nested_message") + + # Fields should default to their type-specific default. + self.assertEqual(0, message.optional_int32) + self.assertEqual(0, message.optional_float) + self.assertEqual("", message.optional_string) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + # Setting a submessage should still return proper presence information. + message.optional_nested_message.bb = 0 + self.assertTrue(message.HasField("optional_nested_message")) + + # Set the fields to non-default values. + message.optional_int32 = 5 + message.optional_float = 1.1 + message.optional_string = "abc" + message.optional_bool = True + message.optional_nested_message.bb = 15 + + # Clearing the fields unsets them and resets their value to default. + message.ClearField("optional_int32") + message.ClearField("optional_float") + message.ClearField("optional_string") + message.ClearField("optional_bool") + message.ClearField("optional_nested_message") + + self.assertEqual(0, message.optional_int32) + self.assertEqual(0, message.optional_float) + self.assertEqual("", message.optional_string) + self.assertEqual(False, message.optional_bool) + self.assertEqual(0, message.optional_nested_message.bb) + + def testAssignUnknownEnum(self): + """Assigning an unknown enum value is allowed and preserves the value.""" + m = unittest_proto3_arena_pb2.TestAllTypes() + + m.optional_nested_enum = 1234567 + self.assertEqual(1234567, m.optional_nested_enum) + m.repeated_nested_enum.append(22334455) + self.assertEqual(22334455, m.repeated_nested_enum[0]) + # Assignment is a different code path than append for the C++ impl. + m.repeated_nested_enum[0] = 7654321 + self.assertEqual(7654321, m.repeated_nested_enum[0]) + serialized = m.SerializeToString() + + m2 = unittest_proto3_arena_pb2.TestAllTypes() + m2.ParseFromString(serialized) + self.assertEqual(1234567, m2.optional_nested_enum) + self.assertEqual(7654321, m2.repeated_nested_enum[0]) + class ValidTypeNamesTest(basetest.TestCase): diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py index 6fda6ae0..6ad0f90d 100755 --- a/python/google/protobuf/internal/python_message.py +++ b/python/google/protobuf/internal/python_message.py @@ -219,12 +219,20 @@ def _AttachFieldHelpers(cls, field_descriptor): def AddDecoder(wiretype, is_packed): tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype) - cls._decoders_by_tag[tag_bytes] = ( - type_checkers.TYPE_TO_DECODER[field_descriptor.type]( - field_descriptor.number, is_repeated, is_packed, - field_descriptor, field_descriptor._default_constructor), - field_descriptor if field_descriptor.containing_oneof is not None - else None) + decode_type = field_descriptor.type + if (decode_type == _FieldDescriptor.TYPE_ENUM and + type_checkers.SupportsOpenEnums(field_descriptor)): + decode_type = _FieldDescriptor.TYPE_INT32 + + oneof_descriptor = None + if field_descriptor.containing_oneof is not None: + oneof_descriptor = field_descriptor + + field_decoder = type_checkers.TYPE_TO_DECODER[decode_type]( + field_descriptor.number, is_repeated, is_packed, + field_descriptor, field_descriptor._default_constructor) + + cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor) AddDecoder(type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], False) @@ -296,6 +304,8 @@ def _DefaultValueConstructorForField(field): def MakeSubMessageDefault(message): result = message_type._concrete_class() result._SetListener(message._listener_for_children) + if field.containing_oneof: + message._UpdateOneofState(field) return result return MakeSubMessageDefault @@ -476,6 +486,7 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls): type_checker = type_checkers.GetTypeChecker(field) default_value = field.default_value valid_values = set() + is_proto3 = field.containing_type.syntax == "proto3" def getter(self): # TODO(protobuf-team): This may be broken since there may not be @@ -483,15 +494,24 @@ def _AddPropertiesForNonRepeatedScalarField(field, cls): return self._fields.get(field, default_value) getter.__module__ = None getter.__doc__ = 'Getter for %s.' % proto_field_name + + clear_when_set_to_default = is_proto3 and not field.containing_oneof + def field_setter(self, new_value): # pylint: disable=protected-access - self._fields[field] = type_checker.CheckValue(new_value) + # Testing the value for truthiness captures all of the proto3 defaults + # (0, 0.0, enum 0, and False). + new_value = type_checker.CheckValue(new_value) + if clear_when_set_to_default and not new_value: + self._fields.pop(field, None) + else: + self._fields[field] = new_value # Check _cached_byte_size_dirty inline to improve performance, since scalar # setters are called frequently. if not self._cached_byte_size_dirty: self._Modified() - if field.containing_oneof is not None: + if field.containing_oneof: def setter(self, new_value): field_setter(self, new_value) self._UpdateOneofState(field) @@ -624,24 +644,35 @@ def _AddListFieldsMethod(message_descriptor, cls): cls.ListFields = ListFields +_Proto3HasError = 'Protocol message has no non-repeated submessage field "%s"' +_Proto2HasError = 'Protocol message has no non-repeated field "%s"' def _AddHasFieldMethod(message_descriptor, cls): """Helper for _AddMessageMethods().""" - singular_fields = {} + is_proto3 = (message_descriptor.syntax == "proto3") + error_msg = _Proto3HasError if is_proto3 else _Proto2HasError + + hassable_fields = {} for field in message_descriptor.fields: - if field.label != _FieldDescriptor.LABEL_REPEATED: - singular_fields[field.name] = field - # Fields inside oneofs are never repeated (enforced by the compiler). - for field in message_descriptor.oneofs: - singular_fields[field.name] = field + if field.label == _FieldDescriptor.LABEL_REPEATED: + continue + # For proto3, only submessages and fields inside a oneof have presence. + if (is_proto3 and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE and + not field.containing_oneof): + continue + hassable_fields[field.name] = field + + if not is_proto3: + # Fields inside oneofs are never repeated (enforced by the compiler). + for oneof in message_descriptor.oneofs: + hassable_fields[oneof.name] = oneof def HasField(self, field_name): try: - field = singular_fields[field_name] + field = hassable_fields[field_name] except KeyError: - raise ValueError( - 'Protocol message has no singular "%s" field.' % field_name) + raise ValueError(error_msg % field_name) if isinstance(field, descriptor_mod.OneofDescriptor): try: @@ -871,6 +902,7 @@ def _AddMergeFromStringMethod(message_descriptor, cls): local_ReadTag = decoder.ReadTag local_SkipField = decoder.SkipField decoders_by_tag = cls._decoders_by_tag + is_proto3 = message_descriptor.syntax == "proto3" def InternalParse(self, buffer, pos, end): self._Modified() @@ -884,9 +916,11 @@ def _AddMergeFromStringMethod(message_descriptor, cls): new_pos = local_SkipField(buffer, new_pos, end, tag_bytes) if new_pos == -1: return pos - if not unknown_field_list: - unknown_field_list = self._unknown_fields = [] - unknown_field_list.append((tag_bytes, buffer[value_start_pos:new_pos])) + if not is_proto3: + if not unknown_field_list: + unknown_field_list = self._unknown_fields = [] + unknown_field_list.append( + (tag_bytes, buffer[value_start_pos:new_pos])) pos = new_pos else: pos = field_decoder(buffer, new_pos, end, self, field_dict) @@ -1008,6 +1042,8 @@ def _AddMergeFromMethod(cls): # Construct a new object to represent this field. field_value = field._default_constructor(self) fields[field] = field_value + if field.containing_oneof: + self._UpdateOneofState(field) field_value.MergeFrom(value) else: self._fields[field] = value @@ -1252,11 +1288,10 @@ class _ExtensionDict(object): # It's slightly wasteful to lookup the type checker each time, # but we expect this to be a vanishingly uncommon case anyway. - type_checker = type_checkers.GetTypeChecker( - extension_handle) + type_checker = type_checkers.GetTypeChecker(extension_handle) # pylint: disable=protected-access self._extended_message._fields[extension_handle] = ( - type_checker.CheckValue(value)) + type_checker.CheckValue(value)) self._extended_message._Modified() def _FindExtensionByName(self, name): diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index 6b24b092..8ac76c63 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -1792,6 +1792,27 @@ class ReflectionTest(basetest.TestCase): # Just check the default value. self.assertEqual(57, msg.inner.value) + @basetest.unittest.skipIf( + api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, + 'CPPv2-specific test') + def testBadArguments(self): + # Some of these assertions used to segfault. + from google.protobuf.pyext import _message + self.assertRaises(TypeError, _message.Message._GetFieldDescriptor, 3) + self.assertRaises(TypeError, _message.Message._GetExtensionDescriptor, 42) + self.assertRaises(TypeError, + unittest_pb2.TestAllTypes().__getattribute__, 42) + + @basetest.unittest.skipIf( + api_implementation.Type() != 'cpp' or api_implementation.Version() != 2, + 'CPPv2-specific test') + def testRosyHack(self): + from google.protobuf.pyext import _message + from google3.gdata.rosy.proto import core_api2_pb2 + from google3.gdata.rosy.proto import core_pb2 + self.assertEqual(_message.Message, core_pb2.PageSelection.__base__) + self.assertEqual(_message.Message, core_api2_pb2.PageSelection.__base__) + # Since we had so many tests for protocol buffer equality, we broke these out # into separate TestCase classes. diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py index 787f4650..d84e3836 100755 --- a/python/google/protobuf/internal/test_util.py +++ b/python/google/protobuf/internal/test_util.py @@ -40,13 +40,19 @@ import os.path from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_pb2 +from google.protobuf import descriptor_pb2 +# Tests whether the given TestAllTypes message is proto2 or not. +# This is used to gate several fields/features that only exist +# for the proto2 version of the message. +def IsProto2(message): + return message.DESCRIPTOR.syntax == "proto2" def SetAllNonLazyFields(message): """Sets every non-lazy field in the message to a unique value. Args: - message: A unittest_pb2.TestAllTypes instance. + message: A TestAllTypes instance. """ # @@ -77,7 +83,8 @@ def SetAllNonLazyFields(message): message.optional_nested_enum = unittest_pb2.TestAllTypes.BAZ message.optional_foreign_enum = unittest_pb2.FOREIGN_BAZ - message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ + if IsProto2(message): + message.optional_import_enum = unittest_import_pb2.IMPORT_BAZ message.optional_string_piece = u'124' message.optional_cord = u'125' @@ -110,7 +117,8 @@ def SetAllNonLazyFields(message): message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAR) message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAR) - message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR) + if IsProto2(message): + message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAR) message.repeated_string_piece.append(u'224') message.repeated_cord.append(u'225') @@ -140,7 +148,8 @@ def SetAllNonLazyFields(message): message.repeated_nested_enum.append(unittest_pb2.TestAllTypes.BAZ) message.repeated_foreign_enum.append(unittest_pb2.FOREIGN_BAZ) - message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ) + if IsProto2(message): + message.repeated_import_enum.append(unittest_import_pb2.IMPORT_BAZ) message.repeated_string_piece.append(u'324') message.repeated_cord.append(u'325') @@ -149,28 +158,29 @@ def SetAllNonLazyFields(message): # Fields that have defaults. # - message.default_int32 = 401 - message.default_int64 = 402 - message.default_uint32 = 403 - message.default_uint64 = 404 - message.default_sint32 = 405 - message.default_sint64 = 406 - message.default_fixed32 = 407 - message.default_fixed64 = 408 - message.default_sfixed32 = 409 - message.default_sfixed64 = 410 - message.default_float = 411 - message.default_double = 412 - message.default_bool = False - message.default_string = '415' - message.default_bytes = b'416' - - message.default_nested_enum = unittest_pb2.TestAllTypes.FOO - message.default_foreign_enum = unittest_pb2.FOREIGN_FOO - message.default_import_enum = unittest_import_pb2.IMPORT_FOO - - message.default_string_piece = '424' - message.default_cord = '425' + if IsProto2(message): + message.default_int32 = 401 + message.default_int64 = 402 + message.default_uint32 = 403 + message.default_uint64 = 404 + message.default_sint32 = 405 + message.default_sint64 = 406 + message.default_fixed32 = 407 + message.default_fixed64 = 408 + message.default_sfixed32 = 409 + message.default_sfixed64 = 410 + message.default_float = 411 + message.default_double = 412 + message.default_bool = False + message.default_string = '415' + message.default_bytes = b'416' + + message.default_nested_enum = unittest_pb2.TestAllTypes.FOO + message.default_foreign_enum = unittest_pb2.FOREIGN_FOO + message.default_import_enum = unittest_import_pb2.IMPORT_FOO + + message.default_string_piece = '424' + message.default_cord = '425' message.oneof_uint32 = 601 message.oneof_nested_message.bb = 602 @@ -398,7 +408,8 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertTrue(message.HasField('optional_nested_enum')) test_case.assertTrue(message.HasField('optional_foreign_enum')) - test_case.assertTrue(message.HasField('optional_import_enum')) + if IsProto2(message): + test_case.assertTrue(message.HasField('optional_import_enum')) test_case.assertTrue(message.HasField('optional_string_piece')) test_case.assertTrue(message.HasField('optional_cord')) @@ -430,8 +441,9 @@ def ExpectAllFieldsSet(test_case, message): message.optional_nested_enum) test_case.assertEqual(unittest_pb2.FOREIGN_BAZ, message.optional_foreign_enum) - test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ, - message.optional_import_enum) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ, + message.optional_import_enum) # ----------------------------------------------------------------- @@ -457,7 +469,8 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual(2, len(message.repeated_import_message)) test_case.assertEqual(2, len(message.repeated_nested_enum)) test_case.assertEqual(2, len(message.repeated_foreign_enum)) - test_case.assertEqual(2, len(message.repeated_import_enum)) + if IsProto2(message): + test_case.assertEqual(2, len(message.repeated_import_enum)) test_case.assertEqual(2, len(message.repeated_string_piece)) test_case.assertEqual(2, len(message.repeated_cord)) @@ -488,8 +501,9 @@ def ExpectAllFieldsSet(test_case, message): message.repeated_nested_enum[0]) test_case.assertEqual(unittest_pb2.FOREIGN_BAR, message.repeated_foreign_enum[0]) - test_case.assertEqual(unittest_import_pb2.IMPORT_BAR, - message.repeated_import_enum[0]) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAR, + message.repeated_import_enum[0]) test_case.assertEqual(301, message.repeated_int32[1]) test_case.assertEqual(302, message.repeated_int64[1]) @@ -517,53 +531,55 @@ def ExpectAllFieldsSet(test_case, message): message.repeated_nested_enum[1]) test_case.assertEqual(unittest_pb2.FOREIGN_BAZ, message.repeated_foreign_enum[1]) - test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ, - message.repeated_import_enum[1]) + if IsProto2(message): + test_case.assertEqual(unittest_import_pb2.IMPORT_BAZ, + message.repeated_import_enum[1]) # ----------------------------------------------------------------- - test_case.assertTrue(message.HasField('default_int32')) - test_case.assertTrue(message.HasField('default_int64')) - test_case.assertTrue(message.HasField('default_uint32')) - test_case.assertTrue(message.HasField('default_uint64')) - test_case.assertTrue(message.HasField('default_sint32')) - test_case.assertTrue(message.HasField('default_sint64')) - test_case.assertTrue(message.HasField('default_fixed32')) - test_case.assertTrue(message.HasField('default_fixed64')) - test_case.assertTrue(message.HasField('default_sfixed32')) - test_case.assertTrue(message.HasField('default_sfixed64')) - test_case.assertTrue(message.HasField('default_float')) - test_case.assertTrue(message.HasField('default_double')) - test_case.assertTrue(message.HasField('default_bool')) - test_case.assertTrue(message.HasField('default_string')) - test_case.assertTrue(message.HasField('default_bytes')) - - test_case.assertTrue(message.HasField('default_nested_enum')) - test_case.assertTrue(message.HasField('default_foreign_enum')) - test_case.assertTrue(message.HasField('default_import_enum')) - - test_case.assertEqual(401, message.default_int32) - test_case.assertEqual(402, message.default_int64) - test_case.assertEqual(403, message.default_uint32) - test_case.assertEqual(404, message.default_uint64) - test_case.assertEqual(405, message.default_sint32) - test_case.assertEqual(406, message.default_sint64) - test_case.assertEqual(407, message.default_fixed32) - test_case.assertEqual(408, message.default_fixed64) - test_case.assertEqual(409, message.default_sfixed32) - test_case.assertEqual(410, message.default_sfixed64) - test_case.assertEqual(411, message.default_float) - test_case.assertEqual(412, message.default_double) - test_case.assertEqual(False, message.default_bool) - test_case.assertEqual('415', message.default_string) - test_case.assertEqual(b'416', message.default_bytes) - - test_case.assertEqual(unittest_pb2.TestAllTypes.FOO, - message.default_nested_enum) - test_case.assertEqual(unittest_pb2.FOREIGN_FOO, - message.default_foreign_enum) - test_case.assertEqual(unittest_import_pb2.IMPORT_FOO, - message.default_import_enum) + if IsProto2(message): + test_case.assertTrue(message.HasField('default_int32')) + test_case.assertTrue(message.HasField('default_int64')) + test_case.assertTrue(message.HasField('default_uint32')) + test_case.assertTrue(message.HasField('default_uint64')) + test_case.assertTrue(message.HasField('default_sint32')) + test_case.assertTrue(message.HasField('default_sint64')) + test_case.assertTrue(message.HasField('default_fixed32')) + test_case.assertTrue(message.HasField('default_fixed64')) + test_case.assertTrue(message.HasField('default_sfixed32')) + test_case.assertTrue(message.HasField('default_sfixed64')) + test_case.assertTrue(message.HasField('default_float')) + test_case.assertTrue(message.HasField('default_double')) + test_case.assertTrue(message.HasField('default_bool')) + test_case.assertTrue(message.HasField('default_string')) + test_case.assertTrue(message.HasField('default_bytes')) + + test_case.assertTrue(message.HasField('default_nested_enum')) + test_case.assertTrue(message.HasField('default_foreign_enum')) + test_case.assertTrue(message.HasField('default_import_enum')) + + test_case.assertEqual(401, message.default_int32) + test_case.assertEqual(402, message.default_int64) + test_case.assertEqual(403, message.default_uint32) + test_case.assertEqual(404, message.default_uint64) + test_case.assertEqual(405, message.default_sint32) + test_case.assertEqual(406, message.default_sint64) + test_case.assertEqual(407, message.default_fixed32) + test_case.assertEqual(408, message.default_fixed64) + test_case.assertEqual(409, message.default_sfixed32) + test_case.assertEqual(410, message.default_sfixed64) + test_case.assertEqual(411, message.default_float) + test_case.assertEqual(412, message.default_double) + test_case.assertEqual(False, message.default_bool) + test_case.assertEqual('415', message.default_string) + test_case.assertEqual(b'416', message.default_bytes) + + test_case.assertEqual(unittest_pb2.TestAllTypes.FOO, + message.default_nested_enum) + test_case.assertEqual(unittest_pb2.FOREIGN_FOO, + message.default_foreign_enum) + test_case.assertEqual(unittest_import_pb2.IMPORT_FOO, + message.default_import_enum) def GoldenFile(filename): @@ -594,7 +610,7 @@ def SetAllPackedFields(message): """Sets every field in the message to a unique value. Args: - message: A unittest_pb2.TestPackedTypes instance. + message: A TestPackedTypes instance. """ message.packed_int32.extend([601, 701]) message.packed_int64.extend([602, 702]) diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index 55e3c2c8..68ab9659 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -37,13 +37,17 @@ __author__ = 'kenton@google.com (Kenton Varda)' import re from google.apputils import basetest -from google.protobuf import text_format +from google.apputils.pybase import parameterized + +from google.protobuf import unittest_mset_pb2 +from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 from google.protobuf.internal import api_implementation from google.protobuf.internal import test_util -from google.protobuf import unittest_pb2 -from google.protobuf import unittest_mset_pb2 +from google.protobuf import text_format -class TextFormatTest(basetest.TestCase): +# Base class with some common functionality. +class TextFormatBase(basetest.TestCase): def ReadGolden(self, golden_filename): with test_util.GoldenFile(golden_filename) as f: @@ -57,73 +61,24 @@ class TextFormatTest(basetest.TestCase): def CompareToGoldenText(self, text, golden_text): self.assertMultiLineEqual(text, golden_text) - def testPrintAllFields(self): - message = unittest_pb2.TestAllTypes() - test_util.SetAllFields(message) - self.CompareToGoldenFile( - self.RemoveRedundantZeros(text_format.MessageToString(message)), - 'text_format_unittest_data_oneof_implemented.txt') - - def testPrintInIndexOrder(self): - message = unittest_pb2.TestFieldOrderings() - message.my_string = '115' - message.my_int = 101 - message.my_float = 111 - message.optional_nested_message.oo = 0 - message.optional_nested_message.bb = 1 - self.CompareToGoldenText( - self.RemoveRedundantZeros(text_format.MessageToString( - message, use_index_order=True)), - 'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n' - 'optional_nested_message {\n oo: 0\n bb: 1\n}\n') - self.CompareToGoldenText( - self.RemoveRedundantZeros(text_format.MessageToString( - message)), - 'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n' - 'optional_nested_message {\n bb: 1\n oo: 0\n}\n') - - def testPrintAllExtensions(self): - message = unittest_pb2.TestAllExtensions() - test_util.SetAllExtensions(message) - self.CompareToGoldenFile( - self.RemoveRedundantZeros(text_format.MessageToString(message)), - 'text_format_unittest_extensions_data.txt') - - def testPrintAllFieldsPointy(self): - message = unittest_pb2.TestAllTypes() - test_util.SetAllFields(message) - self.CompareToGoldenFile( - self.RemoveRedundantZeros( - text_format.MessageToString(message, pointy_brackets=True)), - 'text_format_unittest_data_pointy_oneof.txt') + def RemoveRedundantZeros(self, text): + # Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove + # these zeros in order to match the golden file. + text = text.replace('e+0','e+').replace('e+0','e+') \ + .replace('e-0','e-').replace('e-0','e-') + # Floating point fields are printed with .0 suffix even if they are + # actualy integer numbers. + text = re.compile('\.0$', re.MULTILINE).sub('', text) + return text - def testPrintAllExtensionsPointy(self): - message = unittest_pb2.TestAllExtensions() - test_util.SetAllExtensions(message) - self.CompareToGoldenFile( - self.RemoveRedundantZeros(text_format.MessageToString( - message, pointy_brackets=True)), - 'text_format_unittest_extensions_data_pointy.txt') - def testPrintMessageSet(self): - message = unittest_mset_pb2.TestMessageSetContainer() - ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension - ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension - message.message_set.Extensions[ext1].i = 23 - message.message_set.Extensions[ext2].str = 'foo' - self.CompareToGoldenText( - text_format.MessageToString(message), - 'message_set {\n' - ' [protobuf_unittest.TestMessageSetExtension1] {\n' - ' i: 23\n' - ' }\n' - ' [protobuf_unittest.TestMessageSetExtension2] {\n' - ' str: \"foo\"\n' - ' }\n' - '}\n') +@parameterized.Parameters( + (unittest_pb2), + (unittest_proto3_arena_pb2)) +class TextFormatTest(TextFormatBase): - def testPrintExotic(self): - message = unittest_pb2.TestAllTypes() + def testPrintExotic(self, message_module): + message = message_module.TestAllTypes() message.repeated_int64.append(-9223372036854775808) message.repeated_uint64.append(18446744073709551615) message.repeated_double.append(123.456) @@ -142,61 +97,44 @@ class TextFormatTest(basetest.TestCase): ' "\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""\n' 'repeated_string: "\\303\\274\\352\\234\\237"\n') - def testPrintExoticUnicodeSubclass(self): + def testPrintExoticUnicodeSubclass(self, message_module): class UnicodeSub(unicode): pass - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() message.repeated_string.append(UnicodeSub(u'\u00fc\ua71f')) self.CompareToGoldenText( text_format.MessageToString(message), 'repeated_string: "\\303\\274\\352\\234\\237"\n') - def testPrintNestedMessageAsOneLine(self): - message = unittest_pb2.TestAllTypes() + def testPrintNestedMessageAsOneLine(self, message_module): + message = message_module.TestAllTypes() msg = message.repeated_nested_message.add() msg.bb = 42 self.CompareToGoldenText( text_format.MessageToString(message, as_one_line=True), 'repeated_nested_message { bb: 42 }') - def testPrintRepeatedFieldsAsOneLine(self): - message = unittest_pb2.TestAllTypes() + def testPrintRepeatedFieldsAsOneLine(self, message_module): + message = message_module.TestAllTypes() message.repeated_int32.append(1) message.repeated_int32.append(1) message.repeated_int32.append(3) - message.repeated_string.append("Google") - message.repeated_string.append("Zurich") + message.repeated_string.append('Google') + message.repeated_string.append('Zurich') self.CompareToGoldenText( text_format.MessageToString(message, as_one_line=True), 'repeated_int32: 1 repeated_int32: 1 repeated_int32: 3 ' 'repeated_string: "Google" repeated_string: "Zurich"') - def testPrintNestedNewLineInStringAsOneLine(self): - message = unittest_pb2.TestAllTypes() - message.optional_string = "a\nnew\nline" + def testPrintNestedNewLineInStringAsOneLine(self, message_module): + message = message_module.TestAllTypes() + message.optional_string = 'a\nnew\nline' self.CompareToGoldenText( text_format.MessageToString(message, as_one_line=True), 'optional_string: "a\\nnew\\nline"') - def testPrintMessageSetAsOneLine(self): - message = unittest_mset_pb2.TestMessageSetContainer() - ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension - ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension - message.message_set.Extensions[ext1].i = 23 - message.message_set.Extensions[ext2].str = 'foo' - self.CompareToGoldenText( - text_format.MessageToString(message, as_one_line=True), - 'message_set {' - ' [protobuf_unittest.TestMessageSetExtension1] {' - ' i: 23' - ' }' - ' [protobuf_unittest.TestMessageSetExtension2] {' - ' str: \"foo\"' - ' }' - ' }') - - def testPrintExoticAsOneLine(self): - message = unittest_pb2.TestAllTypes() + def testPrintExoticAsOneLine(self, message_module): + message = message_module.TestAllTypes() message.repeated_int64.append(-9223372036854775808) message.repeated_uint64.append(18446744073709551615) message.repeated_double.append(123.456) @@ -216,8 +154,8 @@ class TextFormatTest(basetest.TestCase): '"\\000\\001\\007\\010\\014\\n\\r\\t\\013\\\\\\\'\\""' ' repeated_string: "\\303\\274\\352\\234\\237"') - def testRoundTripExoticAsOneLine(self): - message = unittest_pb2.TestAllTypes() + def testRoundTripExoticAsOneLine(self, message_module): + message = message_module.TestAllTypes() message.repeated_int64.append(-9223372036854775808) message.repeated_uint64.append(18446744073709551615) message.repeated_double.append(123.456) @@ -229,7 +167,7 @@ class TextFormatTest(basetest.TestCase): # Test as_utf8 = False. wire_text = text_format.MessageToString( message, as_one_line=True, as_utf8=False) - parsed_message = unittest_pb2.TestAllTypes() + parsed_message = message_module.TestAllTypes() r = text_format.Parse(wire_text, parsed_message) self.assertIs(r, parsed_message) self.assertEquals(message, parsed_message) @@ -237,25 +175,25 @@ class TextFormatTest(basetest.TestCase): # Test as_utf8 = True. wire_text = text_format.MessageToString( message, as_one_line=True, as_utf8=True) - parsed_message = unittest_pb2.TestAllTypes() + parsed_message = message_module.TestAllTypes() r = text_format.Parse(wire_text, parsed_message) self.assertIs(r, parsed_message) self.assertEquals(message, parsed_message, '\n%s != %s' % (message, parsed_message)) - def testPrintRawUtf8String(self): - message = unittest_pb2.TestAllTypes() + def testPrintRawUtf8String(self, message_module): + message = message_module.TestAllTypes() message.repeated_string.append(u'\u00fc\ua71f') text = text_format.MessageToString(message, as_utf8=True) self.CompareToGoldenText(text, 'repeated_string: "\303\274\352\234\237"\n') - parsed_message = unittest_pb2.TestAllTypes() + parsed_message = message_module.TestAllTypes() text_format.Parse(text, parsed_message) self.assertEquals(message, parsed_message, '\n%s != %s' % (message, parsed_message)) - def testPrintFloatFormat(self): + def testPrintFloatFormat(self, message_module): # Check that float_format argument is passed to sub-message formatting. - message = unittest_pb2.NestedTestAllTypes() + message = message_module.NestedTestAllTypes() # We use 1.25 as it is a round number in binary. The proto 32-bit float # will not gain additional imprecise digits as a 64-bit Python float and # show up in its str. 32-bit 1.2 is noisy when extended to 64-bit: @@ -285,85 +223,24 @@ class TextFormatTest(basetest.TestCase): self.RemoveRedundantZeros(text_message), 'payload {{ {} {} {} {} }}'.format(*formatted_fields)) - def testMessageToString(self): - message = unittest_pb2.ForeignMessage() + def testMessageToString(self, message_module): + message = message_module.ForeignMessage() message.c = 123 self.assertEqual('c: 123\n', str(message)) - def RemoveRedundantZeros(self, text): - # Some platforms print 1e+5 as 1e+005. This is fine, but we need to remove - # these zeros in order to match the golden file. - text = text.replace('e+0','e+').replace('e+0','e+') \ - .replace('e-0','e-').replace('e-0','e-') - # Floating point fields are printed with .0 suffix even if they are - # actualy integer numbers. - text = re.compile('\.0$', re.MULTILINE).sub('', text) - return text - - def testParseGolden(self): - golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt')) - parsed_message = unittest_pb2.TestAllTypes() - r = text_format.Parse(golden_text, parsed_message) - self.assertIs(r, parsed_message) - - message = unittest_pb2.TestAllTypes() - test_util.SetAllFields(message) - self.assertEquals(message, parsed_message) - - def testParseGoldenExtensions(self): - golden_text = '\n'.join(self.ReadGolden( - 'text_format_unittest_extensions_data.txt')) - parsed_message = unittest_pb2.TestAllExtensions() - text_format.Parse(golden_text, parsed_message) - - message = unittest_pb2.TestAllExtensions() - test_util.SetAllExtensions(message) - self.assertEquals(message, parsed_message) - - def testParseAllFields(self): - message = unittest_pb2.TestAllTypes() + def testParseAllFields(self, message_module): + message = message_module.TestAllTypes() test_util.SetAllFields(message) ascii_text = text_format.MessageToString(message) - parsed_message = unittest_pb2.TestAllTypes() - text_format.Parse(ascii_text, parsed_message) - self.assertEqual(message, parsed_message) - test_util.ExpectAllFieldsSet(self, message) - - def testParseAllExtensions(self): - message = unittest_pb2.TestAllExtensions() - test_util.SetAllExtensions(message) - ascii_text = text_format.MessageToString(message) - - parsed_message = unittest_pb2.TestAllExtensions() + parsed_message = message_module.TestAllTypes() text_format.Parse(ascii_text, parsed_message) self.assertEqual(message, parsed_message) + if message_module is unittest_pb2: + test_util.ExpectAllFieldsSet(self, message) - def testParseMessageSet(self): - message = unittest_pb2.TestAllTypes() - text = ('repeated_uint64: 1\n' - 'repeated_uint64: 2\n') - text_format.Parse(text, message) - self.assertEqual(1, message.repeated_uint64[0]) - self.assertEqual(2, message.repeated_uint64[1]) - - message = unittest_mset_pb2.TestMessageSetContainer() - text = ('message_set {\n' - ' [protobuf_unittest.TestMessageSetExtension1] {\n' - ' i: 23\n' - ' }\n' - ' [protobuf_unittest.TestMessageSetExtension2] {\n' - ' str: \"foo\"\n' - ' }\n' - '}\n') - text_format.Parse(text, message) - ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension - ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension - self.assertEquals(23, message.message_set.Extensions[ext1].i) - self.assertEquals('foo', message.message_set.Extensions[ext2].str) - - def testParseExotic(self): - message = unittest_pb2.TestAllTypes() + def testParseExotic(self, message_module): + message = message_module.TestAllTypes() text = ('repeated_int64: -9223372036854775808\n' 'repeated_uint64: 18446744073709551615\n' 'repeated_double: 123.456\n' @@ -388,8 +265,8 @@ class TextFormatTest(basetest.TestCase): self.assertEqual(u'\u00fc\ua71f', message.repeated_string[2]) self.assertEqual(u'\u00fc', message.repeated_string[3]) - def testParseTrailingCommas(self): - message = unittest_pb2.TestAllTypes() + def testParseTrailingCommas(self, message_module): + message = message_module.TestAllTypes() text = ('repeated_int64: 100;\n' 'repeated_int64: 200;\n' 'repeated_int64: 300,\n' @@ -403,51 +280,37 @@ class TextFormatTest(basetest.TestCase): self.assertEqual(u'one', message.repeated_string[0]) self.assertEqual(u'two', message.repeated_string[1]) - def testParseEmptyText(self): - message = unittest_pb2.TestAllTypes() + def testParseEmptyText(self, message_module): + message = message_module.TestAllTypes() text = '' text_format.Parse(text, message) - self.assertEquals(unittest_pb2.TestAllTypes(), message) + self.assertEquals(message_module.TestAllTypes(), message) - def testParseInvalidUtf8(self): - message = unittest_pb2.TestAllTypes() + def testParseInvalidUtf8(self, message_module): + message = message_module.TestAllTypes() text = 'repeated_string: "\\xc3\\xc3"' self.assertRaises(text_format.ParseError, text_format.Parse, text, message) - def testParseSingleWord(self): - message = unittest_pb2.TestAllTypes() + def testParseSingleWord(self, message_module): + message = message_module.TestAllTypes() text = 'foo' - self.assertRaisesWithLiteralMatch( + self.assertRaisesRegexp( text_format.ParseError, - ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named ' - '"foo".'), + (r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"foo".'), text_format.Parse, text, message) - def testParseUnknownField(self): - message = unittest_pb2.TestAllTypes() + def testParseUnknownField(self, message_module): + message = message_module.TestAllTypes() text = 'unknown_field: 8\n' - self.assertRaisesWithLiteralMatch( + self.assertRaisesRegexp( text_format.ParseError, - ('1:1 : Message type "protobuf_unittest.TestAllTypes" has no field named ' - '"unknown_field".'), + (r'1:1 : Message type "\w+.TestAllTypes" has no field named ' + r'"unknown_field".'), text_format.Parse, text, message) - def testParseBadExtension(self): - message = unittest_pb2.TestAllExtensions() - text = '[unknown_extension]: 8\n' - self.assertRaisesWithLiteralMatch( - text_format.ParseError, - '1:2 : Extension "unknown_extension" not registered.', - text_format.Parse, text, message) - message = unittest_pb2.TestAllTypes() - self.assertRaisesWithLiteralMatch( - text_format.ParseError, - ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have ' - 'extensions.'), - text_format.Parse, text, message) - - def testParseGroupNotClosed(self): - message = unittest_pb2.TestAllTypes() + def testParseGroupNotClosed(self, message_module): + message = message_module.TestAllTypes() text = 'RepeatedGroup: <' self.assertRaisesWithLiteralMatch( text_format.ParseError, '1:16 : Expected ">".', @@ -458,46 +321,46 @@ class TextFormatTest(basetest.TestCase): text_format.ParseError, '1:16 : Expected "}".', text_format.Parse, text, message) - def testParseEmptyGroup(self): - message = unittest_pb2.TestAllTypes() + def testParseEmptyGroup(self, message_module): + message = message_module.TestAllTypes() text = 'OptionalGroup: {}' text_format.Parse(text, message) self.assertTrue(message.HasField('optionalgroup')) message.Clear() - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() text = 'OptionalGroup: <>' text_format.Parse(text, message) self.assertTrue(message.HasField('optionalgroup')) - def testParseBadEnumValue(self): - message = unittest_pb2.TestAllTypes() + def testParseBadEnumValue(self, message_module): + message = message_module.TestAllTypes() text = 'optional_nested_enum: BARR' - self.assertRaisesWithLiteralMatch( + self.assertRaisesRegexp( text_format.ParseError, - ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' - 'has no value named BARR.'), + (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" ' + r'has no value named BARR.'), text_format.Parse, text, message) - message = unittest_pb2.TestAllTypes() + message = message_module.TestAllTypes() text = 'optional_nested_enum: 100' - self.assertRaisesWithLiteralMatch( + self.assertRaisesRegexp( text_format.ParseError, - ('1:23 : Enum type "protobuf_unittest.TestAllTypes.NestedEnum" ' - 'has no value with number 100.'), + (r'1:23 : Enum type "\w+.TestAllTypes.NestedEnum" ' + r'has no value with number 100.'), text_format.Parse, text, message) - def testParseBadIntValue(self): - message = unittest_pb2.TestAllTypes() + def testParseBadIntValue(self, message_module): + message = message_module.TestAllTypes() text = 'optional_int32: bork' self.assertRaisesWithLiteralMatch( text_format.ParseError, ('1:17 : Couldn\'t parse integer: bork'), text_format.Parse, text, message) - def testParseStringFieldUnescape(self): - message = unittest_pb2.TestAllTypes() + def testParseStringFieldUnescape(self, message_module): + message = message_module.TestAllTypes() text = r'''repeated_string: "\xf\x62" repeated_string: "\\xf\\x62" repeated_string: "\\\xf\\\x62" @@ -516,40 +379,205 @@ class TextFormatTest(basetest.TestCase): message.repeated_string[4]) self.assertEqual(SLASH + 'x20', message.repeated_string[5]) - def testMergeDuplicateScalars(self): - message = unittest_pb2.TestAllTypes() + def testMergeDuplicateScalars(self, message_module): + message = message_module.TestAllTypes() text = ('optional_int32: 42 ' 'optional_int32: 67') r = text_format.Merge(text, message) self.assertIs(r, message) self.assertEqual(67, message.optional_int32) - def testParseDuplicateScalars(self): - message = unittest_pb2.TestAllTypes() - text = ('optional_int32: 42 ' - 'optional_int32: 67') - self.assertRaisesWithLiteralMatch( - text_format.ParseError, - ('1:36 : Message type "protobuf_unittest.TestAllTypes" should not ' - 'have multiple "optional_int32" fields.'), - text_format.Parse, text, message) - - def testMergeDuplicateNestedMessageScalars(self): - message = unittest_pb2.TestAllTypes() + def testMergeDuplicateNestedMessageScalars(self, message_module): + message = message_module.TestAllTypes() text = ('optional_nested_message { bb: 1 } ' 'optional_nested_message { bb: 2 }') r = text_format.Merge(text, message) self.assertTrue(r is message) self.assertEqual(2, message.optional_nested_message.bb) - def testParseDuplicateNestedMessageScalars(self): + def testParseOneof(self, message_module): + m = message_module.TestAllTypes() + m.oneof_uint32 = 11 + m2 = message_module.TestAllTypes() + text_format.Parse(text_format.MessageToString(m), m2) + self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + + +# These are tests that aren't fundamentally specific to proto2, but are at +# the moment because of differences between the proto2 and proto3 test schemas. +# Ideally the schemas would be made more similar so these tests could pass. +class OnlyWorksWithProto2RightNowTests(TextFormatBase): + + def testParseGolden(self): + golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt')) + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.Parse(golden_text, parsed_message) + self.assertIs(r, parsed_message) + message = unittest_pb2.TestAllTypes() - text = ('optional_nested_message { bb: 1 } ' - 'optional_nested_message { bb: 2 }') + test_util.SetAllFields(message) + self.assertEquals(message, parsed_message) + + def testPrintAllFields(self): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'text_format_unittest_data_oneof_implemented.txt') + + def testPrintAllFieldsPointy(self): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros( + text_format.MessageToString(message, pointy_brackets=True)), + 'text_format_unittest_data_pointy_oneof.txt') + + def testPrintInIndexOrder(self): + message = unittest_pb2.TestFieldOrderings() + message.my_string = '115' + message.my_int = 101 + message.my_float = 111 + message.optional_nested_message.oo = 0 + message.optional_nested_message.bb = 1 + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString( + message, use_index_order=True)), + 'my_string: \"115\"\nmy_int: 101\nmy_float: 111\n' + 'optional_nested_message {\n oo: 0\n bb: 1\n}\n') + self.CompareToGoldenText( + self.RemoveRedundantZeros(text_format.MessageToString( + message)), + 'my_int: 101\nmy_string: \"115\"\nmy_float: 111\n' + 'optional_nested_message {\n bb: 1\n oo: 0\n}\n') + + def testMergeLinesGolden(self): + opened = self.ReadGolden('text_format_unittest_data.txt') + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.MergeLines(opened, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEqual(message, parsed_message) + + def testParseLinesGolden(self): + opened = self.ReadGolden('text_format_unittest_data.txt') + parsed_message = unittest_pb2.TestAllTypes() + r = text_format.ParseLines(opened, parsed_message) + self.assertIs(r, parsed_message) + + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.assertEquals(message, parsed_message) + + +# Tests of proto2-only features (MessageSet and extensions). +class Proto2Tests(TextFormatBase): + + def testPrintMessageSet(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + self.CompareToGoldenText( + text_format.MessageToString(message), + 'message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + + def testPrintMessageSetAsOneLine(self): + message = unittest_mset_pb2.TestMessageSetContainer() + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + message.message_set.Extensions[ext1].i = 23 + message.message_set.Extensions[ext2].str = 'foo' + self.CompareToGoldenText( + text_format.MessageToString(message, as_one_line=True), + 'message_set {' + ' [protobuf_unittest.TestMessageSetExtension1] {' + ' i: 23' + ' }' + ' [protobuf_unittest.TestMessageSetExtension2] {' + ' str: \"foo\"' + ' }' + ' }') + + def testParseMessageSet(self): + message = unittest_pb2.TestAllTypes() + text = ('repeated_uint64: 1\n' + 'repeated_uint64: 2\n') + text_format.Parse(text, message) + self.assertEqual(1, message.repeated_uint64[0]) + self.assertEqual(2, message.repeated_uint64[1]) + + message = unittest_mset_pb2.TestMessageSetContainer() + text = ('message_set {\n' + ' [protobuf_unittest.TestMessageSetExtension1] {\n' + ' i: 23\n' + ' }\n' + ' [protobuf_unittest.TestMessageSetExtension2] {\n' + ' str: \"foo\"\n' + ' }\n' + '}\n') + text_format.Parse(text, message) + ext1 = unittest_mset_pb2.TestMessageSetExtension1.message_set_extension + ext2 = unittest_mset_pb2.TestMessageSetExtension2.message_set_extension + self.assertEquals(23, message.message_set.Extensions[ext1].i) + self.assertEquals('foo', message.message_set.Extensions[ext2].str) + + def testPrintAllExtensions(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString(message)), + 'text_format_unittest_extensions_data.txt') + + def testPrintAllExtensionsPointy(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros(text_format.MessageToString( + message, pointy_brackets=True)), + 'text_format_unittest_extensions_data_pointy.txt') + + def testParseGoldenExtensions(self): + golden_text = '\n'.join(self.ReadGolden( + 'text_format_unittest_extensions_data.txt')) + parsed_message = unittest_pb2.TestAllExtensions() + text_format.Parse(golden_text, parsed_message) + + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + self.assertEquals(message, parsed_message) + + def testParseAllExtensions(self): + message = unittest_pb2.TestAllExtensions() + test_util.SetAllExtensions(message) + ascii_text = text_format.MessageToString(message) + + parsed_message = unittest_pb2.TestAllExtensions() + text_format.Parse(ascii_text, parsed_message) + self.assertEqual(message, parsed_message) + + def testParseBadExtension(self): + message = unittest_pb2.TestAllExtensions() + text = '[unknown_extension]: 8\n' self.assertRaisesWithLiteralMatch( text_format.ParseError, - ('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" ' - 'should not have multiple "bb" fields.'), + '1:2 : Extension "unknown_extension" not registered.', + text_format.Parse, text, message) + message = unittest_pb2.TestAllTypes() + self.assertRaisesWithLiteralMatch( + text_format.ParseError, + ('1:2 : Message type "protobuf_unittest.TestAllTypes" does not have ' + 'extensions.'), text_format.Parse, text, message) def testMergeDuplicateExtensionScalars(self): @@ -572,32 +600,25 @@ class TextFormatTest(basetest.TestCase): '"protobuf_unittest.optional_int32_extension" extensions.'), text_format.Parse, text, message) - def testParseLinesGolden(self): - opened = self.ReadGolden('text_format_unittest_data.txt') - parsed_message = unittest_pb2.TestAllTypes() - r = text_format.ParseLines(opened, parsed_message) - self.assertIs(r, parsed_message) - + def testParseDuplicateNestedMessageScalars(self): message = unittest_pb2.TestAllTypes() - test_util.SetAllFields(message) - self.assertEquals(message, parsed_message) - - def testMergeLinesGolden(self): - opened = self.ReadGolden('text_format_unittest_data.txt') - parsed_message = unittest_pb2.TestAllTypes() - r = text_format.MergeLines(opened, parsed_message) - self.assertIs(r, parsed_message) + text = ('optional_nested_message { bb: 1 } ' + 'optional_nested_message { bb: 2 }') + self.assertRaisesWithLiteralMatch( + text_format.ParseError, + ('1:65 : Message type "protobuf_unittest.TestAllTypes.NestedMessage" ' + 'should not have multiple "bb" fields.'), + text_format.Parse, text, message) + def testParseDuplicateScalars(self): message = unittest_pb2.TestAllTypes() - test_util.SetAllFields(message) - self.assertEqual(message, parsed_message) - - def testParseOneof(self): - m = unittest_pb2.TestAllTypes() - m.oneof_uint32 = 11 - m2 = unittest_pb2.TestAllTypes() - text_format.Parse(text_format.MessageToString(m), m2) - self.assertEqual('oneof_uint32', m2.WhichOneof('oneof_field')) + text = ('optional_int32: 42 ' + 'optional_int32: 67') + self.assertRaisesWithLiteralMatch( + text_format.ParseError, + ('1:36 : Message type "protobuf_unittest.TestAllTypes" should not ' + 'have multiple "optional_int32" fields.'), + text_format.Parse, text, message) class TokenizerTest(basetest.TestCase): diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py index 118725da..76c056c4 100755 --- a/python/google/protobuf/internal/type_checkers.py +++ b/python/google/protobuf/internal/type_checkers.py @@ -59,6 +59,8 @@ from google.protobuf import descriptor _FieldDescriptor = descriptor.FieldDescriptor +def SupportsOpenEnums(field_descriptor): + return field_descriptor.containing_type.syntax == "proto3" def GetTypeChecker(field): """Returns a type checker for a message field of the specified types. @@ -74,7 +76,11 @@ def GetTypeChecker(field): field.type == _FieldDescriptor.TYPE_STRING): return UnicodeValueChecker() if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: - return EnumValueChecker(field.enum_type) + if SupportsOpenEnums(field): + # When open enums are supported, any int32 can be assigned. + return _VALUE_CHECKERS[_FieldDescriptor.CPPTYPE_INT32] + else: + return EnumValueChecker(field.enum_type) return _VALUE_CHECKERS[field.cpp_type] diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py index a4dc1f7c..59f9ae4c 100755 --- a/python/google/protobuf/internal/unknown_fields_test.py +++ b/python/google/protobuf/internal/unknown_fields_test.py @@ -38,6 +38,7 @@ __author__ = 'bohdank@google.com (Bohdan Koval)' from google.apputils import basetest from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 +from google.protobuf import unittest_proto3_arena_pb2 from google.protobuf.internal import api_implementation from google.protobuf.internal import encoder from google.protobuf.internal import missing_enum_values_pb2 @@ -45,10 +46,81 @@ from google.protobuf.internal import test_util from google.protobuf.internal import type_checkers +class UnknownFieldsTest(basetest.TestCase): + + def setUp(self): + self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR + self.all_fields = unittest_pb2.TestAllTypes() + test_util.SetAllFields(self.all_fields) + self.all_fields_data = self.all_fields.SerializeToString() + self.empty_message = unittest_pb2.TestEmptyMessage() + self.empty_message.ParseFromString(self.all_fields_data) + + def testSerialize(self): + data = self.empty_message.SerializeToString() + + # Don't use assertEqual because we don't want to dump raw binary data to + # stdout. + self.assertTrue(data == self.all_fields_data) + + def testSerializeProto3(self): + # Verify that proto3 doesn't preserve unknown fields. + message = unittest_proto3_arena_pb2.TestEmptyMessage() + message.ParseFromString(self.all_fields_data) + self.assertEqual(0, len(message.SerializeToString())) + + def testByteSize(self): + self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize()) + + def testListFields(self): + # Make sure ListFields doesn't return unknown fields. + self.assertEqual(0, len(self.empty_message.ListFields())) + + def testSerializeMessageSetWireFormatUnknownExtension(self): + # Create a message using the message set wire format with an unknown + # message. + raw = unittest_mset_pb2.RawMessageSet() + + # Add an unknown extension. + item = raw.item.add() + item.type_id = 1545009 + message1 = unittest_mset_pb2.TestMessageSetExtension1() + message1.i = 12345 + item.message = message1.SerializeToString() + + serialized = raw.SerializeToString() + + # Parse message using the message set wire format. + proto = unittest_mset_pb2.TestMessageSet() + proto.MergeFromString(serialized) + + # Verify that the unknown extension is serialized unchanged + reserialized = proto.SerializeToString() + new_raw = unittest_mset_pb2.RawMessageSet() + new_raw.MergeFromString(reserialized) + self.assertEqual(raw, new_raw) + + # C++ implementation for proto2 does not currently take into account unknown + # fields when checking equality. + # + # TODO(haberman): fix this. + @basetest.unittest.skipIf( + api_implementation.Type() == 'cpp' and api_implementation.Version() == 2, + 'C++ implementation does not expose unknown fields to Python') + def testEquals(self): + message = unittest_pb2.TestEmptyMessage() + message.ParseFromString(self.all_fields_data) + self.assertEqual(self.empty_message, message) + + self.all_fields.ClearField('optional_string') + message.ParseFromString(self.all_fields.SerializeToString()) + self.assertNotEqual(self.empty_message, message) + + @basetest.unittest.skipIf( api_implementation.Type() == 'cpp' and api_implementation.Version() == 2, 'C++ implementation does not expose unknown fields to Python') -class UnknownFieldsTest(basetest.TestCase): +class UnknownFieldsAccessorsTest(basetest.TestCase): def setUp(self): self.descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR @@ -98,13 +170,6 @@ class UnknownFieldsTest(basetest.TestCase): value = self.GetField('optionalgroup') self.assertEqual(self.all_fields.optionalgroup, value) - def testSerialize(self): - data = self.empty_message.SerializeToString() - - # Don't use assertEqual because we don't want to dump raw binary data to - # stdout. - self.assertTrue(data == self.all_fields_data) - def testCopyFrom(self): message = unittest_pb2.TestEmptyMessage() message.CopyFrom(self.empty_message) @@ -132,51 +197,12 @@ class UnknownFieldsTest(basetest.TestCase): self.empty_message.Clear() self.assertEqual(0, len(self.empty_message._unknown_fields)) - def testByteSize(self): - self.assertEqual(self.all_fields.ByteSize(), self.empty_message.ByteSize()) - def testUnknownExtensions(self): message = unittest_pb2.TestEmptyMessageWithExtensions() message.ParseFromString(self.all_fields_data) self.assertEqual(self.empty_message._unknown_fields, message._unknown_fields) - def testListFields(self): - # Make sure ListFields doesn't return unknown fields. - self.assertEqual(0, len(self.empty_message.ListFields())) - - def testSerializeMessageSetWireFormatUnknownExtension(self): - # Create a message using the message set wire format with an unknown - # message. - raw = unittest_mset_pb2.RawMessageSet() - - # Add an unknown extension. - item = raw.item.add() - item.type_id = 1545009 - message1 = unittest_mset_pb2.TestMessageSetExtension1() - message1.i = 12345 - item.message = message1.SerializeToString() - - serialized = raw.SerializeToString() - - # Parse message using the message set wire format. - proto = unittest_mset_pb2.TestMessageSet() - proto.MergeFromString(serialized) - - # Verify that the unknown extension is serialized unchanged - reserialized = proto.SerializeToString() - new_raw = unittest_mset_pb2.RawMessageSet() - new_raw.MergeFromString(reserialized) - self.assertEqual(raw, new_raw) - - def testEquals(self): - message = unittest_pb2.TestEmptyMessage() - message.ParseFromString(self.all_fields_data) - self.assertEqual(self.empty_message, message) - - self.all_fields.ClearField('optional_string') - message.ParseFromString(self.all_fields.SerializeToString()) - self.assertNotEqual(self.empty_message, message) @basetest.unittest.skipIf( diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 7343c0b7..d9b90ddb 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -31,10 +31,15 @@ // Author: petar@google.com (Petar Petrov) #include +#include #include +#include #include +#include #include +#include +#include #include #include @@ -42,64 +47,928 @@ #if PY_MAJOR_VERSION >= 3 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize + #define PyString_Check PyUnicode_Check + #define PyString_InternFromString PyUnicode_InternFromString #define PyInt_FromLong PyLong_FromLong + #define PyInt_FromSize_t PyLong_FromSize_t #if PY_VERSION_HEX < 0x03030000 #error "Python 3.0 - 3.2 are not supported." - #else - #define PyString_AsString(ob) \ - (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob)) #endif + #define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob)? \ + ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ + PyBytes_AsStringAndSize(ob, (charpp), (sizep))) #endif namespace google { namespace protobuf { namespace python { +PyObject* PyString_FromCppString(const string& str) { + return PyString_FromStringAndSize(str.c_str(), str.size()); +} + +// Check that the calling Python code is the global scope of a _pb2.py module. +// This function is used to support the current code generated by the proto +// compiler, which creates descriptors, then update some properties. +// For example: +// message_descriptor = Descriptor( +// name='Message', +// fields = [FieldDescriptor(name='field')] +// message_descriptor.fields[0].containing_type = message_descriptor +// +// This code is still executed, but the descriptors now have no other storage +// than the (const) C++ pointer, and are immutable. +// So we let this code pass, by simply ignoring the new value. +// +// From user code, descriptors still look immutable. +// +// TODO(amauryfa): Change the proto2 compiler to remove the assignments, and +// remove this hack. +bool _CalledFromGeneratedFile(int stacklevel) { + PyThreadState *state = PyThreadState_GET(); + if (state == NULL) { + return false; + } + PyFrameObject* frame = state->frame; + if (frame == NULL) { + return false; + } + while (stacklevel-- > 0) { + frame = frame->f_back; + if (frame == NULL) { + return false; + } + } + if (frame->f_globals != frame->f_locals) { + // Not at global module scope + return false; + } + + if (frame->f_code->co_filename == NULL) { + return false; + } + char* filename; + Py_ssize_t filename_size; + if (PyString_AsStringAndSize(frame->f_code->co_filename, + &filename, &filename_size) < 0) { + // filename is not a string. + PyErr_Clear(); + return false; + } + if (filename_size < 7) { + // filename is too short. + return false; + } + if (strcmp(&filename[filename_size - 7], "_pb2.py") != 0) { + // Filename is not ending with _pb2. + return false; + } + return true; +} + +// If the calling code is not a _pb2.py file, raise AttributeError. +// To be used in attribute setters. +static int CheckCalledFromGeneratedFile(const char* attr_name) { + if (_CalledFromGeneratedFile(0)) { + return 0; + } + PyErr_Format(PyExc_AttributeError, + "attribute is not writable: %s", attr_name); + return -1; +} + + +#ifndef PyVarObject_HEAD_INIT +#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, +#endif +#ifndef Py_TYPE +#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) +#endif + + +// Helper functions for descriptor objects. + +// Converts options into a Python protobuf, and cache the result. +// +// This is a bit tricky because options can contain extension fields defined in +// the same proto file. In this case the options parsed from the serialized_pb +// have unkown fields, and we need to parse them again. +// +// Always returns a new reference. +template +static PyObject* GetOrBuildOptions(const DescriptorClass *descriptor) { + hash_map* descriptor_options = + GetDescriptorPool()->descriptor_options; + // First search in the cache. + if (descriptor_options->find(descriptor) != descriptor_options->end()) { + PyObject *value = (*descriptor_options)[descriptor]; + Py_INCREF(value); + return value; + } + + // Build the Options object: get its Python class, and make a copy of the C++ + // read-only instance. + const Message& options(descriptor->options()); + const Descriptor *message_type = options.GetDescriptor(); + PyObject* message_class(cdescriptor_pool::GetMessageClass( + GetDescriptorPool(), message_type)); + if (message_class == NULL) { + PyErr_Format(PyExc_TypeError, "Could not retrieve class for Options: %s", + message_type->full_name().c_str()); + return NULL; + } + ScopedPyObjectPtr value(PyEval_CallObject(message_class, NULL)); + if (value == NULL) { + return NULL; + } + CMessage* cmsg = reinterpret_cast(value.get()); + + const Reflection* reflection = options.GetReflection(); + const UnknownFieldSet& unknown_fields(reflection->GetUnknownFields(options)); + if (unknown_fields.empty()) { + cmsg->message->CopyFrom(options); + } else { + // Reparse options string! XXX call cmessage::MergeFromString + string serialized; + options.SerializeToString(&serialized); + io::CodedInputStream input( + reinterpret_cast(serialized.c_str()), serialized.size()); + input.SetExtensionRegistry(GetDescriptorPool()->pool, + cmessage::GetMessageFactory()); + bool success = cmsg->message->MergePartialFromCodedStream(&input); + if (!success) { + PyErr_Format(PyExc_ValueError, "Error parsing Options message"); + return NULL; + } + } + + // Cache the result. + Py_INCREF(value); + (*GetDescriptorPool()->descriptor_options)[descriptor] = value.get(); + + return value.release(); +} + +// Copy the C++ descriptor to a Python message. +// The Python message is an instance of descriptor_pb2.DescriptorProto +// or similar. +template +static PyObject* CopyToPythonProto(const DescriptorClass *descriptor, + PyObject *target) { + const Descriptor* self_descriptor = + DescriptorProtoClass::default_instance().GetDescriptor(); + CMessage* message = reinterpret_cast(target); + if (!PyObject_TypeCheck(target, &CMessage_Type) || + message->message->GetDescriptor() != self_descriptor) { + PyErr_Format(PyExc_TypeError, "Not a %s message", + self_descriptor->full_name().c_str()); + return NULL; + } + cmessage::AssureWritable(message); + DescriptorProtoClass* descriptor_message = + static_cast(message->message); + descriptor->CopyTo(descriptor_message); + Py_RETURN_NONE; +} + +// All Descriptors classes share the same memory layout. +typedef struct PyBaseDescriptor { + PyObject_HEAD + + // Pointer to the C++ proto2 descriptor. + // Like all descriptors, it is owned by the global DescriptorPool. + const void* descriptor; +} PyBaseDescriptor; + + +// FileDescriptor structure "inherits" from the base descriptor. +typedef struct PyFileDescriptor { + PyBaseDescriptor base; + + // The cached version of serialized pb. Either NULL, or a Bytes string. + // We own the reference. + PyObject *serialized_pb; +} PyFileDescriptor; + + +namespace descriptor { + +// Creates or retrieve a Python descriptor of the specified type. +// Objects are interned: the same descriptor will return the same object if it +// was kept alive. +// Always return a new reference. +PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor) { + if (descriptor == NULL) { + PyErr_BadInternalCall(); + return NULL; + } + + // See if the object is in the map of interned descriptors + hash_map::iterator it = + GetDescriptorPool()->interned_descriptors->find(descriptor); + if (it != GetDescriptorPool()->interned_descriptors->end()) { + GOOGLE_DCHECK(Py_TYPE(it->second) == type); + Py_INCREF(it->second); + return it->second; + } + // Create a new descriptor object + PyBaseDescriptor* py_descriptor = PyObject_New( + PyBaseDescriptor, type); + if (py_descriptor == NULL) { + return NULL; + } + py_descriptor->descriptor = descriptor; + // and cache it. + GetDescriptorPool()->interned_descriptors->insert( + std::make_pair(descriptor, reinterpret_cast(py_descriptor))); + + return reinterpret_cast(py_descriptor); +} + +static void Dealloc(PyBaseDescriptor* self) { + // Remove from interned dictionary + GetDescriptorPool()->interned_descriptors->erase(self->descriptor); + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +static PyGetSetDef Getters[] = { + {NULL} +}; + +PyTypeObject PyBaseDescriptor_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "google.protobuf.internal." + "_message.DescriptorBase", // tp_name + sizeof(PyBaseDescriptor), // tp_basicsize + 0, // tp_itemsize + (destructor)Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "Descriptors base class", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + Getters, // tp_getset +}; + +} // namespace descriptor + +const void* PyDescriptor_AsVoidPtr(PyObject* obj) { + if (!PyObject_TypeCheck(obj, &descriptor::PyBaseDescriptor_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a BaseDescriptor"); + return NULL; + } + return reinterpret_cast(obj)->descriptor; +} + +namespace message_descriptor { + +// Unchecked accessor to the C++ pointer. +static const Descriptor* _GetDescriptor(PyBaseDescriptor* self) { + return reinterpret_cast(self->descriptor); +} + +static PyObject* GetName(PyBaseDescriptor* self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->name()); +} + +static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->full_name()); +} + +static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { + return PyFileDescriptor_New(_GetDescriptor(self)->file()); +} + +static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) { + PyObject* concrete_class(cdescriptor_pool::GetMessageClass( + GetDescriptorPool(), _GetDescriptor(self))); + Py_XINCREF(concrete_class); + return concrete_class; +} + +static int SetConcreteClass(PyBaseDescriptor *self, PyObject *value, + void *closure) { + // This attribute is also set from reflection.py. Check that it's actually a + // no-op. + if (value != cdescriptor_pool::GetMessageClass( + GetDescriptorPool(), _GetDescriptor(self))) { + PyErr_SetString(PyExc_AttributeError, "Cannot change _concrete_class"); + } + return 0; +} + +static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) { + return NewMessageFieldsByName(_GetDescriptor(self)); +} + +static PyObject* GetFieldsByNumber(PyBaseDescriptor* self, void *closure) { + return NewMessageFieldsByNumber(_GetDescriptor(self)); +} + +static PyObject* GetFieldsSeq(PyBaseDescriptor* self, void *closure) { + return NewMessageFieldsSeq(_GetDescriptor(self)); +} + +static PyObject* GetNestedTypesByName(PyBaseDescriptor* self, void *closure) { + return NewMessageNestedTypesByName(_GetDescriptor(self)); +} + +static PyObject* GetNestedTypesSeq(PyBaseDescriptor* self, void *closure) { + return NewMessageNestedTypesSeq(_GetDescriptor(self)); +} + +static PyObject* GetExtensionsByName(PyBaseDescriptor* self, void *closure) { + return NewMessageExtensionsByName(_GetDescriptor(self)); +} + +static PyObject* GetExtensions(PyBaseDescriptor* self, void *closure) { + return NewMessageExtensionsSeq(_GetDescriptor(self)); +} + +static PyObject* GetEnumsSeq(PyBaseDescriptor* self, void *closure) { + return NewMessageEnumsSeq(_GetDescriptor(self)); +} + +static PyObject* GetEnumTypesByName(PyBaseDescriptor* self, void *closure) { + return NewMessageEnumsByName(_GetDescriptor(self)); +} + +static PyObject* GetEnumValuesByName(PyBaseDescriptor* self, void *closure) { + return NewMessageEnumValuesByName(_GetDescriptor(self)); +} + +static PyObject* GetOneofsByName(PyBaseDescriptor* self, void *closure) { + return NewMessageOneofsByName(_GetDescriptor(self)); +} + +static PyObject* GetOneofsSeq(PyBaseDescriptor* self, void *closure) { + return NewMessageOneofsSeq(_GetDescriptor(self)); +} + +static PyObject* IsExtendable(PyBaseDescriptor *self, void *closure) { + if (_GetDescriptor(self)->extension_range_count() > 0) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { + const Descriptor* containing_type = + _GetDescriptor(self)->containing_type(); + if (containing_type) { + return PyMessageDescriptor_New(containing_type); + } else { + Py_RETURN_NONE; + } +} + +static int SetContainingType(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("containing_type"); +} + +static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { + const MessageOptions& options(_GetDescriptor(self)->options()); + if (&options != &MessageOptions::default_instance()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} +static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("has_options"); +} + +static PyObject* GetOptions(PyBaseDescriptor *self) { + return GetOrBuildOptions(_GetDescriptor(self)); +} + +static int SetOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_options"); +} + +static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { + return CopyToPythonProto(_GetDescriptor(self), target); +} + +static PyObject* EnumValueName(PyBaseDescriptor *self, PyObject *args) { + const char *enum_name; + int number; + if (!PyArg_ParseTuple(args, "si", &enum_name, &number)) + return NULL; + const EnumDescriptor *enum_type = + _GetDescriptor(self)->FindEnumTypeByName(enum_name); + if (enum_type == NULL) { + PyErr_SetString(PyExc_KeyError, enum_name); + return NULL; + } + const EnumValueDescriptor *enum_value = + enum_type->FindValueByNumber(number); + if (enum_value == NULL) { + PyErr_Format(PyExc_KeyError, "%d", number); + return NULL; + } + return PyString_FromCppString(enum_value->name()); +} + +static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) { + return PyString_InternFromString( + FileDescriptor::SyntaxName(_GetDescriptor(self)->file()->syntax())); +} + +static PyGetSetDef Getters[] = { + { C("name"), (getter)GetName, NULL, "Last name", NULL}, + { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, + { C("_concrete_class"), (getter)GetConcreteClass, (setter)SetConcreteClass, "concrete class", NULL}, + { C("file"), (getter)GetFile, NULL, "File descriptor", NULL}, + + { C("fields"), (getter)GetFieldsSeq, NULL, "Fields sequence", NULL}, + { C("fields_by_name"), (getter)GetFieldsByName, NULL, "Fields by name", NULL}, + { C("fields_by_number"), (getter)GetFieldsByNumber, NULL, "Fields by number", NULL}, + { C("nested_types"), (getter)GetNestedTypesSeq, NULL, "Nested types sequence", NULL}, + { C("nested_types_by_name"), (getter)GetNestedTypesByName, NULL, "Nested types by name", NULL}, + { C("extensions"), (getter)GetExtensions, NULL, "Extensions Sequence", NULL}, + { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL}, + { C("enum_types"), (getter)GetEnumsSeq, NULL, "Enum sequence", NULL}, + { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enum types by name", NULL}, + { C("enum_values_by_name"), (getter)GetEnumValuesByName, NULL, "Enum values by name", NULL}, + { C("oneofs_by_name"), (getter)GetOneofsByName, NULL, "Oneofs by name", NULL}, + { C("oneofs"), (getter)GetOneofsSeq, NULL, "Oneofs by name", NULL}, + { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL}, + { C("is_extendable"), (getter)IsExtendable, (setter)NULL, NULL, NULL}, + { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, + { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, + { C("syntax"), (getter)GetSyntax, (setter)NULL, "Syntax", NULL}, + {NULL} +}; + +static PyMethodDef Methods[] = { + { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, }, + { "CopyToProto", (PyCFunction)CopyToProto, METH_O, }, + { "EnumValueName", (PyCFunction)EnumValueName, METH_VARARGS, }, + {NULL} +}; + +} // namespace message_descriptor + +PyTypeObject PyMessageDescriptor_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + C("google.protobuf.internal." + "_message.MessageDescriptor"), // tp_name + sizeof(PyBaseDescriptor), // tp_basicsize + 0, // tp_itemsize + 0, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + C("A Message Descriptor"), // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + message_descriptor::Methods, // tp_methods + 0, // tp_members + message_descriptor::Getters, // tp_getset + &descriptor::PyBaseDescriptor_Type, // tp_base +}; + +PyObject* PyMessageDescriptor_New( + const Descriptor* message_descriptor) { + return descriptor::NewInternedDescriptor( + &PyMessageDescriptor_Type, message_descriptor); +} + +const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) { + if (!PyObject_TypeCheck(obj, &PyMessageDescriptor_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a MessageDescriptor"); + return NULL; + } + return reinterpret_cast( + reinterpret_cast(obj)->descriptor); +} + +namespace field_descriptor { + +// Unchecked accessor to the C++ pointer. +static const FieldDescriptor* _GetDescriptor( + PyBaseDescriptor *self) { + return reinterpret_cast(self->descriptor); +} + +static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->full_name()); +} + +static PyObject* GetName(PyBaseDescriptor *self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->name()); +} + +static PyObject* GetType(PyBaseDescriptor *self, void *closure) { + return PyInt_FromLong(_GetDescriptor(self)->type()); +} + +static PyObject* GetCppType(PyBaseDescriptor *self, void *closure) { + return PyInt_FromLong(_GetDescriptor(self)->cpp_type()); +} + +static PyObject* GetLabel(PyBaseDescriptor *self, void *closure) { + return PyInt_FromLong(_GetDescriptor(self)->label()); +} + +static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) { + return PyInt_FromLong(_GetDescriptor(self)->number()); +} + +static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { + return PyInt_FromLong(_GetDescriptor(self)->index()); +} + +static PyObject* GetID(PyBaseDescriptor *self, void *closure) { + return PyLong_FromVoidPtr(self); +} + +static PyObject* IsExtension(PyBaseDescriptor *self, void *closure) { + return PyBool_FromLong(_GetDescriptor(self)->is_extension()); +} + +static PyObject* HasDefaultValue(PyBaseDescriptor *self, void *closure) { + return PyBool_FromLong(_GetDescriptor(self)->has_default_value()); +} + +static PyObject* GetDefaultValue(PyBaseDescriptor *self, void *closure) { + PyObject *result; + + switch (_GetDescriptor(self)->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: { + int32 value = _GetDescriptor(self)->default_value_int32(); + result = PyInt_FromLong(value); + break; + } + case FieldDescriptor::CPPTYPE_INT64: { + int64 value = _GetDescriptor(self)->default_value_int64(); + result = PyLong_FromLongLong(value); + break; + } + case FieldDescriptor::CPPTYPE_UINT32: { + uint32 value = _GetDescriptor(self)->default_value_uint32(); + result = PyInt_FromSize_t(value); + break; + } + case FieldDescriptor::CPPTYPE_UINT64: { + uint64 value = _GetDescriptor(self)->default_value_uint64(); + result = PyLong_FromUnsignedLongLong(value); + break; + } + case FieldDescriptor::CPPTYPE_FLOAT: { + float value = _GetDescriptor(self)->default_value_float(); + result = PyFloat_FromDouble(value); + break; + } + case FieldDescriptor::CPPTYPE_DOUBLE: { + double value = _GetDescriptor(self)->default_value_double(); + result = PyFloat_FromDouble(value); + break; + } + case FieldDescriptor::CPPTYPE_BOOL: { + bool value = _GetDescriptor(self)->default_value_bool(); + result = PyBool_FromLong(value); + break; + } + case FieldDescriptor::CPPTYPE_STRING: { + string value = _GetDescriptor(self)->default_value_string(); + result = ToStringObject(_GetDescriptor(self), value); + break; + } + case FieldDescriptor::CPPTYPE_ENUM: { + const EnumValueDescriptor* value = + _GetDescriptor(self)->default_value_enum(); + result = PyInt_FromLong(value->number()); + break; + } + default: + PyErr_Format(PyExc_NotImplementedError, "default value for %s", + _GetDescriptor(self)->full_name().c_str()); + return NULL; + } + return result; +} + +static PyObject* GetCDescriptor(PyObject *self, void *closure) { + Py_INCREF(self); + return self; +} + +static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) { + const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type(); + if (enum_type) { + return PyEnumDescriptor_New(enum_type); + } else { + Py_RETURN_NONE; + } +} + +static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) { + return CheckCalledFromGeneratedFile("enum_type"); +} + +static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) { + const Descriptor* message_type = _GetDescriptor(self)->message_type(); + if (message_type) { + return PyMessageDescriptor_New(message_type); + } else { + Py_RETURN_NONE; + } +} + +static int SetMessageType(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("message_type"); +} + +static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { + const Descriptor* containing_type = + _GetDescriptor(self)->containing_type(); + if (containing_type) { + return PyMessageDescriptor_New(containing_type); + } else { + Py_RETURN_NONE; + } +} + +static int SetContainingType(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("containing_type"); +} + +static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) { + const Descriptor* extension_scope = + _GetDescriptor(self)->extension_scope(); + if (extension_scope) { + return PyMessageDescriptor_New(extension_scope); + } else { + Py_RETURN_NONE; + } +} + +static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) { + const OneofDescriptor* containing_oneof = + _GetDescriptor(self)->containing_oneof(); + if (containing_oneof) { + return PyOneofDescriptor_New(containing_oneof); + } else { + Py_RETURN_NONE; + } +} + +static int SetContainingOneof(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("containing_oneof"); +} + +static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { + const FieldOptions& options(_GetDescriptor(self)->options()); + if (&options != &FieldOptions::default_instance()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} +static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("has_options"); +} + +static PyObject* GetOptions(PyBaseDescriptor *self) { + return GetOrBuildOptions(_GetDescriptor(self)); +} + +static int SetOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_options"); +} + + +static PyGetSetDef Getters[] = { + { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, + { C("name"), (getter)GetName, NULL, "Unqualified name", NULL}, + { C("type"), (getter)GetType, NULL, "C++ Type", NULL}, + { C("cpp_type"), (getter)GetCppType, NULL, "C++ Type", NULL}, + { C("label"), (getter)GetLabel, NULL, "Label", NULL}, + { C("number"), (getter)GetNumber, NULL, "Number", NULL}, + { C("index"), (getter)GetIndex, NULL, "Index", NULL}, + { C("default_value"), (getter)GetDefaultValue, NULL, "Default Value", NULL}, + { C("has_default_value"), (getter)HasDefaultValue, NULL, NULL, NULL}, + { C("is_extension"), (getter)IsExtension, NULL, "ID", NULL}, + { C("id"), (getter)GetID, NULL, "ID", NULL}, + { C("_cdescriptor"), (getter)GetCDescriptor, NULL, "HAACK REMOVE ME", NULL}, + + { C("message_type"), (getter)GetMessageType, (setter)SetMessageType, "Message type", NULL}, + { C("enum_type"), (getter)GetEnumType, (setter)SetEnumType, "Enum type", NULL}, + { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL}, + { C("extension_scope"), (getter)GetExtensionScope, (setter)NULL, "Extension scope", NULL}, + { C("containing_oneof"), (getter)GetContainingOneof, (setter)SetContainingOneof, "Containing oneof", NULL}, + { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, + { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, + {NULL} +}; + +static PyMethodDef Methods[] = { + { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, }, + {NULL} +}; + +} // namespace field_descriptor + +PyTypeObject PyFieldDescriptor_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + C("google.protobuf.internal." + "_message.FieldDescriptor"), // tp_name + sizeof(PyBaseDescriptor), // tp_basicsize + 0, // tp_itemsize + 0, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + C("A Field Descriptor"), // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + field_descriptor::Methods, // tp_methods + 0, // tp_members + field_descriptor::Getters, // tp_getset + &descriptor::PyBaseDescriptor_Type, // tp_base +}; -#ifndef PyVarObject_HEAD_INIT -#define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, -#endif -#ifndef Py_TYPE -#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type) -#endif +PyObject* PyFieldDescriptor_New( + const FieldDescriptor* field_descriptor) { + return descriptor::NewInternedDescriptor( + &PyFieldDescriptor_Type, field_descriptor); +} + +const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) { + if (!PyObject_TypeCheck(obj, &PyFieldDescriptor_Type)) { + PyErr_SetString(PyExc_TypeError, "Not a FieldDescriptor"); + return NULL; + } + return reinterpret_cast( + reinterpret_cast(obj)->descriptor); +} +namespace enum_descriptor { -static google::protobuf::DescriptorPool* g_descriptor_pool = NULL; +// Unchecked accessor to the C++ pointer. +static const EnumDescriptor* _GetDescriptor( + PyBaseDescriptor *self) { + return reinterpret_cast(self->descriptor); +} -namespace cmessage_descriptor { +static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->full_name()); +} -static void Dealloc(CMessageDescriptor* self) { - Py_TYPE(self)->tp_free(reinterpret_cast(self)); +static PyObject* GetName(PyBaseDescriptor *self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->name()); +} + +static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { + return PyFileDescriptor_New(_GetDescriptor(self)->file()); +} + +static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) { + return NewEnumValuesByName(_GetDescriptor(self)); +} + +static PyObject* GetEnumvaluesByNumber(PyBaseDescriptor* self, void *closure) { + return NewEnumValuesByNumber(_GetDescriptor(self)); +} + +static PyObject* GetEnumvaluesSeq(PyBaseDescriptor* self, void *closure) { + return NewEnumValuesSeq(_GetDescriptor(self)); +} + +static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { + const Descriptor* containing_type = + _GetDescriptor(self)->containing_type(); + if (containing_type) { + return PyMessageDescriptor_New(containing_type); + } else { + Py_RETURN_NONE; + } } -static PyObject* GetFullName(CMessageDescriptor* self, void *closure) { - return PyString_FromStringAndSize( - self->descriptor->full_name().c_str(), - self->descriptor->full_name().size()); +static int SetContainingType(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("containing_type"); } -static PyObject* GetName(CMessageDescriptor *self, void *closure) { - return PyString_FromStringAndSize( - self->descriptor->name().c_str(), - self->descriptor->name().size()); + +static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { + const EnumOptions& options(_GetDescriptor(self)->options()); + if (&options != &EnumOptions::default_instance()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} +static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("has_options"); +} + +static PyObject* GetOptions(PyBaseDescriptor *self) { + return GetOrBuildOptions(_GetDescriptor(self)); +} + +static int SetOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_options"); } +static PyObject* CopyToProto(PyBaseDescriptor *self, PyObject *target) { + return CopyToPythonProto(_GetDescriptor(self), target); +} + +static PyMethodDef Methods[] = { + { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, }, + { "CopyToProto", (PyCFunction)CopyToProto, METH_O, }, + {NULL} +}; + static PyGetSetDef Getters[] = { { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, - { C("name"), (getter)GetName, NULL, "Unqualified name", NULL}, + { C("name"), (getter)GetName, NULL, "last name", NULL}, + { C("file"), (getter)GetFile, NULL, "File descriptor", NULL}, + { C("values"), (getter)GetEnumvaluesSeq, NULL, "values", NULL}, + { C("values_by_name"), (getter)GetEnumvaluesByName, NULL, "Enumvalues by name", NULL}, + { C("values_by_number"), (getter)GetEnumvaluesByNumber, NULL, "Enumvalues by number", NULL}, + + { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL}, + { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, + { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, {NULL} }; -} // namespace cmessage_descriptor +} // namespace enum_descriptor -PyTypeObject CMessageDescriptor_Type = { +PyTypeObject PyEnumDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) C("google.protobuf.internal." - "_net_proto2___python." - "CMessageDescriptor"), // tp_name - sizeof(CMessageDescriptor), // tp_basicsize + "_message.EnumDescriptor"), // tp_name + sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize - (destructor)cmessage_descriptor::Dealloc, // tp_dealloc + 0, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -115,77 +984,97 @@ PyTypeObject CMessageDescriptor_Type = { 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags - C("A Message Descriptor"), // tp_doc + C("A Enum Descriptor"), // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext - 0, // tp_methods + enum_descriptor::Methods, // tp_getset 0, // tp_members - cmessage_descriptor::Getters, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - PyType_GenericAlloc, // tp_alloc - PyType_GenericNew, // tp_new - PyObject_Del, // tp_free + enum_descriptor::Getters, // tp_getset + &descriptor::PyBaseDescriptor_Type, // tp_base }; +PyObject* PyEnumDescriptor_New( + const EnumDescriptor* enum_descriptor) { + return descriptor::NewInternedDescriptor( + &PyEnumDescriptor_Type, enum_descriptor); +} -namespace cfield_descriptor { +namespace enumvalue_descriptor { -static void Dealloc(CFieldDescriptor* self) { - Py_TYPE(self)->tp_free(reinterpret_cast(self)); +// Unchecked accessor to the C++ pointer. +static const EnumValueDescriptor* _GetDescriptor( + PyBaseDescriptor *self) { + return reinterpret_cast(self->descriptor); } -static PyObject* GetFullName(CFieldDescriptor* self, void *closure) { - return PyString_FromStringAndSize( - self->descriptor->full_name().c_str(), - self->descriptor->full_name().size()); +static PyObject* GetName(PyBaseDescriptor *self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->name()); } -static PyObject* GetName(CFieldDescriptor *self, void *closure) { - return PyString_FromStringAndSize( - self->descriptor->name().c_str(), - self->descriptor->name().size()); +static PyObject* GetNumber(PyBaseDescriptor *self, void *closure) { + return PyInt_FromLong(_GetDescriptor(self)->number()); } -static PyObject* GetCppType(CFieldDescriptor *self, void *closure) { - return PyInt_FromLong(self->descriptor->cpp_type()); +static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { + return PyInt_FromLong(_GetDescriptor(self)->index()); } -static PyObject* GetLabel(CFieldDescriptor *self, void *closure) { - return PyInt_FromLong(self->descriptor->label()); +static PyObject* GetType(PyBaseDescriptor *self, void *closure) { + return PyEnumDescriptor_New(_GetDescriptor(self)->type()); } -static PyObject* GetID(CFieldDescriptor *self, void *closure) { - return PyLong_FromVoidPtr(self); +static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { + const EnumValueOptions& options(_GetDescriptor(self)->options()); + if (&options != &EnumValueOptions::default_instance()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} +static int SetHasOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("has_options"); +} + +static PyObject* GetOptions(PyBaseDescriptor *self) { + return GetOrBuildOptions(_GetDescriptor(self)); +} + +static int SetOptions(PyBaseDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_options"); } + static PyGetSetDef Getters[] = { - { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, - { C("name"), (getter)GetName, NULL, "Unqualified name", NULL}, - { C("cpp_type"), (getter)GetCppType, NULL, "C++ Type", NULL}, - { C("label"), (getter)GetLabel, NULL, "Label", NULL}, - { C("id"), (getter)GetID, NULL, "ID", NULL}, + { C("name"), (getter)GetName, NULL, "name", NULL}, + { C("number"), (getter)GetNumber, NULL, "number", NULL}, + { C("index"), (getter)GetIndex, NULL, "index", NULL}, + { C("type"), (getter)GetType, NULL, "index", NULL}, + + { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, + { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, + {NULL} +}; + +static PyMethodDef Methods[] = { + { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, }, {NULL} }; -} // namespace cfield_descriptor +} // namespace enumvalue_descriptor -PyTypeObject CFieldDescriptor_Type = { +PyTypeObject PyEnumValueDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) C("google.protobuf.internal." - "_net_proto2___python." - "CFieldDescriptor"), // tp_name - sizeof(CFieldDescriptor), // tp_basicsize + "_message.EnumValueDescriptor"), // tp_name + sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize - (destructor)cfield_descriptor::Dealloc, // tp_dealloc + 0, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -201,304 +1090,359 @@ PyTypeObject CFieldDescriptor_Type = { 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags - C("A Field Descriptor"), // tp_doc + C("A EnumValue Descriptor"), // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare 0, // tp_weaklistoffset 0, // tp_iter 0, // tp_iternext - 0, // tp_methods + enumvalue_descriptor::Methods, // tp_methods 0, // tp_members - cfield_descriptor::Getters, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - PyType_GenericAlloc, // tp_alloc - PyType_GenericNew, // tp_new - PyObject_Del, // tp_free + enumvalue_descriptor::Getters, // tp_getset + &descriptor::PyBaseDescriptor_Type, // tp_base }; +PyObject* PyEnumValueDescriptor_New( + const EnumValueDescriptor* enumvalue_descriptor) { + return descriptor::NewInternedDescriptor( + &PyEnumValueDescriptor_Type, enumvalue_descriptor); +} + +namespace file_descriptor { + +// Unchecked accessor to the C++ pointer. +static const FileDescriptor* _GetDescriptor(PyFileDescriptor *self) { + return reinterpret_cast(self->base.descriptor); +} + +static void Dealloc(PyFileDescriptor* self) { + Py_XDECREF(self->serialized_pb); + descriptor::Dealloc(&self->base); +} + +static PyObject* GetName(PyFileDescriptor *self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->name()); +} -namespace cdescriptor_pool { +static PyObject* GetPackage(PyFileDescriptor *self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->package()); +} -PyDescriptorPool* NewDescriptorPool() { - PyDescriptorPool* cdescriptor_pool = PyObject_New( - PyDescriptorPool, &PyDescriptorPool_Type); - if (cdescriptor_pool == NULL) { +static PyObject* GetSerializedPb(PyFileDescriptor *self, void *closure) { + PyObject *serialized_pb = self->serialized_pb; + if (serialized_pb != NULL) { + Py_INCREF(serialized_pb); + return serialized_pb; + } + FileDescriptorProto file_proto; + _GetDescriptor(self)->CopyTo(&file_proto); + string contents; + file_proto.SerializePartialToString(&contents); + self->serialized_pb = PyBytes_FromStringAndSize( + contents.c_str(), contents.size()); + if (self->serialized_pb == NULL) { return NULL; } + Py_INCREF(self->serialized_pb); + return self->serialized_pb; +} - // Build a DescriptorPool for messages only declared in Python libraries. - // generated_pool() contains all messages linked in C++ libraries, and is used - // as underlay. - cdescriptor_pool->pool = new google::protobuf::DescriptorPool( - google::protobuf::DescriptorPool::generated_pool()); +static PyObject* GetMessageTypesByName(PyFileDescriptor* self, void *closure) { + return NewFileMessageTypesByName(_GetDescriptor(self)); +} - // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same - // storage. - cdescriptor_pool->classes_by_descriptor = - new PyDescriptorPool::ClassesByMessageMap(); +static PyObject* GetEnumTypesByName(PyFileDescriptor* self, void *closure) { + return NewFileEnumTypesByName(_GetDescriptor(self)); +} - return cdescriptor_pool; +static PyObject* GetExtensionsByName(PyFileDescriptor* self, void *closure) { + return NewFileExtensionsByName(_GetDescriptor(self)); } -static void Dealloc(PyDescriptorPool* self) { - typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; - for (iterator it = self->classes_by_descriptor->begin(); - it != self->classes_by_descriptor->end(); ++it) { - Py_DECREF(it->second); - } - delete self->classes_by_descriptor; - Py_TYPE(self)->tp_free(reinterpret_cast(self)); +static PyObject* GetDependencies(PyFileDescriptor* self, void *closure) { + return NewFileDependencies(_GetDescriptor(self)); } -const google::protobuf::Descriptor* FindMessageTypeByName(PyDescriptorPool* self, - const string& name) { - return self->pool->FindMessageTypeByName(name); +static PyObject* GetPublicDependencies(PyFileDescriptor* self, void *closure) { + return NewFilePublicDependencies(_GetDescriptor(self)); } -static PyObject* NewCMessageDescriptor( - const google::protobuf::Descriptor* message_descriptor) { - CMessageDescriptor* cmessage_descriptor = PyObject_New( - CMessageDescriptor, &CMessageDescriptor_Type); - if (cmessage_descriptor == NULL) { - return NULL; +static PyObject* GetHasOptions(PyFileDescriptor *self, void *closure) { + const FileOptions& options(_GetDescriptor(self)->options()); + if (&options != &FileOptions::default_instance()) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; } - cmessage_descriptor->descriptor = message_descriptor; +} +static int SetHasOptions(PyFileDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("has_options"); +} - return reinterpret_cast(cmessage_descriptor); +static PyObject* GetOptions(PyFileDescriptor *self) { + return GetOrBuildOptions(_GetDescriptor(self)); } -static PyObject* NewCFieldDescriptor( - const google::protobuf::FieldDescriptor* field_descriptor) { - CFieldDescriptor* cfield_descriptor = PyObject_New( - CFieldDescriptor, &CFieldDescriptor_Type); - if (cfield_descriptor == NULL) { - return NULL; - } - cfield_descriptor->descriptor = field_descriptor; +static int SetOptions(PyFileDescriptor *self, PyObject *value, + void *closure) { + return CheckCalledFromGeneratedFile("_options"); +} - return reinterpret_cast(cfield_descriptor); +static PyObject* GetSyntax(PyFileDescriptor *self, void *closure) { + return PyString_InternFromString( + FileDescriptor::SyntaxName(_GetDescriptor(self)->syntax())); } -// Add a message class to our database. -const google::protobuf::Descriptor* RegisterMessageClass( - PyDescriptorPool* self, PyObject *message_class, PyObject* descriptor) { - ScopedPyObjectPtr full_message_name( - PyObject_GetAttrString(descriptor, "full_name")); - const char* full_name = PyString_AsString(full_message_name); - if (full_name == NULL) { - return NULL; - } - const Descriptor *message_descriptor = - self->pool->FindMessageTypeByName(full_name); - if (!message_descriptor) { - PyErr_Format(PyExc_TypeError, "Could not find C++ descriptor for '%s'", - full_name); - return NULL; - } - Py_INCREF(message_class); - typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; - std::pair ret = self->classes_by_descriptor->insert( - make_pair(message_descriptor, message_class)); - if (!ret.second) { - // Update case: DECREF the previous value. - Py_DECREF(ret.first->second); - ret.first->second = message_class; - } +static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) { + return CopyToPythonProto(_GetDescriptor(self), target); +} - // Also add the C++ descriptor to the Python descriptor class. - ScopedPyObjectPtr cdescriptor(NewCMessageDescriptor(message_descriptor)); - if (cdescriptor == NULL) { - return NULL; - } - if (PyObject_SetAttrString( - descriptor, "_cdescriptor", cdescriptor) < 0) { - return NULL; - } - return message_descriptor; +static PyGetSetDef Getters[] = { + { C("name"), (getter)GetName, NULL, "name", NULL}, + { C("package"), (getter)GetPackage, NULL, "package", NULL}, + { C("serialized_pb"), (getter)GetSerializedPb, NULL, NULL, NULL}, + { C("message_types_by_name"), (getter)GetMessageTypesByName, NULL, "Messages by name", NULL}, + { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enums by name", NULL}, + { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL}, + { C("dependencies"), (getter)GetDependencies, NULL, "Dependencies", NULL}, + { C("public_dependencies"), (getter)GetPublicDependencies, NULL, "Dependencies", NULL}, + + { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, + { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, + { C("syntax"), (getter)GetSyntax, (setter)NULL, "Syntax", NULL}, + {NULL} +}; + +static PyMethodDef Methods[] = { + { "GetOptions", (PyCFunction)GetOptions, METH_NOARGS, }, + { "CopyToProto", (PyCFunction)CopyToProto, METH_O, }, + {NULL} +}; + +} // namespace file_descriptor + +PyTypeObject PyFileDescriptor_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + C("google.protobuf.internal." + "_message.FileDescriptor"), // tp_name + sizeof(PyFileDescriptor), // tp_basicsize + 0, // tp_itemsize + (destructor)file_descriptor::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + C("A File Descriptor"), // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + file_descriptor::Methods, // tp_methods + 0, // tp_members + file_descriptor::Getters, // tp_getset + &descriptor::PyBaseDescriptor_Type, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + PyType_GenericAlloc, // tp_alloc + PyType_GenericNew, // tp_new + PyObject_Del, // tp_free +}; + +PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor) { + return descriptor::NewInternedDescriptor( + &PyFileDescriptor_Type, file_descriptor); } -// Retrieve the message class added to our database. -PyObject *GetMessageClass(PyDescriptorPool* self, - const Descriptor *message_descriptor) { - typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; - iterator ret = self->classes_by_descriptor->find(message_descriptor); - if (ret == self->classes_by_descriptor->end()) { - PyErr_Format(PyExc_TypeError, "No message class registered for '%s'", - message_descriptor->full_name().c_str()); +PyObject* PyFileDescriptor_NewWithPb( + const FileDescriptor* file_descriptor, PyObject *serialized_pb) { + PyObject* py_descriptor = PyFileDescriptor_New(file_descriptor); + if (py_descriptor == NULL) { return NULL; - } else { - return ret->second; } + if (serialized_pb != NULL) { + PyFileDescriptor* cfile_descriptor = + reinterpret_cast(py_descriptor); + Py_XINCREF(serialized_pb); + cfile_descriptor->serialized_pb = serialized_pb; + } + + return py_descriptor; } -PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name) { - const char* full_field_name = PyString_AsString(name); - if (full_field_name == NULL) { - return NULL; - } +namespace oneof_descriptor { - const google::protobuf::FieldDescriptor* field_descriptor = NULL; +// Unchecked accessor to the C++ pointer. +static const OneofDescriptor* _GetDescriptor( + PyBaseDescriptor *self) { + return reinterpret_cast(self->descriptor); +} - field_descriptor = self->pool->FindFieldByName(full_field_name); +static PyObject* GetName(PyBaseDescriptor* self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->name()); +} - if (field_descriptor == NULL) { - PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", - full_field_name); - return NULL; - } +static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { + return PyString_FromCppString(_GetDescriptor(self)->full_name()); +} - return NewCFieldDescriptor(field_descriptor); +static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { + return PyInt_FromLong(_GetDescriptor(self)->index()); } -PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) { - const char* full_field_name = PyString_AsString(arg); - if (full_field_name == NULL) { - return NULL; - } +static PyObject* GetFields(PyBaseDescriptor* self, void *closure) { + return NewOneofFieldsSeq(_GetDescriptor(self)); +} - const google::protobuf::FieldDescriptor* field_descriptor = - self->pool->FindExtensionByName(full_field_name); - if (field_descriptor == NULL) { - PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", - full_field_name); - return NULL; +static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { + const Descriptor* containing_type = + _GetDescriptor(self)->containing_type(); + if (containing_type) { + return PyMessageDescriptor_New(containing_type); + } else { + Py_RETURN_NONE; } - - return NewCFieldDescriptor(field_descriptor); } -static PyMethodDef Methods[] = { - { C("FindFieldByName"), - (PyCFunction)FindFieldByName, - METH_O, - C("Searches for a field descriptor by full name.") }, - { C("FindExtensionByName"), - (PyCFunction)FindExtensionByName, - METH_O, - C("Searches for extension descriptor by full name.") }, +static PyGetSetDef Getters[] = { + { C("name"), (getter)GetName, NULL, "Name", NULL}, + { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, + { C("index"), (getter)GetIndex, NULL, "Index", NULL}, + + { C("containing_type"), (getter)GetContainingType, NULL, "Containing type", NULL}, + { C("fields"), (getter)GetFields, NULL, "Fields", NULL}, {NULL} }; -} // namespace cdescriptor_pool +} // namespace oneof_descriptor -PyTypeObject PyDescriptorPool_Type = { +PyTypeObject PyOneofDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) C("google.protobuf.internal." - "_net_proto2___python." - "CFieldDescriptor"), // tp_name - sizeof(PyDescriptorPool), // tp_basicsize - 0, // tp_itemsize - (destructor)cdescriptor_pool::Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - C("A Descriptor Pool"), // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - cdescriptor_pool::Methods, // tp_methods - 0, // tp_members - 0, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - 0, // tp_alloc - 0, // tp_new - PyObject_Del, // tp_free + "_message.OneofDescriptor"), // tp_name + sizeof(PyBaseDescriptor), // tp_basicsize + 0, // tp_itemsize + 0, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + C("A Oneof Descriptor"), // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + 0, // tp_methods + 0, // tp_members + oneof_descriptor::Getters, // tp_getset + &descriptor::PyBaseDescriptor_Type, // tp_base }; +PyObject* PyOneofDescriptor_New( + const OneofDescriptor* oneof_descriptor) { + return descriptor::NewInternedDescriptor( + &PyOneofDescriptor_Type, oneof_descriptor); +} -// Collects errors that occur during proto file building to allow them to be -// propagated in the python exception instead of only living in ERROR logs. -class BuildFileErrorCollector : public google::protobuf::DescriptorPool::ErrorCollector { - public: - BuildFileErrorCollector() : error_message(""), had_errors(false) {} - - void AddError(const string& filename, const string& element_name, - const Message* descriptor, ErrorLocation location, - const string& message) { - // Replicates the logging behavior that happens in the C++ implementation - // when an error collector is not passed in. - if (!had_errors) { - error_message += - ("Invalid proto descriptor for file \"" + filename + "\":\n"); +// Add a enum values to a type dictionary. +static bool AddEnumValues(PyTypeObject *type, + const EnumDescriptor* enum_descriptor) { + for (int i = 0; i < enum_descriptor->value_count(); ++i) { + const EnumValueDescriptor* value = enum_descriptor->value(i); + ScopedPyObjectPtr obj(PyInt_FromLong(value->number())); + if (obj == NULL) { + return false; + } + if (PyDict_SetItemString(type->tp_dict, value->name().c_str(), obj) < 0) { + return false; } - // As this only happens on failure and will result in the program not - // running at all, no effort is made to optimize this string manipulation. - error_message += (" " + element_name + ": " + message + "\n"); } + return true; +} - string error_message; - bool had_errors; -}; +static bool AddIntConstant(PyTypeObject *type, const char* name, int value) { + ScopedPyObjectPtr obj(PyInt_FromLong(value)); + if (PyDict_SetItemString(type->tp_dict, name, obj) < 0) { + return false; + } + return true; +} -PyObject* Python_BuildFile(PyObject* ignored, PyObject* arg) { - char* message_type; - Py_ssize_t message_len; - if (PyBytes_AsStringAndSize(arg, &message_type, &message_len) < 0) { - return NULL; - } +bool InitDescriptor() { + if (PyType_Ready(&PyMessageDescriptor_Type) < 0) + return false; - google::protobuf::FileDescriptorProto file_proto; - if (!file_proto.ParseFromArray(message_type, message_len)) { - PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!"); - return NULL; - } + if (PyType_Ready(&PyFieldDescriptor_Type) < 0) + return false; - // If the file was already part of a C++ library, all its descriptors are in - // the underlying pool. No need to do anything else. - if (google::protobuf::DescriptorPool::generated_pool()->FindFileByName( - file_proto.name()) != NULL) { - Py_RETURN_NONE; + if (!AddEnumValues(&PyFieldDescriptor_Type, + FieldDescriptorProto::Label_descriptor())) { + return false; } - - BuildFileErrorCollector error_collector; - const google::protobuf::FileDescriptor* descriptor = - GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto, - &error_collector); - if (descriptor == NULL) { - PyErr_Format(PyExc_TypeError, - "Couldn't build proto file into descriptor pool!\n%s", - error_collector.error_message.c_str()); - return NULL; + if (!AddEnumValues(&PyFieldDescriptor_Type, + FieldDescriptorProto::Type_descriptor())) { + return false; + } +#define ADD_FIELDDESC_CONSTANT(NAME) AddIntConstant( \ + &PyFieldDescriptor_Type, #NAME, FieldDescriptor::NAME) + if (!ADD_FIELDDESC_CONSTANT(CPPTYPE_INT32) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_INT64) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT32) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_UINT64) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_DOUBLE) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_FLOAT) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_BOOL) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_ENUM) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_STRING) || + !ADD_FIELDDESC_CONSTANT(CPPTYPE_MESSAGE)) { + return false; } +#undef ADD_FIELDDESC_CONSTANT - Py_RETURN_NONE; -} + if (PyType_Ready(&PyEnumDescriptor_Type) < 0) + return false; -bool InitDescriptor() { - if (PyType_Ready(&CMessageDescriptor_Type) < 0) + if (PyType_Ready(&PyEnumValueDescriptor_Type) < 0) + return false; + + if (PyType_Ready(&PyFileDescriptor_Type) < 0) return false; - if (PyType_Ready(&CFieldDescriptor_Type) < 0) + + if (PyType_Ready(&PyOneofDescriptor_Type) < 0) return false; - PyDescriptorPool_Type.tp_new = PyType_GenericNew; - if (PyType_Ready(&PyDescriptorPool_Type) < 0) + if (!InitDescriptorMappingTypes()) return false; return true; diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h index 9e5957b5..ba6e7298 100644 --- a/python/google/protobuf/pyext/descriptor.h +++ b/python/google/protobuf/pyext/descriptor.h @@ -34,105 +34,55 @@ #define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_H__ #include -#include - -#include #include -#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) -typedef int Py_ssize_t; -#define PY_SSIZE_T_MAX INT_MAX -#define PY_SSIZE_T_MIN INT_MIN -#endif - namespace google { namespace protobuf { namespace python { -typedef struct CMessageDescriptor { - PyObject_HEAD - - // The proto2 descriptor that this object represents. - const google::protobuf::Descriptor* descriptor; -} CMessageDescriptor; - - -typedef struct CFieldDescriptor { - PyObject_HEAD - - // The proto2 descriptor that this object represents. - const google::protobuf::FieldDescriptor* descriptor; -} CFieldDescriptor; - - -// Wraps operations to the global DescriptorPool which contains information -// about all messages and fields. -// -// There is normally one pool per process. We make it a Python object only -// because it contains many Python references. -// TODO(amauryfa): See whether such objects can appear in reference cycles, and -// consider adding support for the cyclic GC. -// -// "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool -// namespace. -typedef struct PyDescriptorPool { - PyObject_HEAD - - google::protobuf::DescriptorPool* pool; - - // Make our own mapping to retrieve Python classes from C++ descriptors. - // - // Descriptor pointers stored here are owned by the DescriptorPool above. - // Python references to classes are owned by this PyDescriptorPool. - typedef hash_map ClassesByMessageMap; - ClassesByMessageMap *classes_by_descriptor; -} PyDescriptorPool; - - -extern PyTypeObject CMessageDescriptor_Type; -extern PyTypeObject CFieldDescriptor_Type; - -extern PyTypeObject PyDescriptorPool_Type; - - -namespace cdescriptor_pool { - -// Builds a new DescriptorPool. Normally called only once per process. -PyDescriptorPool* NewDescriptorPool(); - -// Looks up a message by name. -// Returns a message Descriptor, or NULL if not found. -const google::protobuf::Descriptor* FindMessageTypeByName(PyDescriptorPool* self, - const string& name); - -// Registers a new Python class for the given message descriptor. -// Returns the message Descriptor. -// On error, returns NULL with a Python exception set. -const google::protobuf::Descriptor* RegisterMessageClass( - PyDescriptorPool* self, PyObject *message_class, PyObject *descriptor); +extern PyTypeObject PyMessageDescriptor_Type; +extern PyTypeObject PyFieldDescriptor_Type; +extern PyTypeObject PyEnumDescriptor_Type; +extern PyTypeObject PyEnumValueDescriptor_Type; +extern PyTypeObject PyFileDescriptor_Type; +extern PyTypeObject PyOneofDescriptor_Type; + +// Return a new reference to a Descriptor object. +// The C++ pointer is usually borrowed from the global DescriptorPool. +// In any case, it must stay alive as long as the Python object. +PyObject* PyMessageDescriptor_New(const Descriptor* descriptor); +PyObject* PyFieldDescriptor_New(const FieldDescriptor* descriptor); +PyObject* PyEnumDescriptor_New(const EnumDescriptor* descriptor); +PyObject* PyEnumValueDescriptor_New(const EnumValueDescriptor* descriptor); +PyObject* PyOneofDescriptor_New(const OneofDescriptor* descriptor); +PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor); + +// Alternate constructor of PyFileDescriptor, used when we already have a +// serialized FileDescriptorProto that can be cached. +// Returns a new reference. +PyObject* PyFileDescriptor_NewWithPb(const FileDescriptor* file_descriptor, + PyObject* serialized_pb); -// Retrieves the Python class registered with the given message descriptor. -// -// Returns a *borrowed* reference if found, otherwise returns NULL with an +// Return the C++ descriptor pointer. +// This function checks the parameter type; on error, return NULL with a Python // exception set. -PyObject *GetMessageClass(PyDescriptorPool* self, - const Descriptor *message_descriptor); +const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj); +const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj); -// Looks up a field by name. Returns a CDescriptor corresponding to -// the field on success, or NULL on failure. -// -// Returns a new reference. -PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name); +// Returns the raw C++ pointer. +const void* PyDescriptor_AsVoidPtr(PyObject* obj); -// Looks up an extension by name. Returns a CDescriptor corresponding -// to the field on success, or NULL on failure. +// Check that the calling Python code is the global scope of a _pb2.py module. +// This function is used to support the current code generated by the proto +// compiler, which insists on modifying descriptors after they have been +// created. // -// Returns a new reference. -PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg); -} // namespace cdescriptor_pool +// stacklevel indicates which Python frame should be the _pb2.py module. +// +// Don't use this function outside descriptor classes. +bool _CalledFromGeneratedFile(int stacklevel); -PyObject* Python_BuildFile(PyObject* ignored, PyObject* args); bool InitDescriptor(); } // namespace python diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc new file mode 100644 index 00000000..06edebf8 --- /dev/null +++ b/python/google/protobuf/pyext/descriptor_containers.cc @@ -0,0 +1,1564 @@ +// 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. + +// Mappings and Sequences of descriptors. +// Used by Descriptor.fields_by_name, EnumDescriptor.values... +// +// They avoid the allocation of a full dictionary or a full list: they simply +// store a pointer to the parent descriptor, use the C++ Descriptor methods (see +// google/protobuf/descriptor.h) to retrieve other descriptors, and create +// Python objects on the fly. +// +// The containers fully conform to abc.Mapping and abc.Sequence, and behave just +// like read-only dictionaries and lists. +// +// Because the interface of C++ Descriptors is quite regular, this file actually +// defines only three types, the exact behavior of a container is controlled by +// a DescriptorContainerDef structure, which contains functions that uses the +// public Descriptor API. +// +// Note: This DescriptorContainerDef is similar to the "virtual methods table" +// that a C++ compiler generates for a class. We have to make it explicit +// because the Python API is based on C, and does not play well with C++ +// inheritance. + +#include + +#include +#include +#include +#include +#include + +#if PY_MAJOR_VERSION >= 3 + #define PyString_FromStringAndSize PyUnicode_FromStringAndSize + #define PyString_FromFormat PyUnicode_FromFormat + #define PyInt_FromLong PyLong_FromLong + #if PY_VERSION_HEX < 0x03030000 + #error "Python 3.0 - 3.2 are not supported." + #endif + #define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob)? \ + ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ + PyBytes_AsStringAndSize(ob, (charpp), (sizep))) +#endif + +namespace google { +namespace protobuf { +namespace python { + +struct PyContainer; + +typedef int (*CountMethod)(PyContainer* self); +typedef const void* (*GetByIndexMethod)(PyContainer* self, int index); +typedef const void* (*GetByNameMethod)(PyContainer* self, const string& name); +typedef const void* (*GetByNumberMethod)(PyContainer* self, int index); +typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor); +typedef const string& (*GetItemNameMethod)(const void* descriptor); +typedef int (*GetItemNumberMethod)(const void* descriptor); +typedef int (*GetItemIndexMethod)(const void* descriptor); + +struct DescriptorContainerDef { + const char* mapping_name; + // Returns the number of items in the container. + CountMethod count_fn; + // Retrieve item by index (usually the order of declaration in the proto file) + // Used by sequences, but also iterators. 0 <= index < Count(). + GetByIndexMethod get_by_index_fn; + // Retrieve item by name (usually a call to some 'FindByName' method). + // Used by "by_name" mappings. + GetByNameMethod get_by_name_fn; + // Retrieve item by declared number (field tag, or enum value). + // Used by "by_number" mappings. + GetByNumberMethod get_by_number_fn; + // Converts a item C++ descriptor to a Python object. Returns a new reference. + NewObjectFromItemMethod new_object_from_item_fn; + // Retrieve the name of an item. Used by iterators on "by_name" mappings. + GetItemNameMethod get_item_name_fn; + // Retrieve the number of an item. Used by iterators on "by_number" mappings. + GetItemNumberMethod get_item_number_fn; + // Retrieve the index of an item for the container type. + // Used by "__contains__". + // If not set, "x in sequence" will do a linear search. + GetItemIndexMethod get_item_index_fn; +}; + +struct PyContainer { + PyObject_HEAD + + // The proto2 descriptor this container belongs to the global DescriptorPool. + const void* descriptor; + + // A pointer to a static structure with function pointers that control the + // behavior of the container. Very similar to the table of virtual functions + // of a C++ class. + const DescriptorContainerDef* container_def; + + // The kind of container: list, or dict by name or value. + enum ContainerKind { + KIND_SEQUENCE, + KIND_BYNAME, + KIND_BYNUMBER, + } kind; +}; + +struct PyContainerIterator { + PyObject_HEAD + + // The container we are iterating over. Own a reference. + PyContainer* container; + + // The current index in the iterator. + int index; + + // The kind of container: list, or dict by name or value. + enum IterKind { + KIND_ITERKEY, + KIND_ITERVALUE, + KIND_ITERITEM, + KIND_ITERVALUE_REVERSED, // For sequences + } kind; +}; + +namespace descriptor { + +// Returns the C++ item descriptor for a given Python key. +// When the descriptor is found, return true and set *item. +// When the descriptor is not found, return true, but set *item to NULL. +// On error, returns false with an exception set. +static bool _GetItemByKey(PyContainer* self, PyObject* key, const void** item) { + switch (self->kind) { + case PyContainer::KIND_BYNAME: + { + char* name; + Py_ssize_t name_size; + if (PyString_AsStringAndSize(key, &name, &name_size) < 0) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + // Not a string, cannot be in the container. + PyErr_Clear(); + *item = NULL; + return true; + } + return false; + } + *item = self->container_def->get_by_name_fn( + self, string(name, name_size)); + return true; + } + case PyContainer::KIND_BYNUMBER: + { + Py_ssize_t number = PyNumber_AsSsize_t(key, NULL); + if (number == -1 && PyErr_Occurred()) { + if (PyErr_ExceptionMatches(PyExc_TypeError)) { + // Not a number, cannot be in the container. + PyErr_Clear(); + *item = NULL; + return true; + } + return false; + } + *item = self->container_def->get_by_number_fn(self, number); + return true; + } + default: + PyErr_SetNone(PyExc_NotImplementedError); + return false; + } +} + +// Returns the key of the object at the given index. +// Used when iterating over mappings. +static PyObject* _NewKey_ByIndex(PyContainer* self, Py_ssize_t index) { + const void* item = self->container_def->get_by_index_fn(self, index); + switch (self->kind) { + case PyContainer::KIND_BYNAME: + { + const string& name(self->container_def->get_item_name_fn(item)); + return PyString_FromStringAndSize(name.c_str(), name.size()); + } + case PyContainer::KIND_BYNUMBER: + { + int value = self->container_def->get_item_number_fn(item); + return PyInt_FromLong(value); + } + default: + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; + } +} + +// Returns the object at the given index. +// Also used when iterating over mappings. +static PyObject* _NewObj_ByIndex(PyContainer* self, Py_ssize_t index) { + return self->container_def->new_object_from_item_fn( + self->container_def->get_by_index_fn(self, index)); +} + +static Py_ssize_t Length(PyContainer* self) { + return self->container_def->count_fn(self); +} + +// The DescriptorMapping type. + +static PyObject* Subscript(PyContainer* self, PyObject* key) { + const void* item = NULL; + if (!_GetItemByKey(self, key, &item)) { + return NULL; + } + if (!item) { + PyErr_SetObject(PyExc_KeyError, key); + return NULL; + } + return self->container_def->new_object_from_item_fn(item); +} + +static int AssSubscript(PyContainer* self, PyObject* key, PyObject* value) { + if (_CalledFromGeneratedFile(0)) { + return 0; + } + PyErr_Format(PyExc_TypeError, + "'%.200s' object does not support item assignment", + Py_TYPE(self)->tp_name); + return -1; +} + +static PyMappingMethods MappingMappingMethods = { + (lenfunc)Length, // mp_length + (binaryfunc)Subscript, // mp_subscript + (objobjargproc)AssSubscript, // mp_ass_subscript +}; + +static int Contains(PyContainer* self, PyObject* key) { + const void* item = NULL; + if (!_GetItemByKey(self, key, &item)) { + return -1; + } + if (item) { + return 1; + } else { + return 0; + } +} + +static PyObject* ContainerRepr(PyContainer* self) { + const char* kind = ""; + switch (self->kind) { + case PyContainer::KIND_SEQUENCE: + kind = "sequence"; + break; + case PyContainer::KIND_BYNAME: + kind = "mapping by name"; + break; + case PyContainer::KIND_BYNUMBER: + kind = "mapping by number"; + break; + } + return PyString_FromFormat( + "<%s %s>", self->container_def->mapping_name, kind); +} + +extern PyTypeObject DescriptorMapping_Type; +extern PyTypeObject DescriptorSequence_Type; + +// A sequence container can only be equal to another sequence container, or (for +// backward compatibility) to a list containing the same items. +// Returns 1 if equal, 0 if unequal, -1 on error. +static int DescriptorSequence_Equal(PyContainer* self, PyObject* other) { + // Check the identity of C++ pointers. + if (PyObject_TypeCheck(other, &DescriptorSequence_Type)) { + PyContainer* other_container = reinterpret_cast(other); + if (self->descriptor == other_container->descriptor && + self->container_def == other_container->container_def && + self->kind == other_container->kind) { + return 1; + } else { + return 0; + } + } + + // If other is a list + if (PyList_Check(other)) { + // return list(self) == other + int size = Length(self); + if (size != PyList_Size(other)) { + return false; + } + for (int index = 0; index < size; index++) { + ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index)); + if (value1 == NULL) { + return -1; + } + PyObject* value2 = PyList_GetItem(other, index); + if (value2 == NULL) { + return -1; + } + int cmp = PyObject_RichCompareBool(value1, value2, Py_EQ); + if (cmp != 1) // error or not equal + return cmp; + } + // All items were found and equal + return 1; + } + + // Any other object is different. + return 0; +} + +// A mapping container can only be equal to another mapping container, or (for +// backward compatibility) to a dict containing the same items. +// Returns 1 if equal, 0 if unequal, -1 on error. +static int DescriptorMapping_Equal(PyContainer* self, PyObject* other) { + // Check the identity of C++ pointers. + if (PyObject_TypeCheck(other, &DescriptorMapping_Type)) { + PyContainer* other_container = reinterpret_cast(other); + if (self->descriptor == other_container->descriptor && + self->container_def == other_container->container_def && + self->kind == other_container->kind) { + return 1; + } else { + return 0; + } + } + + // If other is a dict + if (PyDict_Check(other)) { + // equivalent to dict(self.items()) == other + int size = Length(self); + if (size != PyDict_Size(other)) { + return false; + } + for (int index = 0; index < size; index++) { + ScopedPyObjectPtr key(_NewKey_ByIndex(self, index)); + if (key == NULL) { + return -1; + } + ScopedPyObjectPtr value1(_NewObj_ByIndex(self, index)); + if (value1 == NULL) { + return -1; + } + PyObject* value2 = PyDict_GetItem(other, key); + if (value2 == NULL) { + // Not found in the other dictionary + return 0; + } + int cmp = PyObject_RichCompareBool(value1, value2, Py_EQ); + if (cmp != 1) // error or not equal + return cmp; + } + // All items were found and equal + return 1; + } + + // Any other object is different. + return 0; +} + +static PyObject* RichCompare(PyContainer* self, PyObject* other, int opid) { + if (opid != Py_EQ && opid != Py_NE) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + + int result; + + if (self->kind == PyContainer::KIND_SEQUENCE) { + result = DescriptorSequence_Equal(self, other); + } else { + result = DescriptorMapping_Equal(self, other); + } + if (result < 0) { + return NULL; + } + if (result ^ (opid == Py_NE)) { + Py_RETURN_TRUE; + } else { + Py_RETURN_FALSE; + } +} + +static PySequenceMethods MappingSequenceMethods = { + 0, // sq_length + 0, // sq_concat + 0, // sq_repeat + 0, // sq_item + 0, // sq_slice + 0, // sq_ass_item + 0, // sq_ass_slice + (objobjproc)Contains, // sq_contains +}; + +static PyObject* Get(PyContainer* self, PyObject* args) { + PyObject* key; + PyObject* default_value = Py_None; + if (!PyArg_UnpackTuple(args, "get", 1, 2, &key, &default_value)) { + return NULL; + } + + const void* item; + if (!_GetItemByKey(self, key, &item)) { + return NULL; + } + if (item == NULL) { + Py_INCREF(default_value); + return default_value; + } + return self->container_def->new_object_from_item_fn(item); +} + +static PyObject* Keys(PyContainer* self, PyObject* args) { + Py_ssize_t count = Length(self); + ScopedPyObjectPtr list(PyList_New(count)); + if (list == NULL) { + return NULL; + } + for (Py_ssize_t index = 0; index < count; ++index) { + PyObject* key = _NewKey_ByIndex(self, index); + if (key == NULL) { + return NULL; + } + PyList_SET_ITEM(list.get(), index, key); + } + return list.release(); +} + +static PyObject* Values(PyContainer* self, PyObject* args) { + Py_ssize_t count = Length(self); + ScopedPyObjectPtr list(PyList_New(count)); + if (list == NULL) { + return NULL; + } + for (Py_ssize_t index = 0; index < count; ++index) { + PyObject* value = _NewObj_ByIndex(self, index); + if (value == NULL) { + return NULL; + } + PyList_SET_ITEM(list.get(), index, value); + } + return list.release(); +} + +static PyObject* Items(PyContainer* self, PyObject* args) { + Py_ssize_t count = Length(self); + ScopedPyObjectPtr list(PyList_New(count)); + if (list == NULL) { + return NULL; + } + for (Py_ssize_t index = 0; index < count; ++index) { + ScopedPyObjectPtr obj(PyTuple_New(2)); + if (obj == NULL) { + return NULL; + } + PyObject* key = _NewKey_ByIndex(self, index); + if (key == NULL) { + return NULL; + } + PyTuple_SET_ITEM(obj.get(), 0, key); + PyObject* value = _NewObj_ByIndex(self, index); + if (value == NULL) { + return NULL; + } + PyTuple_SET_ITEM(obj.get(), 1, value); + PyList_SET_ITEM(list.get(), index, obj.release()); + } + return list.release(); +} + +static PyObject* NewContainerIterator(PyContainer* mapping, + PyContainerIterator::IterKind kind); + +static PyObject* Iter(PyContainer* self) { + return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY); +} +static PyObject* IterKeys(PyContainer* self, PyObject* args) { + return NewContainerIterator(self, PyContainerIterator::KIND_ITERKEY); +} +static PyObject* IterValues(PyContainer* self, PyObject* args) { + return NewContainerIterator(self, PyContainerIterator::KIND_ITERVALUE); +} +static PyObject* IterItems(PyContainer* self, PyObject* args) { + return NewContainerIterator(self, PyContainerIterator::KIND_ITERITEM); +} + +static PyMethodDef MappingMethods[] = { + { "get", (PyCFunction)Get, METH_VARARGS, }, + { "keys", (PyCFunction)Keys, METH_NOARGS, }, + { "values", (PyCFunction)Values, METH_NOARGS, }, + { "items", (PyCFunction)Items, METH_NOARGS, }, + { "iterkeys", (PyCFunction)IterKeys, METH_NOARGS, }, + { "itervalues", (PyCFunction)IterValues, METH_NOARGS, }, + { "iteritems", (PyCFunction)IterItems, METH_NOARGS, }, + {NULL} +}; + +PyTypeObject DescriptorMapping_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "DescriptorMapping", // tp_name + sizeof(PyContainer), // tp_basicsize + 0, // tp_itemsize + 0, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + (reprfunc)ContainerRepr, // tp_repr + 0, // tp_as_number + &MappingSequenceMethods, // tp_as_sequence + &MappingMappingMethods, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + 0, // tp_doc + 0, // tp_traverse + 0, // tp_clear + (richcmpfunc)RichCompare, // tp_richcompare + 0, // tp_weaklistoffset + (getiterfunc)Iter, // tp_iter + 0, // tp_iternext + MappingMethods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + 0, // tp_new + 0, // tp_free +}; + +// The DescriptorSequence type. + +static PyObject* GetItem(PyContainer* self, Py_ssize_t index) { + if (index < 0) { + index += Length(self); + } + if (index < 0 || index >= Length(self)) { + PyErr_SetString(PyExc_IndexError, "index out of range"); + return NULL; + } + return _NewObj_ByIndex(self, index); +} + +// Returns the position of the item in the sequence, of -1 if not found. +// This function never fails. +int Find(PyContainer* self, PyObject* item) { + // The item can only be in one position: item.index. + // Check that self[item.index] == item, it's faster than a linear search. + // + // This assumes that sequences are only defined by syntax of the .proto file: + // a specific item belongs to only one sequence, depending on its position in + // the .proto file definition. + const void* descriptor_ptr = PyDescriptor_AsVoidPtr(item); + if (descriptor_ptr == NULL) { + // Not a descriptor, it cannot be in the list. + return -1; + } + if (self->container_def->get_item_index_fn) { + int index = self->container_def->get_item_index_fn(descriptor_ptr); + if (index < 0 || index >= Length(self)) { + // This index is not from this collection. + return -1; + } + if (self->container_def->get_by_index_fn(self, index) != descriptor_ptr) { + // The descriptor at this index is not the same. + return -1; + } + // self[item.index] == item, so return the index. + return index; + } else { + // Fall back to linear search. + int length = Length(self); + for (int index=0; index < length; index++) { + if (self->container_def->get_by_index_fn(self, index) == descriptor_ptr) { + return index; + } + } + // Not found + return -1; + } +} + +// Implements list.index(): the position of the item is in the sequence. +static PyObject* Index(PyContainer* self, PyObject* item) { + int position = Find(self, item); + if (position < 0) { + // Not found + PyErr_SetNone(PyExc_ValueError); + return NULL; + } else { + return PyInt_FromLong(position); + } +} +// Implements "list.__contains__()": is the object in the sequence. +static int SeqContains(PyContainer* self, PyObject* item) { + int position = Find(self, item); + if (position < 0) { + return 0; + } else { + return 1; + } +} + +// Implements list.count(): number of occurrences of the item in the sequence. +// An item can only appear once in a sequence. If it exists, return 1. +static PyObject* Count(PyContainer* self, PyObject* item) { + int position = Find(self, item); + if (position < 0) { + return PyInt_FromLong(0); + } else { + return PyInt_FromLong(1); + } +} + +static PyObject* Append(PyContainer* self, PyObject* args) { + if (_CalledFromGeneratedFile(0)) { + Py_RETURN_NONE; + } + PyErr_Format(PyExc_TypeError, + "'%.200s' object is not a mutable sequence", + Py_TYPE(self)->tp_name); + return NULL; +} + +static PyObject* Reversed(PyContainer* self, PyObject* args) { + return NewContainerIterator(self, + PyContainerIterator::KIND_ITERVALUE_REVERSED); +} + +static PyMethodDef SeqMethods[] = { + { "index", (PyCFunction)Index, METH_O, }, + { "count", (PyCFunction)Count, METH_O, }, + { "append", (PyCFunction)Append, METH_O, }, + { "__reversed__", (PyCFunction)Reversed, METH_NOARGS, }, + {NULL} +}; + +static PySequenceMethods SeqSequenceMethods = { + (lenfunc)Length, // sq_length + 0, // sq_concat + 0, // sq_repeat + (ssizeargfunc)GetItem, // sq_item + 0, // sq_slice + 0, // sq_ass_item + 0, // sq_ass_slice + (objobjproc)SeqContains, // sq_contains +}; + +PyTypeObject DescriptorSequence_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "DescriptorSequence", // tp_name + sizeof(PyContainer), // tp_basicsize + 0, // tp_itemsize + 0, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + (reprfunc)ContainerRepr, // tp_repr + 0, // tp_as_number + &SeqSequenceMethods, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + 0, // tp_doc + 0, // tp_traverse + 0, // tp_clear + (richcmpfunc)RichCompare, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + SeqMethods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + 0, // tp_new + 0, // tp_free +}; + +static PyObject* NewMappingByName( + DescriptorContainerDef* container_def, const void* descriptor) { + PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type); + if (self == NULL) { + return NULL; + } + self->descriptor = descriptor; + self->container_def = container_def; + self->kind = PyContainer::KIND_BYNAME; + return reinterpret_cast(self); +} + +static PyObject* NewMappingByNumber( + DescriptorContainerDef* container_def, const void* descriptor) { + if (container_def->get_by_number_fn == NULL || + container_def->get_item_number_fn == NULL) { + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; + } + PyContainer* self = PyObject_New(PyContainer, &DescriptorMapping_Type); + if (self == NULL) { + return NULL; + } + self->descriptor = descriptor; + self->container_def = container_def; + self->kind = PyContainer::KIND_BYNUMBER; + return reinterpret_cast(self); +} + +static PyObject* NewSequence( + DescriptorContainerDef* container_def, const void* descriptor) { + PyContainer* self = PyObject_New(PyContainer, &DescriptorSequence_Type); + if (self == NULL) { + return NULL; + } + self->descriptor = descriptor; + self->container_def = container_def; + self->kind = PyContainer::KIND_SEQUENCE; + return reinterpret_cast(self); +} + +// Implement iterators over PyContainers. + +static void Iterator_Dealloc(PyContainerIterator* self) { + Py_CLEAR(self->container); + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +static PyObject* Iterator_Next(PyContainerIterator* self) { + int count = self->container->container_def->count_fn(self->container); + if (self->index >= count) { + // Return NULL with no exception to indicate the end. + return NULL; + } + int index = self->index; + self->index += 1; + switch (self->kind) { + case PyContainerIterator::KIND_ITERKEY: + return _NewKey_ByIndex(self->container, index); + case PyContainerIterator::KIND_ITERVALUE: + return _NewObj_ByIndex(self->container, index); + case PyContainerIterator::KIND_ITERVALUE_REVERSED: + return _NewObj_ByIndex(self->container, count - index - 1); + case PyContainerIterator::KIND_ITERITEM: + { + PyObject* obj = PyTuple_New(2); + if (obj == NULL) { + return NULL; + } + PyObject* key = _NewKey_ByIndex(self->container, index); + if (key == NULL) { + Py_DECREF(obj); + return NULL; + } + PyTuple_SET_ITEM(obj, 0, key); + PyObject* value = _NewObj_ByIndex(self->container, index); + if (value == NULL) { + Py_DECREF(obj); + return NULL; + } + PyTuple_SET_ITEM(obj, 1, value); + return obj; + } + default: + PyErr_SetNone(PyExc_NotImplementedError); + return NULL; + } +} + +static PyTypeObject ContainerIterator_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "DescriptorContainerIterator", // tp_name + sizeof(PyContainerIterator), // tp_basicsize + 0, // tp_itemsize + (destructor)Iterator_Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + 0, // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + PyObject_SelfIter, // tp_iter + (iternextfunc)Iterator_Next, // tp_iternext + 0, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + 0, // tp_new + 0, // tp_free +}; + +static PyObject* NewContainerIterator(PyContainer* container, + PyContainerIterator::IterKind kind) { + PyContainerIterator* self = PyObject_New(PyContainerIterator, + &ContainerIterator_Type); + if (self == NULL) { + return NULL; + } + Py_INCREF(container); + self->container = container; + self->kind = kind; + self->index = 0; + + return reinterpret_cast(self); +} + +} // namespace descriptor + +// Now define the real collections! + +namespace message_descriptor { + +typedef const Descriptor* ParentDescriptor; + +static ParentDescriptor GetDescriptor(PyContainer* self) { + return reinterpret_cast(self->descriptor); +} + +namespace fields { + +typedef const FieldDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->field_count(); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindFieldByName(name); +} + +static ItemDescriptor GetByNumber(PyContainer* self, int number) { + return GetDescriptor(self)->FindFieldByNumber(number); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->field(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyFieldDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemNumber(ItemDescriptor item) { + return item->number(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "MessageFields", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)GetByNumber, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)GetItemNumber, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace fields + +PyObject* NewMessageFieldsByName(ParentDescriptor descriptor) { + return descriptor::NewMappingByName(&fields::ContainerDef, descriptor); +} + +PyObject* NewMessageFieldsByNumber(ParentDescriptor descriptor) { + return descriptor::NewMappingByNumber(&fields::ContainerDef, descriptor); +} + +PyObject* NewMessageFieldsSeq(ParentDescriptor descriptor) { + return descriptor::NewSequence(&fields::ContainerDef, descriptor); +} + +namespace nested_types { + +typedef const Descriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->nested_type_count(); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindNestedTypeByName(name); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->nested_type(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyMessageDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "MessageNestedTypes", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace nested_types + +PyObject* NewMessageNestedTypesSeq(ParentDescriptor descriptor) { + return descriptor::NewSequence(&nested_types::ContainerDef, descriptor); +} + +PyObject* NewMessageNestedTypesByName(ParentDescriptor descriptor) { + return descriptor::NewMappingByName(&nested_types::ContainerDef, descriptor); +} + +namespace enums { + +typedef const EnumDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->enum_type_count(); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindEnumTypeByName(name); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->enum_type(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyEnumDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "MessageNestedEnums", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace enums + +PyObject* NewMessageEnumsByName(ParentDescriptor descriptor) { + return descriptor::NewMappingByName(&enums::ContainerDef, descriptor); +} + +PyObject* NewMessageEnumsSeq(ParentDescriptor descriptor) { + return descriptor::NewSequence(&enums::ContainerDef, descriptor); +} + +namespace enumvalues { + +// This is the "enum_values_by_name" mapping, which collects values from all +// enum types in a message. +// +// Note that the behavior of the C++ descriptor is different: it will search and +// return the first value that matches the name, whereas the Python +// implementation retrieves the last one. + +typedef const EnumValueDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + int count = 0; + for (int i = 0; i < GetDescriptor(self)->enum_type_count(); ++i) { + count += GetDescriptor(self)->enum_type(i)->value_count(); + } + return count; +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindEnumValueByName(name); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + // This is not optimal, but the number of enums *types* in a given message + // is small. This function is only used when iterating over the mapping. + const EnumDescriptor* enum_type = NULL; + int enum_type_count = GetDescriptor(self)->enum_type_count(); + for (int i = 0; i < enum_type_count; ++i) { + enum_type = GetDescriptor(self)->enum_type(i); + int enum_value_count = enum_type->value_count(); + if (index < enum_value_count) { + // Found it! + break; + } + index -= enum_value_count; + } + // The next statement cannot overflow, because this function is only called by + // internal iterators which ensure that 0 <= index < Count(). + return enum_type->value(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyEnumValueDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static DescriptorContainerDef ContainerDef = { + "MessageEnumValues", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)NULL, +}; + +} // namespace enumvalues + +PyObject* NewMessageEnumValuesByName(ParentDescriptor descriptor) { + return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor); +} + +namespace extensions { + +typedef const FieldDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->extension_count(); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindExtensionByName(name); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->extension(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyFieldDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "MessageExtensions", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace extensions + +PyObject* NewMessageExtensionsByName(ParentDescriptor descriptor) { + return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor); +} + +PyObject* NewMessageExtensionsSeq(ParentDescriptor descriptor) { + return descriptor::NewSequence(&extensions::ContainerDef, descriptor); +} + +namespace oneofs { + +typedef const OneofDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->oneof_decl_count(); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindOneofByName(name); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->oneof_decl(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyOneofDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "MessageOneofs", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace oneofs + +PyObject* NewMessageOneofsByName(ParentDescriptor descriptor) { + return descriptor::NewMappingByName(&oneofs::ContainerDef, descriptor); +} + +PyObject* NewMessageOneofsSeq(ParentDescriptor descriptor) { + return descriptor::NewSequence(&oneofs::ContainerDef, descriptor); +} + +} // namespace message_descriptor + +namespace enum_descriptor { + +typedef const EnumDescriptor* ParentDescriptor; + +static ParentDescriptor GetDescriptor(PyContainer* self) { + return reinterpret_cast(self->descriptor); +} + +namespace enumvalues { + +typedef const EnumValueDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->value_count(); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->value(index); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindValueByName(name); +} + +static ItemDescriptor GetByNumber(PyContainer* self, int number) { + return GetDescriptor(self)->FindValueByNumber(number); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyEnumValueDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemNumber(ItemDescriptor item) { + return item->number(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "EnumValues", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)GetByNumber, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)GetItemNumber, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace enumvalues + +PyObject* NewEnumValuesByName(ParentDescriptor descriptor) { + return descriptor::NewMappingByName(&enumvalues::ContainerDef, descriptor); +} + +PyObject* NewEnumValuesByNumber(ParentDescriptor descriptor) { + return descriptor::NewMappingByNumber(&enumvalues::ContainerDef, descriptor); +} + +PyObject* NewEnumValuesSeq(ParentDescriptor descriptor) { + return descriptor::NewSequence(&enumvalues::ContainerDef, descriptor); +} + +} // namespace enum_descriptor + +namespace oneof_descriptor { + +typedef const OneofDescriptor* ParentDescriptor; + +static ParentDescriptor GetDescriptor(PyContainer* self) { + return reinterpret_cast(self->descriptor); +} + +namespace fields { + +typedef const FieldDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->field_count(); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->field(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyFieldDescriptor_New(item); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index_in_oneof(); +} + +static DescriptorContainerDef ContainerDef = { + "OneofFields", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)NULL, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)NULL, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace fields + +PyObject* NewOneofFieldsSeq(ParentDescriptor descriptor) { + return descriptor::NewSequence(&fields::ContainerDef, descriptor); +} + +} // namespace oneof_descriptor + +namespace file_descriptor { + +typedef const FileDescriptor* ParentDescriptor; + +static ParentDescriptor GetDescriptor(PyContainer* self) { + return reinterpret_cast(self->descriptor); +} + +namespace messages { + +typedef const Descriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->message_type_count(); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindMessageTypeByName(name); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->message_type(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyMessageDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "FileMessages", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace messages + +PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor) { + return descriptor::NewMappingByName(&messages::ContainerDef, descriptor); +} + +namespace enums { + +typedef const EnumDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->enum_type_count(); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindEnumTypeByName(name); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->enum_type(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyEnumDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "FileEnums", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace enums + +PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor) { + return descriptor::NewMappingByName(&enums::ContainerDef, descriptor); +} + +namespace extensions { + +typedef const FieldDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->extension_count(); +} + +static ItemDescriptor GetByName(PyContainer* self, const string& name) { + return GetDescriptor(self)->FindExtensionByName(name); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->extension(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyFieldDescriptor_New(item); +} + +static const string& GetItemName(ItemDescriptor item) { + return item->name(); +} + +static int GetItemIndex(ItemDescriptor item) { + return item->index(); +} + +static DescriptorContainerDef ContainerDef = { + "FileExtensions", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)GetByName, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)GetItemName, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)GetItemIndex, +}; + +} // namespace extensions + +PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor) { + return descriptor::NewMappingByName(&extensions::ContainerDef, descriptor); +} + +namespace dependencies { + +typedef const FileDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->dependency_count(); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->dependency(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyFileDescriptor_New(item); +} + +static DescriptorContainerDef ContainerDef = { + "FileDependencies", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)NULL, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)NULL, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)NULL, +}; + +} // namespace dependencies + +PyObject* NewFileDependencies(const FileDescriptor* descriptor) { + return descriptor::NewSequence(&dependencies::ContainerDef, descriptor); +} + +namespace public_dependencies { + +typedef const FileDescriptor* ItemDescriptor; + +static int Count(PyContainer* self) { + return GetDescriptor(self)->public_dependency_count(); +} + +static ItemDescriptor GetByIndex(PyContainer* self, int index) { + return GetDescriptor(self)->public_dependency(index); +} + +static PyObject* NewObjectFromItem(ItemDescriptor item) { + return PyFileDescriptor_New(item); +} + +static DescriptorContainerDef ContainerDef = { + "FilePublicDependencies", + (CountMethod)Count, + (GetByIndexMethod)GetByIndex, + (GetByNameMethod)NULL, + (GetByNumberMethod)NULL, + (NewObjectFromItemMethod)NewObjectFromItem, + (GetItemNameMethod)NULL, + (GetItemNumberMethod)NULL, + (GetItemIndexMethod)NULL, +}; + +} // namespace public_dependencies + +PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor) { + return descriptor::NewSequence(&public_dependencies::ContainerDef, + descriptor); +} + +} // namespace file_descriptor + + +// Register all implementations + +bool InitDescriptorMappingTypes() { + if (PyType_Ready(&descriptor::DescriptorMapping_Type) < 0) + return false; + if (PyType_Ready(&descriptor::DescriptorSequence_Type) < 0) + return false; + if (PyType_Ready(&descriptor::ContainerIterator_Type) < 0) + return false; + return true; +} + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/descriptor_containers.h b/python/google/protobuf/pyext/descriptor_containers.h new file mode 100644 index 00000000..d81537de --- /dev/null +++ b/python/google/protobuf/pyext/descriptor_containers.h @@ -0,0 +1,95 @@ +// 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. + +// Mappings and Sequences of descriptors. +// They implement containers like fields_by_name, EnumDescriptor.values... +// See descriptor_containers.cc for more description. +#include + +namespace google { +namespace protobuf { + +class Descriptor; +class FileDescriptor; +class EnumDescriptor; +class OneofDescriptor; + +namespace python { + +// Initialize the various types and objects. +bool InitDescriptorMappingTypes(); + +// Each function below returns a Mapping, or a Sequence of descriptors. +// They all return a new reference. + +namespace message_descriptor { +PyObject* NewMessageFieldsByName(const Descriptor* descriptor); +PyObject* NewMessageFieldsByNumber(const Descriptor* descriptor); +PyObject* NewMessageFieldsSeq(const Descriptor* descriptor); + +PyObject* NewMessageNestedTypesSeq(const Descriptor* descriptor); +PyObject* NewMessageNestedTypesByName(const Descriptor* descriptor); + +PyObject* NewMessageEnumsByName(const Descriptor* descriptor); +PyObject* NewMessageEnumsSeq(const Descriptor* descriptor); +PyObject* NewMessageEnumValuesByName(const Descriptor* descriptor); + +PyObject* NewMessageExtensionsByName(const Descriptor* descriptor); +PyObject* NewMessageExtensionsSeq(const Descriptor* descriptor); + +PyObject* NewMessageOneofsByName(const Descriptor* descriptor); +PyObject* NewMessageOneofsSeq(const Descriptor* descriptor); +} // namespace message_descriptor + +namespace enum_descriptor { +PyObject* NewEnumValuesByName(const EnumDescriptor* descriptor); +PyObject* NewEnumValuesByNumber(const EnumDescriptor* descriptor); +PyObject* NewEnumValuesSeq(const EnumDescriptor* descriptor); +} // namespace enum_descriptor + +namespace oneof_descriptor { +PyObject* NewOneofFieldsSeq(const OneofDescriptor* descriptor); +} // namespace oneof_descriptor + +namespace file_descriptor { +PyObject* NewFileMessageTypesByName(const FileDescriptor* descriptor); + +PyObject* NewFileEnumTypesByName(const FileDescriptor* descriptor); + +PyObject* NewFileExtensionsByName(const FileDescriptor* descriptor); + +PyObject* NewFileDependencies(const FileDescriptor* descriptor); +PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor); +} // namespace file_descriptor + + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/descriptor_cpp2_test.py b/python/google/protobuf/pyext/descriptor_cpp2_test.py deleted file mode 100644 index 3cf45a22..00000000 --- a/python/google/protobuf/pyext/descriptor_cpp2_test.py +++ /dev/null @@ -1,58 +0,0 @@ -#! /usr/bin/python -# -# 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. - -"""Tests for google.protobuf.pyext behavior.""" - -__author__ = 'anuraag@google.com (Anuraag Agrawal)' - -import os -os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' -os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2' - -# We must set the implementation version above before the google3 imports. -# pylint: disable=g-import-not-at-top -from google.apputils import basetest -from google.protobuf.internal import api_implementation -# Run all tests from the original module by putting them in our namespace. -# pylint: disable=wildcard-import -from google.protobuf.internal.descriptor_test import * - - -class ConfirmCppApi2Test(basetest.TestCase): - - def testImplementationSetting(self): - self.assertEqual('cpp', api_implementation.Type()) - self.assertEqual(2, api_implementation.Version()) - - -if __name__ == '__main__': - basetest.main() diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc new file mode 100644 index 00000000..bc3077bc --- /dev/null +++ b/python/google/protobuf/pyext/descriptor_pool.cc @@ -0,0 +1,370 @@ +// 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. + +// Implements the DescriptorPool, which collects all descriptors. + +#include + +#include +#include +#include +#include + +#define C(str) const_cast(str) + +#if PY_MAJOR_VERSION >= 3 + #define PyString_FromStringAndSize PyUnicode_FromStringAndSize + #if PY_VERSION_HEX < 0x03030000 + #error "Python 3.0 - 3.2 are not supported." + #endif + #define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob)? \ + ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ + PyBytes_AsStringAndSize(ob, (charpp), (sizep))) +#endif + +namespace google { +namespace protobuf { +namespace python { + +namespace cdescriptor_pool { + +PyDescriptorPool* NewDescriptorPool() { + PyDescriptorPool* cdescriptor_pool = PyObject_New( + PyDescriptorPool, &PyDescriptorPool_Type); + if (cdescriptor_pool == NULL) { + return NULL; + } + + // Build a DescriptorPool for messages only declared in Python libraries. + // generated_pool() contains all messages linked in C++ libraries, and is used + // as underlay. + cdescriptor_pool->pool = new DescriptorPool(DescriptorPool::generated_pool()); + + // TODO(amauryfa): Rewrite the SymbolDatabase in C so that it uses the same + // storage. + cdescriptor_pool->classes_by_descriptor = + new PyDescriptorPool::ClassesByMessageMap(); + cdescriptor_pool->interned_descriptors = + new hash_map(); + cdescriptor_pool->descriptor_options = + new hash_map(); + + return cdescriptor_pool; +} + +static void Dealloc(PyDescriptorPool* self) { + typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; + for (iterator it = self->classes_by_descriptor->begin(); + it != self->classes_by_descriptor->end(); ++it) { + Py_DECREF(it->second); + } + delete self->classes_by_descriptor; + delete self->interned_descriptors; // its references were borrowed. + for (hash_map::iterator it = + self->descriptor_options->begin(); + it != self->descriptor_options->end(); ++it) { + Py_DECREF(it->second); + } + delete self->descriptor_options; + Py_TYPE(self)->tp_free(reinterpret_cast(self)); +} + +PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { + Py_ssize_t name_size; + char* name; + if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { + return NULL; + } + + const Descriptor* message_descriptor = + self->pool->FindMessageTypeByName(string(name, name_size)); + + if (message_descriptor == NULL) { + PyErr_Format(PyExc_TypeError, "Couldn't find message %.200s", name); + return NULL; + } + + return PyMessageDescriptor_New(message_descriptor); +} + +// Add a message class to our database. +const Descriptor* RegisterMessageClass( + PyDescriptorPool* self, PyObject *message_class, PyObject* descriptor) { + ScopedPyObjectPtr full_message_name( + PyObject_GetAttrString(descriptor, "full_name")); + Py_ssize_t name_size; + char* name; + if (PyString_AsStringAndSize(full_message_name, &name, &name_size) < 0) { + return NULL; + } + const Descriptor *message_descriptor = + self->pool->FindMessageTypeByName(string(name, name_size)); + if (!message_descriptor) { + PyErr_Format(PyExc_TypeError, "Could not find C++ descriptor for '%s'", + name); + return NULL; + } + Py_INCREF(message_class); + typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; + std::pair ret = self->classes_by_descriptor->insert( + std::make_pair(message_descriptor, message_class)); + if (!ret.second) { + // Update case: DECREF the previous value. + Py_DECREF(ret.first->second); + ret.first->second = message_class; + } + return message_descriptor; +} + +// Retrieve the message class added to our database. +PyObject *GetMessageClass(PyDescriptorPool* self, + const Descriptor *message_descriptor) { + typedef PyDescriptorPool::ClassesByMessageMap::iterator iterator; + iterator ret = self->classes_by_descriptor->find(message_descriptor); + if (ret == self->classes_by_descriptor->end()) { + PyErr_Format(PyExc_TypeError, "No message class registered for '%s'", + message_descriptor->full_name().c_str()); + return NULL; + } else { + return ret->second; + } +} + +PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) { + Py_ssize_t name_size; + char* name; + if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { + return NULL; + } + + const FieldDescriptor* field_descriptor = + self->pool->FindFieldByName(string(name, name_size)); + if (field_descriptor == NULL) { + PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", + name); + return NULL; + } + + return PyFieldDescriptor_New(field_descriptor); +} + +PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) { + Py_ssize_t name_size; + char* name; + if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { + return NULL; + } + + const FieldDescriptor* field_descriptor = + self->pool->FindExtensionByName(string(name, name_size)); + if (field_descriptor == NULL) { + PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", name); + return NULL; + } + + return PyFieldDescriptor_New(field_descriptor); +} + +PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) { + Py_ssize_t name_size; + char* name; + if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { + return NULL; + } + + const EnumDescriptor* enum_descriptor = + self->pool->FindEnumTypeByName(string(name, name_size)); + if (enum_descriptor == NULL) { + PyErr_Format(PyExc_TypeError, "Couldn't find enum %.200s", name); + return NULL; + } + + return PyEnumDescriptor_New(enum_descriptor); +} + +PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) { + Py_ssize_t name_size; + char* name; + if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { + return NULL; + } + + const OneofDescriptor* oneof_descriptor = + self->pool->FindOneofByName(string(name, name_size)); + if (oneof_descriptor == NULL) { + PyErr_Format(PyExc_TypeError, "Couldn't find oneof %.200s", name); + return NULL; + } + + return PyOneofDescriptor_New(oneof_descriptor); +} + +static PyMethodDef Methods[] = { + { C("FindFieldByName"), + (PyCFunction)FindFieldByName, + METH_O, + C("Searches for a field descriptor by full name.") }, + { C("FindExtensionByName"), + (PyCFunction)FindExtensionByName, + METH_O, + C("Searches for extension descriptor by full name.") }, + {NULL} +}; + +} // namespace cdescriptor_pool + +PyTypeObject PyDescriptorPool_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + C("google.protobuf.internal." + "_message.DescriptorPool"), // tp_name + sizeof(PyDescriptorPool), // tp_basicsize + 0, // tp_itemsize + (destructor)cdescriptor_pool::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + C("A Descriptor Pool"), // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + cdescriptor_pool::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + 0, // tp_new + PyObject_Del, // tp_free +}; + +// The code below loads new Descriptors from a serialized FileDescriptorProto. + + +// Collects errors that occur during proto file building to allow them to be +// propagated in the python exception instead of only living in ERROR logs. +class BuildFileErrorCollector : public DescriptorPool::ErrorCollector { + public: + BuildFileErrorCollector() : error_message(""), had_errors(false) {} + + void AddError(const string& filename, const string& element_name, + const Message* descriptor, ErrorLocation location, + const string& message) { + // Replicates the logging behavior that happens in the C++ implementation + // when an error collector is not passed in. + if (!had_errors) { + error_message += + ("Invalid proto descriptor for file \"" + filename + "\":\n"); + } + // As this only happens on failure and will result in the program not + // running at all, no effort is made to optimize this string manipulation. + error_message += (" " + element_name + ": " + message + "\n"); + } + + string error_message; + bool had_errors; +}; + +PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) { + char* message_type; + Py_ssize_t message_len; + + if (PyBytes_AsStringAndSize(serialized_pb, &message_type, &message_len) < 0) { + return NULL; + } + + FileDescriptorProto file_proto; + if (!file_proto.ParseFromArray(message_type, message_len)) { + PyErr_SetString(PyExc_TypeError, "Couldn't parse file content!"); + return NULL; + } + + // If the file was already part of a C++ library, all its descriptors are in + // the underlying pool. No need to do anything else. + const FileDescriptor* generated_file = + DescriptorPool::generated_pool()->FindFileByName(file_proto.name()); + if (generated_file != NULL) { + return PyFileDescriptor_NewWithPb(generated_file, serialized_pb); + } + + BuildFileErrorCollector error_collector; + const FileDescriptor* descriptor = + GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto, + &error_collector); + if (descriptor == NULL) { + PyErr_Format(PyExc_TypeError, + "Couldn't build proto file into descriptor pool!\n%s", + error_collector.error_message.c_str()); + return NULL; + } + + return PyFileDescriptor_NewWithPb(descriptor, serialized_pb); +} + +static PyDescriptorPool* global_cdescriptor_pool = NULL; + +bool InitDescriptorPool() { + if (PyType_Ready(&PyDescriptorPool_Type) < 0) + return false; + + global_cdescriptor_pool = cdescriptor_pool::NewDescriptorPool(); + if (global_cdescriptor_pool == NULL) { + return false; + } + + return true; +} + +PyDescriptorPool* GetDescriptorPool() { + return global_cdescriptor_pool; +} + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h new file mode 100644 index 00000000..4e494b89 --- /dev/null +++ b/python/google/protobuf/pyext/descriptor_pool.h @@ -0,0 +1,152 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace python { + +// Wraps operations to the global DescriptorPool which contains information +// about all messages and fields. +// +// There is normally one pool per process. We make it a Python object only +// because it contains many Python references. +// TODO(amauryfa): See whether such objects can appear in reference cycles, and +// consider adding support for the cyclic GC. +// +// "Methods" that interacts with this DescriptorPool are in the cdescriptor_pool +// namespace. +typedef struct PyDescriptorPool { + PyObject_HEAD + + DescriptorPool* pool; + + // Make our own mapping to retrieve Python classes from C++ descriptors. + // + // Descriptor pointers stored here are owned by the DescriptorPool above. + // Python references to classes are owned by this PyDescriptorPool. + typedef hash_map ClassesByMessageMap; + ClassesByMessageMap* classes_by_descriptor; + + // Store interned descriptors, so that the same C++ descriptor yields the same + // Python object. Objects are not immortal: this map does not own the + // references, and items are deleted when the last reference to the object is + // released. + // This is enough to support the "is" operator on live objects. + // All descriptors are stored here. + hash_map* interned_descriptors; + + // Cache the options for any kind of descriptor. + // Descriptor pointers are owned by the DescriptorPool above. + // Python objects are owned by the map. + hash_map* descriptor_options; +} PyDescriptorPool; + + +extern PyTypeObject PyDescriptorPool_Type; + +namespace cdescriptor_pool { + +// Builds a new DescriptorPool. Normally called only once per process. +PyDescriptorPool* NewDescriptorPool(); + +// Looks up a message by name. +// Returns a message Descriptor, or NULL if not found. +const Descriptor* FindMessageTypeByName(PyDescriptorPool* self, + const string& name); + +// Registers a new Python class for the given message descriptor. +// Returns the message Descriptor. +// On error, returns NULL with a Python exception set. +const Descriptor* RegisterMessageClass( + PyDescriptorPool* self, PyObject* message_class, PyObject* descriptor); + +// Retrieves the Python class registered with the given message descriptor. +// +// Returns a *borrowed* reference if found, otherwise returns NULL with an +// exception set. +PyObject* GetMessageClass(PyDescriptorPool* self, + const Descriptor* message_descriptor); + +// Looks up a message by name. Returns a PyMessageDescriptor corresponding to +// the field on success, or NULL on failure. +// +// Returns a new reference. +PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* name); + +// Looks up a field by name. Returns a PyFieldDescriptor corresponding to +// the field on success, or NULL on failure. +// +// Returns a new reference. +PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* name); + +// Looks up an extension by name. Returns a PyFieldDescriptor corresponding +// to the field on success, or NULL on failure. +// +// Returns a new reference. +PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg); + +// Looks up an enum type by name. Returns a PyEnumDescriptor corresponding +// to the field on success, or NULL on failure. +// +// Returns a new reference. +PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg); + +// Looks up a oneof by name. Returns a COneofDescriptor corresponding +// to the oneof on success, or NULL on failure. +// +// Returns a new reference. +PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg); + +} // namespace cdescriptor_pool + +// Implement the Python "_BuildFile" method, it takes a serialized +// FileDescriptorProto, and adds it to the C++ DescriptorPool. +// It returns a new FileDescriptor object, or NULL when an exception is raised. +PyObject* Python_BuildFile(PyObject* ignored, PyObject* args); + +// Retrieve the global descriptor pool owned by the _message module. +PyDescriptorPool* GetDescriptorPool(); + +// Initialize objects used by this module. +bool InitDescriptorPool(); + +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_POOL_H__ diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc index d83b57d5..8e38fc42 100644 --- a/python/google/protobuf/pyext/extension_dict.cc +++ b/python/google/protobuf/pyext/extension_dict.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -48,13 +49,11 @@ namespace google { namespace protobuf { namespace python { -extern google::protobuf::DynamicMessageFactory* global_message_factory; - namespace extension_dict { // TODO(tibell): Always use self->message for clarity, just like in // RepeatedCompositeContainer. -static google::protobuf::Message* GetMessage(ExtensionDict* self) { +static Message* GetMessage(ExtensionDict* self) { if (self->parent != NULL) { return self->parent->message; } else { @@ -73,10 +72,9 @@ PyObject* len(ExtensionDict* self) { // TODO(tibell): Use VisitCompositeField. int ReleaseExtension(ExtensionDict* self, PyObject* extension, - const google::protobuf::FieldDescriptor* descriptor) { - if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { - if (descriptor->cpp_type() == - google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + const FieldDescriptor* descriptor) { + if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { + if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (repeated_composite_container::Release( reinterpret_cast( extension)) < 0) { @@ -89,8 +87,7 @@ int ReleaseExtension(ExtensionDict* self, return -1; } } - } else if (descriptor->cpp_type() == - google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (cmessage::ReleaseSubMessage( GetMessage(self), descriptor, reinterpret_cast(extension)) < 0) { @@ -102,8 +99,7 @@ int ReleaseExtension(ExtensionDict* self, } PyObject* subscript(ExtensionDict* self, PyObject* key) { - const google::protobuf::FieldDescriptor* descriptor = - cmessage::GetExtensionDescriptor(key); + const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); if (descriptor == NULL) { return NULL; } @@ -162,8 +158,7 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) { } int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) { - const google::protobuf::FieldDescriptor* descriptor = - cmessage::GetExtensionDescriptor(key); + const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); if (descriptor == NULL) { return -1; } @@ -187,7 +182,7 @@ int ass_subscript(ExtensionDict* self, PyObject* key, PyObject* value) { } PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) { - const google::protobuf::FieldDescriptor* descriptor = + const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(extension); if (descriptor == NULL) { return NULL; @@ -208,7 +203,7 @@ PyObject* ClearExtension(ExtensionDict* self, PyObject* extension) { } PyObject* HasExtension(ExtensionDict* self, PyObject* extension) { - const google::protobuf::FieldDescriptor* descriptor = + const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(extension); if (descriptor == NULL) { return NULL; diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h index 47625e23..7e1049f1 100644 --- a/python/google/protobuf/pyext/extension_dict.h +++ b/python/google/protobuf/pyext/extension_dict.h @@ -41,7 +41,6 @@ #include #endif - namespace google { namespace protobuf { @@ -94,7 +93,7 @@ PyObject* len(ExtensionDict* self); // Returns 0 on success, -1 on failure. int ReleaseExtension(ExtensionDict* self, PyObject* extension, - const google::protobuf::FieldDescriptor* descriptor); + const FieldDescriptor* descriptor); // Gets an extension from the dict for the given extension descriptor. // diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index cd956e0e..137f5d5f 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -39,6 +39,7 @@ #endif #include #include +#include // A Python header file. #ifndef PyVarObject_HEAD_INIT #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size, @@ -54,10 +55,12 @@ #include #include #include +#include #include #include #include #include +#include #if PY_MAJOR_VERSION >= 3 #define PyInt_Check PyLong_Check @@ -72,6 +75,10 @@ #else #define PyString_AsString(ob) \ (PyUnicode_Check(ob)? PyUnicode_AsUTF8(ob): PyBytes_AsString(ob)) + #define PyString_AsStringAndSize(ob, charpp, sizep) \ + (PyUnicode_Check(ob)? \ + ((*(charpp) = PyUnicode_AsUTF8AndSize(ob, (sizep))) == NULL? -1: 0): \ + PyBytes_AsStringAndSize(ob, (charpp), (sizep))) #endif #endif @@ -81,14 +88,14 @@ namespace python { // Forward declarations namespace cmessage { -static const google::protobuf::FieldDescriptor* GetFieldDescriptor( +static const FieldDescriptor* GetFieldDescriptor( CMessage* self, PyObject* name); -static const google::protobuf::Descriptor* GetMessageDescriptor(PyTypeObject* cls); +static const Descriptor* GetMessageDescriptor(PyTypeObject* cls); static string GetMessageName(CMessage* self); int InternalReleaseFieldByDescriptor( - const google::protobuf::FieldDescriptor* field_descriptor, + const FieldDescriptor* field_descriptor, PyObject* composite_field, - google::protobuf::Message* parent_message); + Message* parent_message); } // namespace cmessage // --------------------------------------------------------------------- @@ -107,7 +114,7 @@ struct ChildVisitor { // Returns 0 on success, -1 on failure. int VisitCMessage(CMessage* cmessage, - const google::protobuf::FieldDescriptor* field_descriptor) { + const FieldDescriptor* field_descriptor) { return 0; } }; @@ -118,8 +125,8 @@ template static int VisitCompositeField(const FieldDescriptor* descriptor, PyObject* child, Visitor visitor) { - if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { - if (descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { + if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { RepeatedCompositeContainer* container = reinterpret_cast(child); if (visitor.VisitRepeatedCompositeContainer(container) == -1) @@ -130,8 +137,7 @@ static int VisitCompositeField(const FieldDescriptor* descriptor, if (visitor.VisitRepeatedScalarContainer(container) == -1) return -1; } - } else if (descriptor->cpp_type() == - google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { CMessage* cmsg = reinterpret_cast(child); if (visitor.VisitCMessage(cmsg, descriptor) == -1) return -1; @@ -149,25 +155,31 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) { PyObject* key; PyObject* field; - // Never use self->message in this function, it may be already freed. - const google::protobuf::Descriptor* message_descriptor = - cmessage::GetMessageDescriptor(Py_TYPE(self)); - // Visit normal fields. - while (PyDict_Next(self->composite_fields, &pos, &key, &field)) { - const google::protobuf::FieldDescriptor* descriptor = - message_descriptor->FindFieldByName(PyString_AsString(key)); - if (descriptor != NULL) { - if (VisitCompositeField(descriptor, field, visitor) == -1) + if (self->composite_fields) { + // Never use self->message in this function, it may be already freed. + const Descriptor* message_descriptor = + cmessage::GetMessageDescriptor(Py_TYPE(self)); + while (PyDict_Next(self->composite_fields, &pos, &key, &field)) { + Py_ssize_t key_str_size; + char *key_str_data; + if (PyString_AsStringAndSize(key, &key_str_data, &key_str_size) != 0) return -1; + const string key_str(key_str_data, key_str_size); + const FieldDescriptor* descriptor = + message_descriptor->FindFieldByName(key_str); + if (descriptor != NULL) { + if (VisitCompositeField(descriptor, field, visitor) == -1) + return -1; + } } } // Visit extension fields. if (self->extensions != NULL) { + pos = 0; while (PyDict_Next(self->extensions->values, &pos, &key, &field)) { - const google::protobuf::FieldDescriptor* descriptor = - cmessage::GetExtensionDescriptor(key); + const FieldDescriptor* descriptor = cmessage::GetExtensionDescriptor(key); if (descriptor == NULL) return -1; if (VisitCompositeField(descriptor, field, visitor) == -1) @@ -180,6 +192,8 @@ int ForEachCompositeField(CMessage* self, Visitor visitor) { // --------------------------------------------------------------------- +static DynamicMessageFactory* message_factory; + // Constants used for integer type range checking. PyObject* kPythonZero; PyObject* kint32min_py; @@ -198,17 +212,8 @@ PyObject* PickleError_class; static PyObject* kDESCRIPTOR; static PyObject* k_cdescriptor; static PyObject* kfull_name; -static PyObject* kname; -static PyObject* kextensions_by_name; static PyObject* k_extensions_by_name; static PyObject* k_extensions_by_number; -static PyObject* kfields_by_name; - -static PyDescriptorPool* descriptor_pool; - -PyDescriptorPool* GetDescriptorPool() { - return descriptor_pool; -} /* Is 64bit */ void FormatTypeError(PyObject* arg, char* expected_types) { @@ -305,14 +310,14 @@ bool CheckAndGetBool(PyObject* arg, bool* value) { } bool CheckAndSetString( - PyObject* arg, google::protobuf::Message* message, - const google::protobuf::FieldDescriptor* descriptor, - const google::protobuf::Reflection* reflection, + PyObject* arg, Message* message, + const FieldDescriptor* descriptor, + const Reflection* reflection, bool append, int index) { - GOOGLE_DCHECK(descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING || - descriptor->type() == google::protobuf::FieldDescriptor::TYPE_BYTES); - if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) { + GOOGLE_DCHECK(descriptor->type() == FieldDescriptor::TYPE_STRING || + descriptor->type() == FieldDescriptor::TYPE_BYTES); + if (descriptor->type() == FieldDescriptor::TYPE_STRING) { if (!PyBytes_Check(arg) && !PyUnicode_Check(arg)) { FormatTypeError(arg, "bytes, unicode"); return false; @@ -339,7 +344,7 @@ bool CheckAndSetString( } PyObject* encoded_string = NULL; - if (descriptor->type() == google::protobuf::FieldDescriptor::TYPE_STRING) { + if (descriptor->type() == FieldDescriptor::TYPE_STRING) { if (PyBytes_Check(arg)) { // The bytes were already validated as correctly encoded UTF-8 above. encoded_string = arg; // Already encoded. @@ -376,9 +381,8 @@ bool CheckAndSetString( return true; } -PyObject* ToStringObject( - const google::protobuf::FieldDescriptor* descriptor, string value) { - if (descriptor->type() != google::protobuf::FieldDescriptor::TYPE_STRING) { +PyObject* ToStringObject(const FieldDescriptor* descriptor, string value) { + if (descriptor->type() != FieldDescriptor::TYPE_STRING) { return PyBytes_FromStringAndSize(value.c_str(), value.length()); } @@ -394,8 +398,8 @@ PyObject* ToStringObject( return result; } -bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_descriptor, - const google::protobuf::Message* message) { +bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, + const Message* message) { if (message->GetDescriptor() == field_descriptor->containing_type()) { return true; } @@ -405,16 +409,18 @@ bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_d return false; } -google::protobuf::DynamicMessageFactory* global_message_factory; - namespace cmessage { +DynamicMessageFactory* GetMessageFactory() { + return message_factory; +} + static int MaybeReleaseOverlappingOneofField( CMessage* cmessage, - const google::protobuf::FieldDescriptor* field) { + const FieldDescriptor* field) { #ifdef GOOGLE_PROTOBUF_HAS_ONEOF - google::protobuf::Message* message = cmessage->message; - const google::protobuf::Reflection* reflection = message->GetReflection(); + Message* message = cmessage->message; + const Reflection* reflection = message->GetReflection(); if (!field->containing_oneof() || !reflection->HasOneof(*message, field->containing_oneof()) || reflection->HasField(*message, field)) { @@ -425,13 +431,13 @@ static int MaybeReleaseOverlappingOneofField( const OneofDescriptor* oneof = field->containing_oneof(); const FieldDescriptor* existing_field = reflection->GetOneofFieldDescriptor(*message, oneof); - if (existing_field->cpp_type() != google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + if (existing_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { // Non-message fields don't need to be released. return 0; } const char* field_name = existing_field->name().c_str(); - PyObject* child_message = PyDict_GetItemString( - cmessage->composite_fields, field_name); + PyObject* child_message = cmessage->composite_fields ? + PyDict_GetItemString(cmessage->composite_fields, field_name) : NULL; if (child_message == NULL) { // No python reference to this field so no need to release. return 0; @@ -450,21 +456,21 @@ static int MaybeReleaseOverlappingOneofField( // --------------------------------------------------------------------- // Making a message writable -static google::protobuf::Message* GetMutableMessage( +static Message* GetMutableMessage( CMessage* parent, - const google::protobuf::FieldDescriptor* parent_field) { - google::protobuf::Message* parent_message = parent->message; - const google::protobuf::Reflection* reflection = parent_message->GetReflection(); + const FieldDescriptor* parent_field) { + Message* parent_message = parent->message; + const Reflection* reflection = parent_message->GetReflection(); if (MaybeReleaseOverlappingOneofField(parent, parent_field) < 0) { return NULL; } return reflection->MutableMessage( - parent_message, parent_field, global_message_factory); + parent_message, parent_field, message_factory); } struct FixupMessageReference : public ChildVisitor { // message must outlive this object. - explicit FixupMessageReference(google::protobuf::Message* message) : + explicit FixupMessageReference(Message* message) : message_(message) {} int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { @@ -478,7 +484,7 @@ struct FixupMessageReference : public ChildVisitor { } private: - google::protobuf::Message* message_; + Message* message_; }; int AssureWritable(CMessage* self) { @@ -490,7 +496,7 @@ int AssureWritable(CMessage* self) { // If parent is NULL but we are trying to modify a read-only message, this // is a reference to a constant default instance that needs to be replaced // with a mutable top-level message. - const Message* prototype = global_message_factory->GetPrototype( + const Message* prototype = message_factory->GetPrototype( self->message->GetDescriptor()); self->message = prototype->New(); self->owner.reset(self->message); @@ -500,8 +506,8 @@ int AssureWritable(CMessage* self) { return -1; // Make self->message writable. - google::protobuf::Message* parent_message = self->parent->message; - google::protobuf::Message* mutable_message = GetMutableMessage( + Message* parent_message = self->parent->message; + Message* mutable_message = GetMutableMessage( self->parent, self->parent_field_descriptor); if (mutable_message == NULL) { @@ -528,38 +534,35 @@ int AssureWritable(CMessage* self) { // Retrieve the C++ Descriptor of a message class. // On error, returns NULL with an exception set. -static const google::protobuf::Descriptor* GetMessageDescriptor(PyTypeObject* cls) { +static const Descriptor* GetMessageDescriptor(PyTypeObject* cls) { ScopedPyObjectPtr descriptor(PyObject_GetAttr( reinterpret_cast(cls), kDESCRIPTOR)); if (descriptor == NULL) { PyErr_SetString(PyExc_TypeError, "Message class has no DESCRIPTOR"); return NULL; } - ScopedPyObjectPtr cdescriptor(PyObject_GetAttr(descriptor, k_cdescriptor)); - if (cdescriptor == NULL) { - PyErr_SetString(PyExc_TypeError, "Unregistered message."); + if (!PyObject_TypeCheck(descriptor, &PyMessageDescriptor_Type)) { + PyErr_Format(PyExc_TypeError, "Expected a message Descriptor, got %s", + descriptor->ob_type->tp_name); return NULL; } - if (!PyObject_TypeCheck(cdescriptor, &CMessageDescriptor_Type)) { - PyErr_SetString(PyExc_TypeError, "Not a CMessageDescriptor"); - return NULL; - } - return reinterpret_cast(cdescriptor.get())->descriptor; + return PyMessageDescriptor_AsDescriptor(descriptor); } // Retrieve a C++ FieldDescriptor for a message attribute. // The C++ message must be valid. // TODO(amauryfa): This function should stay internal, because exception // handling is not consistent. -static const google::protobuf::FieldDescriptor* GetFieldDescriptor( +static const FieldDescriptor* GetFieldDescriptor( CMessage* self, PyObject* name) { - const google::protobuf::Descriptor *message_descriptor = self->message->GetDescriptor(); - const char* field_name = PyString_AsString(name); - if (field_name == NULL) { + const Descriptor *message_descriptor = self->message->GetDescriptor(); + char* field_name; + Py_ssize_t size; + if (PyString_AsStringAndSize(name, &field_name, &size) < 0) { return NULL; } - const google::protobuf::FieldDescriptor *field_descriptor = - message_descriptor->FindFieldByName(field_name); + const FieldDescriptor *field_descriptor = + message_descriptor->FindFieldByName(string(field_name, size)); if (field_descriptor == NULL) { // Note: No exception is set! return NULL; @@ -568,19 +571,16 @@ static const google::protobuf::FieldDescriptor* GetFieldDescriptor( } // Retrieve a C++ FieldDescriptor for an extension handle. -const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extension) { - ScopedPyObjectPtr cdescriptor( - PyObject_GetAttrString(extension, "_cdescriptor")); - if (cdescriptor == NULL) { - PyErr_SetString(PyExc_KeyError, "Unregistered extension."); +const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) { + ScopedPyObjectPtr cdescriptor; + if (!PyObject_TypeCheck(extension, &PyFieldDescriptor_Type)) { + // Most callers consider extensions as a plain dictionary. We should + // allow input which is not a field descriptor, and simply pretend it does + // not exist. + PyErr_SetObject(PyExc_KeyError, extension); return NULL; } - if (!PyObject_TypeCheck(cdescriptor, &CFieldDescriptor_Type)) { - PyErr_SetString(PyExc_TypeError, "Not a CFieldDescriptor"); - Py_DECREF(cdescriptor); - return NULL; - } - return reinterpret_cast(cdescriptor.get())->descriptor; + return PyFieldDescriptor_AsDescriptor(extension); } // If cmessage_list is not NULL, this function releases values into the @@ -588,12 +588,12 @@ const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extens // needs to do this to make sure CMessages stay alive if they're still // referenced after deletion. Repeated scalar container doesn't need to worry. int InternalDeleteRepeatedField( - google::protobuf::Message* message, - const google::protobuf::FieldDescriptor* field_descriptor, + Message* message, + const FieldDescriptor* field_descriptor, PyObject* slice, PyObject* cmessage_list) { Py_ssize_t length, from, to, step, slice_length; - const google::protobuf::Reflection* reflection = message->GetReflection(); + const Reflection* reflection = message->GetReflection(); int min, max; length = reflection->FieldSize(*message, field_descriptor); @@ -690,18 +690,18 @@ int InitAttributes(CMessage* self, PyObject* kwargs) { PyErr_SetString(PyExc_ValueError, "Field name must be a string"); return -1; } - const google::protobuf::FieldDescriptor* descriptor = GetFieldDescriptor(self, name); + const FieldDescriptor* descriptor = GetFieldDescriptor(self, name); if (descriptor == NULL) { PyErr_Format(PyExc_ValueError, "Protocol message has no \"%s\" field.", PyString_AsString(name)); return -1; } - if (descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { ScopedPyObjectPtr container(GetAttr(self, name)); if (container == NULL) { return -1; } - if (descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (repeated_composite_container::Extend( reinterpret_cast(container.get()), value) @@ -716,8 +716,7 @@ int InitAttributes(CMessage* self, PyObject* kwargs) { return -1; } } - } else if (descriptor->cpp_type() == - google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { ScopedPyObjectPtr message(GetAttr(self, name)); if (message == NULL) { return -1; @@ -737,8 +736,7 @@ int InitAttributes(CMessage* self, PyObject* kwargs) { // Allocates an incomplete Python Message: the caller must fill self->message, // self->owner and eventually self->parent. -CMessage* NewEmptyMessage(PyObject* type, - const google::protobuf::Descriptor *descriptor) { +CMessage* NewEmptyMessage(PyObject* type, const Descriptor *descriptor) { CMessage* self = reinterpret_cast( PyType_GenericAlloc(reinterpret_cast(type), 0)); if (self == NULL) { @@ -751,10 +749,7 @@ CMessage* NewEmptyMessage(PyObject* type, self->read_only = false; self->extensions = NULL; - self->composite_fields = PyDict_New(); - if (self->composite_fields == NULL) { - return NULL; - } + self->composite_fields = NULL; // If there are extension_ranges, the message is "extendable". Allocate a // dictionary to store the extension fields. @@ -776,12 +771,12 @@ CMessage* NewEmptyMessage(PyObject* type, static PyObject* New(PyTypeObject* type, PyObject* unused_args, PyObject* unused_kwargs) { // Retrieve the message descriptor and the default instance (=prototype). - const google::protobuf::Descriptor* message_descriptor = GetMessageDescriptor(type); + const Descriptor* message_descriptor = GetMessageDescriptor(type); if (message_descriptor == NULL) { return NULL; } - const google::protobuf::Message* default_message = - global_message_factory->GetPrototype(message_descriptor); + const Message* default_message = + message_factory->GetPrototype(message_descriptor); if (default_message == NULL) { PyErr_SetString(PyExc_TypeError, message_descriptor->full_name().c_str()); return NULL; @@ -836,7 +831,7 @@ struct ClearWeakReferences : public ChildVisitor { } int VisitCMessage(CMessage* cmessage, - const google::protobuf::FieldDescriptor* field_descriptor) { + const FieldDescriptor* field_descriptor) { cmessage->parent = NULL; return 0; } @@ -886,12 +881,12 @@ PyObject* IsInitialized(CMessage* self, PyObject* args) { } PyObject* HasFieldByDescriptor( - CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) { - google::protobuf::Message* message = self->message; + CMessage* self, const FieldDescriptor* field_descriptor) { + Message* message = self->message; if (!CheckFieldBelongsToMessage(field_descriptor, message)) { return NULL; } - if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { PyErr_SetString(PyExc_KeyError, "Field is repeated. A singular method is required."); return NULL; @@ -901,42 +896,78 @@ PyObject* HasFieldByDescriptor( return PyBool_FromLong(has_field ? 1 : 0); } -const google::protobuf::FieldDescriptor* FindFieldWithOneofs( - const google::protobuf::Message* message, const char* field_name, bool* in_oneof) { - const google::protobuf::Descriptor* descriptor = message->GetDescriptor(); - const google::protobuf::FieldDescriptor* field_descriptor = +const FieldDescriptor* FindFieldWithOneofs( + const Message* message, const string& field_name, bool* in_oneof) { + *in_oneof = false; + const Descriptor* descriptor = message->GetDescriptor(); + const FieldDescriptor* field_descriptor = descriptor->FindFieldByName(field_name); - if (field_descriptor == NULL) { - const google::protobuf::OneofDescriptor* oneof_desc = - message->GetDescriptor()->FindOneofByName(field_name); - if (oneof_desc == NULL) { - *in_oneof = false; - return NULL; - } else { - *in_oneof = true; - return message->GetReflection()->GetOneofFieldDescriptor( - *message, oneof_desc); + if (field_descriptor != NULL) { + return field_descriptor; + } + const OneofDescriptor* oneof_desc = + descriptor->FindOneofByName(field_name); + if (oneof_desc != NULL) { + *in_oneof = true; + return message->GetReflection()->GetOneofFieldDescriptor(*message, + oneof_desc); + } + return NULL; +} + +bool CheckHasPresence(const FieldDescriptor* field_descriptor, bool in_oneof) { + if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { + PyErr_Format(PyExc_ValueError, + "Protocol message has no singular \"%s\" field.", + field_descriptor->name().c_str()); + return false; + } + + if (field_descriptor->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) { + // HasField() for a oneof *itself* isn't supported. + if (in_oneof) { + PyErr_Format(PyExc_ValueError, + "Can't test oneof field \"%s\" for presence in proto3, use " + "WhichOneof instead.", + field_descriptor->containing_oneof()->name().c_str()); + return false; + } + + // ...but HasField() for fields *in* a oneof is supported. + if (field_descriptor->containing_oneof() != NULL) { + return true; + } + + if (field_descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + PyErr_Format( + PyExc_ValueError, + "Can't test non-submessage field \"%s\" for presence in proto3.", + field_descriptor->name().c_str()); + return false; } } - return field_descriptor; + + return true; } PyObject* HasField(CMessage* self, PyObject* arg) { -#if PY_MAJOR_VERSION < 3 char* field_name; - if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) { + Py_ssize_t size; +#if PY_MAJOR_VERSION < 3 + if (PyString_AsStringAndSize(arg, &field_name, &size) < 0) { + return NULL; + } #else - char* field_name = PyUnicode_AsUTF8(arg); + field_name = PyUnicode_AsUTF8AndSize(arg, &size); if (!field_name) { -#endif return NULL; } +#endif - google::protobuf::Message* message = self->message; - const google::protobuf::Descriptor* descriptor = message->GetDescriptor(); + Message* message = self->message; bool is_in_oneof; - const google::protobuf::FieldDescriptor* field_descriptor = - FindFieldWithOneofs(message, field_name, &is_in_oneof); + const FieldDescriptor* field_descriptor = + FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof); if (field_descriptor == NULL) { if (!is_in_oneof) { PyErr_Format(PyExc_ValueError, "Unknown field %s.", field_name); @@ -946,28 +977,28 @@ PyObject* HasField(CMessage* self, PyObject* arg) { } } - if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { - PyErr_Format(PyExc_ValueError, - "Protocol message has no singular \"%s\" field.", field_name); + if (!CheckHasPresence(field_descriptor, is_in_oneof)) { return NULL; } - bool has_field = - message->GetReflection()->HasField(*message, field_descriptor); - if (!has_field && field_descriptor->cpp_type() == - google::protobuf::FieldDescriptor::CPPTYPE_ENUM) { - // We may have an invalid enum value stored in the UnknownFieldSet and need - // to check presence in there as well. - const google::protobuf::UnknownFieldSet& unknown_field_set = + if (message->GetReflection()->HasField(*message, field_descriptor)) { + Py_RETURN_TRUE; + } + if (!message->GetReflection()->SupportsUnknownEnumValues() && + field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + // Special case: Python HasField() differs in semantics from C++ + // slightly: we return HasField('enum_field') == true if there is + // an unknown enum value present. To implement this we have to + // look in the UnknownFieldSet. + const UnknownFieldSet& unknown_field_set = message->GetReflection()->GetUnknownFields(*message); for (int i = 0; i < unknown_field_set.field_count(); ++i) { if (unknown_field_set.field(i).number() == field_descriptor->number()) { Py_RETURN_TRUE; } } - Py_RETURN_FALSE; } - return PyBool_FromLong(has_field ? 1 : 0); + Py_RETURN_FALSE; } PyObject* ClearExtension(CMessage* self, PyObject* arg) { @@ -1034,7 +1065,7 @@ struct SetOwnerVisitor : public ChildVisitor { } int VisitCMessage(CMessage* cmessage, - const google::protobuf::FieldDescriptor* field_descriptor) { + const FieldDescriptor* field_descriptor) { return SetOwner(cmessage, new_owner_); } @@ -1053,18 +1084,17 @@ int SetOwner(CMessage* self, const shared_ptr& new_owner) { // Releases the message specified by 'field' and returns the // pointer. If the field does not exist a new message is created using // 'descriptor'. The caller takes ownership of the returned pointer. -Message* ReleaseMessage(google::protobuf::Message* message, - const google::protobuf::Descriptor* descriptor, - const google::protobuf::FieldDescriptor* field_descriptor) { +Message* ReleaseMessage(Message* message, + const Descriptor* descriptor, + const FieldDescriptor* field_descriptor) { Message* released_message = message->GetReflection()->ReleaseMessage( - message, field_descriptor, global_message_factory); + message, field_descriptor, message_factory); // ReleaseMessage will return NULL which differs from // child_cmessage->message, if the field does not exist. In this case, // the latter points to the default instance via a const_cast<>, so we // have to reset it to a new mutable object since we are taking ownership. if (released_message == NULL) { - const Message* prototype = global_message_factory->GetPrototype( - descriptor); + const Message* prototype = message_factory->GetPrototype(descriptor); GOOGLE_DCHECK(prototype != NULL); released_message = prototype->New(); } @@ -1072,8 +1102,8 @@ Message* ReleaseMessage(google::protobuf::Message* message, return released_message; } -int ReleaseSubMessage(google::protobuf::Message* message, - const google::protobuf::FieldDescriptor* field_descriptor, +int ReleaseSubMessage(Message* message, + const FieldDescriptor* field_descriptor, CMessage* child_cmessage) { // Release the Message shared_ptr released_message(ReleaseMessage( @@ -1089,7 +1119,7 @@ int ReleaseSubMessage(google::protobuf::Message* message, struct ReleaseChild : public ChildVisitor { // message must outlive this object. - explicit ReleaseChild(google::protobuf::Message* parent_message) : + explicit ReleaseChild(Message* parent_message) : parent_message_(parent_message) {} int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { @@ -1103,38 +1133,27 @@ struct ReleaseChild : public ChildVisitor { } int VisitCMessage(CMessage* cmessage, - const google::protobuf::FieldDescriptor* field_descriptor) { + const FieldDescriptor* field_descriptor) { return ReleaseSubMessage(parent_message_, field_descriptor, reinterpret_cast(cmessage)); } - google::protobuf::Message* parent_message_; + Message* parent_message_; }; int InternalReleaseFieldByDescriptor( - const google::protobuf::FieldDescriptor* field_descriptor, + const FieldDescriptor* field_descriptor, PyObject* composite_field, - google::protobuf::Message* parent_message) { + Message* parent_message) { return VisitCompositeField( field_descriptor, composite_field, ReleaseChild(parent_message)); } -int InternalReleaseField(CMessage* self, PyObject* composite_field, - PyObject* name) { - const google::protobuf::FieldDescriptor* descriptor = GetFieldDescriptor(self, name); - if (descriptor != NULL) { - return InternalReleaseFieldByDescriptor( - descriptor, composite_field, self->message); - } - - return 0; -} - PyObject* ClearFieldByDescriptor( CMessage* self, - const google::protobuf::FieldDescriptor* descriptor) { + const FieldDescriptor* descriptor) { if (!CheckFieldBelongsToMessage(descriptor, self->message)) { return NULL; } @@ -1144,25 +1163,23 @@ PyObject* ClearFieldByDescriptor( } PyObject* ClearField(CMessage* self, PyObject* arg) { - char* field_name; if (!PyString_Check(arg)) { PyErr_SetString(PyExc_TypeError, "field name must be a string"); return NULL; } #if PY_MAJOR_VERSION < 3 - if (PyString_AsStringAndSize(arg, &field_name, NULL) < 0) { - return NULL; - } + const char* field_name = PyString_AS_STRING(arg); + Py_ssize_t size = PyString_GET_SIZE(arg); #else - field_name = PyUnicode_AsUTF8(arg); + Py_ssize_t size; + const char* field_name = PyUnicode_AsUTF8AndSize(arg, &size); #endif AssureWritable(self); - google::protobuf::Message* message = self->message; - const google::protobuf::Descriptor* descriptor = message->GetDescriptor(); + Message* message = self->message; ScopedPyObjectPtr arg_in_oneof; bool is_in_oneof; - const google::protobuf::FieldDescriptor* field_descriptor = - FindFieldWithOneofs(message, field_name, &is_in_oneof); + const FieldDescriptor* field_descriptor = + FindFieldWithOneofs(message, string(field_name, size), &is_in_oneof); if (field_descriptor == NULL) { if (!is_in_oneof) { PyErr_Format(PyExc_ValueError, @@ -1172,24 +1189,27 @@ PyObject* ClearField(CMessage* self, PyObject* arg) { Py_RETURN_NONE; } } else if (is_in_oneof) { - arg_in_oneof.reset(PyString_FromString(field_descriptor->name().c_str())); + const string& name = field_descriptor->name(); + arg_in_oneof.reset(PyString_FromStringAndSize(name.c_str(), name.size())); arg = arg_in_oneof.get(); } - PyObject* composite_field = PyDict_GetItem(self->composite_fields, - arg); + PyObject* composite_field = self->composite_fields ? + PyDict_GetItem(self->composite_fields, arg) : NULL; // Only release the field if there's a possibility that there are // references to it. if (composite_field != NULL) { - if (InternalReleaseField(self, composite_field, arg) < 0) { + if (InternalReleaseFieldByDescriptor(field_descriptor, + composite_field, message) < 0) { return NULL; } PyDict_DelItem(self->composite_fields, arg); } message->GetReflection()->ClearField(message, field_descriptor); - if (field_descriptor->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_ENUM) { - google::protobuf::UnknownFieldSet* unknown_field_set = + if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM && + !message->GetReflection()->SupportsUnknownEnumValues()) { + UnknownFieldSet* unknown_field_set = message->GetReflection()->MutableUnknownFields(message); unknown_field_set->DeleteByNumber(field_descriptor->number()); } @@ -1212,7 +1232,9 @@ PyObject* Clear(CMessage* self) { } self->extensions = extension_dict; } - PyDict_Clear(self->composite_fields); + if (self->composite_fields) { + PyDict_Clear(self->composite_fields); + } self->message->Clear(); Py_RETURN_NONE; } @@ -1268,7 +1290,7 @@ static PyObject* SerializePartialToString(CMessage* self) { // Formats proto fields for ascii dumps using python formatting functions where // appropriate. -class PythonFieldValuePrinter : public google::protobuf::TextFormat::FieldValuePrinter { +class PythonFieldValuePrinter : public TextFormat::FieldValuePrinter { public: PythonFieldValuePrinter() : float_holder_(PyFloat_FromDouble(0)) {} @@ -1301,7 +1323,7 @@ class PythonFieldValuePrinter : public google::protobuf::TextFormat::FieldValueP }; static PyObject* ToStr(CMessage* self) { - google::protobuf::TextFormat::Printer printer; + TextFormat::Printer printer; // Passes ownership printer.SetDefaultFieldValuePrinter(new PythonFieldValuePrinter()); printer.SetHideUnknownFields(true); @@ -1383,9 +1405,9 @@ static PyObject* MergeFromString(CMessage* self, PyObject* arg) { } AssureWritable(self); - google::protobuf::io::CodedInputStream input( + io::CodedInputStream input( reinterpret_cast(data), data_length); - input.SetExtensionRegistry(descriptor_pool->pool, global_message_factory); + input.SetExtensionRegistry(GetDescriptorPool()->pool, message_factory); bool success = self->message->MergePartialFromCodedStream(&input); if (success) { return PyInt_FromLong(input.CurrentPosition()); @@ -1412,10 +1434,22 @@ static PyObject* RegisterExtension(PyObject* cls, if (message_descriptor == NULL) { return NULL; } - if (PyObject_SetAttrString(extension_handle, "containing_type", - message_descriptor) < 0) { + + const FieldDescriptor* descriptor = + GetExtensionDescriptor(extension_handle); + if (descriptor == NULL) { return NULL; } + const Descriptor* cmessage_descriptor = GetMessageDescriptor( + reinterpret_cast(cls)); + + if (cmessage_descriptor != descriptor->containing_type()) { + if (PyObject_SetAttrString(extension_handle, "containing_type", + message_descriptor) < 0) { + return NULL; + } + } + ScopedPyObjectPtr extensions_by_name( PyObject_GetAttr(cls, k_extensions_by_name)); if (extensions_by_name == NULL) { @@ -1426,6 +1460,20 @@ static PyObject* RegisterExtension(PyObject* cls, if (full_name == NULL) { return NULL; } + + // If the extension was already registered, check that it is the same. + PyObject* existing_extension = PyDict_GetItem(extensions_by_name, full_name); + if (existing_extension != NULL) { + const FieldDescriptor* existing_extension_descriptor = + GetExtensionDescriptor(existing_extension); + if (existing_extension_descriptor != descriptor) { + PyErr_SetString(PyExc_ValueError, "Double registration of Extensions"); + return NULL; + } + // Nothing else to do. + Py_RETURN_NONE; + } + if (PyDict_SetItem(extensions_by_name, full_name, extension_handle) < 0) { return NULL; } @@ -1445,17 +1493,12 @@ static PyObject* RegisterExtension(PyObject* cls, return NULL; } - const google::protobuf::FieldDescriptor* descriptor = - GetExtensionDescriptor(extension_handle); - if (descriptor == NULL) { - return NULL; - } // Check if it's a message set if (descriptor->is_extension() && descriptor->containing_type()->options().message_set_wire_format() && - descriptor->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE && + descriptor->type() == FieldDescriptor::TYPE_MESSAGE && descriptor->message_type() == descriptor->extension_scope() && - descriptor->label() == google::protobuf::FieldDescriptor::LABEL_OPTIONAL) { + descriptor->label() == FieldDescriptor::LABEL_OPTIONAL) { ScopedPyObjectPtr message_name(PyString_FromStringAndSize( descriptor->message_type()->full_name().c_str(), descriptor->message_type()->full_name().size())); @@ -1474,53 +1517,36 @@ static PyObject* SetInParent(CMessage* self, PyObject* args) { } static PyObject* WhichOneof(CMessage* self, PyObject* arg) { - char* oneof_name; - if (!PyString_Check(arg)) { - PyErr_SetString(PyExc_TypeError, "field name must be a string"); + Py_ssize_t name_size; + char *name_data; + if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0) return NULL; - } - oneof_name = PyString_AsString(arg); - if (oneof_name == NULL) { - return NULL; - } - const google::protobuf::OneofDescriptor* oneof_desc = + string oneof_name = string(name_data, name_size); + const OneofDescriptor* oneof_desc = self->message->GetDescriptor()->FindOneofByName(oneof_name); if (oneof_desc == NULL) { PyErr_Format(PyExc_ValueError, - "Protocol message has no oneof \"%s\" field.", oneof_name); + "Protocol message has no oneof \"%s\" field.", + oneof_name.c_str()); return NULL; } - const google::protobuf::FieldDescriptor* field_in_oneof = + const FieldDescriptor* field_in_oneof = self->message->GetReflection()->GetOneofFieldDescriptor( *self->message, oneof_desc); if (field_in_oneof == NULL) { Py_RETURN_NONE; } else { - return PyString_FromString(field_in_oneof->name().c_str()); + const string& name = field_in_oneof->name(); + return PyString_FromStringAndSize(name.c_str(), name.size()); } } static PyObject* ListFields(CMessage* self) { - vector fields; + vector fields; self->message->GetReflection()->ListFields(*self->message, &fields); - PyObject* descriptor = PyDict_GetItem(Py_TYPE(self)->tp_dict, kDESCRIPTOR); - if (descriptor == NULL) { - return NULL; - } - ScopedPyObjectPtr fields_by_name( - PyObject_GetAttr(descriptor, kfields_by_name)); - if (fields_by_name == NULL) { - return NULL; - } - ScopedPyObjectPtr extensions_by_name(PyObject_GetAttr( - reinterpret_cast(Py_TYPE(self)), k_extensions_by_name)); - if (extensions_by_name == NULL) { - PyErr_SetString(PyExc_ValueError, "no extensionsbyname"); - return NULL; - } // Normally, the list will be exactly the size of the fields. - PyObject* all_fields = PyList_New(fields.size()); + ScopedPyObjectPtr all_fields(PyList_New(fields.size())); if (all_fields == NULL) { return NULL; } @@ -1532,35 +1558,34 @@ static PyObject* ListFields(CMessage* self) { for (Py_ssize_t i = 0; i < fields.size(); ++i) { ScopedPyObjectPtr t(PyTuple_New(2)); if (t == NULL) { - Py_DECREF(all_fields); return NULL; } if (fields[i]->is_extension()) { - const string& field_name = fields[i]->full_name(); - PyObject* extension_field = PyDict_GetItemString(extensions_by_name, - field_name.c_str()); + ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(fields[i])); if (extension_field == NULL) { - // If we couldn't fetch extension_field, it means the module that - // defines this extension has not been explicitly imported in Python - // code, and the extension hasn't been registered. There's nothing much - // we can do about this, so just skip it in the output to match the - // behavior of the python implementation. + return NULL; + } + // With C++ descriptors, the field can always be retrieved, but for + // unknown extensions which have not been imported in Python code, there + // is no message class and we cannot retrieve the value. + // TODO(amauryfa): consider building the class on the fly! + if (fields[i]->message_type() != NULL && + cdescriptor_pool::GetMessageClass( + GetDescriptorPool(), fields[i]->message_type()) == NULL) { + PyErr_Clear(); continue; } PyObject* extensions = reinterpret_cast(self->extensions); if (extensions == NULL) { - Py_DECREF(all_fields); return NULL; } // 'extension' reference later stolen by PyTuple_SET_ITEM. PyObject* extension = PyObject_GetItem(extensions, extension_field); if (extension == NULL) { - Py_DECREF(all_fields); return NULL; } - Py_INCREF(extension_field); - PyTuple_SET_ITEM(t.get(), 0, extension_field); + PyTuple_SET_ITEM(t.get(), 0, extension_field.release()); // Steals reference to 'extension' PyTuple_SET_ITEM(t.get(), 1, extension); } else { @@ -1569,35 +1594,30 @@ static PyObject* ListFields(CMessage* self) { field_name.c_str(), field_name.length())); if (py_field_name == NULL) { PyErr_SetString(PyExc_ValueError, "bad string"); - Py_DECREF(all_fields); return NULL; } - PyObject* field_descriptor = - PyDict_GetItem(fields_by_name, py_field_name); + ScopedPyObjectPtr field_descriptor(PyFieldDescriptor_New(fields[i])); if (field_descriptor == NULL) { - Py_DECREF(all_fields); return NULL; } PyObject* field_value = GetAttr(self, py_field_name); if (field_value == NULL) { PyErr_SetObject(PyExc_ValueError, py_field_name); - Py_DECREF(all_fields); return NULL; } - Py_INCREF(field_descriptor); - PyTuple_SET_ITEM(t.get(), 0, field_descriptor); + PyTuple_SET_ITEM(t.get(), 0, field_descriptor.release()); PyTuple_SET_ITEM(t.get(), 1, field_value); } - PyList_SET_ITEM(all_fields, actual_size, t.release()); + PyList_SET_ITEM(all_fields.get(), actual_size, t.release()); ++actual_size; } - Py_SIZE(all_fields) = actual_size; - return all_fields; + Py_SIZE(all_fields.get()) = actual_size; + return all_fields.release(); } PyObject* FindInitializationErrors(CMessage* self) { - google::protobuf::Message* message = self->message; + Message* message = self->message; vector errors; message->FindInitializationErrors(&errors); @@ -1645,9 +1665,9 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) { PyObject* InternalGetScalar( CMessage* self, - const google::protobuf::FieldDescriptor* field_descriptor) { - google::protobuf::Message* message = self->message; - const google::protobuf::Reflection* reflection = message->GetReflection(); + const FieldDescriptor* field_descriptor) { + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); if (!CheckFieldBelongsToMessage(field_descriptor, message)) { return NULL; @@ -1655,50 +1675,51 @@ PyObject* InternalGetScalar( PyObject* result = NULL; switch (field_descriptor->cpp_type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + case FieldDescriptor::CPPTYPE_INT32: { int32 value = reflection->GetInt32(*message, field_descriptor); result = PyInt_FromLong(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + case FieldDescriptor::CPPTYPE_INT64: { int64 value = reflection->GetInt64(*message, field_descriptor); result = PyLong_FromLongLong(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + case FieldDescriptor::CPPTYPE_UINT32: { uint32 value = reflection->GetUInt32(*message, field_descriptor); result = PyInt_FromSize_t(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + case FieldDescriptor::CPPTYPE_UINT64: { uint64 value = reflection->GetUInt64(*message, field_descriptor); result = PyLong_FromUnsignedLongLong(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + case FieldDescriptor::CPPTYPE_FLOAT: { float value = reflection->GetFloat(*message, field_descriptor); result = PyFloat_FromDouble(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + case FieldDescriptor::CPPTYPE_DOUBLE: { double value = reflection->GetDouble(*message, field_descriptor); result = PyFloat_FromDouble(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + case FieldDescriptor::CPPTYPE_BOOL: { bool value = reflection->GetBool(*message, field_descriptor); result = PyBool_FromLong(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + case FieldDescriptor::CPPTYPE_STRING: { string value = reflection->GetString(*message, field_descriptor); result = ToStringObject(field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { - if (!message->GetReflection()->HasField(*message, field_descriptor)) { + case FieldDescriptor::CPPTYPE_ENUM: { + if (!message->GetReflection()->SupportsUnknownEnumValues() && + !message->GetReflection()->HasField(*message, field_descriptor)) { // Look for the value in the unknown fields. - google::protobuf::UnknownFieldSet* unknown_field_set = + UnknownFieldSet* unknown_field_set = message->GetReflection()->MutableUnknownFields(message); for (int i = 0; i < unknown_field_set->field_count(); ++i) { if (unknown_field_set->field(i).number() == @@ -1710,7 +1731,7 @@ PyObject* InternalGetScalar( } if (result == NULL) { - const google::protobuf::EnumValueDescriptor* enum_value = + const EnumValueDescriptor* enum_value = message->GetReflection()->GetEnum(*message, field_descriptor); result = PyInt_FromLong(enum_value->number()); } @@ -1726,13 +1747,13 @@ PyObject* InternalGetScalar( } PyObject* InternalGetSubMessage( - CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor) { - const google::protobuf::Reflection* reflection = self->message->GetReflection(); - const google::protobuf::Message& sub_message = reflection->GetMessage( - *self->message, field_descriptor, global_message_factory); + CMessage* self, const FieldDescriptor* field_descriptor) { + const Reflection* reflection = self->message->GetReflection(); + const Message& sub_message = reflection->GetMessage( + *self->message, field_descriptor, message_factory); PyObject *message_class = cdescriptor_pool::GetMessageClass( - descriptor_pool, field_descriptor->message_type()); + GetDescriptorPool(), field_descriptor->message_type()); if (message_class == NULL) { return NULL; } @@ -1747,17 +1768,17 @@ PyObject* InternalGetSubMessage( cmsg->parent = self; cmsg->parent_field_descriptor = field_descriptor; cmsg->read_only = !reflection->HasField(*self->message, field_descriptor); - cmsg->message = const_cast(&sub_message); + cmsg->message = const_cast(&sub_message); return reinterpret_cast(cmsg); } int InternalSetScalar( CMessage* self, - const google::protobuf::FieldDescriptor* field_descriptor, + const FieldDescriptor* field_descriptor, PyObject* arg) { - google::protobuf::Message* message = self->message; - const google::protobuf::Reflection* reflection = message->GetReflection(); + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); if (!CheckFieldBelongsToMessage(field_descriptor, message)) { return -1; @@ -1768,59 +1789,62 @@ int InternalSetScalar( } switch (field_descriptor->cpp_type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + case FieldDescriptor::CPPTYPE_INT32: { GOOGLE_CHECK_GET_INT32(arg, value, -1); reflection->SetInt32(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + case FieldDescriptor::CPPTYPE_INT64: { GOOGLE_CHECK_GET_INT64(arg, value, -1); reflection->SetInt64(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + case FieldDescriptor::CPPTYPE_UINT32: { GOOGLE_CHECK_GET_UINT32(arg, value, -1); reflection->SetUInt32(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + case FieldDescriptor::CPPTYPE_UINT64: { GOOGLE_CHECK_GET_UINT64(arg, value, -1); reflection->SetUInt64(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + case FieldDescriptor::CPPTYPE_FLOAT: { GOOGLE_CHECK_GET_FLOAT(arg, value, -1); reflection->SetFloat(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + case FieldDescriptor::CPPTYPE_DOUBLE: { GOOGLE_CHECK_GET_DOUBLE(arg, value, -1); reflection->SetDouble(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + case FieldDescriptor::CPPTYPE_BOOL: { GOOGLE_CHECK_GET_BOOL(arg, value, -1); reflection->SetBool(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + case FieldDescriptor::CPPTYPE_STRING: { if (!CheckAndSetString( arg, message, field_descriptor, reflection, false, -1)) { return -1; } break; } - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { + case FieldDescriptor::CPPTYPE_ENUM: { GOOGLE_CHECK_GET_INT32(arg, value, -1); - const google::protobuf::EnumDescriptor* enum_descriptor = - field_descriptor->enum_type(); - const google::protobuf::EnumValueDescriptor* enum_value = - enum_descriptor->FindValueByNumber(value); - if (enum_value != NULL) { - reflection->SetEnum(message, field_descriptor, enum_value); + if (reflection->SupportsUnknownEnumValues()) { + reflection->SetEnumValue(message, field_descriptor, value); } else { - PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value); - return -1; + const EnumDescriptor* enum_descriptor = field_descriptor->enum_type(); + const EnumValueDescriptor* enum_value = + enum_descriptor->FindValueByNumber(value); + if (enum_value != NULL) { + reflection->SetEnum(message, field_descriptor, enum_value); + } else { + PyErr_Format(PyExc_ValueError, "Unknown enum value: %d", value); + return -1; + } } break; } @@ -1851,14 +1875,35 @@ PyObject* FromString(PyTypeObject* cls, PyObject* serialized) { return py_cmsg; } +// Add the number of a field descriptor to the containing message class. +// Equivalent to: +// _cls._FIELD_NUMBER = +static bool AddFieldNumberToClass( + PyObject* cls, const FieldDescriptor* field_descriptor) { + string constant_name = field_descriptor->name() + "_FIELD_NUMBER"; + UpperString(&constant_name); + ScopedPyObjectPtr attr_name(PyString_FromStringAndSize( + constant_name.c_str(), constant_name.size())); + if (attr_name == NULL) { + return false; + } + ScopedPyObjectPtr number(PyInt_FromLong(field_descriptor->number())); + if (number == NULL) { + return false; + } + if (PyObject_SetAttr(cls, attr_name, number) == -1) { + return false; + } + return true; +} + // Finalize the creation of the Message class. // Called from its metaclass: GeneratedProtocolMessageType.__init__(). -static PyObject* AddDescriptors(PyTypeObject* cls, - PyObject* descriptor) { - const google::protobuf::Descriptor* message_descriptor = +static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) { + const Descriptor* message_descriptor = cdescriptor_pool::RegisterMessageClass( - descriptor_pool, reinterpret_cast(cls), descriptor); + GetDescriptorPool(), cls, descriptor); if (message_descriptor == NULL) { return NULL; } @@ -1867,169 +1912,80 @@ static PyObject* AddDescriptors(PyTypeObject* cls, // classes will register themselves in this class. if (message_descriptor->extension_range_count() > 0) { ScopedPyObjectPtr by_name(PyDict_New()); - if (PyObject_SetAttr(reinterpret_cast(cls), - k_extensions_by_name, by_name) < 0) { + if (PyObject_SetAttr(cls, k_extensions_by_name, by_name) < 0) { return NULL; } ScopedPyObjectPtr by_number(PyDict_New()); - if (PyObject_SetAttr(reinterpret_cast(cls), - k_extensions_by_number, by_number) < 0) { + if (PyObject_SetAttr(cls, k_extensions_by_number, by_number) < 0) { return NULL; } } - ScopedPyObjectPtr fields(PyObject_GetAttrString(descriptor, "fields")); - if (fields == NULL) { - return NULL; - } - - ScopedPyObjectPtr _NUMBER_string(PyString_FromString("_FIELD_NUMBER")); - if (_NUMBER_string == NULL) { - return NULL; - } - - const Py_ssize_t fields_size = PyList_GET_SIZE(fields.get()); - for (int i = 0; i < fields_size; ++i) { - PyObject* field = PyList_GET_ITEM(fields.get(), i); - ScopedPyObjectPtr field_name(PyObject_GetAttr(field, kname)); - ScopedPyObjectPtr full_field_name(PyObject_GetAttr(field, kfull_name)); - if (field_name == NULL || full_field_name == NULL) { - PyErr_SetString(PyExc_TypeError, "Name is null"); - return NULL; - } - - ScopedPyObjectPtr field_descriptor( - cdescriptor_pool::FindFieldByName(descriptor_pool, full_field_name)); - if (field_descriptor == NULL) { - PyErr_SetString(PyExc_TypeError, "Couldn't find field"); - return NULL; - } - CFieldDescriptor* cfield_descriptor = reinterpret_cast( - field_descriptor.get()); - - // The FieldDescriptor's name field might either be of type bytes or - // of type unicode, depending on whether the FieldDescriptor was - // parsed from a serialized message or read from the - // _pb2.py module. - ScopedPyObjectPtr field_name_upcased( - PyObject_CallMethod(field_name, "upper", NULL)); - if (field_name_upcased == NULL) { - return NULL; - } - - ScopedPyObjectPtr field_number_name(PyObject_CallMethod( - field_name_upcased, "__add__", "(O)", _NUMBER_string.get())); - if (field_number_name == NULL) { - return NULL; - } - - ScopedPyObjectPtr number(PyInt_FromLong( - cfield_descriptor->descriptor->number())); - if (number == NULL) { - return NULL; - } - if (PyObject_SetAttr(reinterpret_cast(cls), - field_number_name, number) == -1) { + // For each field set: cls._FIELD_NUMBER = + for (int i = 0; i < message_descriptor->field_count(); ++i) { + if (!AddFieldNumberToClass(cls, message_descriptor->field(i))) { return NULL; } } - // Enum Values - ScopedPyObjectPtr enum_types(PyObject_GetAttrString(descriptor, - "enum_types")); - if (enum_types == NULL) { - return NULL; - } - ScopedPyObjectPtr type_iter(PyObject_GetIter(enum_types)); - if (type_iter == NULL) { - return NULL; - } - ScopedPyObjectPtr enum_type; - while ((enum_type.reset(PyIter_Next(type_iter))) != NULL) { + // For each enum set cls. = EnumTypeWrapper(). + // + // The enum descriptor we get from + // .enum_types_by_name[name] + // which was built previously. + for (int i = 0; i < message_descriptor->enum_type_count(); ++i) { + const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i); + ScopedPyObjectPtr enum_type(PyEnumDescriptor_New(enum_descriptor)); + if (enum_type == NULL) { + return NULL; + } + // Add wrapped enum type to message class. ScopedPyObjectPtr wrapped(PyObject_CallFunctionObjArgs( EnumTypeWrapper_class, enum_type.get(), NULL)); if (wrapped == NULL) { return NULL; } - ScopedPyObjectPtr enum_name(PyObject_GetAttr(enum_type, kname)); - if (enum_name == NULL) { - return NULL; - } - if (PyObject_SetAttr(reinterpret_cast(cls), - enum_name, wrapped) == -1) { + if (PyObject_SetAttrString( + cls, enum_descriptor->name().c_str(), wrapped) == -1) { return NULL; } - ScopedPyObjectPtr enum_values(PyObject_GetAttrString(enum_type, "values")); - if (enum_values == NULL) { - return NULL; - } - ScopedPyObjectPtr values_iter(PyObject_GetIter(enum_values)); - if (values_iter == NULL) { - return NULL; - } - ScopedPyObjectPtr enum_value; - while ((enum_value.reset(PyIter_Next(values_iter))) != NULL) { - ScopedPyObjectPtr value_name(PyObject_GetAttr(enum_value, kname)); - if (value_name == NULL) { - return NULL; - } - ScopedPyObjectPtr value_number(PyObject_GetAttrString(enum_value, - "number")); + // For each enum value add cls. = + for (int j = 0; j < enum_descriptor->value_count(); ++j) { + const EnumValueDescriptor* enum_value_descriptor = + enum_descriptor->value(j); + ScopedPyObjectPtr value_number(PyInt_FromLong( + enum_value_descriptor->number())); if (value_number == NULL) { return NULL; } - if (PyObject_SetAttr(reinterpret_cast(cls), - value_name, value_number) == -1) { + if (PyObject_SetAttrString( + cls, enum_value_descriptor->name().c_str(), value_number) == -1) { return NULL; } } - if (PyErr_Occurred()) { // If PyIter_Next failed - return NULL; - } - } - if (PyErr_Occurred()) { // If PyIter_Next failed - return NULL; } - ScopedPyObjectPtr extension_dict( - PyObject_GetAttr(descriptor, kextensions_by_name)); - if (extension_dict == NULL || !PyDict_Check(extension_dict)) { - PyErr_SetString(PyExc_TypeError, "extensions_by_name not a dict"); - return NULL; - } - Py_ssize_t pos = 0; - PyObject* extension_name; - PyObject* extension_field; - - while (PyDict_Next(extension_dict, &pos, &extension_name, &extension_field)) { - if (PyObject_SetAttr(reinterpret_cast(cls), - extension_name, extension_field) == -1) { - return NULL; - } - const google::protobuf::FieldDescriptor* field_descriptor = - GetExtensionDescriptor(extension_field); - if (field_descriptor == NULL) { + // For each extension set cls. = . + // + // Extension descriptors come from + // .extensions_by_name[name] + // which was defined previously. + for (int i = 0; i < message_descriptor->extension_count(); ++i) { + const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i); + ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(field)); + if (extension_field == NULL) { return NULL; } - ScopedPyObjectPtr field_name_upcased( - PyObject_CallMethod(extension_name, "upper", NULL)); - if (field_name_upcased == NULL) { - return NULL; - } - ScopedPyObjectPtr field_number_name(PyObject_CallMethod( - field_name_upcased, "__add__", "(O)", _NUMBER_string.get())); - if (field_number_name == NULL) { - return NULL; - } - ScopedPyObjectPtr number(PyInt_FromLong( - field_descriptor->number())); - if (number == NULL) { + // Add the extension field to the message class. + if (PyObject_SetAttrString( + cls, field->name().c_str(), extension_field) == -1) { return NULL; } - if (PyObject_SetAttr(reinterpret_cast(cls), - field_number_name, number) == -1) { + + // For each extension set cls._FIELD_NUMBER = . + if (!AddFieldNumberToClass(cls, field)) { return NULL; } } @@ -2121,12 +2077,35 @@ PyObject* SetState(CMessage* self, PyObject* state) { } // CMessage static methods: +PyObject* _GetMessageDescriptor(PyObject* unused, PyObject* arg) { + return cdescriptor_pool::FindMessageByName(GetDescriptorPool(), arg); +} + PyObject* _GetFieldDescriptor(PyObject* unused, PyObject* arg) { - return cdescriptor_pool::FindFieldByName(descriptor_pool, arg); + return cdescriptor_pool::FindFieldByName(GetDescriptorPool(), arg); } PyObject* _GetExtensionDescriptor(PyObject* unused, PyObject* arg) { - return cdescriptor_pool::FindExtensionByName(descriptor_pool, arg); + return cdescriptor_pool::FindExtensionByName(GetDescriptorPool(), arg); +} + +PyObject* _GetEnumDescriptor(PyObject* unused, PyObject* arg) { + return cdescriptor_pool::FindEnumTypeByName(GetDescriptorPool(), arg); +} + +PyObject* _GetOneofDescriptor(PyObject* unused, PyObject* arg) { + return cdescriptor_pool::FindOneofByName(GetDescriptorPool(), arg); +} + +PyObject* _CheckCalledFromGeneratedFile(PyObject* unused, + PyObject* unused_arg) { + if (!_CalledFromGeneratedFile(1)) { + PyErr_SetString(PyExc_TypeError, + "Descriptors should not be created directly, " + "but only retrieved from their parent."); + return NULL; + } + Py_RETURN_NONE; } static PyMemberDef Members[] = { @@ -2191,91 +2170,102 @@ static PyMethodDef Methods[] = { // Static Methods. { "_BuildFile", (PyCFunction)Python_BuildFile, METH_O | METH_STATIC, "Registers a new protocol buffer file in the global C++ descriptor pool." }, + { "_GetMessageDescriptor", (PyCFunction)_GetMessageDescriptor, + METH_O | METH_STATIC, "Finds a message descriptor in the message pool." }, { "_GetFieldDescriptor", (PyCFunction)_GetFieldDescriptor, METH_O | METH_STATIC, "Finds a field descriptor in the message pool." }, { "_GetExtensionDescriptor", (PyCFunction)_GetExtensionDescriptor, METH_O | METH_STATIC, "Finds a extension descriptor in the message pool." }, + { "_GetEnumDescriptor", (PyCFunction)_GetEnumDescriptor, + METH_O | METH_STATIC, + "Finds an enum descriptor in the message pool." }, + { "_GetOneofDescriptor", (PyCFunction)_GetOneofDescriptor, + METH_O | METH_STATIC, + "Finds an oneof descriptor in the message pool." }, + { "_CheckCalledFromGeneratedFile", (PyCFunction)_CheckCalledFromGeneratedFile, + METH_NOARGS | METH_STATIC, + "Raises TypeError if the caller is not in a _pb2.py file."}, { NULL, NULL} }; +static bool SetCompositeField( + CMessage* self, PyObject* name, PyObject* value) { + if (self->composite_fields == NULL) { + self->composite_fields = PyDict_New(); + if (self->composite_fields == NULL) { + return false; + } + } + return PyDict_SetItem(self->composite_fields, name, value) == 0; +} + PyObject* GetAttr(CMessage* self, PyObject* name) { - PyObject* value = PyDict_GetItem(self->composite_fields, name); + PyObject* value = self->composite_fields ? + PyDict_GetItem(self->composite_fields, name) : NULL; if (value != NULL) { Py_INCREF(value); return value; } - const google::protobuf::FieldDescriptor* field_descriptor = GetFieldDescriptor( - self, name); - if (field_descriptor != NULL) { - if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { - if (field_descriptor->cpp_type() == - google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - PyObject *message_class = cdescriptor_pool::GetMessageClass( - descriptor_pool, field_descriptor->message_type()); - if (message_class == NULL) { - return NULL; - } - PyObject* py_container = repeated_composite_container::NewContainer( - self, field_descriptor, message_class); - if (py_container == NULL) { - return NULL; - } - if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) { - Py_DECREF(py_container); - return NULL; - } - return py_container; - } else { - PyObject* py_container = repeated_scalar_container::NewContainer( - self, field_descriptor); - if (py_container == NULL) { - return NULL; - } - if (PyDict_SetItem(self->composite_fields, name, py_container) < 0) { - Py_DECREF(py_container); - return NULL; - } - return py_container; + const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name); + if (field_descriptor == NULL) { + return CMessage_Type.tp_base->tp_getattro( + reinterpret_cast(self), name); + } + + if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { + PyObject* py_container = NULL; + if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + PyObject *message_class = cdescriptor_pool::GetMessageClass( + GetDescriptorPool(), field_descriptor->message_type()); + if (message_class == NULL) { + return NULL; } + py_container = repeated_composite_container::NewContainer( + self, field_descriptor, message_class); } else { - if (field_descriptor->cpp_type() == - google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { - PyObject* sub_message = InternalGetSubMessage(self, field_descriptor); - if (PyDict_SetItem(self->composite_fields, name, sub_message) < 0) { - Py_DECREF(sub_message); - return NULL; - } - return sub_message; - } else { - return InternalGetScalar(self, field_descriptor); - } + py_container = repeated_scalar_container::NewContainer( + self, field_descriptor); + } + if (py_container == NULL) { + return NULL; + } + if (!SetCompositeField(self, name, py_container)) { + Py_DECREF(py_container); + return NULL; + } + return py_container; + } + + if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + PyObject* sub_message = InternalGetSubMessage(self, field_descriptor); + if (!SetCompositeField(self, name, sub_message)) { + Py_DECREF(sub_message); + return NULL; } + return sub_message; } - return CMessage_Type.tp_base->tp_getattro(reinterpret_cast(self), - name); + return InternalGetScalar(self, field_descriptor); } int SetAttr(CMessage* self, PyObject* name, PyObject* value) { - if (PyDict_Contains(self->composite_fields, name)) { + if (self->composite_fields && PyDict_Contains(self->composite_fields, name)) { PyErr_SetString(PyExc_TypeError, "Can't set composite field"); return -1; } - const google::protobuf::FieldDescriptor* field_descriptor = - GetFieldDescriptor(self, name); + const FieldDescriptor* field_descriptor = GetFieldDescriptor(self, name); if (field_descriptor != NULL) { AssureWritable(self); - if (field_descriptor->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) { + if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { PyErr_Format(PyExc_AttributeError, "Assignment not allowed to repeated " "field \"%s\" in protocol message object.", field_descriptor->name().c_str()); return -1; } else { - if (field_descriptor->cpp_type() == - google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { + if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { PyErr_Format(PyExc_AttributeError, "Assignment not allowed to " "field \"%s\" in protocol message object.", field_descriptor->name().c_str()); @@ -2339,7 +2329,7 @@ PyTypeObject CMessage_Type = { const Message* (*GetCProtoInsidePyProtoPtr)(PyObject* msg); Message* (*MutableCProtoInsidePyProtoPtr)(PyObject* msg); -static const google::protobuf::Message* GetCProtoInsidePyProtoImpl(PyObject* msg) { +static const Message* GetCProtoInsidePyProtoImpl(PyObject* msg) { if (!PyObject_TypeCheck(msg, &CMessage_Type)) { return NULL; } @@ -2347,12 +2337,12 @@ static const google::protobuf::Message* GetCProtoInsidePyProtoImpl(PyObject* msg return cmsg->message; } -static google::protobuf::Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { +static Message* MutableCProtoInsidePyProtoImpl(PyObject* msg) { if (!PyObject_TypeCheck(msg, &CMessage_Type)) { return NULL; } CMessage* cmsg = reinterpret_cast(msg); - if (PyDict_Size(cmsg->composite_fields) != 0 || + if ((cmsg->composite_fields && PyDict_Size(cmsg->composite_fields) != 0) || (cmsg->extensions != NULL && PyDict_Size(cmsg->extensions->values) != 0)) { // There is currently no way of accurately syncing arbitrary changes to @@ -2387,29 +2377,35 @@ void InitGlobals() { kDESCRIPTOR = PyString_FromString("DESCRIPTOR"); k_cdescriptor = PyString_FromString("_cdescriptor"); kfull_name = PyString_FromString("full_name"); - kextensions_by_name = PyString_FromString("extensions_by_name"); k_extensions_by_name = PyString_FromString("_extensions_by_name"); k_extensions_by_number = PyString_FromString("_extensions_by_number"); - kname = PyString_FromString("name"); - kfields_by_name = PyString_FromString("fields_by_name"); - descriptor_pool = cdescriptor_pool::NewDescriptorPool(); - - global_message_factory = new DynamicMessageFactory(descriptor_pool->pool); - global_message_factory->SetDelegateToGeneratedFactory(true); + message_factory = new DynamicMessageFactory(GetDescriptorPool()->pool); + message_factory->SetDelegateToGeneratedFactory(true); } bool InitProto2MessageModule(PyObject *m) { + // Initialize types and globals in descriptor.cc + if (!InitDescriptor()) { + return false; + } + + // Initialize types and globals in descriptor_pool.cc + if (!InitDescriptorPool()) { + return false; + } + + // Initialize constants defined in this file. InitGlobals(); - google::protobuf::python::CMessage_Type.tp_hash = PyObject_HashNotImplemented; - if (PyType_Ready(&google::protobuf::python::CMessage_Type) < 0) { + CMessage_Type.tp_hash = PyObject_HashNotImplemented; + if (PyType_Ready(&CMessage_Type) < 0) { return false; } // DESCRIPTOR is set on each protocol buffer message class elsewhere, but set // it here as well to document that subclasses need to set it. - PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, kDESCRIPTOR, Py_None); + PyDict_SetItem(CMessage_Type.tp_dict, kDESCRIPTOR, Py_None); // Subclasses with message extensions will override _extensions_by_name and // _extensions_by_number with fresh mutable dictionaries in AddDescriptors. // All other classes can share this same immutable mapping. @@ -2421,58 +2417,69 @@ bool InitProto2MessageModule(PyObject *m) { if (immutable_dict == NULL) { return false; } - if (PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, + if (PyDict_SetItem(CMessage_Type.tp_dict, k_extensions_by_name, immutable_dict) < 0) { return false; } - if (PyDict_SetItem(google::protobuf::python::CMessage_Type.tp_dict, + if (PyDict_SetItem(CMessage_Type.tp_dict, k_extensions_by_number, immutable_dict) < 0) { return false; } - PyModule_AddObject(m, "Message", reinterpret_cast( - &google::protobuf::python::CMessage_Type)); + PyModule_AddObject(m, "Message", reinterpret_cast(&CMessage_Type)); - google::protobuf::python::RepeatedScalarContainer_Type.tp_hash = + RepeatedScalarContainer_Type.tp_hash = PyObject_HashNotImplemented; - if (PyType_Ready(&google::protobuf::python::RepeatedScalarContainer_Type) < 0) { + if (PyType_Ready(&RepeatedScalarContainer_Type) < 0) { return false; } PyModule_AddObject(m, "RepeatedScalarContainer", reinterpret_cast( - &google::protobuf::python::RepeatedScalarContainer_Type)); + &RepeatedScalarContainer_Type)); - google::protobuf::python::RepeatedCompositeContainer_Type.tp_hash = - PyObject_HashNotImplemented; - if (PyType_Ready(&google::protobuf::python::RepeatedCompositeContainer_Type) < 0) { + RepeatedCompositeContainer_Type.tp_hash = PyObject_HashNotImplemented; + if (PyType_Ready(&RepeatedCompositeContainer_Type) < 0) { return false; } PyModule_AddObject( m, "RepeatedCompositeContainer", reinterpret_cast( - &google::protobuf::python::RepeatedCompositeContainer_Type)); + &RepeatedCompositeContainer_Type)); - google::protobuf::python::ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented; - if (PyType_Ready(&google::protobuf::python::ExtensionDict_Type) < 0) { + ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented; + if (PyType_Ready(&ExtensionDict_Type) < 0) { return false; } PyModule_AddObject( m, "ExtensionDict", - reinterpret_cast(&google::protobuf::python::ExtensionDict_Type)); - - if (!google::protobuf::python::InitDescriptor()) { - return false; - } + reinterpret_cast(&ExtensionDict_Type)); + + // This implementation provides full Descriptor types, we advertise it so that + // descriptor.py can use them in replacement of the Python classes. + PyModule_AddIntConstant(m, "_USE_C_DESCRIPTORS", 1); + + PyModule_AddObject(m, "Descriptor", reinterpret_cast( + &PyMessageDescriptor_Type)); + PyModule_AddObject(m, "FieldDescriptor", reinterpret_cast( + &PyFieldDescriptor_Type)); + PyModule_AddObject(m, "EnumDescriptor", reinterpret_cast( + &PyEnumDescriptor_Type)); + PyModule_AddObject(m, "EnumValueDescriptor", reinterpret_cast( + &PyEnumValueDescriptor_Type)); + PyModule_AddObject(m, "FileDescriptor", reinterpret_cast( + &PyFileDescriptor_Type)); + PyModule_AddObject(m, "OneofDescriptor", reinterpret_cast( + &PyOneofDescriptor_Type)); PyObject* enum_type_wrapper = PyImport_ImportModule( "google.protobuf.internal.enum_type_wrapper"); if (enum_type_wrapper == NULL) { return false; } - google::protobuf::python::EnumTypeWrapper_class = + EnumTypeWrapper_class = PyObject_GetAttrString(enum_type_wrapper, "EnumTypeWrapper"); Py_DECREF(enum_type_wrapper); @@ -2481,25 +2488,20 @@ bool InitProto2MessageModule(PyObject *m) { if (message_module == NULL) { return false; } - google::protobuf::python::EncodeError_class = PyObject_GetAttrString(message_module, - "EncodeError"); - google::protobuf::python::DecodeError_class = PyObject_GetAttrString(message_module, - "DecodeError"); + EncodeError_class = PyObject_GetAttrString(message_module, "EncodeError"); + DecodeError_class = PyObject_GetAttrString(message_module, "DecodeError"); Py_DECREF(message_module); PyObject* pickle_module = PyImport_ImportModule("pickle"); if (pickle_module == NULL) { return false; } - google::protobuf::python::PickleError_class = PyObject_GetAttrString(pickle_module, - "PickleError"); + PickleError_class = PyObject_GetAttrString(pickle_module, "PickleError"); Py_DECREF(pickle_module); // Override {Get,Mutable}CProtoInsidePyProto. - google::protobuf::python::GetCProtoInsidePyProtoPtr = - google::protobuf::python::GetCProtoInsidePyProtoImpl; - google::protobuf::python::MutableCProtoInsidePyProtoPtr = - google::protobuf::python::MutableCProtoInsidePyProtoImpl; + GetCProtoInsidePyProtoPtr = GetCProtoInsidePyProtoImpl; + MutableCProtoInsidePyProtoPtr = MutableCProtoInsidePyProtoImpl; return true; } diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index 0fef92a0..2f2da795 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -42,7 +42,6 @@ #endif #include - namespace google { namespace protobuf { @@ -50,12 +49,12 @@ class Message; class Reflection; class FieldDescriptor; class Descriptor; +class DynamicMessageFactory; using internal::shared_ptr; namespace python { -struct PyDescriptorPool; struct ExtensionDict; typedef struct CMessage { @@ -84,7 +83,7 @@ typedef struct CMessage { // Used together with the parent's message when making a default message // instance mutable. // The pointer is owned by the global DescriptorPool. - const google::protobuf::FieldDescriptor* parent_field_descriptor; + const FieldDescriptor* parent_field_descriptor; // Pointer to the C++ Message object for this CMessage. The // CMessage does not own this pointer. @@ -115,27 +114,26 @@ namespace cmessage { // Internal function to create a new empty Message Python object, but with empty // pointers to the C++ objects. // The caller must fill self->message, self->owner and eventually self->parent. -CMessage* NewEmptyMessage(PyObject* type, - const google::protobuf::Descriptor* descriptor); +CMessage* NewEmptyMessage(PyObject* type, const Descriptor* descriptor); // Release a submessage from its proto tree, making it a new top-level messgae. // A new message will be created if this is a read-only default instance. // // Corresponds to reflection api method ReleaseMessage. -int ReleaseSubMessage(google::protobuf::Message* message, - const google::protobuf::FieldDescriptor* field_descriptor, +int ReleaseSubMessage(Message* message, + const FieldDescriptor* field_descriptor, CMessage* child_cmessage); // Retrieves the C++ descriptor of a Python Extension descriptor. // On error, return NULL with an exception set. -const google::protobuf::FieldDescriptor* GetExtensionDescriptor(PyObject* extension); +const FieldDescriptor* GetExtensionDescriptor(PyObject* extension); // Initializes a new CMessage instance for a submessage. Only called once per // submessage as the result is cached in composite_fields. // // Corresponds to reflection api method GetMessage. PyObject* InternalGetSubMessage( - CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor); + CMessage* self, const FieldDescriptor* field_descriptor); // Deletes a range of C++ submessages in a repeated field (following a // removal in a RepeatedCompositeContainer). @@ -146,20 +144,20 @@ PyObject* InternalGetSubMessage( // by slice will be removed from cmessage_list by this function. // // Corresponds to reflection api method RemoveLast. -int InternalDeleteRepeatedField(google::protobuf::Message* message, - const google::protobuf::FieldDescriptor* field_descriptor, +int InternalDeleteRepeatedField(Message* message, + const FieldDescriptor* field_descriptor, PyObject* slice, PyObject* cmessage_list); // Sets the specified scalar value to the message. int InternalSetScalar(CMessage* self, - const google::protobuf::FieldDescriptor* field_descriptor, + const FieldDescriptor* field_descriptor, PyObject* value); // Retrieves the specified scalar value from the message. // // Returns a new python reference. PyObject* InternalGetScalar(CMessage* self, - const google::protobuf::FieldDescriptor* field_descriptor); + const FieldDescriptor* field_descriptor); // Clears the message, removing all contained data. Extension dictionary and // submessages are released first if there are remaining external references. @@ -175,8 +173,7 @@ PyObject* Clear(CMessage* self); // // Corresponds to reflection api method ClearField. PyObject* ClearFieldByDescriptor( - CMessage* self, - const google::protobuf::FieldDescriptor* descriptor); + CMessage* self, const FieldDescriptor* descriptor); // Clears the data for the given field name. The message is released if there // are any external references. @@ -189,7 +186,7 @@ PyObject* ClearField(CMessage* self, PyObject* arg); // // Corresponds to reflection api method HasField PyObject* HasFieldByDescriptor( - CMessage* self, const google::protobuf::FieldDescriptor* field_descriptor); + CMessage* self, const FieldDescriptor* field_descriptor); // Checks if the message has the named field. // @@ -220,18 +217,16 @@ int SetOwner(CMessage* self, const shared_ptr& new_owner); int AssureWritable(CMessage* self); -} // namespace cmessage - +DynamicMessageFactory* GetMessageFactory(); -// Retrieve the global descriptor pool owned by the _message module. -PyDescriptorPool* GetDescriptorPool(); +} // namespace cmessage /* Is 64bit */ #define IS_64BIT (SIZEOF_LONG == 8) #define FIELD_IS_REPEATED(field_descriptor) \ - ((field_descriptor)->label() == google::protobuf::FieldDescriptor::LABEL_REPEATED) + ((field_descriptor)->label() == FieldDescriptor::LABEL_REPEATED) #define GOOGLE_CHECK_GET_INT32(arg, value, err) \ int32 value; \ @@ -294,18 +289,17 @@ bool CheckAndGetDouble(PyObject* arg, double* value); bool CheckAndGetFloat(PyObject* arg, float* value); bool CheckAndGetBool(PyObject* arg, bool* value); bool CheckAndSetString( - PyObject* arg, google::protobuf::Message* message, - const google::protobuf::FieldDescriptor* descriptor, - const google::protobuf::Reflection* reflection, + PyObject* arg, Message* message, + const FieldDescriptor* descriptor, + const Reflection* reflection, bool append, int index); -PyObject* ToStringObject( - const google::protobuf::FieldDescriptor* descriptor, string value); +PyObject* ToStringObject(const FieldDescriptor* descriptor, string value); // Check if the passed field descriptor belongs to the given message. // If not, return false and set a Python exception (a KeyError) -bool CheckFieldBelongsToMessage(const google::protobuf::FieldDescriptor* field_descriptor, - const google::protobuf::Message* message); +bool CheckFieldBelongsToMessage(const FieldDescriptor* field_descriptor, + const Message* message); extern PyObject* PickleError_class; diff --git a/python/google/protobuf/pyext/message_factory_cpp2_test.py b/python/google/protobuf/pyext/message_factory_cpp2_test.py deleted file mode 100644 index 32ab4f85..00000000 --- a/python/google/protobuf/pyext/message_factory_cpp2_test.py +++ /dev/null @@ -1,56 +0,0 @@ -#! /usr/bin/python -# -# 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. - -"""Tests for google.protobuf.message_factory.""" - -import os -os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' -os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2' - -# We must set the implementation version above before the google3 imports. -# pylint: disable=g-import-not-at-top -from google.apputils import basetest -from google.protobuf.internal import api_implementation -# Run all tests from the original module by putting them in our namespace. -# pylint: disable=wildcard-import -from google.protobuf.internal.message_factory_test import * - - -class ConfirmCppApi2Test(basetest.TestCase): - - def testImplementationSetting(self): - self.assertEqual('cpp', api_implementation.Type()) - self.assertEqual(2, api_implementation.Version()) - - -if __name__ == '__main__': - basetest.main() diff --git a/python/google/protobuf/pyext/reflection_cpp2_generated_test.py b/python/google/protobuf/pyext/reflection_cpp2_generated_test.py deleted file mode 100755 index 552efd48..00000000 --- a/python/google/protobuf/pyext/reflection_cpp2_generated_test.py +++ /dev/null @@ -1,94 +0,0 @@ -#! /usr/bin/python -# -*- coding: utf-8 -*- -# -# 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. - -"""Unittest for reflection.py, which tests the generated C++ implementation.""" - -__author__ = 'jasonh@google.com (Jason Hsueh)' - -import os -os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' -os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION'] = '2' - -from google.apputils import basetest -from google.protobuf.internal import api_implementation -from google.protobuf.internal import more_extensions_dynamic_pb2 -from google.protobuf.internal import more_extensions_pb2 -from google.protobuf.internal.reflection_test import * - - -class ReflectionCppTest(basetest.TestCase): - def testImplementationSetting(self): - self.assertEqual('cpp', api_implementation.Type()) - self.assertEqual(2, api_implementation.Version()) - - def testExtensionOfGeneratedTypeInDynamicFile(self): - """Tests that a file built dynamically can extend a generated C++ type. - - The C++ implementation uses a DescriptorPool that has the generated - DescriptorPool as an underlay. Typically, a type can only find - extensions in its own pool. With the python C-extension, the generated C++ - extendee may be available, but not the extension. This tests that the - C-extension implements the correct special handling to make such extensions - available. - """ - pb1 = more_extensions_pb2.ExtendedMessage() - # Test that basic accessors work. - self.assertFalse( - pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension)) - self.assertFalse( - pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension)) - pb1.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension] = 17 - pb1.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a = 24 - self.assertTrue( - pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension)) - self.assertTrue( - pb1.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension)) - - # Now serialize the data and parse to a new message. - pb2 = more_extensions_pb2.ExtendedMessage() - pb2.MergeFromString(pb1.SerializeToString()) - - self.assertTrue( - pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_int32_extension)) - self.assertTrue( - pb2.HasExtension(more_extensions_dynamic_pb2.dynamic_message_extension)) - self.assertEqual( - 17, pb2.Extensions[more_extensions_dynamic_pb2.dynamic_int32_extension]) - self.assertEqual( - 24, - pb2.Extensions[more_extensions_dynamic_pb2.dynamic_message_extension].a) - - - -if __name__ == '__main__': - basetest.main() diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index 36fe86ae..49ef7991 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -56,8 +56,6 @@ namespace google { namespace protobuf { namespace python { -extern google::protobuf::DynamicMessageFactory* global_message_factory; - namespace repeated_composite_container { // TODO(tibell): We might also want to check: @@ -120,9 +118,9 @@ static int InternalQuickSort(RepeatedCompositeContainer* self, GOOGLE_CHECK_ATTACHED(self); - google::protobuf::Message* message = self->message; - const google::protobuf::Reflection* reflection = message->GetReflection(); - const google::protobuf::FieldDescriptor* descriptor = self->parent_field_descriptor; + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + const FieldDescriptor* descriptor = self->parent_field_descriptor; Py_ssize_t left; Py_ssize_t right; @@ -199,7 +197,7 @@ static int InternalQuickSort(RepeatedCompositeContainer* self, // len() static Py_ssize_t Length(RepeatedCompositeContainer* self) { - google::protobuf::Message* message = self->message; + Message* message = self->message; if (message != NULL) { return message->GetReflection()->FieldSize(*message, self->parent_field_descriptor); @@ -221,8 +219,8 @@ static int UpdateChildMessages(RepeatedCompositeContainer* self) { // be removed in such a way so there's no need to worry about that. Py_ssize_t message_length = Length(self); Py_ssize_t child_length = PyList_GET_SIZE(self->child_messages); - google::protobuf::Message* message = self->message; - const google::protobuf::Reflection* reflection = message->GetReflection(); + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); for (Py_ssize_t i = child_length; i < message_length; ++i) { const Message& sub_message = reflection->GetRepeatedMessage( *(self->message), self->parent_field_descriptor, i); @@ -233,7 +231,7 @@ static int UpdateChildMessages(RepeatedCompositeContainer* self) { return -1; } cmsg->owner = self->owner; - cmsg->message = const_cast(&sub_message); + cmsg->message = const_cast(&sub_message); cmsg->parent = self->parent; if (PyList_Append(self->child_messages, py_cmsg) < 0) { return -1; @@ -255,8 +253,8 @@ static PyObject* AddToAttached(RepeatedCompositeContainer* self, } if (cmessage::AssureWritable(self->parent) == -1) return NULL; - google::protobuf::Message* message = self->message; - google::protobuf::Message* sub_message = + Message* message = self->message; + Message* sub_message = message->GetReflection()->AddMessage(message, self->parent_field_descriptor); CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init, @@ -482,9 +480,9 @@ static PyObject* SortAttached(RepeatedCompositeContainer* self, // Finally reverse the result if requested. if (reverse) { - google::protobuf::Message* message = self->message; - const google::protobuf::Reflection* reflection = message->GetReflection(); - const google::protobuf::FieldDescriptor* descriptor = self->parent_field_descriptor; + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + const FieldDescriptor* descriptor = self->parent_field_descriptor; // Reverse the Message array. for (int i = 0; i < length / 2; ++i) @@ -554,6 +552,26 @@ static PyObject* Item(RepeatedCompositeContainer* self, Py_ssize_t index) { return item; } +static PyObject* Pop(RepeatedCompositeContainer* self, + PyObject* args) { + Py_ssize_t index = -1; + if (!PyArg_ParseTuple(args, "|n", &index)) { + return NULL; + } + PyObject* item = Item(self, index); + if (item == NULL) { + PyErr_Format(PyExc_IndexError, + "list index (%zd) out of range", + index); + return NULL; + } + ScopedPyObjectPtr py_index(PyLong_FromSsize_t(index)); + if (AssignSubscript(self, py_index, NULL) < 0) { + return NULL; + } + return item; +} + // The caller takes ownership of the returned Message. Message* ReleaseLast(const FieldDescriptor* field, const Descriptor* type, @@ -571,7 +589,8 @@ Message* ReleaseLast(const FieldDescriptor* field, // the latter points to the default instance via a const_cast<>, so we // have to reset it to a new mutable object since we are taking ownership. if (released_message == NULL) { - const Message* prototype = global_message_factory->GetPrototype(type); + const Message* prototype = + cmessage::GetMessageFactory()->GetPrototype(type); GOOGLE_CHECK_NOTNULL(prototype); return prototype->New(); } else { @@ -646,7 +665,7 @@ int SetOwner(RepeatedCompositeContainer* self, // The private constructor of RepeatedCompositeContainer objects. PyObject *NewContainer( CMessage* parent, - const google::protobuf::FieldDescriptor* parent_field_descriptor, + const FieldDescriptor* parent_field_descriptor, PyObject *concrete_class) { if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { return NULL; @@ -698,6 +717,8 @@ static PyMethodDef Methods[] = { "Adds an object to the repeated container." }, { "extend", (PyCFunction) Extend, METH_O, "Adds objects to the repeated container." }, + { "pop", (PyCFunction)Pop, METH_VARARGS, + "Removes an object from the repeated container and returns it." }, { "remove", (PyCFunction) Remove, METH_O, "Removes an object from the repeated container." }, { "sort", (PyCFunction) Sort, METH_VARARGS | METH_KEYWORDS, diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h index 0969af08..ce7cee0f 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.h +++ b/python/google/protobuf/pyext/repeated_composite_container.h @@ -43,7 +43,6 @@ #include #include - namespace google { namespace protobuf { @@ -82,7 +81,7 @@ typedef struct RepeatedCompositeContainer { // A descriptor used to modify the underlying 'message'. // The pointer is owned by the global DescriptorPool. - const google::protobuf::FieldDescriptor* parent_field_descriptor; + const FieldDescriptor* parent_field_descriptor; // Pointer to the C++ Message that contains this container. The // RepeatedCompositeContainer does not own this pointer. @@ -106,7 +105,7 @@ namespace repeated_composite_container { // field descriptor. PyObject *NewContainer( CMessage* parent, - const google::protobuf::FieldDescriptor* parent_field_descriptor, + const FieldDescriptor* parent_field_descriptor, PyObject *concrete_class); // Returns the number of items in this repeated composite container. @@ -150,8 +149,7 @@ int AssignSubscript(RepeatedCompositeContainer* self, // Releases the messages in the container to the given message. // // Returns 0 on success, -1 on failure. -int ReleaseToMessage(RepeatedCompositeContainer* self, - google::protobuf::Message* new_message); +int ReleaseToMessage(RepeatedCompositeContainer* self, Message* new_message); // Releases the messages in the container to a new message. // diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc index 49d23fd6..9f8075b2 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.cc +++ b/python/google/protobuf/pyext/repeated_scalar_container.cc @@ -60,8 +60,6 @@ namespace google { namespace protobuf { namespace python { -extern google::protobuf::DynamicMessageFactory* global_message_factory; - namespace repeated_scalar_container { static int InternalAssignRepeatedField( @@ -78,7 +76,7 @@ static int InternalAssignRepeatedField( } static Py_ssize_t Len(RepeatedScalarContainer* self) { - google::protobuf::Message* message = self->message; + Message* message = self->message; return message->GetReflection()->FieldSize(*message, self->parent_field_descriptor); } @@ -87,11 +85,10 @@ static int AssignItem(RepeatedScalarContainer* self, Py_ssize_t index, PyObject* arg) { cmessage::AssureWritable(self->parent); - google::protobuf::Message* message = self->message; - const google::protobuf::FieldDescriptor* field_descriptor = - self->parent_field_descriptor; + Message* message = self->message; + const FieldDescriptor* field_descriptor = self->parent_field_descriptor; - const google::protobuf::Reflection* reflection = message->GetReflection(); + const Reflection* reflection = message->GetReflection(); int field_size = reflection->FieldSize(*message, field_descriptor); if (index < 0) { index = field_size + index; @@ -115,64 +112,68 @@ static int AssignItem(RepeatedScalarContainer* self, } switch (field_descriptor->cpp_type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + case FieldDescriptor::CPPTYPE_INT32: { GOOGLE_CHECK_GET_INT32(arg, value, -1); reflection->SetRepeatedInt32(message, field_descriptor, index, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + case FieldDescriptor::CPPTYPE_INT64: { GOOGLE_CHECK_GET_INT64(arg, value, -1); reflection->SetRepeatedInt64(message, field_descriptor, index, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + case FieldDescriptor::CPPTYPE_UINT32: { GOOGLE_CHECK_GET_UINT32(arg, value, -1); reflection->SetRepeatedUInt32(message, field_descriptor, index, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + case FieldDescriptor::CPPTYPE_UINT64: { GOOGLE_CHECK_GET_UINT64(arg, value, -1); reflection->SetRepeatedUInt64(message, field_descriptor, index, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + case FieldDescriptor::CPPTYPE_FLOAT: { GOOGLE_CHECK_GET_FLOAT(arg, value, -1); reflection->SetRepeatedFloat(message, field_descriptor, index, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + case FieldDescriptor::CPPTYPE_DOUBLE: { GOOGLE_CHECK_GET_DOUBLE(arg, value, -1); reflection->SetRepeatedDouble(message, field_descriptor, index, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + case FieldDescriptor::CPPTYPE_BOOL: { GOOGLE_CHECK_GET_BOOL(arg, value, -1); reflection->SetRepeatedBool(message, field_descriptor, index, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + case FieldDescriptor::CPPTYPE_STRING: { if (!CheckAndSetString( arg, message, field_descriptor, reflection, false, index)) { return -1; } break; } - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { + case FieldDescriptor::CPPTYPE_ENUM: { GOOGLE_CHECK_GET_INT32(arg, value, -1); - const google::protobuf::EnumDescriptor* enum_descriptor = - field_descriptor->enum_type(); - const google::protobuf::EnumValueDescriptor* enum_value = - enum_descriptor->FindValueByNumber(value); - if (enum_value != NULL) { - reflection->SetRepeatedEnum(message, field_descriptor, index, - enum_value); + if (reflection->SupportsUnknownEnumValues()) { + reflection->SetRepeatedEnumValue(message, field_descriptor, index, + value); } else { - ScopedPyObjectPtr s(PyObject_Str(arg)); - if (s != NULL) { - PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", - PyString_AsString(s)); + const EnumDescriptor* enum_descriptor = field_descriptor->enum_type(); + const EnumValueDescriptor* enum_value = + enum_descriptor->FindValueByNumber(value); + if (enum_value != NULL) { + reflection->SetRepeatedEnum(message, field_descriptor, index, + enum_value); + } else { + ScopedPyObjectPtr s(PyObject_Str(arg)); + if (s != NULL) { + PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", + PyString_AsString(s)); + } + return -1; } - return -1; } break; } @@ -186,10 +187,9 @@ static int AssignItem(RepeatedScalarContainer* self, } static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { - google::protobuf::Message* message = self->message; - const google::protobuf::FieldDescriptor* field_descriptor = - self->parent_field_descriptor; - const google::protobuf::Reflection* reflection = message->GetReflection(); + Message* message = self->message; + const FieldDescriptor* field_descriptor = self->parent_field_descriptor; + const Reflection* reflection = message->GetReflection(); int field_size = reflection->FieldSize(*message, field_descriptor); if (index < 0) { @@ -197,80 +197,80 @@ static PyObject* Item(RepeatedScalarContainer* self, Py_ssize_t index) { } if (index < 0 || index >= field_size) { PyErr_Format(PyExc_IndexError, - "list assignment index (%d) out of range", - static_cast(index)); + "list index (%zd) out of range", + index); return NULL; } PyObject* result = NULL; switch (field_descriptor->cpp_type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + case FieldDescriptor::CPPTYPE_INT32: { int32 value = reflection->GetRepeatedInt32( *message, field_descriptor, index); result = PyInt_FromLong(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + case FieldDescriptor::CPPTYPE_INT64: { int64 value = reflection->GetRepeatedInt64( *message, field_descriptor, index); result = PyLong_FromLongLong(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + case FieldDescriptor::CPPTYPE_UINT32: { uint32 value = reflection->GetRepeatedUInt32( *message, field_descriptor, index); result = PyLong_FromLongLong(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + case FieldDescriptor::CPPTYPE_UINT64: { uint64 value = reflection->GetRepeatedUInt64( *message, field_descriptor, index); result = PyLong_FromUnsignedLongLong(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + case FieldDescriptor::CPPTYPE_FLOAT: { float value = reflection->GetRepeatedFloat( *message, field_descriptor, index); result = PyFloat_FromDouble(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + case FieldDescriptor::CPPTYPE_DOUBLE: { double value = reflection->GetRepeatedDouble( *message, field_descriptor, index); result = PyFloat_FromDouble(value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + case FieldDescriptor::CPPTYPE_BOOL: { bool value = reflection->GetRepeatedBool( *message, field_descriptor, index); result = PyBool_FromLong(value ? 1 : 0); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { - const google::protobuf::EnumValueDescriptor* enum_value = + case FieldDescriptor::CPPTYPE_ENUM: { + const EnumValueDescriptor* enum_value = message->GetReflection()->GetRepeatedEnum( *message, field_descriptor, index); result = PyInt_FromLong(enum_value->number()); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + case FieldDescriptor::CPPTYPE_STRING: { string value = reflection->GetRepeatedString( *message, field_descriptor, index); result = ToStringObject(field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE: { + case FieldDescriptor::CPPTYPE_MESSAGE: { PyObject* py_cmsg = PyObject_CallObject(reinterpret_cast( &CMessage_Type), NULL); if (py_cmsg == NULL) { return NULL; } CMessage* cmsg = reinterpret_cast(py_cmsg); - const google::protobuf::Message& msg = reflection->GetRepeatedMessage( + const Message& msg = reflection->GetRepeatedMessage( *message, field_descriptor, index); cmsg->owner = self->owner; cmsg->parent = self->parent; - cmsg->message = const_cast(&msg); + cmsg->message = const_cast(&msg); cmsg->read_only = false; result = reinterpret_cast(py_cmsg); break; @@ -351,69 +351,71 @@ static PyObject* Subscript(RepeatedScalarContainer* self, PyObject* slice) { PyObject* Append(RepeatedScalarContainer* self, PyObject* item) { cmessage::AssureWritable(self->parent); - google::protobuf::Message* message = self->message; - const google::protobuf::FieldDescriptor* field_descriptor = - self->parent_field_descriptor; + Message* message = self->message; + const FieldDescriptor* field_descriptor = self->parent_field_descriptor; - const google::protobuf::Reflection* reflection = message->GetReflection(); + const Reflection* reflection = message->GetReflection(); switch (field_descriptor->cpp_type()) { - case google::protobuf::FieldDescriptor::CPPTYPE_INT32: { + case FieldDescriptor::CPPTYPE_INT32: { GOOGLE_CHECK_GET_INT32(item, value, NULL); reflection->AddInt32(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_INT64: { + case FieldDescriptor::CPPTYPE_INT64: { GOOGLE_CHECK_GET_INT64(item, value, NULL); reflection->AddInt64(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT32: { + case FieldDescriptor::CPPTYPE_UINT32: { GOOGLE_CHECK_GET_UINT32(item, value, NULL); reflection->AddUInt32(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_UINT64: { + case FieldDescriptor::CPPTYPE_UINT64: { GOOGLE_CHECK_GET_UINT64(item, value, NULL); reflection->AddUInt64(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT: { + case FieldDescriptor::CPPTYPE_FLOAT: { GOOGLE_CHECK_GET_FLOAT(item, value, NULL); reflection->AddFloat(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE: { + case FieldDescriptor::CPPTYPE_DOUBLE: { GOOGLE_CHECK_GET_DOUBLE(item, value, NULL); reflection->AddDouble(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_BOOL: { + case FieldDescriptor::CPPTYPE_BOOL: { GOOGLE_CHECK_GET_BOOL(item, value, NULL); reflection->AddBool(message, field_descriptor, value); break; } - case google::protobuf::FieldDescriptor::CPPTYPE_STRING: { + case FieldDescriptor::CPPTYPE_STRING: { if (!CheckAndSetString( item, message, field_descriptor, reflection, true, -1)) { return NULL; } break; } - case google::protobuf::FieldDescriptor::CPPTYPE_ENUM: { + case FieldDescriptor::CPPTYPE_ENUM: { GOOGLE_CHECK_GET_INT32(item, value, NULL); - const google::protobuf::EnumDescriptor* enum_descriptor = - field_descriptor->enum_type(); - const google::protobuf::EnumValueDescriptor* enum_value = - enum_descriptor->FindValueByNumber(value); - if (enum_value != NULL) { - reflection->AddEnum(message, field_descriptor, enum_value); + if (reflection->SupportsUnknownEnumValues()) { + reflection->AddEnumValue(message, field_descriptor, value); } else { - ScopedPyObjectPtr s(PyObject_Str(item)); - if (s != NULL) { - PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", - PyString_AsString(s)); + const EnumDescriptor* enum_descriptor = field_descriptor->enum_type(); + const EnumValueDescriptor* enum_value = + enum_descriptor->FindValueByNumber(value); + if (enum_value != NULL) { + reflection->AddEnum(message, field_descriptor, enum_value); + } else { + ScopedPyObjectPtr s(PyObject_Str(item)); + if (s != NULL) { + PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", + PyString_AsString(s)); + } + return NULL; } - return NULL; } break; } @@ -438,8 +440,8 @@ static int AssSubscript(RepeatedScalarContainer* self, bool create_list = false; cmessage::AssureWritable(self->parent); - google::protobuf::Message* message = self->message; - const google::protobuf::FieldDescriptor* field_descriptor = + Message* message = self->message; + const FieldDescriptor* field_descriptor = self->parent_field_descriptor; #if PY_MAJOR_VERSION < 3 @@ -450,7 +452,7 @@ static int AssSubscript(RepeatedScalarContainer* self, if (PyLong_Check(slice)) { from = to = PyLong_AsLong(slice); } else if (PySlice_Check(slice)) { - const google::protobuf::Reflection* reflection = message->GetReflection(); + const Reflection* reflection = message->GetReflection(); length = reflection->FieldSize(*message, field_descriptor); #if PY_MAJOR_VERSION >= 3 if (PySlice_GetIndicesEx(slice, @@ -492,9 +494,15 @@ static int AssSubscript(RepeatedScalarContainer* self, PyObject* Extend(RepeatedScalarContainer* self, PyObject* value) { cmessage::AssureWritable(self->parent); - if (PyObject_Not(value)) { + + // TODO(ptucker): Deprecate this behavior. b/18413862 + if (value == Py_None) { + Py_RETURN_NONE; + } + if ((Py_TYPE(value)->tp_as_sequence == NULL) && PyObject_Not(value)) { Py_RETURN_NONE; } + ScopedPyObjectPtr iter(PyObject_GetIter(value)); if (iter == NULL) { PyErr_SetString(PyExc_TypeError, "Value must be iterable"); @@ -627,9 +635,28 @@ static PyObject* Sort(RepeatedScalarContainer* self, Py_RETURN_NONE; } +static PyObject* Pop(RepeatedScalarContainer* self, + PyObject* args) { + Py_ssize_t index = -1; + if (!PyArg_ParseTuple(args, "|n", &index)) { + return NULL; + } + PyObject* item = Item(self, index); + if (item == NULL) { + PyErr_Format(PyExc_IndexError, + "list index (%zd) out of range", + index); + return NULL; + } + if (AssignItem(self, index, NULL) < 0) { + return NULL; + } + return item; +} + // The private constructor of RepeatedScalarContainer objects. PyObject *NewContainer( - CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) { + CMessage* parent, const FieldDescriptor* parent_field_descriptor) { if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { return NULL; } @@ -663,7 +690,7 @@ static int InitializeAndCopyToParentContainer( if (values == NULL) { return -1; } - google::protobuf::Message* new_message = global_message_factory->GetPrototype( + Message* new_message = cmessage::GetMessageFactory()->GetPrototype( from->message->GetDescriptor())->New(); to->parent = NULL; to->parent_field_descriptor = from->parent_field_descriptor; @@ -729,6 +756,8 @@ static PyMethodDef Methods[] = { "Appends objects to the repeated container." }, { "insert", (PyCFunction)Insert, METH_VARARGS, "Appends objects to the repeated container." }, + { "pop", (PyCFunction)Pop, METH_VARARGS, + "Removes an object from the repeated container and returns it." }, { "remove", (PyCFunction)Remove, METH_O, "Removes an object from the repeated container." }, { "sort", (PyCFunction)Sort, METH_VARARGS | METH_KEYWORDS, diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h index 513bfe48..5dfa21e0 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.h +++ b/python/google/protobuf/pyext/repeated_scalar_container.h @@ -77,7 +77,7 @@ typedef struct RepeatedScalarContainer { // field. Used together with the parent's message when making a // default message instance mutable. // The pointer is owned by the global DescriptorPool. - const google::protobuf::FieldDescriptor* parent_field_descriptor; + const FieldDescriptor* parent_field_descriptor; } RepeatedScalarContainer; extern PyTypeObject RepeatedScalarContainer_Type; @@ -87,7 +87,7 @@ namespace repeated_scalar_container { // Builds a RepeatedScalarContainer object, from a parent message and a // field descriptor. extern PyObject *NewContainer( - CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor); + CMessage* parent, const FieldDescriptor* parent_field_descriptor); // Appends the scalar 'item' to the end of the container 'self'. // diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py index 1fc704a2..55e653a0 100755 --- a/python/google/protobuf/reflection.py +++ b/python/google/protobuf/reflection.py @@ -56,18 +56,12 @@ _FieldDescriptor = descriptor_mod.FieldDescriptor if api_implementation.Type() == 'cpp': - if api_implementation.Version() == 2: - from google.protobuf.pyext import cpp_message - _NewMessage = cpp_message.NewMessage - _InitMessage = cpp_message.InitMessage - else: - from google.protobuf.internal import cpp_message - _NewMessage = cpp_message.NewMessage - _InitMessage = cpp_message.InitMessage + from google.protobuf.pyext import cpp_message as message_impl else: - from google.protobuf.internal import python_message - _NewMessage = python_message.NewMessage - _InitMessage = python_message.InitMessage + from google.protobuf.internal import python_message as message_impl + +_NewMessage = message_impl.NewMessage +_InitMessage = message_impl.InitMessage class GeneratedProtocolMessageType(type): @@ -127,7 +121,6 @@ class GeneratedProtocolMessageType(type): superclass = super(GeneratedProtocolMessageType, cls) new_class = superclass.__new__(cls, name, bases, dictionary) - setattr(descriptor, '_concrete_class', new_class) return new_class def __init__(cls, name, bases, dictionary): @@ -151,6 +144,7 @@ class GeneratedProtocolMessageType(type): _InitMessage(descriptor, cls) superclass = super(GeneratedProtocolMessageType, cls) superclass.__init__(name, bases, dictionary) + setattr(descriptor, '_concrete_class', cls) def ParseMessage(descriptor, byte_str): diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index fb54c50c..a47ce3e3 100755 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -319,6 +319,11 @@ def _MergeField(tokenizer, message, allow_multiple_scalars): ParseError: In case of ASCII parsing problems. """ message_descriptor = message.DESCRIPTOR + if (hasattr(message_descriptor, 'syntax') and + message_descriptor.syntax == 'proto3'): + # Proto3 doesn't represent presence so we can't test if multiple + # scalars have occurred. We have to allow them. + allow_multiple_scalars = True if tokenizer.TryConsume('['): name = [tokenizer.ConsumeIdentifier()] while tokenizer.TryConsume('.'): diff --git a/python/setup.py b/python/setup.py index 45dd0761..c6ff7454 100755 --- a/python/setup.py +++ b/python/setup.py @@ -77,6 +77,7 @@ def GenerateUnittestProtos(): generate_proto("../src/google/protobuf/unittest_import_public.proto") generate_proto("../src/google/protobuf/unittest_mset.proto") generate_proto("../src/google/protobuf/unittest_no_generic_services.proto") + generate_proto("../src/google/protobuf/unittest_proto3_arena.proto") generate_proto("google/protobuf/internal/descriptor_pool_test1.proto") generate_proto("google/protobuf/internal/descriptor_pool_test2.proto") generate_proto("google/protobuf/internal/test_bad_identifiers.proto") @@ -90,23 +91,6 @@ def GenerateUnittestProtos(): generate_proto("google/protobuf/internal/import_test_package/outer.proto") generate_proto("google/protobuf/pyext/python.proto") -def MakeTestSuite(): - # Test C++ implementation - import unittest - import google.protobuf.pyext.descriptor_cpp2_test as descriptor_cpp2_test - import google.protobuf.pyext.message_factory_cpp2_test \ - as message_factory_cpp2_test - import google.protobuf.pyext.reflection_cpp2_generated_test \ - as reflection_cpp2_generated_test - - loader = unittest.defaultTestLoader - suite = unittest.TestSuite() - for test in [ descriptor_cpp2_test, - message_factory_cpp2_test, - reflection_cpp2_generated_test]: - suite.addTest(loader.loadTestsFromModule(test)) - return suite - class clean(_clean): def run(self): # Delete generated files in the code tree. @@ -152,6 +136,8 @@ if __name__ == '__main__': ext_module_list.append(Extension( "google.protobuf.pyext._message", [ "google/protobuf/pyext/descriptor.cc", + "google/protobuf/pyext/descriptor_containers.cc", + "google/protobuf/pyext/descriptor_pool.cc", "google/protobuf/pyext/message.cc", "google/protobuf/pyext/extension_dict.cc", "google/protobuf/pyext/repeated_scalar_container.cc", @@ -161,12 +147,12 @@ if __name__ == '__main__': libraries = [ "protobuf" ], library_dirs = [ '../src/.libs' ], )) + os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp' setup(name = 'protobuf', version = '3.0.0-alpha-2', packages = [ 'google' ], namespace_packages = [ 'google' ], - test_suite = 'setup.MakeTestSuite', google_test_dir = "google/protobuf/internal", # Must list modules explicitly so that we don't install tests. py_modules = [ diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index 0c65b993..7b3b5fa3 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -273,6 +273,19 @@ string StringifyDefaultValue(const FieldDescriptor& field) { return ""; } +string StringifySyntax(FileDescriptor::Syntax syntax) { + switch (syntax) { + case FileDescriptor::SYNTAX_PROTO2: + return "proto2"; + case FileDescriptor::SYNTAX_PROTO3: + return "proto3"; + case FileDescriptor::SYNTAX_UNKNOWN: + default: + GOOGLE_LOG(FATAL) << "Unsupported syntax; this generator only supports proto2 " + "and proto3 syntax."; + return ""; + } +} } // namespace @@ -367,10 +380,12 @@ void Generator::PrintFileDescriptor() const { m["descriptor_name"] = kDescriptorKey; m["name"] = file_->name(); m["package"] = file_->package(); + m["syntax"] = StringifySyntax(file_->syntax()); const char file_descriptor_template[] = "$descriptor_name$ = _descriptor.FileDescriptor(\n" " name='$name$',\n" - " package='$package$',\n"; + " package='$package$',\n" + " syntax='$syntax$',\n"; printer_->Print(m, file_descriptor_template); printer_->Indent(); printer_->Print( @@ -414,7 +429,7 @@ void Generator::PrintTopLevelEnums() const { for (int j = 0; j < enum_descriptor.value_count(); ++j) { const EnumValueDescriptor& value_descriptor = *enum_descriptor.value(j); top_level_enum_values.push_back( - make_pair(value_descriptor.name(), value_descriptor.number())); + std::make_pair(value_descriptor.name(), value_descriptor.number())); } } @@ -665,10 +680,12 @@ void Generator::PrintDescriptor(const Descriptor& message_descriptor) const { message_descriptor.options().SerializeToString(&options_string); printer_->Print( "options=$options_value$,\n" - "is_extendable=$extendable$", + "is_extendable=$extendable$,\n" + "syntax='$syntax$'", "options_value", OptionsValue("MessageOptions", options_string), "extendable", message_descriptor.extension_range_count() > 0 ? - "True" : "False"); + "True" : "False", + "syntax", StringifySyntax(message_descriptor.file()->syntax())); printer_->Print(",\n"); // Extension ranges diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3 new file mode 100644 index 00000000..934f36fa Binary files /dev/null and b/src/google/protobuf/testdata/golden_message_proto3 differ diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto index 53f23d87..6d7bada8 100644 --- a/src/google/protobuf/unittest_proto3_arena.proto +++ b/src/google/protobuf/unittest_proto3_arena.proto @@ -47,9 +47,10 @@ message TestAllTypes { } enum NestedEnum { - FOO = 0; - BAR = 1; - BAZ = 2; + ZERO = 0; + FOO = 1; + BAR = 2; + BAZ = 3; NEG = -1; // Intentionally negative. } @@ -81,6 +82,11 @@ message TestAllTypes { optional NestedEnum optional_nested_enum = 21; optional ForeignEnum optional_foreign_enum = 22; + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // optional protobuf_unittest_import.ImportEnum optional_import_enum = 23; + optional string optional_string_piece = 24 [ctype=STRING_PIECE]; optional string optional_cord = 25 [ctype=CORD]; @@ -118,6 +124,11 @@ message TestAllTypes { repeated NestedEnum repeated_nested_enum = 51; repeated ForeignEnum repeated_foreign_enum = 52; + // Omitted (compared to unittest.proto) because proto2 enums are not allowed + // inside proto2 messages. + // + // repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; repeated string repeated_cord = 55 [ctype=CORD]; @@ -131,6 +142,31 @@ message TestAllTypes { } } +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; +} + // Define these after TestAllTypes to make sure the compiler can handle // that. message ForeignMessage { @@ -138,7 +174,13 @@ message ForeignMessage { } enum ForeignEnum { - FOREIGN_FOO = 0; - FOREIGN_BAR = 1; - FOREIGN_BAZ = 2; + FOREIGN_ZERO = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +// TestEmptyMessage is used to test behavior of unknown fields. +message TestEmptyMessage { } + -- cgit v1.2.3 From 885b612f74f133678bf82808c589331e4c59dad9 Mon Sep 17 00:00:00 2001 From: Jisi Liu Date: Sat, 28 Feb 2015 14:51:22 -0800 Subject: Down integrate from Google internal branch for C++ and Java. - Maps for C++ lite - C++ Arena optimizations. - Java Lite runtime code size optimization. Change-Id: I7537a4357c1cb385d23f9e8aa7ffdfeefe079f13 --- generate_descriptor_proto.sh | 38 +- .../java/com/google/protobuf/AbstractMessage.java | 6 +- .../com/google/protobuf/BoundedByteString.java | 2 +- .../main/java/com/google/protobuf/ByteString.java | 7 +- .../main/java/com/google/protobuf/Descriptors.java | 2 +- .../java/com/google/protobuf/DynamicMessage.java | 11 +- .../main/java/com/google/protobuf/FieldSet.java | 56 +- .../java/com/google/protobuf/GeneratedMessage.java | 212 +- .../com/google/protobuf/GeneratedMessageLite.java | 145 +- .../java/com/google/protobuf/LazyFieldLite.java | 249 +- .../com/google/protobuf/LiteralByteString.java | 6 +- .../src/main/java/com/google/protobuf/Message.java | 4 +- .../com/google/protobuf/MessageReflection.java | 60 +- .../java/com/google/protobuf/RopeByteString.java | 8 +- .../main/java/com/google/protobuf/TextFormat.java | 119 +- .../main/java/com/google/protobuf/WireFormat.java | 82 + .../com/google/protobuf/GeneratedMessageTest.java | 2 +- .../com/google/protobuf/LazyFieldLiteTest.java | 139 +- .../com/google/protobuf/LazyMessageLiteTest.java | 19 + .../com/google/protobuf/LiteralByteStringTest.java | 24 +- .../java/com/google/protobuf/MapForProto2Test.java | 14 + .../src/test/java/com/google/protobuf/MapTest.java | 1 - .../com/google/protobuf/RopeByteStringTest.java | 28 + .../com/google/protobuf/lazy_fields_lite.proto | 9 + .../google/protobuf/map_for_proto2_lite_test.proto | 7 + .../com/google/protobuf/map_for_proto2_test.proto | 7 + .../test/java/com/google/protobuf/map_test.proto | 1 + .../com/google/protobuf/test_bad_identifiers.proto | 1 + python/google/protobuf/internal/message_test.py | 3 +- .../google/protobuf/internal/text_format_test.py | 2 +- python/google/protobuf/pyext/descriptor.cc | 15 +- python/google/protobuf/pyext/message.cc | 5 +- .../protobuf/pyext/repeated_composite_container.cc | 7 +- .../protobuf/pyext/repeated_scalar_container.cc | 5 +- src/Makefile.am | 19 +- src/google/protobuf/arena.cc | 67 +- src/google/protobuf/arena.h | 156 +- src/google/protobuf/arena_test_util.cc | 49 + src/google/protobuf/arena_test_util.h | 59 + src/google/protobuf/arena_unittest.cc | 227 +- .../protobuf/compiler/command_line_interface.cc | 203 +- .../compiler/command_line_interface_unittest.cc | 5 +- .../compiler/cpp/cpp_bootstrap_unittest.cc | 3 +- src/google/protobuf/compiler/cpp/cpp_enum.cc | 9 +- src/google/protobuf/compiler/cpp/cpp_enum_field.cc | 113 +- src/google/protobuf/compiler/cpp/cpp_enum_field.h | 9 +- src/google/protobuf/compiler/cpp/cpp_field.h | 2 +- src/google/protobuf/compiler/cpp/cpp_file.cc | 42 +- src/google/protobuf/compiler/cpp/cpp_helpers.cc | 11 +- src/google/protobuf/compiler/cpp/cpp_helpers.h | 4 + src/google/protobuf/compiler/cpp/cpp_map_field.cc | 144 +- src/google/protobuf/compiler/cpp/cpp_map_field.h | 3 +- src/google/protobuf/compiler/cpp/cpp_message.cc | 95 +- src/google/protobuf/compiler/cpp/cpp_message.h | 4 +- .../protobuf/compiler/cpp/cpp_message_field.cc | 270 +- .../protobuf/compiler/cpp/cpp_message_field.h | 11 +- .../protobuf/compiler/cpp/cpp_primitive_field.cc | 52 +- .../protobuf/compiler/cpp/cpp_primitive_field.h | 9 +- .../protobuf/compiler/cpp/cpp_string_field.cc | 168 +- .../protobuf/compiler/cpp/cpp_string_field.h | 9 +- src/google/protobuf/compiler/java/java_field.h | 1 + src/google/protobuf/compiler/java/java_helpers.cc | 4 +- src/google/protobuf/compiler/java/java_helpers.h | 10 + .../compiler/java/java_lazy_message_field.cc | 10 +- .../protobuf/compiler/java/java_map_field.cc | 101 +- src/google/protobuf/compiler/java/java_map_field.h | 1 + src/google/protobuf/compiler/java/java_message.cc | 284 +- src/google/protobuf/compiler/java/java_message.h | 2 +- .../protobuf/compiler/java/java_primitive_field.cc | 3 + .../compiler/java/java_shared_code_generator.cc | 2 +- .../protobuf/compiler/java/java_string_field.cc | 2 +- .../protobuf/compiler/mock_code_generator.cc | 8 +- src/google/protobuf/compiler/parser.cc | 94 +- src/google/protobuf/compiler/parser.h | 37 +- src/google/protobuf/compiler/parser_unittest.cc | 206 +- src/google/protobuf/compiler/plugin.cc | 13 +- src/google/protobuf/compiler/plugin.pb.cc | 395 +- src/google/protobuf/compiler/plugin.pb.h | 155 +- src/google/protobuf/compiler/plugin.proto | 2 + src/google/protobuf/descriptor.cc | 88 +- src/google/protobuf/descriptor.h | 24 +- src/google/protobuf/descriptor.pb.cc | 3885 +++++++++++++++++++- src/google/protobuf/descriptor.pb.h | 1347 ++++--- src/google/protobuf/descriptor.proto | 23 +- src/google/protobuf/descriptor_database.cc | 28 +- .../protobuf/descriptor_database_unittest.cc | 6 +- src/google/protobuf/descriptor_pb2_test.py | 54 - src/google/protobuf/descriptor_unittest.cc | 4 +- src/google/protobuf/extension_set.cc | 16 +- src/google/protobuf/extension_set_heavy.cc | 7 +- src/google/protobuf/generated_enum_reflection.h | 5 +- src/google/protobuf/generated_enum_util.h | 46 + .../protobuf/generated_message_reflection.cc | 41 +- src/google/protobuf/io/coded_stream.cc | 77 +- src/google/protobuf/io/coded_stream.h | 56 +- src/google/protobuf/io/coded_stream_unittest.cc | 4 +- src/google/protobuf/io/gzip_stream.cc | 1 + .../protobuf/io/zero_copy_stream_impl_lite.h | 2 +- src/google/protobuf/lite_unittest.cc | 2 +- src/google/protobuf/map.h | 181 +- src/google/protobuf/map_entry.h | 328 +- src/google/protobuf/map_entry_lite.h | 409 +++ src/google/protobuf/map_field.cc | 8 +- src/google/protobuf/map_field.h | 88 +- src/google/protobuf/map_field_inl.h | 298 +- src/google/protobuf/map_field_lite.h | 278 ++ src/google/protobuf/map_field_test.cc | 67 +- src/google/protobuf/map_lite_test_util.cc | 93 + src/google/protobuf/map_lite_test_util.h | 80 + src/google/protobuf/map_lite_unittest.proto | 98 +- src/google/protobuf/map_test.cc | 84 +- src/google/protobuf/map_test_util.cc | 272 +- src/google/protobuf/map_test_util.h | 9 +- src/google/protobuf/map_test_util_impl.h | 474 +++ src/google/protobuf/map_type_handler.h | 200 +- src/google/protobuf/map_unittest.proto | 23 + src/google/protobuf/message.cc | 24 +- src/google/protobuf/message.h | 26 +- src/google/protobuf/message_lite.h | 14 +- src/google/protobuf/new_delete_capture.cc | 121 - src/google/protobuf/new_delete_capture.h | 175 - src/google/protobuf/preserve_unknown_enum_test.cc | 107 +- src/google/protobuf/reflection.h | 301 +- src/google/protobuf/repeated_field.h | 2 +- .../protobuf/repeated_field_reflection_unittest.cc | 2 + src/google/protobuf/repeated_field_unittest.cc | 29 +- src/google/protobuf/stubs/hash.h | 8 +- src/google/protobuf/stubs/strutil.cc | 205 ++ src/google/protobuf/stubs/strutil.h | 203 +- src/google/protobuf/text_format.cc | 7 +- src/google/protobuf/text_format.h | 16 +- src/google/protobuf/unittest_no_arena.proto | 3 +- .../protobuf/unittest_preserve_unknown_enum.proto | 12 +- .../protobuf/unittest_preserve_unknown_enum2.proto | 50 + src/google/protobuf/unknown_enum_impl.h | 23 + src/google/protobuf/unknown_field_set.h | 5 +- src/google/protobuf/wire_format.cc | 35 +- src/google/protobuf/wire_format.h | 8 + src/google/protobuf/wire_format_lite.cc | 28 + src/google/protobuf/wire_format_lite.h | 19 +- 140 files changed, 11212 insertions(+), 3286 deletions(-) create mode 100644 src/google/protobuf/arena_test_util.cc create mode 100644 src/google/protobuf/arena_test_util.h delete mode 100644 src/google/protobuf/descriptor_pb2_test.py create mode 100644 src/google/protobuf/generated_enum_util.h create mode 100644 src/google/protobuf/map_entry_lite.h create mode 100644 src/google/protobuf/map_field_lite.h create mode 100644 src/google/protobuf/map_lite_test_util.cc create mode 100644 src/google/protobuf/map_lite_test_util.h create mode 100644 src/google/protobuf/map_test_util_impl.h delete mode 100644 src/google/protobuf/new_delete_capture.cc delete mode 100644 src/google/protobuf/new_delete_capture.h create mode 100644 src/google/protobuf/unittest_preserve_unknown_enum2.proto (limited to 'src/google/protobuf/compiler') diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh index 07219dc1..a8d95aaf 100755 --- a/generate_descriptor_proto.sh +++ b/generate_descriptor_proto.sh @@ -27,7 +27,39 @@ __EOF__ fi cd src -make $@ protoc && - ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto && \ - ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:. google/protobuf/compiler/plugin.proto +CORE_PROTO_IS_CORRECT=0 +while [ $CORE_PROTO_IS_CORRECT -ne 1 ] +do + CORE_PROTO_IS_CORRECT=1 + cp google/protobuf/descriptor.pb.h google/protobuf/descriptor.pb.h.tmp + cp google/protobuf/descriptor.pb.cc google/protobuf/descriptor.pb.cc.tmp + cp google/protobuf/compiler/plugin.pb.h google/protobuf/compiler/plugin.pb.h.tmp + cp google/protobuf/compiler/plugin.pb.cc google/protobuf/compiler/plugin.pb.cc.tmp + + make -j8 $@ protoc && + ./protoc --cpp_out=dllexport_decl=LIBPROTOBUF_EXPORT:. google/protobuf/descriptor.proto && \ + ./protoc --cpp_out=dllexport_decl=LIBPROTOC_EXPORT:. google/protobuf/compiler/plugin.proto + + diff google/protobuf/descriptor.pb.h google/protobuf/descriptor.pb.h.tmp > /dev/null + if test $? -ne 0; then + CORE_PROTO_IS_CORRECT=0 + fi + diff google/protobuf/descriptor.pb.cc google/protobuf/descriptor.pb.cc.tmp > /dev/null + if test $? -ne 0; then + CORE_PROTO_IS_CORRECT=0 + fi + diff google/protobuf/compiler/plugin.pb.h google/protobuf/compiler/plugin.pb.h.tmp > /dev/null + if test $? -ne 0; then + CORE_PROTO_IS_CORRECT=0 + fi + diff google/protobuf/compiler/plugin.pb.cc google/protobuf/compiler/plugin.pb.cc.tmp > /dev/null + if test $? -ne 0; then + CORE_PROTO_IS_CORRECT=0 + fi + + rm google/protobuf/descriptor.pb.h.tmp + rm google/protobuf/descriptor.pb.cc.tmp + rm google/protobuf/compiler/plugin.pb.h.tmp + rm google/protobuf/compiler/plugin.pb.cc.tmp +done cd .. diff --git a/java/src/main/java/com/google/protobuf/AbstractMessage.java b/java/src/main/java/com/google/protobuf/AbstractMessage.java index 6de4cae3..cc89173a 100644 --- a/java/src/main/java/com/google/protobuf/AbstractMessage.java +++ b/java/src/main/java/com/google/protobuf/AbstractMessage.java @@ -83,10 +83,10 @@ public abstract class AbstractMessage extends AbstractMessageLite } public void writeTo(final CodedOutputStream output) throws IOException { - MessageReflection.writeMessageTo(this, output, false); + MessageReflection.writeMessageTo(this, getAllFields(), output, false); } - private int memoizedSize = -1; + protected int memoizedSize = -1; public int getSerializedSize() { int size = memoizedSize; @@ -94,7 +94,7 @@ public abstract class AbstractMessage extends AbstractMessageLite return size; } - memoizedSize = MessageReflection.getSerializedSize(this); + memoizedSize = MessageReflection.getSerializedSize(this, getAllFields()); return memoizedSize; } diff --git a/java/src/main/java/com/google/protobuf/BoundedByteString.java b/java/src/main/java/com/google/protobuf/BoundedByteString.java index 8cb6f463..b4c3fb1b 100644 --- a/java/src/main/java/com/google/protobuf/BoundedByteString.java +++ b/java/src/main/java/com/google/protobuf/BoundedByteString.java @@ -30,8 +30,8 @@ package com.google.protobuf; -import java.io.InvalidObjectException; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.util.NoSuchElementException; diff --git a/java/src/main/java/com/google/protobuf/ByteString.java b/java/src/main/java/com/google/protobuf/ByteString.java index cff1ee51..9b0a524b 100644 --- a/java/src/main/java/com/google/protobuf/ByteString.java +++ b/java/src/main/java/com/google/protobuf/ByteString.java @@ -76,6 +76,9 @@ public abstract class ByteString implements Iterable, Serializable { static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k + // Defined by java.nio.charset.Charset + protected static final String UTF_8 = "UTF-8"; + /** * Empty {@code ByteString}. */ @@ -267,7 +270,7 @@ public abstract class ByteString implements Iterable, Serializable { */ public static ByteString copyFromUtf8(String text) { try { - return new LiteralByteString(text.getBytes("UTF-8")); + return new LiteralByteString(text.getBytes(UTF_8)); } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8 not supported?", e); } @@ -622,7 +625,7 @@ public abstract class ByteString implements Iterable, Serializable { */ public String toStringUtf8() { try { - return toString("UTF-8"); + return toString(UTF_8); } catch (UnsupportedEncodingException e) { throw new RuntimeException("UTF-8 not supported?", e); } diff --git a/java/src/main/java/com/google/protobuf/Descriptors.java b/java/src/main/java/com/google/protobuf/Descriptors.java index d65e8b49..806f46c1 100644 --- a/java/src/main/java/com/google/protobuf/Descriptors.java +++ b/java/src/main/java/com/google/protobuf/Descriptors.java @@ -897,7 +897,7 @@ public final class Descriptors { return (type == Type.STRING) && (getFile().getOptions().getJavaStringCheckUtf8()); } - boolean isMapField() { + public boolean isMapField() { return getType() == Type.MESSAGE && isRepeated() && getMessageType().getOptions().getMapEntry(); } diff --git a/java/src/main/java/com/google/protobuf/DynamicMessage.java b/java/src/main/java/com/google/protobuf/DynamicMessage.java index 9c5e6c61..3ea1b688 100644 --- a/java/src/main/java/com/google/protobuf/DynamicMessage.java +++ b/java/src/main/java/com/google/protobuf/DynamicMessage.java @@ -35,8 +35,8 @@ import com.google.protobuf.Descriptors.EnumValueDescriptor; import com.google.protobuf.Descriptors.FieldDescriptor; import com.google.protobuf.Descriptors.OneofDescriptor; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.util.Collections; import java.util.List; import java.util.Map; @@ -600,9 +600,12 @@ public final class DynamicMessage extends AbstractMessage { } // TODO(xiaofeng): Re-enable this check after Orgstore is fixed to not // set incorrect EnumValueDescriptors. - // if (field.getEnumType() != ((EnumValueDescriptor) value).getType()) { - // throw new IllegalArgumentException( - // "EnumValueDescriptor doesn't match Enum Field."); + // EnumDescriptor fieldType = field.getEnumType(); + // EnumDescriptor fieldValueType = ((EnumValueDescriptor) value).getType(); + // if (fieldType != fieldValueType) { + // throw new IllegalArgumentException(String.format( + // "EnumDescriptor %s of field doesn't match EnumDescriptor %s of field value", + // fieldType.getFullName(), fieldValueType.getFullName())); // } } diff --git a/java/src/main/java/com/google/protobuf/FieldSet.java b/java/src/main/java/com/google/protobuf/FieldSet.java index ff9b5bc0..47924b65 100644 --- a/java/src/main/java/com/google/protobuf/FieldSet.java +++ b/java/src/main/java/com/google/protobuf/FieldSet.java @@ -553,42 +553,13 @@ final class FieldSet getAllFieldsMutable() { + /** + * Internal helper to return a modifiable map containing all the fields. + * The returned Map is modifialbe so that the caller can add additional + * extension fields to implement {@link #getAllFields()}. + * + * @param getBytesForString whether to generate ByteString for string fields + */ + private Map getAllFieldsMutable( + boolean getBytesForString) { final TreeMap result = new TreeMap(); final Descriptor descriptor = internalGetFieldAccessorTable().descriptor; @@ -122,7 +129,12 @@ public abstract class GeneratedMessage extends AbstractMessage } } else { if (hasField(field)) { - result.put(field, getField(field)); + if (getBytesForString + && field.getJavaType() == FieldDescriptor.JavaType.STRING) { + result.put(field, getFieldRaw(field)); + } else { + result.put(field, getField(field)); + } } } } @@ -161,7 +173,23 @@ public abstract class GeneratedMessage extends AbstractMessage //@Override (Java 1.6 override semantics, but we must support 1.5) public Map getAllFields() { - return Collections.unmodifiableMap(getAllFieldsMutable()); + return Collections.unmodifiableMap( + getAllFieldsMutable(/* getBytesForString = */ false)); + } + + /** + * Returns a collection of all the fields in this message which are set + * and their corresponding values. A singular ("required" or "optional") + * field is set iff hasField() returns true for that field. A "repeated" + * field is set iff getRepeatedFieldCount() is greater than zero. The + * values are exactly what would be returned by calling + * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field. The map + * is guaranteed to be a sorted map, so iterating over it will return fields + * in order by field number. + */ + Map getAllFieldsRaw() { + return Collections.unmodifiableMap( + getAllFieldsMutable(/* getBytesForString = */ true)); } //@Override (Java 1.6 override semantics, but we must support 1.5) @@ -184,6 +212,18 @@ public abstract class GeneratedMessage extends AbstractMessage return internalGetFieldAccessorTable().getField(field).get(this); } + /** + * Obtains the value of the given field, or the default value if it is + * not set. For primitive fields, the boxed primitive value is returned. + * For enum fields, the EnumValueDescriptor for the value is returned. For + * embedded message fields, the sub-message is returned. For repeated + * fields, a java.util.List is returned. For present string fields, a + * ByteString is returned representing the bytes that the field contains. + */ + Object getFieldRaw(final FieldDescriptor field) { + return internalGetFieldAccessorTable().getField(field).getRaw(this); + } + //@Override (Java 1.6 override semantics, but we must support 1.5) public int getRepeatedFieldCount(final FieldDescriptor field) { return internalGetFieldAccessorTable().getField(field) @@ -214,6 +254,24 @@ public abstract class GeneratedMessage extends AbstractMessage return unknownFields.mergeFieldFrom(tag, input); } + @Override + public void writeTo(final CodedOutputStream output) throws IOException { + MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false); + } + + @Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) { + return size; + } + + memoizedSize = MessageReflection.getSerializedSize( + this, getAllFieldsRaw()); + return memoizedSize; + } + + /** * Used by parsing constructors in generated classes. @@ -563,6 +621,15 @@ public abstract class GeneratedMessage extends AbstractMessage throw new RuntimeException( "No map fields found in " + getClass().getName()); } + + /** Like {@link internalGetMapField} but return a mutable version. */ + @SuppressWarnings({"unused", "rawtypes"}) + protected MapField internalGetMutableMapField(int fieldNumber) { + // Note that we can't use descriptor names here because this method will + // be called when descriptor is being initialized. + throw new RuntimeException( + "No map fields found in " + getClass().getName()); + } } // ================================================================= @@ -825,7 +892,16 @@ public abstract class GeneratedMessage extends AbstractMessage @Override public Map getAllFields() { - final Map result = super.getAllFieldsMutable(); + final Map result = + super.getAllFieldsMutable(/* getBytesForString = */ false); + result.putAll(getExtensionFields()); + return Collections.unmodifiableMap(result); + } + + @Override + public Map getAllFieldsRaw() { + final Map result = + super.getAllFieldsMutable(/* getBytesForString = */ false); result.putAll(getExtensionFields()); return Collections.unmodifiableMap(result); } @@ -1761,6 +1837,10 @@ public abstract class GeneratedMessage extends AbstractMessage fields[i] = new SingularEnumFieldAccessor( field, camelCaseNames[i], messageClass, builderClass, containingOneofCamelCaseName); + } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) { + fields[i] = new SingularStringFieldAccessor( + field, camelCaseNames[i], messageClass, builderClass, + containingOneofCamelCaseName); } else { fields[i] = new SingularFieldAccessor( field, camelCaseNames[i], messageClass, builderClass, @@ -1817,9 +1897,13 @@ public abstract class GeneratedMessage extends AbstractMessage private interface FieldAccessor { Object get(GeneratedMessage message); Object get(GeneratedMessage.Builder builder); + Object getRaw(GeneratedMessage message); + Object getRaw(GeneratedMessage.Builder builder); void set(Builder builder, Object value); Object getRepeated(GeneratedMessage message, int index); Object getRepeated(GeneratedMessage.Builder builder, int index); + Object getRepeatedRaw(GeneratedMessage message, int index); + Object getRepeatedRaw(GeneratedMessage.Builder builder, int index); void setRepeated(Builder builder, int index, Object value); void addRepeated(Builder builder, Object value); @@ -1949,6 +2033,12 @@ public abstract class GeneratedMessage extends AbstractMessage public Object get(GeneratedMessage.Builder builder) { return invokeOrDie(getMethodBuilder, builder); } + public Object getRaw(final GeneratedMessage message) { + return get(message); + } + public Object getRaw(GeneratedMessage.Builder builder) { + return get(builder); + } public void set(final Builder builder, final Object value) { invokeOrDie(setMethod, builder, value); } @@ -1957,12 +2047,22 @@ public abstract class GeneratedMessage extends AbstractMessage throw new UnsupportedOperationException( "getRepeatedField() called on a singular field."); } + public Object getRepeatedRaw(final GeneratedMessage message, + final int index) { + throw new UnsupportedOperationException( + "getRepeatedFieldRaw() called on a singular field."); + } public Object getRepeated(GeneratedMessage.Builder builder, int index) { throw new UnsupportedOperationException( "getRepeatedField() called on a singular field."); } - public void setRepeated(final Builder builder, - final int index, final Object value) { + public Object getRepeatedRaw(GeneratedMessage.Builder builder, + int index) { + throw new UnsupportedOperationException( + "getRepeatedFieldRaw() called on a singular field."); + } + public void setRepeated(final Builder builder, final int index, + final Object value) { throw new UnsupportedOperationException( "setRepeatedField() called on a singular field."); } @@ -2058,6 +2158,12 @@ public abstract class GeneratedMessage extends AbstractMessage public Object get(GeneratedMessage.Builder builder) { return invokeOrDie(getMethodBuilder, builder); } + public Object getRaw(final GeneratedMessage message) { + return get(message); + } + public Object getRaw(GeneratedMessage.Builder builder) { + return get(builder); + } public void set(final Builder builder, final Object value) { // Add all the elements individually. This serves two purposes: // 1) Verifies that each element has the correct type. @@ -2075,6 +2181,13 @@ public abstract class GeneratedMessage extends AbstractMessage public Object getRepeated(GeneratedMessage.Builder builder, int index) { return invokeOrDie(getRepeatedMethodBuilder, builder, index); } + public Object getRepeatedRaw(GeneratedMessage message, int index) { + return getRepeated(message, index); + } + public Object getRepeatedRaw(GeneratedMessage.Builder builder, + int index) { + return getRepeated(builder, index); + } public void setRepeated(final Builder builder, final int index, final Object value) { invokeOrDie(setRepeatedMethod, builder, index, value); @@ -2139,6 +2252,12 @@ public abstract class GeneratedMessage extends AbstractMessage return (MapField) builder.internalGetMapField(field.getNumber()); } + private MapField getMutableMapField( + GeneratedMessage.Builder builder) { + return (MapField) builder.internalGetMutableMapField( + field.getNumber()); + } + public Object get(GeneratedMessage message) { List result = new ArrayList(); for (int i = 0; i < getRepeatedCount(message); i++) { @@ -2155,6 +2274,14 @@ public abstract class GeneratedMessage extends AbstractMessage return Collections.unmodifiableList(result); } + public Object getRaw(GeneratedMessage message) { + return get(message); + } + + public Object getRaw(GeneratedMessage.Builder builder) { + return get(builder); + } + public void set(Builder builder, Object value) { clear(builder); for (Object entry : (List) value) { @@ -2170,14 +2297,20 @@ public abstract class GeneratedMessage extends AbstractMessage return getMapField(builder).getList().get(index); } + public Object getRepeatedRaw(GeneratedMessage message, int index) { + return getRepeated(message, index); + } + + public Object getRepeatedRaw(Builder builder, int index) { + return getRepeated(builder, index); + } + public void setRepeated(Builder builder, int index, Object value) { - builder.onChanged(); - getMapField(builder).getMutableList().set(index, (Message) value); + getMutableMapField(builder).getMutableList().set(index, (Message) value); } public void addRepeated(Builder builder, Object value) { - builder.onChanged(); - getMapField(builder).getMutableList().add((Message) value); + getMutableMapField(builder).getMutableList().add((Message) value); } public boolean has(GeneratedMessage message) { @@ -2199,8 +2332,7 @@ public abstract class GeneratedMessage extends AbstractMessage } public void clear(Builder builder) { - builder.onChanged(); - getMapField(builder).getMutableList().clear(); + getMutableMapField(builder).getMutableList().clear(); } public com.google.protobuf.Message.Builder newBuilder() { @@ -2391,6 +2523,60 @@ public abstract class GeneratedMessage extends AbstractMessage // --------------------------------------------------------------- + /** + * Field accessor for string fields. + * + *

This class makes getFooBytes() and setFooBytes() available for + * reflection API so that reflection based serialize/parse functions can + * access the raw bytes of the field to preserve non-UTF8 bytes in the + * string. + * + *

This ensures the serialize/parse round-trip safety, which is important + * for servers which forward messages. + */ + private static final class SingularStringFieldAccessor + extends SingularFieldAccessor { + SingularStringFieldAccessor( + final FieldDescriptor descriptor, final String camelCaseName, + final Class messageClass, + final Class builderClass, + final String containingOneofCamelCaseName) { + super(descriptor, camelCaseName, messageClass, builderClass, + containingOneofCamelCaseName); + getBytesMethod = getMethodOrDie(messageClass, + "get" + camelCaseName + "Bytes"); + getBytesMethodBuilder = getMethodOrDie(builderClass, + "get" + camelCaseName + "Bytes"); + setBytesMethodBuilder = getMethodOrDie(builderClass, + "set" + camelCaseName + "Bytes", ByteString.class); + } + + private final Method getBytesMethod; + private final Method getBytesMethodBuilder; + private final Method setBytesMethodBuilder; + + @Override + public Object getRaw(final GeneratedMessage message) { + return invokeOrDie(getBytesMethod, message); + } + + @Override + public Object getRaw(GeneratedMessage.Builder builder) { + return invokeOrDie(getBytesMethodBuilder, builder); + } + + @Override + public void set(GeneratedMessage.Builder builder, Object value) { + if (value instanceof ByteString) { + invokeOrDie(setBytesMethodBuilder, builder, value); + } else { + super.set(builder, value); + } + } + } + + // --------------------------------------------------------------- + private static final class SingularMessageFieldAccessor extends SingularFieldAccessor { SingularMessageFieldAccessor( diff --git a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java index 4d25c077..6839c9dd 100644 --- a/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java +++ b/java/src/main/java/com/google/protobuf/GeneratedMessageLite.java @@ -42,22 +42,58 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * Lite version of {@link GeneratedMessage}. * * @author kenton@google.com Kenton Varda */ -public abstract class GeneratedMessageLite extends AbstractMessageLite - implements Serializable { +public abstract class GeneratedMessageLite< + MessageType extends GeneratedMessageLite, + BuilderType extends GeneratedMessageLite.Builder> + extends AbstractMessageLite + implements Serializable { + + /** + * Holds all the {@link PrototypeHolder}s for loaded classes. + */ + // TODO(dweis): Consider different concurrency values. + // TODO(dweis): This will prevent garbage collection of the class loader. + // Ideally we'd use something like ClassValue but that's Java 7 only. + private static final Map, PrototypeHolder> PROTOTYPE_MAP = + new ConcurrentHashMap, PrototypeHolder>(); + + // For use by generated code only. + protected static < + MessageType extends GeneratedMessageLite, + BuilderType extends GeneratedMessageLite.Builder< + MessageType, BuilderType>> void onLoad(Class clazz, + PrototypeHolder protoTypeHolder) { + PROTOTYPE_MAP.put(clazz, protoTypeHolder); + } + private static final long serialVersionUID = 1L; /** For use by generated code only. */ protected UnknownFieldSetLite unknownFields; - public Parser getParserForType() { - throw new UnsupportedOperationException( - "This is supposed to be overridden by subclasses."); + @SuppressWarnings("unchecked") // Guaranteed by runtime. + public final Parser getParserForType() { + return (Parser) PROTOTYPE_MAP + .get(getClass()).getParserForType(); + } + + @SuppressWarnings("unchecked") // Guaranteed by runtime. + public final MessageType getDefaultInstanceForType() { + return (MessageType) PROTOTYPE_MAP + .get(getClass()).getDefaultInstanceForType(); + } + + @SuppressWarnings("unchecked") // Guaranteed by runtime. + public final BuilderType newBuilderForType() { + return (BuilderType) PROTOTYPE_MAP + .get(getClass()).newBuilderForType(); } /** @@ -73,10 +109,17 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite return unknownFields.mergeFieldFrom(tag, input); } + // The default behavior. If a message has required fields in its subtree, the + // generated code will override. + public boolean isInitialized() { + return true; + } + @SuppressWarnings("unchecked") - public abstract static class Builder - extends AbstractMessageLite.Builder { + public abstract static class Builder< + MessageType extends GeneratedMessageLite, + BuilderType extends Builder> + extends AbstractMessageLite.Builder { private final MessageType defaultInstance; @@ -88,6 +131,12 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite this.defaultInstance = defaultInstance; } + // The default behavior. If a message has required fields in its subtree, + // the generated code will override. + public boolean isInitialized() { + return true; + } + //@Override (Java 1.6 override semantics, but we must support 1.5) public BuilderType clear() { unknownFields = UnknownFieldSetLite.getDefaultInstance(); @@ -174,7 +223,9 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite * Lite equivalent of {@link com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder}. */ public interface ExtendableMessageOrBuilder< - MessageType extends ExtendableMessage> extends MessageLiteOrBuilder { + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends MessageLiteOrBuilder { /** Check if a singular extension is present. */ boolean hasExtension( @@ -197,16 +248,30 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite * Lite equivalent of {@link GeneratedMessage.ExtendableMessage}. */ public abstract static class ExtendableMessage< - MessageType extends ExtendableMessage> - extends GeneratedMessageLite - implements ExtendableMessageOrBuilder { + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder> + extends GeneratedMessageLite + implements ExtendableMessageOrBuilder { /** * Represents the set of extensions on this message. For use by generated * code only. */ protected FieldSet extensions = FieldSet.newFieldSet(); - + + // -1 => not memoized, 0 => false, 1 => true. + private byte memoizedIsInitialized = -1; + + // The default behavior. If a message has required fields in its subtree, + // the generated code will override. + public boolean isInitialized() { + if (memoizedIsInitialized == -1) { + memoizedIsInitialized = (byte) (extensions.isInitialized() ? 1 : 0); + } + + return memoizedIsInitialized == 1; + } + private void verifyExtensionContainingType( final GeneratedExtension extension) { if (extension.getContainingTypeDefaultInstance() != @@ -349,10 +414,10 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite */ @SuppressWarnings("unchecked") public abstract static class ExtendableBuilder< - MessageType extends ExtendableMessage, + MessageType extends ExtendableMessage, BuilderType extends ExtendableBuilder> extends Builder - implements ExtendableMessageOrBuilder { + implements ExtendableMessageOrBuilder { protected ExtendableBuilder(MessageType defaultInstance) { super(defaultInstance); } @@ -360,6 +425,12 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite private FieldSet extensions = FieldSet.emptySet(); private boolean extensionsIsMutable; + // The default behavior. If a message has required fields in its subtree, + // the generated code will override. + public boolean isInitialized() { + return extensions.isInitialized(); + } + // For immutable message conversion. void internalSetExtensionSet(FieldSet extensions) { this.extensions = extensions; @@ -991,7 +1062,10 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite * Checks that the {@link Extension} is Lite and returns it as a * {@link GeneratedExtension}. */ - private static , T> + private static < + MessageType extends ExtendableMessage, + BuilderType extends ExtendableBuilder, + T> GeneratedExtension checkIsLite( ExtensionLite extension) { if (!extension.isLite()) { @@ -1000,4 +1074,43 @@ public abstract class GeneratedMessageLite extends AbstractMessageLite return (GeneratedExtension) extension; } + + /** + * Represents the state needed to implement *ForType methods. Generated code + * must provide a static singleton instance by adding it with + * {@link GeneratedMessageLite#onLoad(Class, PrototypeHolder)} on class load. + *

    + *
  • {@link #getDefaultInstanceForType()} + *
  • {@link #getParserForType()} + *
  • {@link #newBuilderForType()} + *
+ * This allows us to trade three generated methods for a static Map. + */ + protected static class PrototypeHolder< + MessageType extends GeneratedMessageLite, + BuilderType extends GeneratedMessageLite.Builder< + MessageType, BuilderType>> { + + private final MessageType defaultInstance; + private final Parser parser; + + public PrototypeHolder( + MessageType defaultInstance, Parser parser) { + this.defaultInstance = defaultInstance; + this.parser = parser; + } + + public MessageType getDefaultInstanceForType() { + return defaultInstance; + } + + public Parser getParserForType() { + return parser; + } + + @SuppressWarnings("unchecked") // Guaranteed by runtime. + public BuilderType newBuilderForType() { + return (BuilderType) defaultInstance.toBuilder(); + } + } } diff --git a/java/src/main/java/com/google/protobuf/LazyFieldLite.java b/java/src/main/java/com/google/protobuf/LazyFieldLite.java index 1fc80e87..eea1fe3c 100644 --- a/java/src/main/java/com/google/protobuf/LazyFieldLite.java +++ b/java/src/main/java/com/google/protobuf/LazyFieldLite.java @@ -30,8 +30,6 @@ package com.google.protobuf; -import java.io.IOException; - /** * LazyFieldLite encapsulates the logic of lazily parsing message fields. It stores * the message in a ByteString initially and then parse it on-demand. @@ -44,40 +42,102 @@ import java.io.IOException; * @author xiangl@google.com (Xiang Li) */ public class LazyFieldLite { - private ByteString bytes; + private static final ExtensionRegistryLite EMPTY_REGISTRY = + ExtensionRegistryLite.getEmptyRegistry(); + + /** + * A delayed-parsed version of the bytes. When this is non-null then {@code extensionRegistry } is + * also non-null and {@code value} and {@code memoizedBytes} are null. + */ + private ByteString delayedBytes; + + /** + * An {@code ExtensionRegistryLite} for parsing bytes. It is non-null on a best-effort basis. It + * is only guaranteed to be non-null if this message was initialized using bytes and an + * {@code ExtensionRegistry}. If it directly had a value set then it will be null, unless it has + * been merged with another {@code LazyFieldLite} that had an {@code ExtensionRegistry}. + */ private ExtensionRegistryLite extensionRegistry; - private volatile boolean isDirty = false; + /** + * The parsed value. When this is non-null then {@code delayedBytes} will be null. + */ protected volatile MessageLite value; + /** + * The memoized bytes for {@code value}. Will be null when {@code value} is null. + */ + private volatile ByteString memoizedBytes; + + /** + * Constructs a LazyFieldLite with bytes that will be parsed lazily. + */ public LazyFieldLite(ExtensionRegistryLite extensionRegistry, ByteString bytes) { + checkArguments(extensionRegistry, bytes); this.extensionRegistry = extensionRegistry; - this.bytes = bytes; + this.delayedBytes = bytes; } + /** + * Constructs a LazyFieldLite with no contents, and no ability to parse extensions. + */ public LazyFieldLite() { } + /** + * Constructs a LazyFieldLite instance with a value. The LazyFieldLite may not be able to parse + * the extensions in the value as it has no ExtensionRegistry. + */ public static LazyFieldLite fromValue(MessageLite value) { LazyFieldLite lf = new LazyFieldLite(); lf.setValue(value); return lf; } + /** + * Determines whether this LazyFieldLite instance represents the default instance of this type. + */ public boolean containsDefaultInstance() { - return value == null && bytes == null; + return memoizedBytes == ByteString.EMPTY + || value == null && (delayedBytes == null || delayedBytes == ByteString.EMPTY); } + /** + * Clears the value state of this instance. + * + *

LazyField is not thread-safe for write access. Synchronizations are needed + * under read/write situations. + */ public void clear() { - bytes = null; + // Don't clear the ExtensionRegistry. It might prove useful later on when merging in another + // value, but there is no guarantee that it will contain all extensions that were directly set + // on the values that need to be merged. + delayedBytes = null; value = null; - extensionRegistry = null; - isDirty = true; + memoizedBytes = null; + } + + /** + * Overrides the contents of this LazyField. + * + *

LazyField is not thread-safe for write access. Synchronizations are needed + * under read/write situations. + */ + public void set(LazyFieldLite other) { + this.delayedBytes = other.delayedBytes; + this.value = other.value; + this.memoizedBytes = other.memoizedBytes; + // If the other LazyFieldLite was created by directly setting the value rather than first by + // parsing, then it will not have an extensionRegistry. In this case we hold on to the existing + // extensionRegistry, which has no guarantees that it has all the extensions that will be + // directly set on the value. + if (other.extensionRegistry != null) { + this.extensionRegistry = other.extensionRegistry; + } } /** - * Returns message instance. At first time, serialized data is parsed by - * {@code defaultInstance.getParserForType()}. + * Returns message instance. It may do some thread-safe delayed parsing of bytes. * * @param defaultInstance its message's default instance. It's also used to get parser for the * message type. @@ -88,38 +148,109 @@ public class LazyFieldLite { } /** - * LazyField is not thread-safe for write access. Synchronizations are needed + * Sets the value of the instance and returns the old value without delay parsing anything. + * + *

LazyField is not thread-safe for write access. Synchronizations are needed * under read/write situations. */ public MessageLite setValue(MessageLite value) { MessageLite originalValue = this.value; + this.delayedBytes = null; + this.memoizedBytes = null; this.value = value; - bytes = null; - isDirty = true; return originalValue; } - public void merge(LazyFieldLite value) { - if (value.containsDefaultInstance()) { + /** + * Merges another instance's contents. In some cases may drop some extensions if both fields + * contain data. If the other field has an {@code ExtensionRegistry} but this does not, then this + * field will copy over that {@code ExtensionRegistry}. + * + *

LazyField is not thread-safe for write access. Synchronizations are needed + * under read/write situations. + */ + public void merge(LazyFieldLite other) { + if (other.containsDefaultInstance()) { return; } - if (bytes == null) { - this.bytes = value.bytes; + if (this.containsDefaultInstance()) { + set(other); + return; + } + + // If the other field has an extension registry but this does not, copy over the other extension + // registry. + if (this.extensionRegistry == null) { + this.extensionRegistry = other.extensionRegistry; + } + + // In the case that both of them are not parsed we simply concatenate the bytes to save time. In + // the (probably rare) case that they have different extension registries there is a chance that + // some of the extensions may be dropped, but the tradeoff of making this operation fast seems + // to outway the benefits of combining the extension registries, which is not normally done for + // lite protos anyways. + if (this.delayedBytes != null && other.delayedBytes != null) { + this.delayedBytes = this.delayedBytes.concat(other.delayedBytes); + return; + } + + // At least one is parsed and both contain data. We won't drop any extensions here directly, but + // in the case that the extension registries are not the same then we might in the future if we + // need to serialze and parse a message again. + if (this.value == null && other.value != null) { + setValue(mergeValueAndBytes(other.value, this.delayedBytes, this.extensionRegistry)); + return; + } else if (this.value != null && other.value == null) { + setValue(mergeValueAndBytes(this.value, other.delayedBytes, other.extensionRegistry)); + return; + } + + // At this point we have two fully parsed messages. We can't merge directly from one to the + // other because only generated builder code contains methods to mergeFrom another parsed + // message. We have to serialize one instance and then merge the bytes into the other. This may + // drop extensions from one of the messages if one of the values had an extension set on it + // directly. + // + // To mitigate this we prefer serializing a message that has an extension registry, and + // therefore a chance that all extensions set on it are in that registry. + // + // NOTE: The check for other.extensionRegistry not being null must come first because at this + // point in time if other.extensionRegistry is not null then this.extensionRegistry will not be + // null either. + if (other.extensionRegistry != null) { + setValue(mergeValueAndBytes(this.value, other.toByteString(), other.extensionRegistry)); + return; + } else if (this.extensionRegistry != null) { + setValue(mergeValueAndBytes(other.value, this.toByteString(), this.extensionRegistry)); + return; } else { - this.bytes.concat(value.toByteString()); + // All extensions from the other message will be dropped because we have no registry. + setValue(mergeValueAndBytes(this.value, other.toByteString(), EMPTY_REGISTRY)); + return; } - isDirty = false; } - public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) { - this.bytes = bytes; - this.extensionRegistry = extensionRegistry; - isDirty = false; + private static MessageLite mergeValueAndBytes( + MessageLite value, ByteString otherBytes, ExtensionRegistryLite extensionRegistry) { + try { + return value.toBuilder().mergeFrom(otherBytes, extensionRegistry).build(); + } catch (InvalidProtocolBufferException e) { + // Nothing is logged and no exceptions are thrown. Clients will be unaware that a proto + // was invalid. + return value; + } } - public ExtensionRegistryLite getExtensionRegistry() { - return extensionRegistry; + /** + * Sets this field with bytes to delay-parse. + */ + public void setByteString(ByteString bytes, ExtensionRegistryLite extensionRegistry) { + checkArguments(extensionRegistry, bytes); + this.delayedBytes = bytes; + this.extensionRegistry = extensionRegistry; + this.value = null; + this.memoizedBytes = null; } /** @@ -128,30 +259,43 @@ public class LazyFieldLite { * parsed. Be careful when using this method. */ public int getSerializedSize() { - if (isDirty) { + if (delayedBytes != null) { + return delayedBytes.size(); + } else if (memoizedBytes != null) { + return memoizedBytes.size(); + } else if (value != null) { return value.getSerializedSize(); + } else { + return 0; } - return bytes.size(); } + /** + * Returns a BytesString for this field in a thread-safe way. + */ public ByteString toByteString() { - if (!isDirty) { - return bytes; + if (delayedBytes != null) { + return delayedBytes; + } + if (memoizedBytes != null) { + return memoizedBytes; } synchronized (this) { - if (!isDirty) { - return bytes; + if (memoizedBytes != null) { + return memoizedBytes; } if (value == null) { - bytes = ByteString.EMPTY; + memoizedBytes = ByteString.EMPTY; } else { - bytes = value.toByteString(); + memoizedBytes = value.toByteString(); } - isDirty = false; - return bytes; + return memoizedBytes; } } + /** + * Might lazily parse the bytes that were previously passed in. Is thread-safe. + */ protected void ensureInitialized(MessageLite defaultInstance) { if (value != null) { return; @@ -161,16 +305,35 @@ public class LazyFieldLite { return; } try { - if (bytes != null) { - value = defaultInstance.getParserForType() - .parseFrom(bytes, extensionRegistry); + if (delayedBytes != null) { + // The extensionRegistry shouldn't be null here since we have delayedBytes. + MessageLite parsedValue = defaultInstance.getParserForType() + .parseFrom(delayedBytes, extensionRegistry); + this.value = parsedValue; + this.memoizedBytes = delayedBytes; + this.delayedBytes = null; } else { - value = defaultInstance; + this.value = defaultInstance; + this.memoizedBytes = ByteString.EMPTY; + this.delayedBytes = null; } - } catch (IOException e) { - // TODO(xiangl): Refactory the API to support the exception thrown from - // lazily load messages. + } catch (InvalidProtocolBufferException e) { + // Nothing is logged and no exceptions are thrown. Clients will be unaware that this proto + // was invalid. + this.value = defaultInstance; + this.memoizedBytes = ByteString.EMPTY; + this.delayedBytes = null; } } } + + + private static void checkArguments(ExtensionRegistryLite extensionRegistry, ByteString bytes) { + if (extensionRegistry == null) { + throw new NullPointerException("found null ExtensionRegistry"); + } + if (bytes == null) { + throw new NullPointerException("found null ByteString"); + } + } } diff --git a/java/src/main/java/com/google/protobuf/LiteralByteString.java b/java/src/main/java/com/google/protobuf/LiteralByteString.java index 767b9f35..6893ddf1 100644 --- a/java/src/main/java/com/google/protobuf/LiteralByteString.java +++ b/java/src/main/java/com/google/protobuf/LiteralByteString.java @@ -154,7 +154,11 @@ class LiteralByteString extends ByteString { @Override public String toString(String charsetName) throws UnsupportedEncodingException { - return new String(bytes, getOffsetIntoBytes(), size(), charsetName); + // Optimize for empty strings, but ensure we don't silently ignore invalid + // encodings. + return size() == 0 && UTF_8.equals(charsetName) + ? "" + : new String(bytes, getOffsetIntoBytes(), size(), charsetName); } // ================================================================= diff --git a/java/src/main/java/com/google/protobuf/Message.java b/java/src/main/java/com/google/protobuf/Message.java index 5c75b58b..fa0265e2 100644 --- a/java/src/main/java/com/google/protobuf/Message.java +++ b/java/src/main/java/com/google/protobuf/Message.java @@ -163,7 +163,7 @@ public interface Message extends MessageLite, MessageOrBuilder { * field builder, which will then be nested into its parent builder. *

* NOTE: implementations that do not support nested builders will throw - * UnsupportedException. + * UnsupportedOperationException. */ Builder getFieldBuilder(Descriptors.FieldDescriptor field); @@ -181,7 +181,7 @@ public interface Message extends MessageLite, MessageOrBuilder { * field builder, which will then be nested into its parent builder. *

* NOTE: implementations that do not support nested builders will throw - * UnsupportedException. + * UnsupportedOperationException. */ Builder getRepeatedFieldBuilder(Descriptors.FieldDescriptor field, int index); diff --git a/java/src/main/java/com/google/protobuf/MessageReflection.java b/java/src/main/java/com/google/protobuf/MessageReflection.java index 06e3c99b..de4bfd3e 100644 --- a/java/src/main/java/com/google/protobuf/MessageReflection.java +++ b/java/src/main/java/com/google/protobuf/MessageReflection.java @@ -45,13 +45,14 @@ import java.util.TreeMap; */ class MessageReflection { - static void writeMessageTo(Message message, CodedOutputStream output, + static void writeMessageTo( + Message message, + Map fields, + CodedOutputStream output, boolean alwaysWriteRequiredFields) throws IOException { final boolean isMessageSet = message.getDescriptorForType().getOptions().getMessageSetWireFormat(); - - Map fields = message.getAllFields(); if (alwaysWriteRequiredFields) { fields = new TreeMap(fields); for (final FieldDescriptor field : @@ -82,13 +83,15 @@ class MessageReflection { } } - static int getSerializedSize(Message message) { + static int getSerializedSize( + Message message, + Map fields) { int size = 0; final boolean isMessageSet = message.getDescriptorForType().getOptions().getMessageSetWireFormat(); for (final Map.Entry entry : - message.getAllFields().entrySet()) { + fields.entrySet()) { final Descriptors.FieldDescriptor field = entry.getKey(); final Object value = entry.getValue(); if (isMessageSet && field.isExtension() && @@ -340,14 +343,12 @@ class MessageReflection { ByteString bytes, ExtensionRegistryLite registry, Descriptors.FieldDescriptor descriptor, Message defaultInstance) throws IOException; - + /** - * Read a primitive field from input. Note that builders and mutable - * messages may use different Java types to represent a primtive field. + * Returns the UTF8 validation level for the field. */ - Object readPrimitiveField( - CodedInputStream input, WireFormat.FieldType type, - boolean checkUtf8) throws IOException; + WireFormat.Utf8Validation getUtf8Validation(Descriptors.FieldDescriptor + descriptor); /** * Returns a new merge target for a sub-field. When defaultInstance is @@ -513,11 +514,18 @@ class MessageReflection { return new BuilderAdapter(builder.newBuilderForField(field)); } } - - public Object readPrimitiveField( - CodedInputStream input, WireFormat.FieldType type, - boolean checkUtf8) throws IOException { - return FieldSet.readPrimitiveField(input, type, checkUtf8); + + public WireFormat.Utf8Validation + getUtf8Validation(Descriptors.FieldDescriptor descriptor) { + if (descriptor.needsUtf8Check()) { + return WireFormat.Utf8Validation.STRICT; + } + // TODO(liujisi): support lazy strings for repeated fields. + if (!descriptor.isRepeated() + && builder instanceof GeneratedMessage.Builder) { + return WireFormat.Utf8Validation.LAZY; + } + return WireFormat.Utf8Validation.LOOSE; } public Object finish() { @@ -651,11 +659,14 @@ class MessageReflection { throw new UnsupportedOperationException( "newMergeTargetForField() called on FieldSet object"); } - - public Object readPrimitiveField( - CodedInputStream input, WireFormat.FieldType type, - boolean checkUtf8) throws IOException { - return FieldSet.readPrimitiveField(input, type, checkUtf8); + + public WireFormat.Utf8Validation + getUtf8Validation(Descriptors.FieldDescriptor descriptor) { + if (descriptor.needsUtf8Check()) { + return WireFormat.Utf8Validation.STRICT; + } + // TODO(liujisi): support lazy strings for ExtesnsionSet. + return WireFormat.Utf8Validation.LOOSE; } public Object finish() { @@ -767,8 +778,8 @@ class MessageReflection { } } else { while (input.getBytesUntilLimit() > 0) { - final Object value = - target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check()); + final Object value = WireFormat.readPrimitiveField( + input, field.getLiteType(), target.getUtf8Validation(field)); target.addRepeatedField(field, value); } } @@ -801,7 +812,8 @@ class MessageReflection { } break; default: - value = target.readPrimitiveField(input, field.getLiteType(), field.needsUtf8Check()); + value = WireFormat.readPrimitiveField( + input, field.getLiteType(), target.getUtf8Validation(field)); break; } diff --git a/java/src/main/java/com/google/protobuf/RopeByteString.java b/java/src/main/java/com/google/protobuf/RopeByteString.java index fa23c9dd..168bcce2 100644 --- a/java/src/main/java/com/google/protobuf/RopeByteString.java +++ b/java/src/main/java/com/google/protobuf/RopeByteString.java @@ -30,9 +30,9 @@ package com.google.protobuf; -import java.io.InvalidObjectException; import java.io.IOException; import java.io.InputStream; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; @@ -420,7 +420,11 @@ class RopeByteString extends ByteString { @Override public String toString(String charsetName) throws UnsupportedEncodingException { - return new String(toByteArray(), charsetName); + // Optimize for empty strings, but ensure we don't silently ignore invalid + // encodings. + return size() == 0 && UTF_8.equals(charsetName) + ? "" + : new String(toByteArray(), charsetName); } // ================================================================= diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java index 4f6756ed..dd2b4600 100644 --- a/java/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/src/main/java/com/google/protobuf/TextFormat.java @@ -409,9 +409,9 @@ public final class TextFormat { case STRING: generator.print("\""); - generator.print(escapeNonAscii ? - escapeText((String) value) : - escapeDoubleQuotesAndBackslashes((String) value) + generator.print(escapeNonAscii + ? escapeText((String) value) + : escapeDoubleQuotesAndBackslashes((String) value) .replace("\n", "\\n")); generator.print("\""); break; @@ -730,8 +730,8 @@ public final class TextFormat { } final char c = currentToken.charAt(0); - return ('0' <= c && c <= '9') || - c == '-' || c == '+'; + return ('0' <= c && c <= '9') + || c == '-' || c == '+'; } /** @@ -749,10 +749,10 @@ public final class TextFormat { public String consumeIdentifier() throws ParseException { for (int i = 0; i < currentToken.length(); i++) { final char c = currentToken.charAt(i); - if (('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - ('0' <= c && c <= '9') || - (c == '_') || (c == '.')) { + if (('a' <= c && c <= 'z') + || ('A' <= c && c <= 'Z') + || ('0' <= c && c <= '9') + || (c == '_') || (c == '.')) { // OK } else { throw parseException( @@ -941,14 +941,14 @@ public final class TextFormat { * Otherwise, throw a {@link ParseException}. */ public boolean consumeBoolean() throws ParseException { - if (currentToken.equals("true") || - currentToken.equals("t") || - currentToken.equals("1")) { + if (currentToken.equals("true") + || currentToken.equals("t") + || currentToken.equals("1")) { nextToken(); return true; - } else if (currentToken.equals("false") || - currentToken.equals("f") || - currentToken.equals("0")) { + } else if (currentToken.equals("false") + || currentToken.equals("f") + || currentToken.equals("0")) { nextToken(); return false; } else { @@ -999,14 +999,15 @@ public final class TextFormat { */ private void consumeByteString(List list) throws ParseException { - final char quote = currentToken.length() > 0 ? currentToken.charAt(0) - : '\0'; + final char quote = currentToken.length() > 0 + ? currentToken.charAt(0) + : '\0'; if (quote != '\"' && quote != '\'') { throw parseException("Expected string."); } - if (currentToken.length() < 2 || - currentToken.charAt(currentToken.length() - 1) != quote) { + if (currentToken.length() < 2 + || currentToken.charAt(currentToken.length() - 1) != quote) { throw parseException("String missing ending quote."); } @@ -1340,8 +1341,8 @@ public final class TextFormat { } else { if (extension.descriptor.getContainingType() != type) { throw tokenizer.parseExceptionPreviousToken( - "Extension \"" + name + "\" does not extend message type \"" + - type.getFullName() + "\"."); + "Extension \"" + name + "\" does not extend message type \"" + + type.getFullName() + "\"."); } field = extension.descriptor; } @@ -1365,20 +1366,20 @@ public final class TextFormat { } } // Again, special-case group names as described above. - if (field != null && field.getType() == FieldDescriptor.Type.GROUP && - !field.getMessageType().getName().equals(name)) { + if (field != null && field.getType() == FieldDescriptor.Type.GROUP + && !field.getMessageType().getName().equals(name)) { field = null; } if (field == null) { if (!allowUnknownFields) { throw tokenizer.parseExceptionPreviousToken( - "Message type \"" + type.getFullName() + - "\" has no field named \"" + name + "\"."); + "Message type \"" + type.getFullName() + + "\" has no field named \"" + name + "\"."); } else { logger.warning( - "Message type \"" + type.getFullName() + - "\" has no field named \"" + name + "\"."); + "Message type \"" + type.getFullName() + + "\" has no field named \"" + name + "\"."); } } } @@ -1391,8 +1392,9 @@ public final class TextFormat { // start with "{" or "<" which indicates the beginning of a message body. // If there is no ":" or there is a "{" or "<" after ":", this field has // to be a message or the input is ill-formed. - if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("{") && - !tokenizer.lookingAt("<")) { + if (tokenizer.tryConsume(":") + && !tokenizer.lookingAt("{") + && !tokenizer.lookingAt("<")) { skipFieldValue(tokenizer); } else { skipFieldMessage(tokenizer); @@ -1516,16 +1518,16 @@ public final class TextFormat { value = enumType.findValueByNumber(number); if (value == null) { throw tokenizer.parseExceptionPreviousToken( - "Enum type \"" + enumType.getFullName() + - "\" has no value with number " + number + '.'); + "Enum type \"" + enumType.getFullName() + + "\" has no value with number " + number + '.'); } } else { final String id = tokenizer.consumeIdentifier(); value = enumType.findValueByName(id); if (value == null) { throw tokenizer.parseExceptionPreviousToken( - "Enum type \"" + enumType.getFullName() + - "\" has no value named \"" + id + "\"."); + "Enum type \"" + enumType.getFullName() + + "\" has no value named \"" + id + "\"."); } } @@ -1578,8 +1580,9 @@ public final class TextFormat { // start with "{" or "<" which indicates the beginning of a message body. // If there is no ":" or there is a "{" or "<" after ":", this field has // to be a message or the input is ill-formed. - if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("<") && - !tokenizer.lookingAt("{")) { + if (tokenizer.tryConsume(":") + && !tokenizer.lookingAt("<") + && !tokenizer.lookingAt("{")) { skipFieldValue(tokenizer); } else { skipFieldMessage(tokenizer); @@ -1617,11 +1620,11 @@ public final class TextFormat { while (tokenizer.tryConsumeString()) {} return; } - if (!tokenizer.tryConsumeIdentifier() && // includes enum & boolean - !tokenizer.tryConsumeInt64() && // includes int32 - !tokenizer.tryConsumeUInt64() && // includes uint32 - !tokenizer.tryConsumeDouble() && - !tokenizer.tryConsumeFloat()) { + if (!tokenizer.tryConsumeIdentifier() // includes enum & boolean + && !tokenizer.tryConsumeInt64() // includes int32 + && !tokenizer.tryConsumeUInt64() // includes uint32 + && !tokenizer.tryConsumeDouble() + && !tokenizer.tryConsumeFloat()) { throw tokenizer.parseException( "Invalid field value: " + tokenizer.currentToken); } @@ -1647,19 +1650,19 @@ public final class TextFormat { * which no defined short-hand escape sequence is defined will be escaped * using 3-digit octal sequences. */ - private static String escapeBytes(final ByteSequence input) { + public static String escapeBytes(final ByteSequence input) { final StringBuilder builder = new StringBuilder(input.size()); for (int i = 0; i < input.size(); i++) { final byte b = input.byteAt(i); switch (b) { // Java does not recognize \a or \v, apparently. - case 0x07: builder.append("\\a" ); break; - case '\b': builder.append("\\b" ); break; - case '\f': builder.append("\\f" ); break; - case '\n': builder.append("\\n" ); break; - case '\r': builder.append("\\r" ); break; - case '\t': builder.append("\\t" ); break; - case 0x0b: builder.append("\\v" ); break; + case 0x07: builder.append("\\a"); break; + case '\b': builder.append("\\b"); break; + case '\f': builder.append("\\f"); break; + case '\n': builder.append("\\n"); break; + case '\r': builder.append("\\r"); break; + case '\t': builder.append("\\t"); break; + case 0x0b: builder.append("\\v"); break; case '\\': builder.append("\\\\"); break; case '\'': builder.append("\\\'"); break; case '"' : builder.append("\\\""); break; @@ -1688,11 +1691,13 @@ public final class TextFormat { * which no defined short-hand escape sequence is defined will be escaped * using 3-digit octal sequences. */ - static String escapeBytes(final ByteString input) { + public static String escapeBytes(final ByteString input) { return escapeBytes(new ByteSequence() { + @Override public int size() { return input.size(); } + @Override public byte byteAt(int offset) { return input.byteAt(offset); } @@ -1702,11 +1707,13 @@ public final class TextFormat { /** * Like {@link #escapeBytes(ByteString)}, but used for byte array. */ - static String escapeBytes(final byte[] input) { + public static String escapeBytes(final byte[] input) { return escapeBytes(new ByteSequence() { + @Override public int size() { return input.length; } + @Override public byte byteAt(int offset) { return input[offset]; } @@ -1749,7 +1756,7 @@ public final class TextFormat { code = code * 8 + digitValue(input.byteAt(i)); } // TODO: Check that 0 <= code && code <= 0xFF. - result[pos++] = (byte)code; + result[pos++] = (byte) code; } else { switch (c) { case 'a' : result[pos++] = 0x07; break; @@ -1777,12 +1784,12 @@ public final class TextFormat { ++i; code = code * 16 + digitValue(input.byteAt(i)); } - result[pos++] = (byte)code; + result[pos++] = (byte) code; break; default: throw new InvalidEscapeSequenceException( - "Invalid escape sequence: '\\" + (char)c + '\''); + "Invalid escape sequence: '\\" + (char) c + '\''); } } } else { @@ -1841,9 +1848,9 @@ public final class TextFormat { /** Is this a hex digit? */ private static boolean isHex(final byte c) { - return ('0' <= c && c <= '9') || - ('a' <= c && c <= 'f') || - ('A' <= c && c <= 'F'); + return ('0' <= c && c <= '9') + || ('a' <= c && c <= 'f') + || ('A' <= c && c <= 'F'); } /** diff --git a/java/src/main/java/com/google/protobuf/WireFormat.java b/java/src/main/java/com/google/protobuf/WireFormat.java index eba2528e..ba83b666 100644 --- a/java/src/main/java/com/google/protobuf/WireFormat.java +++ b/java/src/main/java/com/google/protobuf/WireFormat.java @@ -30,6 +30,8 @@ package com.google.protobuf; +import java.io.IOException; + /** * This class is used internally by the Protocol Buffer library and generated * message implementations. It is public only because those generated messages @@ -160,4 +162,84 @@ public final class WireFormat { makeTag(MESSAGE_SET_TYPE_ID, WIRETYPE_VARINT); static final int MESSAGE_SET_MESSAGE_TAG = makeTag(MESSAGE_SET_MESSAGE, WIRETYPE_LENGTH_DELIMITED); + + /** + * Validation level for handling incoming string field data which potentially + * contain non-UTF8 bytes. + */ + enum Utf8Validation { + /** Eagerly parses to String; silently accepts invalid UTF8 bytes. */ + LOOSE { + Object readString(CodedInputStream input) throws IOException { + return input.readString(); + } + }, + /** Eagerly parses to String; throws an IOException on invalid bytes. */ + STRICT { + Object readString(CodedInputStream input) throws IOException { + return input.readStringRequireUtf8(); + } + }, + /** Keep data as ByteString; validation/conversion to String is lazy. */ + LAZY { + Object readString(CodedInputStream input) throws IOException { + return input.readBytes(); + } + }; + + /** Read a string field from the input with the proper UTF8 validation. */ + abstract Object readString(CodedInputStream input) throws IOException; + } + + /** + * Read a field of any primitive type for immutable messages from a + * CodedInputStream. Enums, groups, and embedded messages are not handled by + * this method. + * + * @param input The stream from which to read. + * @param type Declared type of the field. + * @param utf8Validation Different string UTF8 validation level for handling + * string fields. + * @return An object representing the field's value, of the exact + * type which would be returned by + * {@link Message#getField(Descriptors.FieldDescriptor)} for + * this field. + */ + static Object readPrimitiveField( + CodedInputStream input, + FieldType type, + Utf8Validation utf8Validation) throws IOException { + switch (type) { + case DOUBLE : return input.readDouble (); + case FLOAT : return input.readFloat (); + case INT64 : return input.readInt64 (); + case UINT64 : return input.readUInt64 (); + case INT32 : return input.readInt32 (); + case FIXED64 : return input.readFixed64 (); + case FIXED32 : return input.readFixed32 (); + case BOOL : return input.readBool (); + case BYTES : return input.readBytes (); + case UINT32 : return input.readUInt32 (); + case SFIXED32: return input.readSFixed32(); + case SFIXED64: return input.readSFixed64(); + case SINT32 : return input.readSInt32 (); + case SINT64 : return input.readSInt64 (); + + case STRING : return utf8Validation.readString(input); + case GROUP: + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle nested groups."); + case MESSAGE: + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle embedded messages."); + case ENUM: + // We don't handle enums because we don't know what to do if the + // value is not recognized. + throw new IllegalArgumentException( + "readPrimitiveField() cannot handle enums."); + } + + throw new RuntimeException( + "There is no way to get here, but the compiler thinks otherwise."); + } } diff --git a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java index 2d101ba7..2bd8d1a9 100644 --- a/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java +++ b/java/src/test/java/com/google/protobuf/GeneratedMessageTest.java @@ -58,8 +58,8 @@ import protobuf_unittest.UnittestProto.ForeignMessage; import protobuf_unittest.UnittestProto.ForeignMessageOrBuilder; import protobuf_unittest.UnittestProto.NestedTestAllTypes; import protobuf_unittest.UnittestProto.TestAllExtensions; -import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; import protobuf_unittest.UnittestProto.TestAllTypes; +import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage; import protobuf_unittest.UnittestProto.TestAllTypesOrBuilder; import protobuf_unittest.UnittestProto.TestExtremeDefaultValues; import protobuf_unittest.UnittestProto.TestOneof2; diff --git a/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java index e67c6d27..211b5697 100644 --- a/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java +++ b/java/src/test/java/com/google/protobuf/LazyFieldLiteTest.java @@ -30,6 +30,9 @@ package com.google.protobuf; +import static protobuf_unittest.UnittestProto.optionalInt32Extension; +import static protobuf_unittest.UnittestProto.optionalInt64Extension; + import protobuf_unittest.UnittestProto.TestAllExtensions; import protobuf_unittest.UnittestProto.TestAllTypes; @@ -111,12 +114,146 @@ public class LazyFieldLiteTest extends TestCase { assertNotEqual(message.toByteString(), lazyField.toByteString()); } + public void testMergeExtensions() throws Exception { + TestAllExtensions message = TestUtil.getAllExtensionsSet(); + LazyFieldLite original = createLazyFieldLiteFromMessage(message); + LazyFieldLite merged = new LazyFieldLite(); + merged.merge(original); + TestAllExtensions value = (TestAllExtensions) merged.getValue( + TestAllExtensions.getDefaultInstance()); + assertEquals(message, value); + } + + public void testEmptyLazyField() throws Exception { + LazyFieldLite field = new LazyFieldLite(); + assertEquals(0, field.getSerializedSize()); + assertEquals(ByteString.EMPTY, field.toByteString()); + } + + public void testInvalidProto() throws Exception { + // Silently fails and uses the default instance. + LazyFieldLite field = new LazyFieldLite( + TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid")); + assertEquals( + TestAllTypes.getDefaultInstance(), field.getValue(TestAllTypes.getDefaultInstance())); + assertEquals(0, field.getSerializedSize()); + assertEquals(ByteString.EMPTY, field.toByteString()); + } + + public void testMergeBeforeParsing() throws Exception { + TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build(); + LazyFieldLite field1 = createLazyFieldLiteFromMessage(message1); + TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build(); + LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2); + + field1.merge(field2); + TestAllTypes expected = + TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build(); + assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance())); + } + + public void testMergeOneNotParsed() throws Exception { + // Test a few different paths that involve one message that was not parsed. + TestAllTypes message1 = TestAllTypes.newBuilder().setOptionalInt32(1).build(); + TestAllTypes message2 = TestAllTypes.newBuilder().setOptionalInt64(2).build(); + TestAllTypes expected = + TestAllTypes.newBuilder().setOptionalInt32(1).setOptionalInt64(2).build(); + + LazyFieldLite field1 = LazyFieldLite.fromValue(message1); + field1.getValue(TestAllTypes.getDefaultInstance()); // Force parsing. + LazyFieldLite field2 = createLazyFieldLiteFromMessage(message2); + field1.merge(field2); + assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance())); + + // Now reverse which one is parsed first. + field1 = LazyFieldLite.fromValue(message1); + field2 = createLazyFieldLiteFromMessage(message2); + field2.getValue(TestAllTypes.getDefaultInstance()); // Force parsing. + field1.merge(field2); + assertEquals(expected, field1.getValue(TestAllTypes.getDefaultInstance())); + } + + public void testMergeInvalid() throws Exception { + // Test a few different paths that involve one message that was not parsed. + TestAllTypes message = TestAllTypes.newBuilder().setOptionalInt32(1).build(); + LazyFieldLite valid = LazyFieldLite.fromValue(message); + LazyFieldLite invalid = new LazyFieldLite( + TestUtil.getExtensionRegistry(), ByteString.copyFromUtf8("invalid")); + invalid.merge(valid); + + // We swallow the exception and just use the set field. + assertEquals(message, invalid.getValue(TestAllTypes.getDefaultInstance())); + } + + public void testMergeKeepsExtensionsWhenPossible() throws Exception { + // In this test we attempt to only use the empty registry, which will strip out all extensions + // when serializing and then parsing. We verify that each code path will attempt to not + // serialize and parse a message that was set directly without going through the + // extensionRegistry. + TestAllExtensions messageWithExtensions = + TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 42).build(); + TestAllExtensions emptyMessage = TestAllExtensions.newBuilder().build(); + + ExtensionRegistryLite emptyRegistry = ExtensionRegistryLite.getEmptyRegistry(); + + LazyFieldLite field = LazyFieldLite.fromValue(messageWithExtensions); + field.merge(createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage)); + assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance())); + + // Now reverse the order of the merging. + field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage); + field.merge(LazyFieldLite.fromValue(messageWithExtensions)); + assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance())); + + // Now try parsing the empty field first. + field = LazyFieldLite.fromValue(messageWithExtensions); + LazyFieldLite other = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage); + other.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing. + field.merge(other); + assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance())); + + // And again reverse. + field = createLazyFieldLiteFromMessage(emptyRegistry, emptyMessage); + field.getValue(TestAllExtensions.getDefaultInstance()); // Force parsing. + other = LazyFieldLite.fromValue(messageWithExtensions); + field.merge(other); + assertEquals(messageWithExtensions, field.getValue(TestAllExtensions.getDefaultInstance())); + } + + public void testMergeMightLoseExtensions() throws Exception { + // Test that we don't know about the extensions when parsing. + TestAllExtensions message1 = + TestAllExtensions.newBuilder().setExtension(optionalInt32Extension, 1).build(); + TestAllExtensions message2 = + TestAllExtensions.newBuilder().setExtension(optionalInt64Extension, 2L).build(); + + LazyFieldLite field = LazyFieldLite.fromValue(message1); + field.merge(LazyFieldLite.fromValue(message2)); + + // We lose the extensions from message 2 because we have to serialize it and then parse it + // again, using the empty registry this time. + TestAllExtensions value = + (TestAllExtensions) field.getValue(TestAllExtensions.getDefaultInstance()); + assertTrue(value.hasExtension(optionalInt32Extension)); + assertEquals(Integer.valueOf(1), value.getExtension(optionalInt32Extension)); + assertFalse(value.hasExtension(optionalInt64Extension)); + + // The field is still there, it is just unknown. + assertTrue(value.getUnknownFields() + .hasField(optionalInt64Extension.getDescriptor().getNumber())); + } + // Help methods. private LazyFieldLite createLazyFieldLiteFromMessage(MessageLite message) { + return createLazyFieldLiteFromMessage(TestUtil.getExtensionRegistry(), message); + } + + private LazyFieldLite createLazyFieldLiteFromMessage( + ExtensionRegistryLite extensionRegistry, MessageLite message) { ByteString bytes = message.toByteString(); - return new LazyFieldLite(TestUtil.getExtensionRegistry(), bytes); + return new LazyFieldLite(extensionRegistry, bytes); } private void changeValue(LazyFieldLite lazyField) { diff --git a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java index 9de794fe..afe0fffd 100644 --- a/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java +++ b/java/src/test/java/com/google/protobuf/LazyMessageLiteTest.java @@ -30,6 +30,7 @@ package com.google.protobuf; +import protobuf_unittest.LazyFieldsLite.LazyExtension; import protobuf_unittest.LazyFieldsLite.LazyInnerMessageLite; import protobuf_unittest.LazyFieldsLite.LazyMessageLite; import protobuf_unittest.LazyFieldsLite.LazyNestedInnerMessageLite; @@ -285,4 +286,22 @@ public class LazyMessageLiteTest extends TestCase { assertEquals(bytes, deserialized.toByteString()); } + + public void testExtensions() throws Exception { + LazyInnerMessageLite.Builder innerBuilder = LazyInnerMessageLite.newBuilder(); + innerBuilder.setExtension( + LazyExtension.extension, LazyExtension.newBuilder() + .setName("name").build()); + assertTrue(innerBuilder.hasExtension(LazyExtension.extension)); + assertEquals("name", innerBuilder.getExtension(LazyExtension.extension).getName()); + + LazyInnerMessageLite innerMessage = innerBuilder.build(); + assertTrue(innerMessage.hasExtension(LazyExtension.extension)); + assertEquals("name", innerMessage.getExtension(LazyExtension.extension).getName()); + + LazyMessageLite lite = LazyMessageLite.newBuilder() + .setInner(innerMessage).build(); + assertTrue(lite.getInner().hasExtension(LazyExtension.extension)); + assertEquals("name", lite.getInner().getExtension(LazyExtension.extension).getName()); + } } diff --git a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java index ff39ca3f..046832de 100644 --- a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java +++ b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java @@ -289,7 +289,6 @@ public class LiteralByteStringTest extends TestCase { assertEquals("Output.reset() resets the output", 0, output.size()); assertEquals("Output.reset() resets the output", ByteString.EMPTY, output.toByteString()); - } public void testToString() throws UnsupportedEncodingException { @@ -299,6 +298,27 @@ public class LiteralByteStringTest extends TestCase { assertEquals(classUnderTest + " unicode must match", testString, roundTripString); } + public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException{ + assertSame(classUnderTest + " must be the same string references", + ByteString.EMPTY.toString(UTF_8), new LiteralByteString(new byte[]{}).toString(UTF_8)); + } + + public void testToString_raisesException() throws UnsupportedEncodingException{ + try { + ByteString.EMPTY.toString("invalid"); + fail("Should have thrown an exception."); + } catch (UnsupportedEncodingException expected) { + // This is success + } + + try { + new LiteralByteString(referenceBytes).toString("invalid"); + fail("Should have thrown an exception."); + } catch (UnsupportedEncodingException expected) { + // This is success + } + } + public void testEquals() { assertEquals(classUnderTest + " must not equal null", false, stringUnderTest.equals(null)); assertEquals(classUnderTest + " must equal self", stringUnderTest, stringUnderTest); @@ -311,7 +331,7 @@ public class LiteralByteStringTest extends TestCase { byte[] mungedBytes = new byte[referenceBytes.length]; System.arraycopy(referenceBytes, 0, mungedBytes, 0, referenceBytes.length); - mungedBytes[mungedBytes.length - 5] ^= 0xFF; + mungedBytes[mungedBytes.length - 5] = (byte) (mungedBytes[mungedBytes.length - 5] ^ 0xFF); assertFalse(classUnderTest + " must not equal every string with the same length", stringUnderTest.equals(new LiteralByteString(mungedBytes))); } diff --git a/java/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/src/test/java/com/google/protobuf/MapForProto2Test.java index 33ba7150..78cba1b4 100644 --- a/java/src/test/java/com/google/protobuf/MapForProto2Test.java +++ b/java/src/test/java/com/google/protobuf/MapForProto2Test.java @@ -34,6 +34,7 @@ import com.google.protobuf.Descriptors.FieldDescriptor; import map_test.MapForProto2TestProto.TestMap; import map_test.MapForProto2TestProto.TestMap.MessageValue; import map_test.MapForProto2TestProto.TestMap.MessageWithRequiredFields; +import map_test.MapForProto2TestProto.TestRecursiveMap; import map_test.MapForProto2TestProto.TestUnknownEnumValue; import junit.framework.TestCase; @@ -499,4 +500,17 @@ public class MapForProto2Test extends TestCase { message = builder.build(); assertTrue(message.isInitialized()); } + + public void testRecursiveMap() throws Exception { + TestRecursiveMap.Builder builder = TestRecursiveMap.newBuilder(); + builder.getMutableRecursiveMapField().put( + 1, TestRecursiveMap.newBuilder().setValue(2).build()); + builder.getMutableRecursiveMapField().put( + 3, TestRecursiveMap.newBuilder().setValue(4).build()); + ByteString data = builder.build().toByteString(); + + TestRecursiveMap message = TestRecursiveMap.parseFrom(data); + assertEquals(2, message.getRecursiveMapField().get(1).getValue()); + assertEquals(4, message.getRecursiveMapField().get(3).getValue()); + } } diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java index 6a1e9078..b8e67b7c 100644 --- a/java/src/test/java/com/google/protobuf/MapTest.java +++ b/java/src/test/java/com/google/protobuf/MapTest.java @@ -269,7 +269,6 @@ public class MapTest extends TestCase { assertFalse(m2.equals(m1)); } - public void testNestedBuilderOnChangeEventPropagation() { TestOnChangeEventPropagation.Builder parent = TestOnChangeEventPropagation.newBuilder(); diff --git a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java index b3970196..0f2344d6 100644 --- a/java/src/test/java/com/google/protobuf/RopeByteStringTest.java +++ b/java/src/test/java/com/google/protobuf/RopeByteStringTest.java @@ -118,6 +118,34 @@ public class RopeByteStringTest extends LiteralByteStringTest { flatString.hashCode(), unicode.hashCode()); } + @Override + public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException { + RopeByteString ropeByteString = + RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY); + assertSame(classUnderTest + " must be the same string references", + ByteString.EMPTY.toString(UTF_8), ropeByteString.toString(UTF_8)); + } + + public void testToString_raisesException() throws UnsupportedEncodingException{ + try { + ByteString byteString = + RopeByteString.newInstanceForTest(ByteString.EMPTY, ByteString.EMPTY); + byteString.toString("invalid"); + fail("Should have thrown an exception."); + } catch (UnsupportedEncodingException expected) { + // This is success + } + + try { + ByteString byteString = RopeByteString.concatenate(ByteString.copyFromUtf8("foo"), + ByteString.copyFromUtf8("bar")); + byteString.toString("invalid"); + fail("Should have thrown an exception."); + } catch (UnsupportedEncodingException expected) { + // This is success + } + } + public void testJavaSerialization() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(out); diff --git a/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto index 015dc267..5580f72d 100644 --- a/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto +++ b/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto @@ -54,6 +54,15 @@ message LazyInnerMessageLite { optional int32 num = 1; optional int32 num_with_default = 2 [default = 42]; optional LazyNestedInnerMessageLite nested = 3 [lazy = true]; + + extensions 1000 to max; +} + +message LazyExtension { + extend LazyInnerMessageLite { + optional LazyExtension extension = 1000; + } + optional string name = 1; } message LazyNestedInnerMessageLite { diff --git a/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto b/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto index a1fe856c..d5418f28 100644 --- a/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto +++ b/java/src/test/java/com/google/protobuf/map_for_proto2_lite_test.proto @@ -63,6 +63,13 @@ message TestUnknownEnumValue { // parsing behavior of TestMap regarding unknown enum values. map int32_to_int32_field = 4; } + +// Test that the maps initialization code works correctly when the map field +// references the containing message. +message TestRecursiveMap { + optional int32 value = 1; + map recursive_map_field = 2; +} package map_for_proto2_lite_test; option java_package = "map_lite_test"; option optimize_for = LITE_RUNTIME; diff --git a/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto b/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto index a0ec7ac5..a9be5166 100644 --- a/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto +++ b/java/src/test/java/com/google/protobuf/map_for_proto2_test.proto @@ -65,3 +65,10 @@ message TestUnknownEnumValue { // parsing behavior of TestMap regarding unknown enum values. map int32_to_int32_field = 4; } + +// Test that the maps initialization code works correctly when the map field +// references the containing message. +message TestRecursiveMap { + optional int32 value = 1; + map recursive_map_field = 2; +} diff --git a/java/src/test/java/com/google/protobuf/map_test.proto b/java/src/test/java/com/google/protobuf/map_test.proto index 105ee3f8..bf692c22 100644 --- a/java/src/test/java/com/google/protobuf/map_test.proto +++ b/java/src/test/java/com/google/protobuf/map_test.proto @@ -36,6 +36,7 @@ option java_package = "map_test"; option java_outer_classname = "MapTestProto"; option java_generate_equals_and_hash = true; + message TestMap { message MessageValue { optional int32 value = 1; diff --git a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto index 67035fd5..dc082615 100644 --- a/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto +++ b/java/src/test/java/com/google/protobuf/test_bad_identifiers.proto @@ -45,6 +45,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "TestBadIdentifiersProto"; option java_generate_equals_and_hash = true; + message TestMessage { optional string cached_size = 1; optional string serialized_size = 2; diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index 4d4de510..ed1298af 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -51,10 +51,10 @@ import sys import unittest from google.apputils import basetest +from google.protobuf.internal import _parameterized from google.protobuf import unittest_pb2 from google.protobuf import unittest_proto3_arena_pb2 from google.protobuf.internal import api_implementation -from google.protobuf.internal import _parameterized from google.protobuf.internal import test_util from google.protobuf import message @@ -982,6 +982,7 @@ class Proto2Test(basetest.TestCase): # This is still an incomplete proto - so serializing should fail self.assertRaises(message.EncodeError, unpickled_message.SerializeToString) + # TODO(haberman): this isn't really a proto2-specific test except that this # message has a required field in it. Should probably be factored out so # that we can test the other parts with proto3. diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index b307620d..7d5813fb 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -37,12 +37,12 @@ __author__ = 'kenton@google.com (Kenton Varda)' import re from google.apputils import basetest +from google.protobuf.internal import _parameterized from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 from google.protobuf import unittest_proto3_arena_pb2 from google.protobuf.internal import api_implementation -from google.protobuf.internal import _parameterized from google.protobuf.internal import test_util from google.protobuf import text_format diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index 6890cd04..e77d0bb9 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -298,8 +298,9 @@ static PyGetSetDef Getters[] = { PyTypeObject PyBaseDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "google.protobuf.internal." - "_message.DescriptorBase", // tp_name + // Keep the fully qualified _message symbol in a line for opensource. + "google.protobuf.internal._message." + "DescriptorBase", // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize (destructor)Dealloc, // tp_dealloc @@ -551,8 +552,9 @@ static PyMethodDef Methods[] = { PyTypeObject PyMessageDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - C("google.protobuf.internal." - "_message.MessageDescriptor"), // tp_name + // Keep the fully qualified _message symbol in a line for opensource. + C("google.protobuf.internal._message." + "MessageDescriptor"), // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize 0, // tp_dealloc @@ -979,8 +981,9 @@ static PyGetSetDef Getters[] = { PyTypeObject PyEnumDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - C("google.protobuf.internal." - "_message.EnumDescriptor"), // tp_name + // Keep the fully qualified _message symbol in a line for opensource. + C("google.protobuf.internal._message." + "EnumDescriptor"), // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize 0, // tp_dealloc diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index c48f94c3..a2b357b2 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -2304,8 +2304,9 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) { PyTypeObject CMessage_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "google.protobuf." - "pyext._message.CMessage", // tp_name + // Keep the fully qualified _message symbol in a line for opensource. + "google.protobuf.pyext._message." + "CMessage", // tp_name sizeof(CMessage), // tp_basicsize 0, // tp_itemsize (destructor)cmessage::Dealloc, // tp_dealloc diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index abc859d7..0fe98e73 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -732,9 +732,10 @@ static PyMethodDef Methods[] = { PyTypeObject RepeatedCompositeContainer_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "google.protobuf.pyext." - "_message.RepeatedCompositeContainer", // tp_name - sizeof(RepeatedCompositeContainer), // tp_basicsize + // Keep the fully qualified _message symbol in a line for opensource. + "google.protobuf.pyext._message." + "RepeatedCompositeContainer", // tp_name + sizeof(RepeatedCompositeContainer), // tp_basicsize 0, // tp_itemsize (destructor)repeated_composite_container::Dealloc, // tp_dealloc 0, // tp_print diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc index 17474598..110a4c85 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.cc +++ b/python/google/protobuf/pyext/repeated_scalar_container.cc @@ -769,8 +769,9 @@ static PyMethodDef Methods[] = { PyTypeObject RepeatedScalarContainer_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "google.protobuf." - "pyext._message.RepeatedScalarContainer", // tp_name + // Keep the fully qualified _message symbol in a line for opensource. + "google.protobuf.pyext._message." + "RepeatedScalarContainer", // tp_name sizeof(RepeatedScalarContainer), // tp_basicsize 0, // tp_itemsize (destructor)repeated_scalar_container::Dealloc, // tp_dealloc diff --git a/src/Makefile.am b/src/Makefile.am index 14756ff8..f84cd7fc 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -84,10 +84,13 @@ nobase_include_HEADERS = \ google/protobuf/dynamic_message.h \ google/protobuf/extension_set.h \ google/protobuf/generated_enum_reflection.h \ + google/protobuf/generated_enum_util.h \ google/protobuf/generated_message_reflection.h \ google/protobuf/generated_message_util.h \ google/protobuf/map_entry.h \ + google/protobuf/map_entry_lite.h \ google/protobuf/map_field.h \ + google/protobuf/map_field_lite.h \ google/protobuf/map_field_inl.h \ google/protobuf/map.h \ google/protobuf/map_type_handler.h \ @@ -316,6 +319,7 @@ protoc_inputs = \ google/protobuf/unittest_no_generic_services.proto \ google/protobuf/unittest_optimize_for.proto \ google/protobuf/unittest_preserve_unknown_enum.proto \ + google/protobuf/unittest_preserve_unknown_enum2.proto \ google/protobuf/unittest_proto3_arena.proto \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -342,6 +346,8 @@ EXTRA_DIST = \ google/protobuf/unittest_enormous_descriptor.proto protoc_lite_outputs = \ + google/protobuf/map_lite_unittest.pb.cc \ + google/protobuf/map_lite_unittest.pb.h \ google/protobuf/unittest_lite.pb.cc \ google/protobuf/unittest_lite.pb.h \ google/protobuf/unittest_import_lite.pb.cc \ @@ -351,8 +357,6 @@ protoc_lite_outputs = \ protoc_outputs = \ $(protoc_lite_outputs) \ - google/protobuf/map_lite_unittest.pb.cc \ - google/protobuf/map_lite_unittest.pb.h \ google/protobuf/map_proto2_unittest.pb.cc \ google/protobuf/map_proto2_unittest.pb.h \ google/protobuf/map_unittest.pb.cc \ @@ -389,12 +393,14 @@ protoc_outputs = \ google/protobuf/unittest_optimize_for.pb.h \ google/protobuf/unittest_preserve_unknown_enum.pb.cc \ google/protobuf/unittest_preserve_unknown_enum.pb.h \ + google/protobuf/unittest_preserve_unknown_enum2.pb.cc \ + google/protobuf/unittest_preserve_unknown_enum2.pb.h \ google/protobuf/unittest_proto3_arena.pb.cc \ google/protobuf/unittest_proto3_arena.pb.h \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h -BUILT_SOURCES = $(public_config) $(protoc_outputs) +BUILT_SOURCES = $(public_config) $(protoc_outputs) if USE_EXTERNAL_PROTOC @@ -416,8 +422,11 @@ endif $(protoc_outputs): unittest_proto_middleman COMMON_TEST_SOURCES = \ + google/protobuf/arena_test_util.cc \ + google/protobuf/arena_test_util.h \ google/protobuf/map_test_util.cc \ google/protobuf/map_test_util.h \ + google/protobuf/map_test_util_impl.h \ google/protobuf/test_util.cc \ google/protobuf/test_util.h \ google/protobuf/testing/googletest.cc \ @@ -503,8 +512,12 @@ protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lite_test_SOURCES = \ google/protobuf/lite_unittest.cc \ + google/protobuf/map_lite_test_util.cc \ + google/protobuf/map_lite_test_util.h \ google/protobuf/test_util_lite.cc \ google/protobuf/test_util_lite.h + # TODO(teboring) add the file back and make the test build. + # google/protobuf/map_lite_test.cc nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs) # Test plugin binary. diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index 18536781..e9ee6170 100644 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -44,38 +44,56 @@ Arena::ThreadCache& Arena::thread_cache() { return thread_cache_; } #else -GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL }; +__thread Arena::ThreadCache Arena::thread_cache_ = { -1, NULL }; #endif -void Arena::Init(const ArenaOptions& options) { +void Arena::Init() { lifecycle_id_ = lifecycle_id_generator_.GetNext(); - start_block_size_ = options.start_block_size; - max_block_size_ = options.max_block_size; - block_alloc = options.block_alloc; - block_dealloc = options.block_dealloc; blocks_ = 0; hint_ = 0; owns_first_block_ = true; cleanup_list_ = 0; - if (options.initial_block != NULL && options.initial_block_size > 0) { + if (options_.initial_block != NULL && options_.initial_block_size > 0) { // Add first unowned block to list. - Block* first_block = reinterpret_cast(options.initial_block); - first_block->size = options.initial_block_size; + Block* first_block = reinterpret_cast(options_.initial_block); + first_block->size = options_.initial_block_size; first_block->pos = kHeaderSize; first_block->next = NULL; first_block->owner = &first_block->owner; AddBlock(first_block); owns_first_block_ = false; } + + // Call the initialization hook + if (options_.on_arena_init != NULL) { + hooks_cookie_ = options_.on_arena_init(this); + } else { + hooks_cookie_ = NULL; + } +} + +Arena::~Arena() { + uint64 space_allocated = Reset(); + + // Call the destruction hook + if (options_.on_arena_destruction != NULL) { + options_.on_arena_destruction(this, hooks_cookie_, space_allocated); + } } uint64 Arena::Reset() { CleanupList(); - uint64 space_used = FreeBlocks(); + uint64 space_allocated = FreeBlocks(); // Invalidate any ThreadCaches pointing to any blocks we just destroyed. lifecycle_id_ = lifecycle_id_generator_.GetNext(); - return space_used; + + // Call the reset hook + if (options_.on_arena_reset != NULL) { + options_.on_arena_reset(this, hooks_cookie_, space_allocated); + } + + return space_allocated; } Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n, @@ -93,7 +111,7 @@ Arena::Block* Arena::NewBlock(void* me, Block* my_last_block, size_t n, size = kHeaderSize + n; } - Block* b = reinterpret_cast(block_alloc(size)); + Block* b = reinterpret_cast(options_.block_alloc(size)); b->pos = kHeaderSize + n; b->size = size; if (b->avail() == 0) { @@ -184,7 +202,7 @@ void* Arena::SlowAlloc(size_t n) { google::protobuf::internal::NoBarrier_Store(&hint_, reinterpret_cast(b)); return AllocFromBlock(b, n); } - b = NewBlock(me, b, n, start_block_size_, max_block_size_); + b = NewBlock(me, b, n, options_.start_block_size, options_.max_block_size); AddBlock(b); if (b->owner == me) { // If this block can be reused (see NewBlock()). SetThreadCacheBlock(b); @@ -192,29 +210,38 @@ void* Arena::SlowAlloc(size_t n) { return reinterpret_cast(b) + kHeaderSize; } +uint64 Arena::SpaceAllocated() const { + uint64 space_allocated = 0; + Block* b = reinterpret_cast(google::protobuf::internal::NoBarrier_Load(&blocks_)); + while (b != NULL) { + space_allocated += (b->size); + b = b->next; + } + return space_allocated; +} + uint64 Arena::SpaceUsed() const { uint64 space_used = 0; Block* b = reinterpret_cast(google::protobuf::internal::NoBarrier_Load(&blocks_)); while (b != NULL) { - space_used += (b->size); + space_used += (b->pos - kHeaderSize); b = b->next; } return space_used; } - uint64 Arena::FreeBlocks() { - uint64 space_used = 0; + uint64 space_allocated = 0; Block* b = reinterpret_cast(google::protobuf::internal::NoBarrier_Load(&blocks_)); Block* first_block = NULL; while (b != NULL) { - space_used += (b->size); + space_allocated += (b->size); Block* next = b->next; if (next != NULL) { - block_dealloc(b, b->size); + options_.block_dealloc(b, b->size); } else { if (owns_first_block_) { - block_dealloc(b, b->size); + options_.block_dealloc(b, b->size); } else { // User passed in the first block, skip free'ing the memory. first_block = b; @@ -231,7 +258,7 @@ uint64 Arena::FreeBlocks() { first_block->owner = &first_block->owner; AddBlock(first_block); } - return space_used; + return space_allocated; } void Arena::CleanupList() { diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index 4f9e39e1..a83a4fbf 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -34,9 +34,11 @@ #ifndef GOOGLE_PROTOBUF_ARENA_H__ #define GOOGLE_PROTOBUF_ARENA_H__ -#include +#include + #include #include +#include #include namespace google { @@ -89,19 +91,44 @@ struct ArenaOptions { // A function pointer to an alloc method that returns memory blocks of size // requested. By default, it contains a ptr to the malloc function. + // + // NOTE: block_alloc and dealloc functions are expected to behave like + // malloc and free, including Asan poisoning. void* (*block_alloc)(size_t); // A function pointer to a dealloc method that takes ownership of the blocks // from the arena. By default, it contains a ptr to a wrapper function that // calls free. void (*block_dealloc)(void*, size_t); + // Hooks for adding external functionality such as user-specific metrics + // collection, specific debugging abilities, etc. + // Init hook may return a pointer to a cookie to be stored in the arena. + // reset and destruction hooks will then be called with the same cookie + // pointer. This allows us to save an external object per arena instance and + // use it on the other hooks (Note: It is just as legal for init to return + // NULL and not use the cookie feature). + // on_arena_reset and on_arena_destruction also receive the space used in + // the arena just before the reset. + void* (*on_arena_init)(Arena* arena); + void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used); + void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used); + + // type_name is promised to be a static string - its lifetime extends to + // match program's lifetime. + void (*on_arena_allocation)(const char* type_name, uint64 alloc_size, + Arena* arena, void* cookie); + ArenaOptions() : start_block_size(kDefaultStartBlockSize), max_block_size(kDefaultMaxBlockSize), initial_block(NULL), initial_block_size(0), block_alloc(&malloc), - block_dealloc(&internal::arena_free) {} + block_dealloc(&internal::arena_free), + on_arena_init(NULL), + on_arena_reset(NULL), + on_arena_destruction(NULL), + on_arena_allocation(NULL) {} private: // Constants define default starting block size and max block size for @@ -123,23 +150,21 @@ class LIBPROTOBUF_EXPORT Arena { public: // Arena constructor taking custom options. See ArenaOptions below for // descriptions of the options available. - explicit Arena(const ArenaOptions& options) { - Init(options); + explicit Arena(const ArenaOptions& options) : options_(options) { + Init(); } // Default constructor with sensible default options, tuned for average // use-cases. Arena() { - Init(ArenaOptions()); + Init(); } // Destructor deletes all owned heap allocated objects, and destructs objects // that have non-trivial destructors, except for proto2 message objects whose // destructors can be skipped. Also, frees all blocks except the initial block // if it was passed in. - ~Arena() { - Reset(); - } + ~Arena(); // API to create proto2 message objects on the arena. If the arena passed in // is NULL, then a heap allocated object is returned. Type T must be a message @@ -195,6 +220,40 @@ class LIBPROTOBUF_EXPORT Arena { } } + // Version of the above with three constructor arguments for the created + // object. + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, + const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3) { + if (arena == NULL) { + return new T(arg1, arg2, arg3); + } else { + return arena->CreateInternal(SkipDeleteList(static_cast(0)), + arg1, + arg2, + arg3); + } + } + + // Version of the above with four constructor arguments for the created + // object. + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, + const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4) { + if (arena == NULL) { + return new T(arg1, arg2, arg3, arg4); + } else { + return arena->CreateInternal(SkipDeleteList(static_cast(0)), + arg1, + arg2, + arg3, + arg4); + } + } + // Create an array of object type T on the arena. Type T must have a trivial // constructor, as it will not be invoked when created on the arena. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE @@ -202,8 +261,7 @@ class LIBPROTOBUF_EXPORT Arena { if (arena == NULL) { return new T[num_elements]; } else { - return static_cast( - arena->AllocateAligned(num_elements * sizeof(T))); + return arena->CreateInternalRawArray(num_elements); } } @@ -211,6 +269,8 @@ class LIBPROTOBUF_EXPORT Arena { // of the underlying blocks. The total space used may not include the new // blocks that are allocated by this arena from other threads concurrently // with the call to this method. + uint64 SpaceAllocated() const GOOGLE_ATTRIBUTE_NOINLINE; + // As above, but does not include any free space in underlying blocks. uint64 SpaceUsed() const GOOGLE_ATTRIBUTE_NOINLINE; // Frees all storage allocated by this arena after calling destructors @@ -253,7 +313,7 @@ class LIBPROTOBUF_EXPORT Arena { // latter is a virtual call, while this method is a templated call that // resolves at compile-time. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArena(T* value) { + static inline ::google::protobuf::Arena* GetArena(const T* value) { return GetArenaInternal(value, static_cast(0)); } @@ -295,9 +355,6 @@ class LIBPROTOBUF_EXPORT Arena { // data follows }; - void* (*block_alloc)(size_t); // Allocates a free block of a particular size. - void (*block_dealloc)(void*, size_t); // Deallocates the given block. - template friend class ::google::protobuf::internal::GenericTypeHandler; friend class MockArena; // For unit-testing. friend class internal::ArenaString; // For AllocateAligned. @@ -317,7 +374,7 @@ class LIBPROTOBUF_EXPORT Arena { // wrap them in static functions. static ThreadCache& thread_cache(); #else - static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; + static __thread ThreadCache thread_cache_; static ThreadCache& thread_cache() { return thread_cache_; } #endif @@ -354,6 +411,13 @@ class LIBPROTOBUF_EXPORT Arena { return Create(arena); } + // Just allocate the required size for the given type assuming the + // type has a trivial constructor. + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE + inline T* CreateInternalRawArray(uint32 num_elements) { + return static_cast(AllocateAligned(sizeof(T) * num_elements)); + } + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal( bool skip_explicit_ownership) { @@ -384,12 +448,57 @@ class LIBPROTOBUF_EXPORT Arena { return t; } + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3) { + T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3); + if (!skip_explicit_ownership) { + AddListNode(t, &internal::arena_destruct_object); + } + return t; + } + + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4) { + T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3, arg4); + if (!skip_explicit_ownership) { + AddListNode(t, &internal::arena_destruct_object); + } + return t; + } + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*) { return CreateInternal(SkipDeleteList(static_cast(0)), this); } + // CreateInArenaStorage is used to implement map field. Without it, + // google::protobuf::Map need to call generated message's protected arena constructor, + // which needs to declare google::protobuf::Map as friend of generated message. + template + static void CreateInArenaStorage(T* ptr, Arena* arena) { + CreateInArenaStorageInternal(ptr, arena, is_arena_constructable::value); + } + template + static void CreateInArenaStorageInternal( + T* ptr, Arena* arena, google::protobuf::internal::true_type) { + new (ptr) T(arena); + } + + template + static void CreateInArenaStorageInternal( + T* ptr, Arena* arena, google::protobuf::internal::false_type) { + new (ptr) T; + } + // These implement Own(), which registers an object for deletion (destructor // call and operator delete()). The second parameter has type 'true_type' if T // is a subtype of ::google::protobuf::Message and 'false_type' otherwise. Collapsing @@ -412,20 +521,20 @@ class LIBPROTOBUF_EXPORT Arena { // InternalArenaConstructable_ tags can be associated with an arena, and such // objects must implement a GetArenaNoVirtual() method. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArenaInternal(T* value, + static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, typename T::InternalArenaConstructable_*) { return value->GetArenaNoVirtual(); } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - static inline ::google::protobuf::Arena* GetArenaInternal(T* value, ...) { + static inline ::google::protobuf::Arena* GetArenaInternal(const T* value, ...) { return NULL; } void* AllocateAligned(size_t size); - void Init(const ArenaOptions& options); + void Init(); // Free all blocks and return the total space used which is the sums of sizes // of the all the allocated blocks. @@ -446,8 +555,6 @@ class LIBPROTOBUF_EXPORT Arena { } int64 lifecycle_id_; // Unique for each arena. Changes on Reset(). - size_t start_block_size_; // Starting block size of the arena. - size_t max_block_size_; // Max block size of the arena. google::protobuf::internal::AtomicWord blocks_; // Head of linked list of all allocated blocks google::protobuf::internal::AtomicWord hint_; // Fast thread-local block access @@ -472,6 +579,15 @@ class LIBPROTOBUF_EXPORT Arena { Block* NewBlock(void* me, Block* my_last_block, size_t n, size_t start_block_size, size_t max_block_size); static void* AllocFromBlock(Block* b, size_t n); + template + friend class Map; + + // The arena may save a cookie it receives from the external on_init hook + // and then use it when calling the on_reset and on_destruction hooks. + void* hooks_cookie_; + + ArenaOptions options_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena); }; diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc new file mode 100644 index 00000000..21f55c6e --- /dev/null +++ b/src/google/protobuf/arena_test_util.cc @@ -0,0 +1,49 @@ +// 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 +#include + + +#define EXPECT_EQ GOOGLE_CHECK_EQ + +namespace google { +namespace protobuf { +namespace internal { + +NoHeapChecker::~NoHeapChecker() { + capture_alloc.Unhook(); + EXPECT_EQ(0, capture_alloc.alloc_count()); + EXPECT_EQ(0, capture_alloc.free_count()); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h new file mode 100644 index 00000000..7db7a90e --- /dev/null +++ b/src/google/protobuf/arena_test_util.h @@ -0,0 +1,59 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__ +#define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__ + +namespace google { +namespace protobuf { +namespace internal { + +class NoHeapChecker { + public: + NoHeapChecker() { + capture_alloc.Hook(); + } + ~NoHeapChecker(); + private: + class NewDeleteCapture { + public: + // TOOD(xiaofeng): Implement this for opensource protobuf. + void Hook() {} + void Unhook() {} + int alloc_count() { return 0; } + int free_count() { return 0; } + } capture_alloc; +}; + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__ diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 390141a3..d9b198e0 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -30,6 +30,8 @@ #include +#include + #include #include #include @@ -40,6 +42,7 @@ #include #include +#include #include #include #include @@ -91,6 +94,37 @@ class SimpleDataType { private: Notifier* notifier_; }; + +// A simple class that does not allow copying and so cannot be used as a +// parameter type without "const &". +class PleaseDontCopyMe { + public: + explicit PleaseDontCopyMe(int value) : value_(value) {} + + int value() const { return value_; } + + private: + int value_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PleaseDontCopyMe); +}; + +// A class that takes four different types as constructor arguments. +class MustBeConstructedWithOneThroughFour { + public: + MustBeConstructedWithOneThroughFour( + int one, const char* two, const string& three, + const PleaseDontCopyMe* four) + : one_(one), two_(two), three_(three), four_(four) {} + + int one_; + const char* const two_; + string three_; + const PleaseDontCopyMe* four_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour); +}; + } // namespace TEST(ArenaTest, ArenaConstructable) { @@ -122,6 +156,20 @@ TEST(ArenaTest, BasicCreate) { EXPECT_EQ(2, notifier.GetCount()); } +TEST(ArenaTest, CreateWithManyConstructorArguments) { + Arena arena; + const string three("3"); + const PleaseDontCopyMe four(4); + const MustBeConstructedWithOneThroughFour* new_object = + Arena::Create( + &arena, 1, "2", three, &four); + EXPECT_TRUE(new_object != NULL); + ASSERT_EQ(1, new_object->one_); + ASSERT_STREQ("2", new_object->two_); + ASSERT_EQ("3", new_object->three_); + ASSERT_EQ(4, new_object->four_->value()); +} + TEST(ArenaTest, InitialBlockTooSmall) { // Construct a small (64 byte) initial block of memory to be used by the // arena allocator; then, allocate an object which will not fit in the @@ -380,6 +428,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) { delete nested_string; } +#ifndef GOOGLE_PROTOBUF_NO_RTTI TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) { TestAllTypes::NestedMessage* nested_msg = NULL; // Note: no string: reflection API only supports releasing submessages. @@ -396,6 +445,7 @@ TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) { EXPECT_EQ(42, nested_msg->bb()); delete nested_msg; } +#endif // !GOOGLE_PROTOBUF_NO_RTTI TEST(ArenaTest, UnsafeArenaReleaseDoesNotMakeCopy) { Arena arena; @@ -671,6 +721,57 @@ TEST(ArenaTest, UnsafeArenaAddAllocated) { } } +TEST(ArenaTest, UnsafeArenaRelease) { + Arena arena; + TestAllTypes* message = Arena::CreateMessage(&arena); + + string* s = new string("test string"); + message->unsafe_arena_set_allocated_optional_string(s); + EXPECT_TRUE(message->has_optional_string()); + EXPECT_EQ("test string", message->optional_string()); + s = message->unsafe_arena_release_optional_string(); + EXPECT_FALSE(message->has_optional_string()); + delete s; + + s = new string("test string"); + message->unsafe_arena_set_allocated_oneof_string(s); + EXPECT_TRUE(message->has_oneof_string()); + EXPECT_EQ("test string", message->oneof_string()); + s = message->unsafe_arena_release_oneof_string(); + EXPECT_FALSE(message->has_oneof_string()); + delete s; +} + +TEST(ArenaTest, ArenaOneofReflection) { + Arena arena; + TestAllTypes* message = Arena::CreateMessage(&arena); + const Descriptor* desc = message->GetDescriptor(); + const Reflection* refl = message->GetReflection(); + + const FieldDescriptor* string_field = desc->FindFieldByName( + "oneof_string"); + const FieldDescriptor* msg_field = desc->FindFieldByName( + "oneof_nested_message"); + const OneofDescriptor* oneof = desc->FindOneofByName( + "oneof_field"); + + refl->SetString(message, string_field, "Test value"); + EXPECT_TRUE(refl->HasOneof(*message, oneof)); + refl->ClearOneof(message, oneof); + EXPECT_FALSE(refl->HasOneof(*message, oneof)); + + Message* submsg = refl->MutableMessage(message, msg_field); + EXPECT_TRUE(refl->HasOneof(*message, oneof)); + refl->ClearOneof(message, oneof); + EXPECT_FALSE(refl->HasOneof(*message, oneof)); + refl->MutableMessage(message, msg_field); + EXPECT_TRUE(refl->HasOneof(*message, oneof)); + submsg = refl->ReleaseMessage(message, msg_field); + EXPECT_FALSE(refl->HasOneof(*message, oneof)); + EXPECT_TRUE(submsg->GetArena() == NULL); + delete submsg; +} + namespace { void TestSwapRepeatedField(Arena* arena1, Arena* arena2) { // Test "safe" (copying) semantics for direct Swap() on RepeatedPtrField @@ -746,27 +847,6 @@ TEST(ArenaTest, ExtensionsOnArena) { protobuf_unittest::optional_nested_message_extension)->set_bb(42); } -class NoHeapChecker { - public: - NoHeapChecker() { - capture_alloc.Hook(); - } - ~NoHeapChecker() { - capture_alloc.Unhook(); - EXPECT_EQ(0, capture_alloc.alloc_count()); - EXPECT_EQ(0, capture_alloc.free_count()); - } - private: - class NewDeleteCapture { - public: - // TOOD(xiaofeng): Implement this for opensource protobuf. - void Hook() {} - void Unhook() {} - int alloc_count() { return 0; } - int free_count() { return 0; } - } capture_alloc; -}; - TEST(ArenaTest, RepeatedFieldOnArena) { // Preallocate an initial arena block to avoid mallocs during hooked region. std::vector arena_block(1024 * 1024); @@ -776,7 +856,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) { Arena arena(options); { - NoHeapChecker no_heap; + internal::NoHeapChecker no_heap; // Fill some repeated fields on the arena to test for leaks. Also verify no // memory allocations. @@ -846,6 +926,7 @@ TEST(ArenaTest, RepeatedFieldOnArena) { } +#ifndef GOOGLE_PROTOBUF_NO_RTTI TEST(ArenaTest, MutableMessageReflection) { Arena arena; TestAllTypes* message = Arena::CreateMessage(&arena); @@ -869,6 +950,7 @@ TEST(ArenaTest, MutableMessageReflection) { EXPECT_EQ(submessage_expected, submessage); EXPECT_EQ(&arena, submessage->GetArena()); } +#endif // !GOOGLE_PROTOBUF_NO_RTTI namespace { @@ -911,7 +993,7 @@ TEST(ArenaTest, NoHeapAllocationsTest) { arena.Reset(); } - +#ifndef GOOGLE_PROTOBUF_NO_RTTI // Test construction on an arena via generic MessageLite interface. We should be // able to successfully deserialize on the arena without incurring heap // allocations, i.e., everything should still be arena-allocation-aware. @@ -921,8 +1003,7 @@ TEST(ArenaTest, MessageLiteOnArena) { options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); - const google::protobuf::MessageLite* prototype = - &TestAllTypes::default_instance(); + const google::protobuf::MessageLite* prototype = &TestAllTypes::default_instance(); TestAllTypes initial_message; FillArenaAwareFields(&initial_message); @@ -941,6 +1022,7 @@ TEST(ArenaTest, MessageLiteOnArena) { arena.Reset(); } +#endif // !GOOGLE_PROTOBUF_NO_RTTI // RepeatedField should support non-POD types, and invoke constructors and @@ -962,16 +1044,23 @@ TEST(ArenaTest, RepeatedFieldWithNonPODType) { } } -TEST(ArenaTest, SpaceUsed) { +// Align n to next multiple of 8 +namespace { +uint64 Align8(uint64 n) { return (n + 7) & -8; } +} // namespace + +TEST(ArenaTest, SpaceAllocated_and_Used) { ArenaOptions options; options.start_block_size = 256; options.max_block_size = 8192; Arena arena_1(options); + EXPECT_EQ(0, arena_1.SpaceAllocated()); EXPECT_EQ(0, arena_1.SpaceUsed()); EXPECT_EQ(0, arena_1.Reset()); ::google::protobuf::Arena::CreateArray(&arena_1, 320); // Arena will allocate slightly more than 320 for the block headers. - EXPECT_LE(320, arena_1.SpaceUsed()); + EXPECT_LE(320, arena_1.SpaceAllocated()); + EXPECT_EQ(Align8(320), arena_1.SpaceUsed()); EXPECT_LE(320, arena_1.Reset()); // Test with initial block. @@ -979,20 +1068,25 @@ TEST(ArenaTest, SpaceUsed) { options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena_2(options); - EXPECT_EQ(1024, arena_2.SpaceUsed()); + EXPECT_EQ(1024, arena_2.SpaceAllocated()); + EXPECT_EQ(0, arena_2.SpaceUsed()); EXPECT_EQ(1024, arena_2.Reset()); ::google::protobuf::Arena::CreateArray(&arena_2, 55); - EXPECT_EQ(1024, arena_2.SpaceUsed()); + EXPECT_EQ(1024, arena_2.SpaceAllocated()); + EXPECT_EQ(Align8(55), arena_2.SpaceUsed()); EXPECT_EQ(1024, arena_2.Reset()); // Reset options to test doubling policy explicitly. options.initial_block = NULL; options.initial_block_size = 0; Arena arena_3(options); + EXPECT_EQ(0, arena_3.SpaceUsed()); ::google::protobuf::Arena::CreateArray(&arena_3, 190); - EXPECT_EQ(256, arena_3.SpaceUsed()); + EXPECT_EQ(256, arena_3.SpaceAllocated()); + EXPECT_EQ(Align8(190), arena_3.SpaceUsed()); ::google::protobuf::Arena::CreateArray(&arena_3, 70); - EXPECT_EQ(256 + 512, arena_3.SpaceUsed()); + EXPECT_EQ(256 + 512, arena_3.SpaceAllocated()); + EXPECT_EQ(Align8(190) + Align8(70), arena_3.SpaceUsed()); EXPECT_EQ(256 + 512, arena_3.Reset()); } @@ -1004,5 +1098,76 @@ TEST(ArenaTest, Alignment) { } } +TEST(ArenaTest, GetArenaShouldReturnTheArenaForArenaAllocatedMessages) { + ::google::protobuf::Arena arena; + ArenaMessage* message = Arena::CreateMessage(&arena); + const ArenaMessage* const_pointer_to_message = message; + EXPECT_EQ(&arena, Arena::GetArena(message)); + EXPECT_EQ(&arena, Arena::GetArena(const_pointer_to_message)); +} + +TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) { + ArenaMessage message; + const ArenaMessage* const_pointer_to_message = &message; + EXPECT_EQ(NULL, Arena::GetArena(&message)); + EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message)); +} + +// A helper utility class to only contain static hook functions, some +// counters to be used to verify the counters have been called and a cookie +// value to be verified. +class ArenaHooksTestUtil { + public: + static void* on_init(::google::protobuf::Arena* arena) { + ++num_init; + int* cookie = new int(kCookieValue); + return static_cast(cookie); + } + + static void on_reset(::google::protobuf::Arena* arena, void* cookie, + uint64 space_used) { + ++num_reset; + int cookie_value = *static_cast(cookie); + EXPECT_EQ(kCookieValue, cookie_value); + } + + static void on_destruction(::google::protobuf::Arena* arena, void* cookie, + uint64 space_used) { + ++num_destruct; + int cookie_value = *static_cast(cookie); + EXPECT_EQ(kCookieValue, cookie_value); + delete static_cast(cookie); + } + + static const int kCookieValue = 999; + static uint32 num_init; + static uint32 num_reset; + static uint32 num_destruct; +}; +uint32 ArenaHooksTestUtil::num_init = 0; +uint32 ArenaHooksTestUtil::num_reset = 0; +uint32 ArenaHooksTestUtil::num_destruct = 0; +const int ArenaHooksTestUtil::kCookieValue; + +// Test the hooks are correctly called and that the cookie is passed. +TEST(ArenaTest, ArenaHooksSanity) { + ::google::protobuf::ArenaOptions options; + options.on_arena_init = ArenaHooksTestUtil::on_init; + options.on_arena_reset = ArenaHooksTestUtil::on_reset; + options.on_arena_destruction = ArenaHooksTestUtil::on_destruction; + + // Scope for defining the arena + { + ::google::protobuf::Arena arena(options); + EXPECT_EQ(1, ArenaHooksTestUtil::num_init); + + arena.Reset(); + arena.Reset(); + EXPECT_EQ(2, ArenaHooksTestUtil::num_reset); + } + EXPECT_EQ(3, ArenaHooksTestUtil::num_reset); + EXPECT_EQ(1, ArenaHooksTestUtil::num_destruct); +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 13250702..09106313 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -152,7 +152,7 @@ bool VerifyDirectoryExists(const string& path) { if (path.empty()) return true; if (access(path.c_str(), F_OK) == -1) { - cerr << path << ": " << strerror(errno) << endl; + std::cerr << path << ": " << strerror(errno) << std::endl; return false; } else { return true; @@ -171,8 +171,8 @@ bool TryCreateParentDirectory(const string& prefix, const string& filename) { path_so_far += parts[i]; if (mkdir(path_so_far.c_str(), 0777) != 0) { if (errno != EEXIST) { - cerr << filename << ": while trying to create directory " - << path_so_far << ": " << strerror(errno) << endl; + std::cerr << filename << ": while trying to create directory " + << path_so_far << ": " << strerror(errno) << std::endl; return false; } } @@ -201,9 +201,9 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS && tree_ != NULL && tree_->VirtualFileToDiskFile(filename, &dfile)) { - cerr << dfile; + std::cerr << dfile; } else { - cerr << filename; + std::cerr << filename; } // Users typically expect 1-based line/column numbers, so we add 1 @@ -212,15 +212,16 @@ class CommandLineInterface::ErrorPrinter : public MultiFileErrorCollector, // Allow for both GCC- and Visual-Studio-compatible output. switch (format_) { case CommandLineInterface::ERROR_FORMAT_GCC: - cerr << ":" << (line + 1) << ":" << (column + 1); + std::cerr << ":" << (line + 1) << ":" << (column + 1); break; case CommandLineInterface::ERROR_FORMAT_MSVS: - cerr << "(" << (line + 1) << ") : error in column=" << (column + 1); + std::cerr << "(" << (line + 1) + << ") : error in column=" << (column + 1); break; } } - cerr << ": " << message << endl; + std::cerr << ": " << message << std::endl; } // implements io::ErrorCollector ----------------------------------- @@ -345,7 +346,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( if (file_descriptor < 0) { int error = errno; - cerr << filename << ": " << strerror(error); + std::cerr << filename << ": " << strerror(error); return false; } @@ -369,9 +370,9 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( if (write_result < 0) { int error = errno; - cerr << filename << ": write: " << strerror(error); + std::cerr << filename << ": write: " << strerror(error); } else { - cerr << filename << ": write() returned zero?" << endl; + std::cerr << filename << ": write() returned zero?" << std::endl; } return false; } @@ -382,7 +383,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToDisk( if (close(file_descriptor) != 0) { int error = errno; - cerr << filename << ": close: " << strerror(error); + std::cerr << filename << ": close: " << strerror(error); return false; } } @@ -405,7 +406,7 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( if (file_descriptor < 0) { int error = errno; - cerr << filename << ": " << strerror(error); + std::cerr << filename << ": " << strerror(error); return false; } @@ -421,11 +422,11 @@ bool CommandLineInterface::GeneratorContextImpl::WriteAllToZip( zip_writer.WriteDirectory(); if (stream.GetErrno() != 0) { - cerr << filename << ": " << strerror(stream.GetErrno()) << endl; + std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl; } if (!stream.Close()) { - cerr << filename << ": " << strerror(stream.GetErrno()) << endl; + std::cerr << filename << ": " << strerror(stream.GetErrno()) << std::endl; } return true; @@ -490,7 +491,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { if (append_mode_) { (*map_slot)->append(data_); } else { - cerr << filename_ << ": Tried to write the same file twice." << endl; + std::cerr << filename_ << ": Tried to write the same file twice." + << std::endl; directory_->had_error_ = true; } return; @@ -508,8 +510,9 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { // Find the file we are going to insert into. if (*map_slot == NULL) { - cerr << filename_ << ": Tried to insert into file that doesn't exist." - << endl; + std::cerr << filename_ + << ": Tried to insert into file that doesn't exist." + << std::endl; directory_->had_error_ = true; return; } @@ -521,8 +524,8 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { string::size_type pos = target->find(magic_string); if (pos == string::npos) { - cerr << filename_ << ": insertion point \"" << insertion_point_ - << "\" not found." << endl; + std::cerr << filename_ << ": insertion point \"" << insertion_point_ + << "\" not found." << std::endl; directory_->had_error_ = true; return; } @@ -793,27 +796,31 @@ bool CommandLineInterface::MakeInputsBeProtoPathRelative( input_files_[i] = virtual_file; break; case DiskSourceTree::SHADOWED: - cerr << input_files_[i] << ": Input is shadowed in the --proto_path " - "by \"" << shadowing_disk_file << "\". Either use the latter " - "file as your input or reorder the --proto_path so that the " - "former file's location comes first." << endl; + std::cerr << input_files_[i] + << ": Input is shadowed in the --proto_path by \"" + << shadowing_disk_file + << "\". Either use the latter file as your input or reorder " + "the --proto_path so that the former file's location " + "comes first." << std::endl; return false; case DiskSourceTree::CANNOT_OPEN: - cerr << input_files_[i] << ": " << strerror(errno) << endl; + std::cerr << input_files_[i] << ": " << strerror(errno) << std::endl; return false; case DiskSourceTree::NO_MAPPING: // First check if the file exists at all. if (access(input_files_[i].c_str(), F_OK) < 0) { // File does not even exist. - cerr << input_files_[i] << ": " << strerror(ENOENT) << endl; + std::cerr << input_files_[i] << ": " << strerror(ENOENT) << std::endl; } else { - cerr << input_files_[i] << ": File does not reside within any path " - "specified using --proto_path (or -I). You must specify a " - "--proto_path which encompasses this file. Note that the " - "proto_path must be an exact prefix of the .proto file " - "names -- protoc is too dumb to figure out when two paths " - "(e.g. absolute and relative) are equivalent (it's harder " - "than you think)." << endl; + std::cerr + << input_files_[i] + << ": File does not reside within any path " + "specified using --proto_path (or -I). You must specify a " + "--proto_path which encompasses this file. Note that the " + "proto_path must be an exact prefix of the .proto file " + "names -- protoc is too dumb to figure out when two paths " + "(e.g. absolute and relative) are equivalent (it's harder " + "than you think)." << std::endl; } return false; } @@ -833,9 +840,10 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { if (ParseArgument(argv[i], &name, &value)) { // Returned true => Use the next argument as the flag value. if (i + 1 == argc || argv[i+1][0] == '-') { - cerr << "Missing value for flag: " << name << endl; + std::cerr << "Missing value for flag: " << name << std::endl; if (name == "--decode") { - cerr << "To decode an unknown message, use --decode_raw." << endl; + std::cerr << "To decode an unknown message, use --decode_raw." + << std::endl; } return PARSE_ARGUMENT_FAIL; } else { @@ -860,24 +868,25 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { // Check some errror cases. bool decoding_raw = (mode_ == MODE_DECODE) && codec_type_.empty(); if (decoding_raw && !input_files_.empty()) { - cerr << "When using --decode_raw, no input files should be given." << endl; + std::cerr << "When using --decode_raw, no input files should be given." + << std::endl; return PARSE_ARGUMENT_FAIL; } else if (!decoding_raw && input_files_.empty()) { - cerr << "Missing input file." << endl; + std::cerr << "Missing input file." << std::endl; return PARSE_ARGUMENT_FAIL; } if (mode_ == MODE_COMPILE && output_directives_.empty() && descriptor_set_name_.empty()) { - cerr << "Missing output directives." << endl; + std::cerr << "Missing output directives." << std::endl; return PARSE_ARGUMENT_FAIL; } if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { - cerr << "--include_imports only makes sense when combined with " - "--descriptor_set_out." << endl; + std::cerr << "--include_imports only makes sense when combined with " + "--descriptor_set_out." << std::endl; } if (source_info_in_descriptor_set_ && descriptor_set_name_.empty()) { - cerr << "--include_source_info only makes sense when combined with " - "--descriptor_set_out." << endl; + std::cerr << "--include_source_info only makes sense when combined with " + "--descriptor_set_out." << std::endl; } return PARSE_ARGUMENT_DONE_AND_CONTINUE; @@ -950,10 +959,12 @@ CommandLineInterface::InterpretArgument(const string& name, if (name.empty()) { // Not a flag. Just a filename. if (value.empty()) { - cerr << "You seem to have passed an empty string as one of the " - "arguments to " << executable_name_ << ". This is actually " - "sort of hard to do. Congrats. Unfortunately it is not valid " - "input so the program is going to die now." << endl; + std::cerr + << "You seem to have passed an empty string as one of the " + "arguments to " << executable_name_ + << ". This is actually " + "sort of hard to do. Congrats. Unfortunately it is not valid " + "input so the program is going to die now." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -980,14 +991,16 @@ CommandLineInterface::InterpretArgument(const string& name, } if (disk_path.empty()) { - cerr << "--proto_path passed empty directory name. (Use \".\" for " - "current directory.)" << endl; + std::cerr + << "--proto_path passed empty directory name. (Use \".\" for " + "current directory.)" << std::endl; return PARSE_ARGUMENT_FAIL; } // Make sure disk path exists, warn otherwise. if (access(disk_path.c_str(), F_OK) < 0) { - cerr << disk_path << ": warning: directory does not exist." << endl; + std::cerr << disk_path << ": warning: directory does not exist." + << std::endl; } // Don't use make_pair as the old/default standard library on Solaris @@ -998,30 +1011,31 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "-o" || name == "--descriptor_set_out") { if (!descriptor_set_name_.empty()) { - cerr << name << " may only be passed once." << endl; + std::cerr << name << " may only be passed once." << std::endl; return PARSE_ARGUMENT_FAIL; } if (value.empty()) { - cerr << name << " requires a non-empty value." << endl; + std::cerr << name << " requires a non-empty value." << std::endl; return PARSE_ARGUMENT_FAIL; } if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode or --decode and generate descriptors at the " - "same time." << endl; + std::cerr + << "Cannot use --encode or --decode and generate descriptors at the " + "same time." << std::endl; return PARSE_ARGUMENT_FAIL; } descriptor_set_name_ = value; } else if (name == "--include_imports") { if (imports_in_descriptor_set_) { - cerr << name << " may only be passed once." << endl; + std::cerr << name << " may only be passed once." << std::endl; return PARSE_ARGUMENT_FAIL; } imports_in_descriptor_set_ = true; } else if (name == "--include_source_info") { if (source_info_in_descriptor_set_) { - cerr << name << " may only be passed once." << endl; + std::cerr << name << " may only be passed once." << std::endl; return PARSE_ARGUMENT_FAIL; } source_info_in_descriptor_set_ = true; @@ -1032,7 +1046,7 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "--version") { if (!version_info_.empty()) { - cout << version_info_ << endl; + std::cout << version_info_ << std::endl; } cout << "libprotoc " << protobuf::internal::VersionString(GOOGLE_PROTOBUF_VERSION) @@ -1045,25 +1059,28 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "--encode" || name == "--decode" || name == "--decode_raw") { if (mode_ != MODE_COMPILE) { - cerr << "Only one of --encode and --decode can be specified." << endl; + std::cerr << "Only one of --encode and --decode can be specified." + << std::endl; return PARSE_ARGUMENT_FAIL; } if (!output_directives_.empty() || !descriptor_set_name_.empty()) { - cerr << "Cannot use " << name - << " and generate code or descriptors at the same time." << endl; + std::cerr << "Cannot use " << name + << " and generate code or descriptors at the same time." + << std::endl; return PARSE_ARGUMENT_FAIL; } mode_ = (name == "--encode") ? MODE_ENCODE : MODE_DECODE; if (value.empty() && name != "--decode_raw") { - cerr << "Type name for " << name << " cannot be blank." << endl; + std::cerr << "Type name for " << name << " cannot be blank." << std::endl; if (name == "--decode") { - cerr << "To decode an unknown message, use --decode_raw." << endl; + std::cerr << "To decode an unknown message, use --decode_raw." + << std::endl; } return PARSE_ARGUMENT_FAIL; } else if (!value.empty() && name == "--decode_raw") { - cerr << "--decode_raw does not take a parameter." << endl; + std::cerr << "--decode_raw does not take a parameter." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -1075,13 +1092,13 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (value == "msvs") { error_format_ = ERROR_FORMAT_MSVS; } else { - cerr << "Unknown error format: " << value << endl; + std::cerr << "Unknown error format: " << value << std::endl; return PARSE_ARGUMENT_FAIL; } } else if (name == "--plugin") { if (plugin_prefix_.empty()) { - cerr << "This compiler does not support plugins." << endl; + std::cerr << "This compiler does not support plugins." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -1107,13 +1124,15 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "--print_free_field_numbers") { if (mode_ != MODE_COMPILE) { - cerr << "Cannot use " << name << " and use --encode, --decode or print " - << "other info at the same time." << endl; + std::cerr << "Cannot use " << name + << " and use --encode, --decode or print " + << "other info at the same time." << std::endl; return PARSE_ARGUMENT_FAIL; } if (!output_directives_.empty() || !descriptor_set_name_.empty()) { - cerr << "Cannot use " << name - << " and generate code or descriptors at the same time." << endl; + std::cerr << "Cannot use " << name + << " and generate code or descriptors at the same time." + << std::endl; return PARSE_ARGUMENT_FAIL; } mode_ = MODE_PRINT; @@ -1127,7 +1146,7 @@ CommandLineInterface::InterpretArgument(const string& name, // Check if it's a generator option flag. generator_info = FindOrNull(generators_by_option_name_, name); if (generator_info == NULL) { - cerr << "Unknown flag: " << name << endl; + std::cerr << "Unknown flag: " << name << std::endl; return PARSE_ARGUMENT_FAIL; } else { string* parameters = &generator_parameters_[generator_info->flag_name]; @@ -1139,8 +1158,8 @@ CommandLineInterface::InterpretArgument(const string& name, } else { // It's an output flag. Add it to the output directives. if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode, --decode or print .proto info and " - "generate code at the same time." << endl; + std::cerr << "Cannot use --encode, --decode or print .proto info and " + "generate code at the same time." << std::endl; return PARSE_ARGUMENT_FAIL; } @@ -1172,7 +1191,7 @@ CommandLineInterface::InterpretArgument(const string& name, void CommandLineInterface::PrintHelpText() { // Sorry for indentation here; line wrapping would be uglier. - cerr << + std::cerr << "Usage: " << executable_name_ << " [OPTION] PROTO_FILES\n" "Parse PROTO_FILES and generate output based on the options given:\n" " -IPATH, --proto_path=PATH Specify the directory in which to search for\n" @@ -1213,9 +1232,9 @@ void CommandLineInterface::PrintHelpText() { " defined in the given proto files. Groups share\n" " the same field number space with the parent \n" " message. Extension ranges are counted as \n" -" occupied fields numbers." << endl; +" occupied fields numbers." << std::endl; if (!plugin_prefix_.empty()) { - cerr << + std::cerr << " --plugin=EXECUTABLE Specifies a plugin executable to use.\n" " Normally, protoc searches the PATH for\n" " plugins, but you may specify additional\n" @@ -1223,7 +1242,7 @@ void CommandLineInterface::PrintHelpText() { " Additionally, EXECUTABLE may be of the form\n" " NAME=PATH, in which case the given plugin name\n" " is mapped to the given executable even if\n" -" the executable's own name differs." << endl; +" the executable's own name differs." << std::endl; } for (GeneratorMap::iterator iter = generators_by_flag_name_.begin(); @@ -1231,9 +1250,9 @@ void CommandLineInterface::PrintHelpText() { // FIXME(kenton): If the text is long enough it will wrap, which is ugly, // but fixing this nicely (e.g. splitting on spaces) is probably more // trouble than it's worth. - cerr << " " << iter->first << "=OUT_DIR " - << string(19 - iter->first.size(), ' ') // Spaces for alignment. - << iter->second.help_text << endl; + std::cerr << " " << iter->first << "=OUT_DIR " + << string(19 - iter->first.size(), ' ') // Spaces for alignment. + << iter->second.help_text << std::endl; } } @@ -1256,7 +1275,7 @@ bool CommandLineInterface::GenerateOutput( if (!GeneratePluginOutput(parsed_files, plugin_name, output_directive.parameter, generator_context, &error)) { - cerr << output_directive.name << ": " << error << endl; + std::cerr << output_directive.name << ": " << error << std::endl; return false; } } else { @@ -1272,8 +1291,8 @@ bool CommandLineInterface::GenerateOutput( if (!output_directive.generator->Generate(parsed_files[i], parameters, generator_context, &error)) { // Generator returned an error. - cerr << output_directive.name << ": " << parsed_files[i]->name() << ": " - << error << endl; + std::cerr << output_directive.name << ": " << parsed_files[i]->name() + << ": " << error << std::endl; return false; } } @@ -1365,7 +1384,7 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { // Look up the type. const Descriptor* type = pool->FindMessageTypeByName(codec_type_); if (type == NULL) { - cerr << "Type not defined: " << codec_type_ << endl; + std::cerr << "Type not defined: " << codec_type_ << std::endl; return false; } @@ -1391,32 +1410,32 @@ bool CommandLineInterface::EncodeOrDecode(const DescriptorPool* pool) { parser.AllowPartialMessage(true); if (!parser.Parse(&in, message.get())) { - cerr << "Failed to parse input." << endl; + std::cerr << "Failed to parse input." << std::endl; return false; } } else { // Input is binary. if (!message->ParsePartialFromZeroCopyStream(&in)) { - cerr << "Failed to parse input." << endl; + std::cerr << "Failed to parse input." << std::endl; return false; } } if (!message->IsInitialized()) { - cerr << "warning: Input message is missing required fields: " - << message->InitializationErrorString() << endl; + std::cerr << "warning: Input message is missing required fields: " + << message->InitializationErrorString() << std::endl; } if (mode_ == MODE_ENCODE) { // Output is binary. if (!message->SerializePartialToZeroCopyStream(&out)) { - cerr << "output: I/O error." << endl; + std::cerr << "output: I/O error." << std::endl; return false; } } else { // Output is text. if (!TextFormat::Print(*message, &out)) { - cerr << "output: I/O error." << endl; + std::cerr << "output: I/O error." << std::endl; return false; } } @@ -1458,12 +1477,14 @@ bool CommandLineInterface::WriteDescriptorSet( io::FileOutputStream out(fd); if (!file_set.SerializeToZeroCopyStream(&out)) { - cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl; + std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) + << std::endl; out.Close(); return false; } if (!out.Close()) { - cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) << endl; + std::cerr << descriptor_set_name_ << ": " << strerror(out.GetErrno()) + << std::endl; return false; } @@ -1582,7 +1603,7 @@ void FormatFreeFieldNumbers(const string& name, if (next_free_number <= FieldDescriptor::kMaxNumber) { StringAppendF(&output, " %d-INF", next_free_number); } - cout << output << endl; + std::cout << output << std::endl; } } // namespace diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 64e877a3..3d27829e 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -67,7 +67,6 @@ // Disable the whole test when we use tcmalloc for "draconian" heap checks, in // which case tcmalloc will print warnings that fail the plugin tests. #if !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN - namespace google { namespace protobuf { namespace compiler { @@ -1666,6 +1665,6 @@ TEST_F(EncodeDecodeTest, ProtoParseError) { } // namespace compiler } // namespace protobuf -} // namespace google -#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN +#endif // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN +} // namespace google diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index 48788197..13ed0b64 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -98,7 +98,8 @@ class MockGeneratorContext : public GeneratorContext { &actual_contents, true)); EXPECT_TRUE(actual_contents == *expected_contents) << physical_filename << " needs to be regenerated. Please run " - "generate_descriptor_proto.sh and add this file " + "google/protobuf/compiler/release_compiler.sh and " + "generate_descriptor_proto.sh. Then add this file " "to your CL."; } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 3ce1f120..0404b739 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -47,7 +47,7 @@ namespace cpp { namespace { // The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value -// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the +// is ::google::protobuf::kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the // generation of the GOOGLE_ARRAYSIZE constant. bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { int32 max_value = descriptor->value(0)->number(); @@ -56,7 +56,7 @@ bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { max_value = descriptor->value(i)->number(); } } - return max_value != kint32max; + return max_value != ::google::protobuf::kint32max; } } // namespace @@ -153,9 +153,12 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { void EnumGenerator:: GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { + printer->Print( + "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type " + "{};\n", + "classname", ClassName(descriptor_, true)); if (HasDescriptorMethods(descriptor_->file())) { printer->Print( - "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n" "template <>\n" "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" " return $classname$_descriptor();\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 17926135..74989703 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -76,23 +76,26 @@ GeneratePrivateMembers(io::Printer* printer) const { void EnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$() const$deprecation$;\n" - "inline void set_$name$($type$ value)$deprecation$;\n"); + "$type$ $name$() const$deprecation$;\n" + "void set_$name$($type$ value)$deprecation$;\n"); } void EnumFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_);\n" "}\n" - "inline void $classname$::set_$name$($type$ value) {\n"); + "$inline$ void $classname$::set_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, + printer->Print(variables, " assert($type$_IsValid(value));\n"); } - printer->Print(variables_, + printer->Print(variables, " $set_hasbit$\n" " $name$_ = value;\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" @@ -181,21 +184,24 @@ EnumOneofFieldGenerator(const FieldDescriptor* descriptor, EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {} void EnumOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return static_cast< $type$ >($oneof_prefix$$name$_);\n" " }\n" " return static_cast< $type$ >($default$);\n" "}\n" - "inline void $classname$::set_$name$($type$ value) {\n"); + "$inline$ void $classname$::set_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, + printer->Print(variables, " assert($type$_IsValid(value));\n"); } - printer->Print(variables_, + printer->Print(variables, " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -246,46 +252,49 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$(int index) const$deprecation$;\n" - "inline void set_$name$(int index, $type$ value)$deprecation$;\n" - "inline void add_$name$($type$ value)$deprecation$;\n"); + "$type$ $name$(int index) const$deprecation$;\n" + "void set_$name$(int index, $type$ value)$deprecation$;\n" + "void add_$name$($type$ value)$deprecation$;\n"); printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField& $name$() const$deprecation$;\n" - "inline ::google::protobuf::RepeatedField* mutable_$name$()$deprecation$;\n"); + "const ::google::protobuf::RepeatedField& $name$() const$deprecation$;\n" + "::google::protobuf::RepeatedField* mutable_$name$()$deprecation$;\n"); } void RepeatedEnumFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$(int index) const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_.Get(index));\n" "}\n" - "inline void $classname$::set_$name$(int index, $type$ value) {\n"); + "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, + printer->Print(variables, " assert($type$_IsValid(value));\n"); } - printer->Print(variables_, + printer->Print(variables, " $name$_.Set(index, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::add_$name$($type$ value) {\n"); + "$inline$ void $classname$::add_$name$($type$ value) {\n"); if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { - printer->Print(variables_, + printer->Print(variables, " assert($type$_IsValid(value));\n"); } - printer->Print(variables_, + printer->Print(variables, " $name$_.Add(value);\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField&\n" + printer->Print(variables, + "$inline$ const ::google::protobuf::RepeatedField&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::google::protobuf::RepeatedField*\n" + "$inline$ ::google::protobuf::RepeatedField*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" @@ -344,20 +353,34 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { if (!descriptor_->options().packed()) { - // We use a non-inlined implementation in this case, since this path will - // rarely be executed. - printer->Print(variables_, - "DO_((::google::protobuf::internal::WireFormatLite::ReadPackedEnumNoInline(\n" - " input,\n"); + // This path is rarely executed, so we use a non-inlined implementation. if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { printer->Print(variables_, - " NULL,\n"); + "DO_((::google::protobuf::internal::" + "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " NULL,\n" + " NULL,\n" + " this->mutable_$name$())));\n"); + } else if (UseUnknownFieldSet(descriptor_->file())) { + printer->Print(variables_, + "DO_((::google::protobuf::internal::WireFormat::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " $type$_IsValid,\n" + " mutable_unknown_fields(),\n" + " this->mutable_$name$())));\n"); } else { printer->Print(variables_, - " &$type$_IsValid,\n"); + "DO_((::google::protobuf::internal::" + "WireFormatLite::ReadPackedEnumPreserveUnknowns(\n" + " input,\n" + " $number$,\n" + " $type$_IsValid,\n" + " &unknown_fields_stream,\n" + " this->mutable_$name$())));\n"); } - printer->Print(variables_, - " this->mutable_$name$())));\n"); } else { printer->Print(variables_, "::google::protobuf::uint32 length;\n" @@ -376,6 +399,16 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { printer->Print(variables_, " if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n" + " } else {\n"); + if (UseUnknownFieldSet(descriptor_->file())) { + printer->Print(variables_, + " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } else { + printer->Print(variables_, + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(value);\n"); + } + printer->Print( " }\n"); } printer->Print(variables_, diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h index def2b232..5b1d01ea 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -53,7 +53,8 @@ class EnumFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; @@ -78,7 +79,8 @@ class EnumOneofFieldGenerator : public EnumFieldGenerator { ~EnumOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -96,7 +98,8 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index c37fe0be..cd2b6b75 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -89,7 +89,7 @@ class FieldGenerator { // Generate inline definitions of accessor functions for this field. // These are placed inside the header after all class definitions. virtual void GenerateInlineAccessorDefinitions( - io::Printer* printer) const = 0; + io::Printer* printer, bool is_inline) const = 0; // Generate definitions of accessors that aren't inlined. These are // placed somewhere in the .cc file. diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index fae4df40..a98c7d92 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -136,8 +136,11 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print( "#include \n" "#include \n" - "#include \n" - "#include \n"); + "#include \n"); + if (UseUnknownFieldSet(file_)) { + printer->Print( + "#include \n"); + } if (file_->message_type_count() > 0) { if (HasDescriptorMethods(file_)) { printer->Print( @@ -152,13 +155,24 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "#include \n"); if (HasMapFields(file_)) { printer->Print( - "#include \n" - "#include \n"); + "#include \n"); + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n"); + } else { + printer->Print( + "#include \n"); + } } - if (HasDescriptorMethods(file_) && HasEnumDefinitions(file_)) { - printer->Print( - "#include \n"); + if (HasEnumDefinitions(file_)) { + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n"); + } else { + printer->Print( + "#include \n"); + } } if (HasGenericServices(file_)) { @@ -272,15 +286,17 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); - + printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); // Generate class inline methods. for (int i = 0; i < file_->message_type_count(); i++) { if (i > 0) { printer->Print(kThinSeparator); printer->Print("\n"); } - message_generators_[i]->GenerateInlineMethods(printer); + message_generators_[i]->GenerateInlineMethods(printer, + /* is_inline = */ true); } + printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); printer->Print( "\n" @@ -290,7 +306,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { GenerateNamespaceClosers(printer); // Emit GetEnumDescriptor specializations into google::protobuf namespace: - if (HasDescriptorMethods(file_)) { + if (HasEnumDefinitions(file_)) { // The SWIG conditional is to avoid a null-pointer dereference // (bug 1984964) in swig-1.3.21 resulting from the following syntax: // namespace X { void Y(); } @@ -417,6 +433,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); message_generators_[i]->GenerateClassMethods(printer); + + printer->Print("#if PROTOBUF_INLINE_NOT_IN_HEADERS\n"); + // Generate class inline methods. + message_generators_[i]->GenerateInlineMethods(printer, + /* is_inline = */ false); + printer->Print("#endif // PROTOBUF_INLINE_NOT_IN_HEADERS\n"); } if (HasGenericServices(file_)) { diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 28c4dd54..237278db 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -352,9 +352,7 @@ string FilenameIdentifier(const string& filename) { } else { // Not alphanumeric. To avoid any possibility of name conflicts we // use the hex code for the character. - result.push_back('_'); - char buffer[kFastToBufferSize]; - result.append(FastHexToBuffer(static_cast(filename[i]), buffer)); + StrAppend(&result, "_", ToHex(static_cast(filename[i]))); } } return result; @@ -508,6 +506,13 @@ bool IsStringOrMessage(const FieldDescriptor* field) { return false; } +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) { + GOOGLE_DCHECK(field->cpp_type() == FieldDescriptor::CPPTYPE_STRING); + // Open-source protobuf release only supports STRING ctype. + return FieldOptions::STRING; + +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index e60fa7c2..c7bb8f98 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -211,6 +211,10 @@ inline bool IsMapEntryMessage(const Descriptor* descriptor) { // Returns true if the field's CPPTYPE is string or message. bool IsStringOrMessage(const FieldDescriptor* field); +// For a string field, returns the effective ctype. If the actual ctype is +// not supported, returns the default of STRING. +FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field); + string UnderscoresToCamelCase(const string& input, bool cap_next_letter); inline bool HasFieldPresence(const FileDescriptor* file) { diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index 0154eeb8..8c38db2b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include namespace google { @@ -72,14 +73,21 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["val_cpp"] = PrimitiveTypeName(val->cpp_type()); (*variables)["wrapper"] = "EntryWrapper"; } - (*variables)["key_type"] = - "::google::protobuf::FieldDescriptor::TYPE_" + + (*variables)["key_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); - (*variables)["val_type"] = - "::google::protobuf::FieldDescriptor::TYPE_" + + (*variables)["val_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); (*variables)["map_classname"] = ClassName(descriptor->message_type(), false); - (*variables)["number"] = Int32ToString(descriptor->number()); + (*variables)["number"] = SimpleItoa(descriptor->number()); + (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + + if (HasDescriptorMethods(descriptor->file())) { + (*variables)["lite"] = ""; + } else { + (*variables)["lite"] = "Lite"; + } if (!IsProto3Field(descriptor) && val->type() == FieldDescriptor::TYPE_ENUM) { @@ -102,33 +110,40 @@ MapFieldGenerator::~MapFieldGenerator() {} void MapFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, - "typedef ::google::protobuf::internal::MapEntry<\n" + "typedef ::google::protobuf::internal::MapEntryLite<\n" " $key_cpp$, $val_cpp$,\n" - " $key_type$,\n" - " $val_type$, $default_enum_value$>\n" + " $key_wire_type$,\n" + " $val_wire_type$,\n" + " $default_enum_value$ >\n" " $map_classname$;\n" - "::google::protobuf::internal::MapField< $key_cpp$, $val_cpp$," - "$key_type$, $val_type$, $default_enum_value$ > $name$_;\n"); + "::google::protobuf::internal::MapField$lite$<\n" + " $key_cpp$, $val_cpp$,\n" + " $key_wire_type$,\n" + " $val_wire_type$,\n" + " $default_enum_value$ > $name$_;\n"); } void MapFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" + "const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" " $name$() const$deprecation$;\n" - "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" + "::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" " mutable_$name$()$deprecation$;\n"); } void MapFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ const ::google::protobuf::Map< $key_cpp$, $val_cpp$ >&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_map:$full_name$)\n" " return $name$_.GetMap();\n" "}\n" - "inline ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" + "$inline$ ::google::protobuf::Map< $key_cpp$, $val_cpp$ >*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_map:$full_name$)\n" " return $name$_.MutableMap();\n" @@ -198,11 +213,29 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " if ($val_cpp$_IsValid(*entry->mutable_value())) {\n" " (*mutable_$name$())[entry->key()] =\n" " static_cast<$val_cpp$>(*entry->mutable_value());\n" - " } else {\n" - " mutable_unknown_fields()->AddLengthDelimited($number$, data);\n" + " } else {\n"); + if (HasDescriptorMethods(descriptor_->file())) { + printer->Print(variables_, + " mutable_unknown_fields()" + "->AddLengthDelimited($number$, data);\n"); + } else { + printer->Print(variables_, + " unknown_fields_stream.WriteVarint32($tag$);\n" + " unknown_fields_stream.WriteVarint32(data.size());\n" + " unknown_fields_stream.WriteString(data);\n"); + } + + + printer->Print(variables_, " }\n" "}\n"); } + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + "if (entry->GetArena() != NULL) entry.release();\n"); + } } void MapFieldGenerator:: @@ -211,12 +244,31 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n" + " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print(variables_, " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" " ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n" " $number$, *entry, output);\n" - " }\n" - "}\n"); + " }\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print("}\n"); } void MapFieldGenerator:: @@ -225,13 +277,32 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n" + " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print(variables_, " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" " target = ::google::protobuf::internal::WireFormatLite::\n" " Write$declared_type$NoVirtualToArray(\n" " $number$, *entry, target);\n" - " }\n" - "}\n"); + " }\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print("}\n"); } void MapFieldGenerator:: @@ -241,12 +312,31 @@ GenerateByteSize(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n" + " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print(variables_, " entry.reset($name$_.New$wrapper$(it->first, it->second));\n" " total_size += ::google::protobuf::internal::WireFormatLite::\n" " $declared_type$SizeNoVirtual(*entry);\n" - " }\n" - "}\n"); + " }\n"); + + // If entry is allocated by arena, its desctructor should be avoided. + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + " if (entry.get() != NULL && entry->GetArena() != NULL) {\n" + " entry.release();\n" + " }\n"); + } + + printer->Print("}\n"); } } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h index 0ff032fd..d27d4851 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h @@ -50,7 +50,8 @@ class MapFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index d0fd6c6d..bafa36f5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -87,8 +87,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { for (int i = 0; i < descriptor->field_count(); i++) { fields[i] = descriptor->field(i); } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); return fields; } @@ -253,7 +253,7 @@ void OptimizePadding(vector* fields) { // Sort by preferred location to keep fields as close to their original // location as possible. Using stable_sort ensures that the output is // consistent across runs. - stable_sort(aligned_to_4.begin(), aligned_to_4.end()); + std::stable_sort(aligned_to_4.begin(), aligned_to_4.end()); // Now group fields aligned to 4 bytes (or the 4-field groups created above) // into pairs, and treat those like a single field aligned to 8 bytes. @@ -269,7 +269,7 @@ void OptimizePadding(vector* fields) { aligned_to_8.push_back(field_group); } // Sort by preferred location. - stable_sort(aligned_to_8.begin(), aligned_to_8.end()); + std::stable_sort(aligned_to_8.begin(), aligned_to_8.end()); // Now pull out all the FieldDescriptors in order. fields->clear(); @@ -347,11 +347,11 @@ void CollectMapInfo(const Descriptor* descriptor, default: (*variables)["val"] = PrimitiveTypeName(val->cpp_type()); } - (*variables)["key_type"] = - "::google::protobuf::FieldDescriptor::TYPE_" + + (*variables)["key_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + ToUpper(DeclaredTypeMethodName(key->type())); - (*variables)["val_type"] = - "::google::protobuf::FieldDescriptor::TYPE_" + + (*variables)["val_wire_type"] = + "::google::protobuf::internal::WireFormatLite::TYPE_" + ToUpper(DeclaredTypeMethodName(val->type())); } @@ -453,17 +453,17 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { vars["constant_name"] = FieldConstantName(field); if (field->is_repeated()) { - printer->Print(vars, "inline int $name$_size() const$deprecation$;\n"); + printer->Print(vars, "int $name$_size() const$deprecation$;\n"); } else if (HasHasMethod(field)) { - printer->Print(vars, "inline bool has_$name$() const$deprecation$;\n"); + printer->Print(vars, "bool has_$name$() const$deprecation$;\n"); } else if (HasPrivateHasMethod(field)) { printer->Print(vars, "private:\n" - "inline bool has_$name$() const$deprecation$;\n" + "bool has_$name$() const$deprecation$;\n" "public:\n"); } - printer->Print(vars, "inline void clear_$name$()$deprecation$;\n"); + printer->Print(vars, "void clear_$name$()$deprecation$;\n"); printer->Print(vars, "static const int $constant_name$ = $number$;\n"); // Generate type-specific accessor declarations. @@ -482,7 +482,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { printer->Print( - "inline $camel_oneof_name$Case $oneof_name$_case() const;\n", + "$camel_oneof_name$Case $oneof_name$_case() const;\n", "camel_oneof_name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true), "oneof_name", descriptor_->oneof_decl(i)->name()); @@ -490,7 +490,7 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { } void MessageGenerator:: -GenerateFieldAccessorDefinitions(io::Printer* printer) { +GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { printer->Print("// $classname$\n\n", "classname", classname_); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -500,11 +500,12 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { map vars; SetCommonFieldVariables(field, &vars, options_); + vars["inline"] = is_inline ? "inline" : ""; // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { printer->Print(vars, - "inline int $classname$::$name$_size() const {\n" + "$inline$ int $classname$::$name$_size() const {\n" " return $name$_.size();\n" "}\n"); } else if (field->containing_oneof()) { @@ -518,11 +519,11 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { vars["oneof_name"] = field->containing_oneof()->name(); vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" + "$inline$ bool $classname$::has_$name$() const {\n" " return $oneof_name$_case() == k$field_name$;\n" "}\n"); printer->Print(vars, - "inline void $classname$::set_has_$name$() {\n" + "$inline$ void $classname$::set_has_$name$() {\n" " _oneof_case_[$oneof_index$] = k$field_name$;\n" "}\n"); } else { @@ -535,13 +536,13 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), buffer); printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" + "$inline$ bool $classname$::has_$name$() const {\n" " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" "}\n" - "inline void $classname$::set_has_$name$() {\n" + "$inline$ void $classname$::set_has_$name$() {\n" " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" "}\n" - "inline void $classname$::clear_has_$name$() {\n" + "$inline$ void $classname$::clear_has_$name$() {\n" " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" "}\n" ); @@ -551,12 +552,12 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { bool is_lazy = false; if (is_lazy) { printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" + "$inline$ bool $classname$::has_$name$() const {\n" " return !$name$_.IsCleared();\n" "}\n"); } else { printer->Print(vars, - "inline bool $classname$::has_$name$() const {\n" + "$inline$ bool $classname$::has_$name$() const {\n" " return !_is_default_instance_ && $name$_ != NULL;\n" "}\n"); } @@ -566,7 +567,7 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { // Generate clear_$name$() printer->Print(vars, - "inline void $classname$::clear_$name$() {\n"); + "$inline$ void $classname$::clear_$name$() {\n"); printer->Indent(); @@ -595,7 +596,8 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { printer->Print("}\n"); // Generate type-specific accessors. - field_generators_.get(field).GenerateInlineAccessorDefinitions(printer); + field_generators_.get(field).GenerateInlineAccessorDefinitions(printer, + is_inline); printer->Print("\n"); } @@ -608,12 +610,13 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { vars["cap_oneof_name"] = ToUpper(descriptor_->oneof_decl(i)->name()); vars["classname"] = classname_; + vars["inline"] = is_inline ? "inline" : ""; printer->Print( vars, - "inline bool $classname$::has_$oneof_name$() const {\n" + "$inline$ bool $classname$::has_$oneof_name$() const {\n" " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" "}\n" - "inline void $classname$::clear_has_$oneof_name$() {\n" + "$inline$ void $classname$::clear_has_$oneof_name$() {\n" " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" "}\n"); } @@ -1169,18 +1172,18 @@ GenerateClassDefinition(io::Printer* printer) { } void MessageGenerator:: -GenerateInlineMethods(io::Printer* printer) { +GenerateInlineMethods(io::Printer* printer, bool is_inline) { for (int i = 0; i < descriptor_->nested_type_count(); i++) { // map entry message doesn't need inline methods. Since map entry message // cannot be a top level class, we just need to avoid calling // GenerateInlineMethods here. if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; - nested_generators_[i]->GenerateInlineMethods(printer); + nested_generators_[i]->GenerateInlineMethods(printer, is_inline); printer->Print(kThinSeparator); printer->Print("\n"); } - GenerateFieldAccessorDefinitions(printer); + GenerateFieldAccessorDefinitions(printer, is_inline); // Generate oneof_case() functions. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { @@ -1190,9 +1193,10 @@ GenerateInlineMethods(io::Printer* printer) { descriptor_->oneof_decl(i)->name(), true); vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["inline"] = is_inline ? "inline " : ""; printer->Print( vars, - "inline $class_name$::$camel_oneof_name$Case $class_name$::" + "$inline$$class_name$::$camel_oneof_name$Case $class_name$::" "$oneof_name$_case() const {\n" " return $class_name$::$camel_oneof_name$Case(" "_oneof_case_[$oneof_index$]);\n" @@ -1222,7 +1226,9 @@ GenerateDescriptorDeclarations(io::Printer* printer) { for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); printer->Print(" "); - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING && + EffectiveStringCType(field) != FieldOptions::STRING)) { printer->Print("const "); } field_generators_.get(field).GeneratePrivateMembers(printer); @@ -1391,8 +1397,8 @@ GenerateTypeRegistrations(io::Printer* printer) { " ::google::protobuf::internal::MapEntry<\n" " $key$,\n" " $val$,\n" - " $key_type$,\n" - " $val_type$,\n" + " $key_wire_type$,\n" + " $val_wire_type$,\n" " $default_enum_value$>::CreateDefaultInstance(\n" " $classname$_descriptor_));\n"); } @@ -2034,17 +2040,16 @@ GenerateClear(io::Printer* printer) { // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0. // The generated code uses two macros to help it clear runs of fields: - // OFFSET_OF_FIELD_ computes the offset (in bytes) of a field in the Message. + // ZR_HELPER_(f1) - ZR_HELPER_(f0) computes the difference, in bytes, of the + // positions of two fields in the Message. // ZR_ zeroes a non-empty range of fields via memset. const char* macros = - "#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \\\n" - " &reinterpret_cast<$classname$*>(16)->f) - \\\n" - " reinterpret_cast(16))\n\n" - "#define ZR_(first, last) do { \\\n" - " size_t f = OFFSET_OF_FIELD_(first); \\\n" - " size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \\\n" - " ::memset(&first, 0, n); \\\n" - " } while (0)\n\n"; + "#define ZR_HELPER_(f) reinterpret_cast(\\\n" + " &reinterpret_cast<$classname$*>(16)->f)\n\n" + "#define ZR_(first, last) do {\\\n" + " ::memset(&first, 0,\\\n" + " ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\\\n" + "} while (0)\n\n"; for (int i = 0; i < runs_of_fields_.size(); i++) { const vector& run = runs_of_fields_[i]; if (run.size() < 2) continue; @@ -2133,7 +2138,7 @@ GenerateClear(io::Printer* printer) { } if (macros_are_needed) { printer->Outdent(); - printer->Print("\n#undef OFFSET_OF_FIELD_\n#undef ZR_\n\n"); + printer->Print("\n#undef ZR_HELPER_\n#undef ZR_\n\n"); printer->Indent(); } @@ -2919,8 +2924,8 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { 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(), - ExtensionRangeSorter()); + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeSorter()); // Merge the fields and the extension ranges, both sorted by field number. int i, j; diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index dfbc9af5..ea96581d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -82,7 +82,7 @@ class MessageGenerator { // Generate definitions of inline methods (placed at the end of the header // file). - void GenerateInlineMethods(io::Printer* printer); + void GenerateInlineMethods(io::Printer* printer, bool is_inline); // Source file stuff. @@ -116,7 +116,7 @@ class MessageGenerator { private: // Generate declarations and definitions of accessors for fields. void GenerateFieldAccessorDeclarations(io::Printer* printer); - void GenerateFieldAccessorDefinitions(io::Printer* printer); + void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline); // Generate the field offsets array. void GenerateOffsets(io::Printer* printer); diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index b3cd0ba1..467b6bf6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -85,76 +85,141 @@ GeneratePrivateMembers(io::Printer* printer) const { void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + "private:\n" + "void _slow_mutable_$name$()$deprecation$;\n"); + if (SupportsArenas(descriptor_->message_type())) { + printer->Print(variables_, + "void _slow_set_allocated_$name$(\n" + " ::google::protobuf::Arena* message_arena, $type$** $name$)$deprecation$;\n"); + } + printer->Print(variables_, + "$type$* _slow_$release_name$()$deprecation$;\n" + "public:\n"); + } printer->Print(variables_, - "inline const $type$& $name$() const$deprecation$;\n" - "inline $type$* mutable_$name$()$deprecation$;\n" - "inline $type$* $release_name$()$deprecation$;\n" - "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n"); + "const $type$& $name$() const$deprecation$;\n" + "$type$* mutable_$name$()$deprecation$;\n" + "$type$* $release_name$()$deprecation$;\n" + "void set_allocated_$name$($type$* $name$)$deprecation$;\n"); if (SupportsArenas(descriptor_)) { printer->Print(variables_, - "inline $type$* unsafe_arena_release_$name$()$deprecation$;\n" - "inline void unsafe_arena_set_allocated_$name$(\n" + "$type$* unsafe_arena_release_$name$()$deprecation$;\n" + "void unsafe_arena_set_allocated_$name$(\n" " $type$* $name$)$deprecation$;\n"); } } +void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( + io::Printer* printer) const { + if (SupportsArenas(descriptor_)) { + printer->Print(variables_, + "void $classname$::_slow_mutable_$name$() {\n"); + if (SupportsArenas(descriptor_->message_type())) { + printer->Print(variables_, + " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n" + " GetArenaNoVirtual());\n"); + } else { + printer->Print(variables_, + " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" + " GetArenaNoVirtual());\n"); + } + printer->Print(variables_, + "}\n" + "$type$* $classname$::_slow_$release_name$() {\n" + " if ($name$_ == NULL) {\n" + " return NULL;\n" + " } else {\n" + " $type$* temp = new $type$;\n" + " temp->MergeFrom(*$name$_);\n" + " $name$_ = NULL;\n" + " return temp;\n" + " }\n" + "}\n" + "$type$* $classname$::unsafe_arena_release_$name$() {\n" + " $clear_hasbit$\n" + " $type$* temp = $name$_;\n" + " $name$_ = NULL;\n" + " return temp;\n" + "}\n"); + if (SupportsArenas(descriptor_->message_type())) { + printer->Print(variables_, + "void $classname$::_slow_set_allocated_$name$(\n" + " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n" + " if (message_arena != NULL && \n" + " ::google::protobuf::Arena::GetArena(*$name$) == NULL) {\n" + " message_arena->Own(*$name$);\n" + " } else if (message_arena !=\n" + " ::google::protobuf::Arena::GetArena(*$name$)) {\n" + " $type$* new_$name$ = \n" + " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" + " message_arena);\n" + " new_$name$->CopyFrom(**$name$);\n" + " *$name$ = new_$name$;\n" + " }\n" + "}\n"); + } + printer->Print(variables_, + "void $classname$::unsafe_arena_set_allocated_$name$(\n" + " $type$* $name$) {\n" + // If we're not on an arena, free whatever we were holding before. + // (If we are on arena, we can just forget the earlier pointer.) + " if (GetArenaNoVirtual() == NULL) {\n" + " delete $name$_;\n" + " }\n" + " $name$_ = $name$;\n" + " if ($name$) {\n" + " $set_hasbit$\n" + " } else {\n" + " $clear_hasbit$\n" + " }\n" + " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" + ":$full_name$)\n" + "}\n"); + } +} + void MessageFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ const $type$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n"); PrintHandlingOptionalStaticInitializers( - variables_, descriptor_->file(), printer, + variables, descriptor_->file(), printer, // With static initializers. " return $name$_ != NULL ? *$name$_ : *default_instance_->$name$_;\n", // Without. " return $name$_ != NULL ? *$name$_ : *default_instance().$name$_;\n"); if (SupportsArenas(descriptor_)) { - printer->Print(variables_, + printer->Print(variables, "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" + "$inline$ $type$* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" - " if ($name$_ == NULL) {\n"); - if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " GetArenaNoVirtual());\n"); - } else { - printer->Print(variables_, - " $name$_ = ::google::protobuf::Arena::Create< $type$ >(\n" - " GetArenaNoVirtual());\n"); - } - printer->Print(variables_, " }\n" + " if ($name$_ == NULL) {\n" + " _slow_mutable_$name$();" + " }\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" "}\n" - "inline $type$* $classname$::$release_name$() {\n" + "$inline$ $type$* $classname$::$release_name$() {\n" " $clear_hasbit$\n" " if (GetArenaNoVirtual() != NULL) {\n" - " if ($name$_ == NULL) {\n" - " return NULL;\n" - " } else {\n" - " $type$* temp = new $type$;\n" - " temp->MergeFrom(*$name$_);\n" - " $name$_ = NULL;\n" - " return temp;\n" - " }\n" + " return _slow_$release_name$();\n" " } else {\n" " $type$* temp = $name$_;\n" " $name$_ = NULL;\n" " return temp;\n" " }\n" "}\n" - "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" - " $clear_hasbit$\n" - " $type$* temp = $name$_;\n" - " $name$_ = NULL;\n" - " return temp;\n" - "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" - " if (GetArenaNoVirtual() == NULL) {\n" + "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" + " ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();\n" + " if (message_arena == NULL) {\n" " delete $name$_;\n" " }\n" " if ($name$ != NULL) {\n"); @@ -164,26 +229,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { // so we might as well defer it. Otherwise, if incoming message is on a // different ownership domain (specific arena, or the heap) than we are, // copy to our arena (or heap, as the case may be). - printer->Print(variables_, - " if (GetArenaNoVirtual() != NULL && \n" - " ::google::protobuf::Arena::GetArena($name$) == NULL) {\n" - " GetArenaNoVirtual()->Own($name$);\n" - " } else if (GetArenaNoVirtual() !=\n" - " ::google::protobuf::Arena::GetArena($name$)) {\n" - " $type$* new_$name$ = \n" - " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" - " GetArenaNoVirtual());\n" - " new_$name$->CopyFrom(*$name$);\n" - " $name$ = new_$name$;\n" - " }\n"); + printer->Print(variables, + " _slow_set_allocated_$name$(message_arena, &$name$);\n"); } else { - printer->Print(variables_, - " if (GetArenaNoVirtual() != NULL) {\n" - " GetArenaNoVirtual()->Own($name$);\n" + printer->Print(variables, + " if (message_arena != NULL) {\n" + " message_arena->Own($name$);\n" " }\n"); } - - printer->Print(variables_, + printer->Print(variables, " }\n" " $name$_ = $name$;\n" " if ($name$) {\n" @@ -192,27 +246,11 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $clear_hasbit$\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" - "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" - " $type$* $name$) {\n" - // If we're not on an arena, free whatever we were holding before. - // (If we are on arena, we can just forget the earlier pointer.) - " if (GetArenaNoVirtual() == NULL) {\n" - " delete $name$_;\n" - " }\n" - " $name$_ = $name$;\n" - " if ($name$) {\n" - " $set_hasbit$\n" - " } else {\n" - " $clear_hasbit$\n" - " }\n" - " // @@protoc_insertion_point(field_unsafe_arena_set_allocated" - ":$full_name$)\n" "}\n"); } else { - printer->Print(variables_, + printer->Print(variables, "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" + "$inline$ $type$* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " if ($name$_ == NULL) {\n" " $name$_ = new $type$;\n" @@ -220,17 +258,17 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" "}\n" - "inline $type$* $classname$::$release_name$() {\n" + "$inline$ $type$* $classname$::$release_name$() {\n" " $clear_hasbit$\n" " $type$* temp = $name$_;\n" " $name$_ = NULL;\n" " return temp;\n" "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" " delete $name$_;\n"); if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, + printer->Print(variables, " if ($name$ != NULL && $name$->GetArena() != NULL) {\n" " $type$* new_$name$ = new $type$;\n" " new_$name$->CopyFrom(*$name$);\n" @@ -238,7 +276,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " }\n"); } - printer->Print(variables_, + printer->Print(variables, " $name$_ = $name$;\n" " if ($name$) {\n" " $set_hasbit$\n" @@ -328,35 +366,38 @@ MessageOneofFieldGenerator(const FieldDescriptor* descriptor, MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} void MessageOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const $type$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return has_$name$() ? *$oneof_prefix$$name$_\n" " : $type$::default_instance();\n" "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" + "$inline$ $type$* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n"); if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, + printer->Print(variables, " $oneof_prefix$$name$_ = \n" " ::google::protobuf::Arena::CreateMessage< $type$ >(\n" " GetArenaNoVirtual());\n"); } else { - printer->Print(variables_, + printer->Print(variables, " $oneof_prefix$$name$_ = \n" " ::google::protobuf::Arena::Create< $type$ >(\n" " GetArenaNoVirtual());\n"); } - printer->Print(variables_, + printer->Print(variables, " }\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $oneof_prefix$$name$_;\n" "}\n" - "inline $type$* $classname$::$release_name$() {\n" + "$inline$ $type$* $classname$::$release_name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " if (GetArenaNoVirtual() != NULL) {\n" @@ -375,7 +416,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline $type$* $classname$::unsafe_arena_release_$name$() {\n" + "$inline$ $type$* $classname$::unsafe_arena_release_$name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " $type$* temp = $oneof_prefix$$name$_;\n" @@ -385,12 +426,12 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" " clear_$oneof_name$();\n" " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, + printer->Print(variables, // If incoming message is on the heap and we are on an arena, just Own() // it (see above). If it's on a different arena than we are or one of us // is on the heap, we make a copy to our arena/heap. @@ -406,19 +447,19 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $name$ = new_$name$;\n" " }\n"); } else { - printer->Print(variables_, + printer->Print(variables, " if (GetArenaNoVirtual() != NULL) {\n" " GetArenaNoVirtual()->Own($name$);\n" " }\n"); } - printer->Print(variables_, + printer->Print(variables, " set_has_$name$();\n" " $oneof_prefix$$name$_ = $name$;\n" " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(" + "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(" "$type$* $name$) {\n" // We rely on the oneof clear method to free the earlier contents of this // oneof. We can directly use the pointer we're given to set the new @@ -432,13 +473,13 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "$full_name$)\n" "}\n"); } else { - printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const $type$& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return has_$name$() ? *$oneof_prefix$$name$_\n" " : $type$::default_instance();\n" "}\n" - "inline $type$* $classname$::mutable_$name$() {\n" + "$inline$ $type$* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -447,7 +488,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $oneof_prefix$$name$_;\n" "}\n" - "inline $type$* $classname$::$release_name$() {\n" + "$inline$ $type$* $classname$::$release_name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " $type$* temp = $oneof_prefix$$name$_;\n" @@ -457,18 +498,18 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$($type$* $name$) {\n" " clear_$oneof_name$();\n" " if ($name$) {\n"); if (SupportsArenas(descriptor_->message_type())) { - printer->Print(variables_, + printer->Print(variables, " if ($name$->GetArena() != NULL) {\n" " $type$* new_$name$ = new $type$;\n" " new_$name$->CopyFrom(*$name$);\n" " $name$ = new_$name$;\n" " }\n"); } - printer->Print(variables_, + printer->Print(variables, " set_has_$name$();\n" " $oneof_prefix$$name$_ = $name$;\n" " }\n" @@ -521,38 +562,41 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedMessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline const $type$& $name$(int index) const$deprecation$;\n" - "inline $type$* mutable_$name$(int index)$deprecation$;\n" - "inline $type$* add_$name$()$deprecation$;\n"); + "const $type$& $name$(int index) const$deprecation$;\n" + "$type$* mutable_$name$(int index)$deprecation$;\n" + "$type$* add_$name$()$deprecation$;\n"); printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + "const ::google::protobuf::RepeatedPtrField< $type$ >&\n" " $name$() const$deprecation$;\n" - "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" + "::google::protobuf::RepeatedPtrField< $type$ >*\n" " mutable_$name$()$deprecation$;\n"); } void RepeatedMessageFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const $type$& $classname$::$name$(int index) const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ const $type$& $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.$cppget$(index);\n" "}\n" - "inline $type$* $classname$::mutable_$name$(int index) {\n" + "$inline$ $type$* $classname$::mutable_$name$(int index) {\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" - "inline $type$* $classname$::add_$name$() {\n" + "$inline$ $type$* $classname$::add_$name$() {\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" " return $name$_.Add();\n" "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" + printer->Print(variables, + "$inline$ const ::google::protobuf::RepeatedPtrField< $type$ >&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" + "$inline$ ::google::protobuf::RepeatedPtrField< $type$ >*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index 2dff3144..c1704fc1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -53,7 +53,9 @@ class MessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; + void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; @@ -78,7 +80,9 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; + void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {} void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -96,7 +100,8 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 9a2c930e..329eae32 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -117,18 +117,20 @@ GeneratePrivateMembers(io::Printer* printer) const { void PrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$() const$deprecation$;\n" - "inline void set_$name$($type$ value)$deprecation$;\n"); + "$type$ $name$() const$deprecation$;\n" + "void set_$name$($type$ value)$deprecation$;\n"); } void PrimitiveFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_;\n" "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" + "$inline$ void $classname$::set_$name$($type$ value) {\n" " $set_hasbit$\n" " $name$_ = value;\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" @@ -204,16 +206,18 @@ PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} void PrimitiveOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$() const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return $oneof_prefix$$name$_;\n" " }\n" " return $default$;\n" "}\n" - "inline void $classname$::set_$name$($type$ value) {\n" + "$inline$ void $classname$::set_$name$($type$ value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -282,38 +286,40 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, - "inline $type$ $name$(int index) const$deprecation$;\n" - "inline void set_$name$(int index, $type$ value)$deprecation$;\n" - "inline void add_$name$($type$ value)$deprecation$;\n"); + "$type$ $name$(int index) const$deprecation$;\n" + "void set_$name$(int index, $type$ value)$deprecation$;\n" + "void add_$name$($type$ value)$deprecation$;\n"); printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField< $type$ >&\n" + "const ::google::protobuf::RepeatedField< $type$ >&\n" " $name$() const$deprecation$;\n" - "inline ::google::protobuf::RepeatedField< $type$ >*\n" + "::google::protobuf::RepeatedField< $type$ >*\n" " mutable_$name$()$deprecation$;\n"); } void RepeatedPrimitiveFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline $type$ $classname$::$name$(int index) const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ $type$ $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.Get(index);\n" "}\n" - "inline void $classname$::set_$name$(int index, $type$ value) {\n" + "$inline$ void $classname$::set_$name$(int index, $type$ value) {\n" " $name$_.Set(index, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::add_$name$($type$ value) {\n" + "$inline$ void $classname$::add_$name$($type$ value) {\n" " $name$_.Add(value);\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedField< $type$ >&\n" + printer->Print(variables, + "$inline$ const ::google::protobuf::RepeatedField< $type$ >&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::google::protobuf::RepeatedField< $type$ >*\n" + "$inline$ ::google::protobuf::RepeatedField< $type$ >*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h index 97b5e867..fcd7d684 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -53,7 +53,8 @@ class PrimitiveFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; @@ -78,7 +79,8 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { ~PrimitiveOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -97,7 +99,8 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 04ed08c9..1a1bcd3d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -127,7 +127,11 @@ GenerateAccessorDeclarations(io::Printer* printer) const { // files that applied the ctype. The field can still be accessed via the // reflection interface since the reflection interface is independent of // the string's underlying representation. - if (descriptor_->options().ctype() != FieldOptions::STRING) { + + bool unknown_ctype = + descriptor_->options().ctype() != EffectiveStringCType(descriptor_); + + if (unknown_ctype) { printer->Outdent(); printer->Print( " private:\n" @@ -136,23 +140,23 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "inline const ::std::string& $name$() const$deprecation$;\n" - "inline void set_$name$(const ::std::string& value)$deprecation$;\n" - "inline void set_$name$(const char* value)$deprecation$;\n" - "inline void set_$name$(const $pointer_type$* value, size_t size)" + "const ::std::string& $name$() const$deprecation$;\n" + "void set_$name$(const ::std::string& value)$deprecation$;\n" + "void set_$name$(const char* value)$deprecation$;\n" + "void set_$name$(const $pointer_type$* value, size_t size)" "$deprecation$;\n" - "inline ::std::string* mutable_$name$()$deprecation$;\n" - "inline ::std::string* $release_name$()$deprecation$;\n" - "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); + "::std::string* mutable_$name$()$deprecation$;\n" + "::std::string* $release_name$()$deprecation$;\n" + "void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); if (SupportsArenas(descriptor_)) { printer->Print(variables_, - "inline ::std::string* unsafe_arena_release_$name$()$deprecation$;\n" - "inline void unsafe_arena_set_allocated_$name$(\n" + "::std::string* unsafe_arena_release_$name$()$deprecation$;\n" + "void unsafe_arena_set_allocated_$name$(\n" " ::std::string* $name$)$deprecation$;\n"); } - if (descriptor_->options().ctype() != FieldOptions::STRING) { + if (unknown_ctype) { printer->Outdent(); printer->Print(" public:\n"); printer->Indent(); @@ -160,25 +164,28 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } void StringFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.Get($default_variable$);\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n" " $set_hasbit$\n" " $name$_.Set($default_variable$, value, GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "$inline$ void $classname$::set_$name$(const char* value) {\n" " $set_hasbit$\n" " $name$_.Set($default_variable$, $string_piece$(value),\n" " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline " + "$inline$ " "void $classname$::set_$name$(const $pointer_type$* value,\n" " size_t size) {\n" " $set_hasbit$\n" @@ -186,22 +193,22 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " reinterpret_cast(value), size), GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "$inline$ ::std::string* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable($default_variable$, GetArenaNoVirtual());\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "$inline$ ::std::string* $classname$::$release_name$() {\n" " $clear_hasbit$\n" " return $name$_.Release($default_variable$, GetArenaNoVirtual());\n" "}\n" - "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n" + "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " $clear_hasbit$\n" " return $name$_.UnsafeArenaRelease($default_variable$,\n" " GetArenaNoVirtual());\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if ($name$ != NULL) {\n" " $set_hasbit$\n" " } else {\n" @@ -211,7 +218,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(\n" + "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(\n" " ::std::string* $name$) {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " if ($name$ != NULL) {\n" @@ -226,22 +233,22 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "}\n"); } else { // No-arena case. - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.GetNoArena($default_variable$);\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n" " $set_hasbit$\n" " $name$_.SetNoArena($default_variable$, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "$inline$ void $classname$::set_$name$(const char* value) {\n" " $set_hasbit$\n" " $name$_.SetNoArena($default_variable$, $string_piece$(value));\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline " + "$inline$ " "void $classname$::set_$name$(const $pointer_type$* value, " "size_t size) {\n" " $set_hasbit$\n" @@ -249,16 +256,16 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $string_piece$(reinterpret_cast(value), size));\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "$inline$ ::std::string* $classname$::mutable_$name$() {\n" " $set_hasbit$\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.MutableNoArena($default_variable$);\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "$inline$ ::std::string* $classname$::$release_name$() {\n" " $clear_hasbit$\n" " return $name$_.ReleaseNoArena($default_variable$);\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if ($name$ != NULL) {\n" " $set_hasbit$\n" " } else {\n" @@ -422,17 +429,20 @@ StringOneofFieldGenerator(const FieldDescriptor* descriptor, StringOneofFieldGenerator::~StringOneofFieldGenerator() {} void StringOneofFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; if (SupportsArenas(descriptor_)) { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return $oneof_prefix$$name$_.Get($default_variable$);\n" " }\n" " return *$default_variable$;\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -442,7 +452,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "$inline$ void $classname$::set_$name$(const char* value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -452,7 +462,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $string_piece$(value), GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline " + "$inline$ " "void $classname$::set_$name$(const $pointer_type$* value,\n" " size_t size) {\n" " if (!has_$name$()) {\n" @@ -465,7 +475,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "$inline$ ::std::string* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -475,7 +485,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "$inline$ ::std::string* $classname$::$release_name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " return $oneof_prefix$$name$_.Release($default_variable$,\n" @@ -484,7 +494,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline ::std::string* $classname$::unsafe_arena_release_$name$() {\n" + "$inline$ ::std::string* $classname$::unsafe_arena_release_$name$() {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" @@ -494,7 +504,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if (!has_$name$()) {\n" " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" " }\n" @@ -506,7 +516,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " }\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n" - "inline void $classname$::unsafe_arena_set_allocated_$name$(" + "$inline$ void $classname$::unsafe_arena_set_allocated_$name$(" "::std::string* $name$) {\n" " GOOGLE_DCHECK(GetArenaNoVirtual() != NULL);\n" " if (!has_$name$()) {\n" @@ -522,15 +532,15 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "}\n"); } else { // No-arena case. - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$() const {\n" + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$() const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " if (has_$name$()) {\n" " return $oneof_prefix$$name$_.GetNoArena($default_variable$);\n" " }\n" " return *$default_variable$;\n" "}\n" - "inline void $classname$::set_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(const ::std::string& value) {\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" @@ -540,7 +550,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $oneof_prefix$$name$_.SetNoArena($default_variable$, value);\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" - "inline void $classname$::set_$name$(const char* value) {\n" + "$inline$ void $classname$::set_$name$(const char* value) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -550,7 +560,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $string_piece$(value));\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline " + "$inline$ " "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" @@ -561,7 +571,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " reinterpret_cast(value), size));\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$() {\n" + "$inline$ ::std::string* $classname$::mutable_$name$() {\n" " if (!has_$name$()) {\n" " clear_$oneof_name$();\n" " set_has_$name$();\n" @@ -570,7 +580,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $oneof_prefix$$name$_.MutableNoArena($default_variable$);\n" "}\n" - "inline ::std::string* $classname$::$release_name$() {\n" + "$inline$ ::std::string* $classname$::$release_name$() {\n" " if (has_$name$()) {\n" " clear_has_$oneof_name$();\n" " return $oneof_prefix$$name$_.ReleaseNoArena($default_variable$);\n" @@ -578,7 +588,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " return NULL;\n" " }\n" "}\n" - "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + "$inline$ void $classname$::set_allocated_$name$(::std::string* $name$) {\n" " if (!has_$name$()) {\n" " $oneof_prefix$$name$_.UnsafeSetDefault($default_variable$);\n" " }\n" @@ -670,7 +680,10 @@ GeneratePrivateMembers(io::Printer* printer) const { void RepeatedStringFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { // See comment above about unknown ctypes. - if (descriptor_->options().ctype() != FieldOptions::STRING) { + bool unknown_ctype = + descriptor_->options().ctype() != EffectiveStringCType(descriptor_); + + if (unknown_ctype) { printer->Outdent(); printer->Print( " private:\n" @@ -679,26 +692,26 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } printer->Print(variables_, - "inline const ::std::string& $name$(int index) const$deprecation$;\n" - "inline ::std::string* mutable_$name$(int index)$deprecation$;\n" - "inline void set_$name$(int index, const ::std::string& value)$deprecation$;\n" - "inline void set_$name$(int index, const char* value)$deprecation$;\n" - "inline " + "const ::std::string& $name$(int index) const$deprecation$;\n" + "::std::string* mutable_$name$(int index)$deprecation$;\n" + "void set_$name$(int index, const ::std::string& value)$deprecation$;\n" + "void set_$name$(int index, const char* value)$deprecation$;\n" + "" "void set_$name$(int index, const $pointer_type$* value, size_t size)" "$deprecation$;\n" - "inline ::std::string* add_$name$()$deprecation$;\n" - "inline void add_$name$(const ::std::string& value)$deprecation$;\n" - "inline void add_$name$(const char* value)$deprecation$;\n" - "inline void add_$name$(const $pointer_type$* value, size_t size)" + "::std::string* add_$name$()$deprecation$;\n" + "void add_$name$(const ::std::string& value)$deprecation$;\n" + "void add_$name$(const char* value)$deprecation$;\n" + "void add_$name$(const $pointer_type$* value, size_t size)" "$deprecation$;\n"); printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const" + "const ::google::protobuf::RepeatedPtrField< ::std::string>& $name$() const" "$deprecation$;\n" - "inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" + "::google::protobuf::RepeatedPtrField< ::std::string>* mutable_$name$()" "$deprecation$;\n"); - if (descriptor_->options().ctype() != FieldOptions::STRING) { + if (unknown_ctype) { printer->Outdent(); printer->Print(" public:\n"); printer->Indent(); @@ -706,54 +719,57 @@ GenerateAccessorDeclarations(io::Printer* printer) const { } void RepeatedStringFieldGenerator:: -GenerateInlineAccessorDefinitions(io::Printer* printer) const { - printer->Print(variables_, - "inline const ::std::string& $classname$::$name$(int index) const {\n" +GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const { + map variables(variables_); + variables["inline"] = is_inline ? "inline" : ""; + printer->Print(variables, + "$inline$ const ::std::string& $classname$::$name$(int index) const {\n" " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.$cppget$(index);\n" "}\n" - "inline ::std::string* $classname$::mutable_$name$(int index) {\n" + "$inline$ ::std::string* $classname$::mutable_$name$(int index) {\n" " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" - "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n" + "$inline$ void $classname$::set_$name$(int index, const ::std::string& value) {\n" " // @@protoc_insertion_point(field_set:$full_name$)\n" " $name$_.Mutable(index)->assign(value);\n" "}\n" - "inline void $classname$::set_$name$(int index, const char* value) {\n" + "$inline$ void $classname$::set_$name$(int index, const char* value) {\n" " $name$_.Mutable(index)->assign(value);\n" " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" - "inline void " + "$inline$ void " "$classname$::set_$name$" "(int index, const $pointer_type$* value, size_t size) {\n" " $name$_.Mutable(index)->assign(\n" " reinterpret_cast(value), size);\n" " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" - "inline ::std::string* $classname$::add_$name$() {\n" + "$inline$ ::std::string* $classname$::add_$name$() {\n" " return $name$_.Add();\n" "}\n" - "inline void $classname$::add_$name$(const ::std::string& value) {\n" + "$inline$ void $classname$::add_$name$(const ::std::string& value) {\n" " $name$_.Add()->assign(value);\n" " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n" - "inline void $classname$::add_$name$(const char* value) {\n" + "$inline$ void $classname$::add_$name$(const char* value) {\n" " $name$_.Add()->assign(value);\n" " // @@protoc_insertion_point(field_add_char:$full_name$)\n" "}\n" - "inline void " + "$inline$ void " "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" " $name$_.Add()->assign(reinterpret_cast(value), size);\n" " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" "}\n"); - printer->Print(variables_, - "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" + printer->Print(variables, + "$inline$ const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" "$classname$::$name$() const {\n" " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n" + "$inline$ ::google::protobuf::RepeatedPtrField< ::std::string>*\n" "$classname$::mutable_$name$() {\n" " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 0a5ca440..d1f19cd9 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -54,7 +54,8 @@ class StringFieldGenerator : public FieldGenerator { void GeneratePrivateMembers(io::Printer* printer) const; void GenerateStaticMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; @@ -83,7 +84,8 @@ class StringOneofFieldGenerator : public StringFieldGenerator { ~StringOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; void GenerateConstructorCode(io::Printer* printer) const; @@ -103,7 +105,8 @@ class RepeatedStringFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; - void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateInlineAccessorDefinitions(io::Printer* printer, + bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; void GenerateMergingCode(io::Printer* printer) const; void GenerateSwappingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index e8d6f3a2..1cf360c1 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -83,6 +83,7 @@ class ImmutableFieldGenerator { virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) const = 0; + virtual void GenerateStaticInitializationCode(io::Printer* printer) const {} virtual void GenerateEqualsCode(io::Printer* printer) const = 0; virtual void GenerateHashCode(io::Printer* printer) const = 0; diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index 23685385..e24894b1 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -690,8 +690,8 @@ const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { for (int i = 0; i < descriptor->field_count(); i++) { fields[i] = descriptor->field(i); } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); + std::sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); return fields; } diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index d957fdc4..62efbefa 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -297,6 +297,16 @@ struct ExtensionRangeOrdering { // and return it. The caller should delete the returned array. const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor); +// Does this message class have any packed fields? +inline bool HasPackedFields(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); i++) { + if (descriptor->field(i)->is_packed()) { + return true; + } + } + return false; +} + // Check a message type and its sub-message types recursively to see if any of // them has a required field. Return true if a required field is found. bool HasRequiredFields(const Descriptor* descriptor); diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc index 21cab7db..6e29a40b 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc @@ -243,9 +243,8 @@ GenerateBuildingCode(io::Printer* printer) const { "}\n"); printer->Print(variables_, - "result.$name$_.setByteString(\n" - " $name$_.toByteString(),\n" - " $name$_.getExtensionRegistry());\n"); + "result.$name$_.set(\n" + " $name$_);\n"); } void ImmutableLazyMessageFieldGenerator:: @@ -425,9 +424,8 @@ GenerateBuildingCode(io::Printer* printer) const { printer->Print(variables_, "result.$oneof_name$_ = new $lazy_type$();\n" - "(($lazy_type$) result.$oneof_name$_).setByteString(\n" - " (($lazy_type$) $oneof_name$_).toByteString(),\n" - " (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n"); + "(($lazy_type$) result.$oneof_name$_).set(\n" + " (($lazy_type$) $oneof_name$_));\n"); printer->Outdent(); printer->Print("}\n"); } diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index 2986f51f..cf1ef589 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -197,26 +197,39 @@ GenerateInterfaceMembers(io::Printer* printer) const { } } +void ImmutableMapFieldGenerator:: +GenerateStaticInitializationCode(io::Printer* printer) const { + printer->Print( + variables_, + "$name$DefaultEntry =\n" + " com.google.protobuf.MapEntry$lite$\n" + " .<$type_parameters$>newDefaultInstance(\n" + " $descriptor$\n" + " $key_wire_type$,\n" + " $key_default_value$,\n" + " $value_wire_type$,\n" + " $value_default_value$);\n" + "\n"); +} + void ImmutableMapFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print( variables_, "private static final com.google.protobuf.MapEntry$lite$<\n" - " $type_parameters$> $name$DefaultEntry =\n" - " com.google.protobuf.MapEntry$lite$\n" - " .<$type_parameters$>newDefaultInstance(\n" - " $descriptor$\n" - " $key_wire_type$,\n" - " $key_default_value$,\n" - " $value_wire_type$,\n" - " $value_default_value$);\n"); + " $type_parameters$> $name$DefaultEntry;\n"); printer->Print( variables_, "private com.google.protobuf.MapField$lite$<\n" - " $type_parameters$> $name$_ =\n" - " com.google.protobuf.MapField$lite$.emptyMapField(\n" - " $map_field_parameter$);\n" - "\n"); + " $type_parameters$> $name$_;\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField$lite$.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { printer->Print( variables_, @@ -233,7 +246,7 @@ GenerateMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "get$capitalized_name$Value() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); } WriteFieldDocComment(printer, descriptor_); @@ -244,7 +257,8 @@ GenerateMembers(io::Printer* printer) const { "get$capitalized_name$() {\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMap(), $name$ValueConverter);\n" + " internalGet$capitalized_name$().getMap(),\n" + " $name$ValueConverter);\n" "}\n"); } else { WriteFieldDocComment(printer, descriptor_); @@ -252,7 +266,7 @@ GenerateMembers(io::Printer* printer) const { variables_, "$deprecation$\n" "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); } } @@ -262,10 +276,24 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print( variables_, "private com.google.protobuf.MapField$lite$<\n" - " $type_parameters$> $name$_ =\n" - " com.google.protobuf.MapField$lite$.newMapField(\n" - " $map_field_parameter$);\n" - "\n"); + " $type_parameters$> $name$_;\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " if ($name$_ == null) {\n" + " return com.google.protobuf.MapField$lite$.emptyMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGetMutable$capitalized_name$() {\n" + " $on_changed$;\n" + " if ($name$_ == null) {\n" + " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n" + " $map_field_parameter$);\n" + " }\n" + " return $name$_;\n" + "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -275,7 +303,8 @@ GenerateBuilderMembers(io::Printer* printer) const { "get$capitalized_name$() {\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMap(), $name$ValueConverter);\n" + " internalGet$capitalized_name$().getMap(),\n" + " $name$ValueConverter);\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -283,10 +312,10 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" "getMutable$capitalized_name$() {\n" - " $on_changed$\n" " return new com.google.protobuf.Internal.MapAdapter<\n" " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" - " $name$_.getMutableMap(), $name$ValueConverter);\n" + " internalGetMutable$capitalized_name$().getMutableMap(),\n" + " $name$ValueConverter);\n" "}\n"); if (SupportUnknownEnumValue(descriptor_->file())) { WriteFieldDocComment(printer, descriptor_); @@ -295,7 +324,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "get$capitalized_name$Value() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( @@ -303,8 +332,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$\n" "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" "getMutable$capitalized_name$Value() {\n" - " $on_changed$\n" - " return $name$_.getMutableMap();\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" "}\n"); } } else { @@ -312,15 +340,14 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print( variables_, "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n" - " return $name$_.getMap();\n" + " return internalGet$capitalized_name$().getMap();\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print( variables_, "public java.util.Map<$type_parameters$>\n" "getMutable$capitalized_name$() {\n" - " $on_changed$\n" - " return $name$_.getMutableMap();\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" "}\n"); } } @@ -339,14 +366,15 @@ void ImmutableMapFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print( variables_, - "$name$_.clear();\n"); + "internalGetMutable$capitalized_name$().clear();\n"); } void ImmutableMapFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print( variables_, - "$name$_.mergeFrom(other.$name$_);\n"); + "internalGetMutable$capitalized_name$().mergeFrom(\n" + " other.internalGet$capitalized_name$());\n"); } void ImmutableMapFieldGenerator:: @@ -356,7 +384,7 @@ GenerateBuildingCode(io::Printer* printer) const { // We do a copy of the map field to ensure that the built result is // immutable. Implementation of this copy() method can do copy-on-write // to defer this copy until further modifications are made on the field. - "result.$name$_ = $name$_.copy();\n"); + "result.$name$_ = internalGet$capitalized_name$().copy();\n"); } void ImmutableMapFieldGenerator:: @@ -402,7 +430,7 @@ GenerateSerializationCode(io::Printer* printer) const { printer->Print( variables_, "for (java.util.Map.Entry<$type_parameters$> entry\n" - " : $name$_.getMap().entrySet()) {\n" + " : internalGet$capitalized_name$().getMap().entrySet()) {\n" " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" " $name$ = $name$DefaultEntry.newBuilderForType()\n" " .setKey(entry.getKey())\n" @@ -417,7 +445,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print( variables_, "for (java.util.Map.Entry<$type_parameters$> entry\n" - " : $name$_.getMap().entrySet()) {\n" + " : internalGet$capitalized_name$().getMap().entrySet()) {\n" " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" " $name$ = $name$DefaultEntry.newBuilderForType()\n" " .setKey(entry.getKey())\n" @@ -432,16 +460,17 @@ void ImmutableMapFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print( variables_, - "result = result && $name$_.equals(other.$name$_);\n"); + "result = result && internalGet$capitalized_name$().equals(\n" + " other.internalGet$capitalized_name$());\n"); } void ImmutableMapFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print( variables_, - "if (!$name$_.getMap().isEmpty()) {\n" + "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n" " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + $name$_.hashCode();\n" + " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n" "}\n"); } diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h index 80a94f45..3e6dd973 100644 --- a/src/google/protobuf/compiler/java/java_map_field.h +++ b/src/google/protobuf/compiler/java/java_map_field.h @@ -60,6 +60,7 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateStaticInitializationCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 1171b718..e982a17b 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -234,7 +234,8 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { "public interface $classname$OrBuilder extends \n" " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessageLite.\n" - " ExtendableMessageOrBuilder<$classname$> {\n", + " ExtendableMessageOrBuilder<\n" + " $classname$, $classname$.Builder> {\n", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } @@ -285,22 +286,41 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // The builder_type stores the super type name of the nested Builder class. string builder_type; if (descriptor_->extension_range_count() > 0) { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage$lite$.ExtendableMessage<\n" - " $classname$> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } else { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", - name_resolver_->GetImmutableClassName(descriptor_), - variables["lite"]); + "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_), + variables["lite"]); } else { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage$lite$ implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } else { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + } + builder_type = strings::Substitute( "com.google.protobuf.GeneratedMessage$0.Builder", variables["lite"]); @@ -349,7 +369,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { GenerateParsingConstructor(printer); } - GenerateDescriptorMethods(printer); + GenerateDescriptorMethods(printer, false); GenerateParser(printer); // Nested types @@ -481,7 +501,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // Carefully initialize the default instance in such a way that it doesn't // conflict with other initialization. printer->Print( - "private static final $classname$ defaultInstance;", + "private static final $classname$ defaultInstance;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( @@ -494,15 +514,11 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // LITE_RUNTIME only has one constructor. printer->Print( "static {\n" - " try {\n" - " defaultInstance = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw new ExceptionInInitializerError(e);\n" - " }\n" + " defaultInstance = new $classname$(\n" + " com.google.protobuf.Internal\n" + " .EMPTY_CODED_INPUT_STREAM,\n" + " com.google.protobuf.ExtensionRegistryLite\n" + " .getEmptyRegistry());\n" "}\n" "\n", "classname", descriptor_->name()); @@ -511,12 +527,30 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { "public static $classname$ getDefaultInstance() {\n" " return defaultInstance;\n" "}\n" - "\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( "public $classname$ getDefaultInstanceForType() {\n" " return defaultInstance;\n" "}\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + // LITE_RUNTIME uses this to implement the *ForType methods at the + // GeneratedMessageLite level. + printer->Print( + "static {" + " com.google.protobuf.GeneratedMessageLite.onLoad(\n" + " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n" + " .PrototypeHolder<$classname$, Builder>(\n" + " defaultInstance, PARSER));" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } // Extensions must be declared after the defaultInstance is initialized // because the defaultInstance is used by the extension to lazily retrieve @@ -526,6 +560,19 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { .Generate(printer); } + // Some fields also have static members that must be initialized after we + // have the default instance available. + printer->Print( + "static {\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateStaticInitializationCode(printer); + } + printer->Outdent(); + printer->Print( + "}\n"); + printer->Outdent(); printer->Print("}\n\n"); } @@ -542,37 +589,55 @@ GenerateMessageSerializationMethods(io::Printer* printer) { 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()); + std::sort(sorted_extensions.begin(), sorted_extensions.end(), + ExtensionRangeOrdering()); printer->Print( "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" " throws java.io.IOException {\n"); printer->Indent(); - // writeTo(CodedOutputStream output) might be invoked without - // getSerializedSize() ever being called, but we need the memoized - // sizes in case this message has packed fields. Rather than emit checks for - // each packed field, just call getSerializedSize() up front for all messages. - // In most cases, getSerializedSize() will have already been called anyway by - // one of the wrapper writeTo() methods, making this call cheap. - printer->Print( - "getSerializedSize();\n"); + if (HasPackedFields(descriptor_)) { + // writeTo(CodedOutputStream output) might be invoked without + // getSerializedSize() ever being called, but we need the memoized + // sizes in case this message has packed fields. Rather than emit checks for + // each packed field, just call getSerializedSize() up front. + // In most cases, getSerializedSize() will have already been called anyway + // by one of the wrapper writeTo() methods, making this call cheap. + printer->Print( + "getSerializedSize();\n"); + } if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { - printer->Print( - "com.google.protobuf.GeneratedMessage$lite$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" - " newMessageSetExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "com.google.protobuf.GeneratedMessage\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } } else { - printer->Print( - "com.google.protobuf.GeneratedMessage$lite$\n" - " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" - " newExtensionWriter();\n", - "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "com.google.protobuf.GeneratedMessage\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } } } @@ -727,13 +792,23 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( // =================================================================== void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( + "public Builder newBuilderForType() { return newBuilder(); }\n"); + } + printer->Print( - "public static Builder newBuilder() { return new Builder(); }\n" - "public Builder newBuilderForType() { return newBuilder(); }\n" + "public static Builder newBuilder() {\n" + " return defaultInstance.toBuilder();\n" + "}\n" "public static Builder newBuilder($classname$ prototype) {\n" - " return newBuilder().mergeFrom(prototype);\n" + " return defaultInstance.toBuilder().mergeFrom(prototype);\n" + "}\n" + "public Builder toBuilder() {\n" + " return this == defaultInstance\n" + " ? new Builder() : new Builder().mergeFrom(this);\n" "}\n" - "public Builder toBuilder() { return newBuilder(this); }\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -792,7 +867,7 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { } printer->Indent(); - GenerateDescriptorMethods(printer); + GenerateDescriptorMethods(printer, true); GenerateCommonBuilderMethods(printer); if (HasGeneratedMethods(descriptor_)) { @@ -876,7 +951,7 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { } void ImmutableMessageGenerator:: -GenerateDescriptorMethods(io::Printer* printer) { +GenerateDescriptorMethods(io::Printer* printer, bool is_builder) { if (HasDescriptorMethods(descriptor_)) { if (!descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( @@ -909,9 +984,9 @@ GenerateDescriptorMethods(io::Printer* printer) { const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); printer->Print( "case $number$:\n" - " return $name$_;\n", + " return internalGet$capitalized_name$();\n", "number", SimpleItoa(field->number()), - "name", info->name); + "capitalized_name", info->capitalized_name); } printer->Print( "default:\n" @@ -922,6 +997,34 @@ GenerateDescriptorMethods(io::Printer* printer) { printer->Print( " }\n" "}\n"); + if (is_builder) { + printer->Print( + "@SuppressWarnings({\"rawtypes\"})\n" + "protected com.google.protobuf.MapField internalGetMutableMapField(\n" + " int number) {\n" + " switch (number) {\n"); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < map_fields.size(); ++i) { + const FieldDescriptor* field = map_fields[i]; + const FieldGeneratorInfo* info = + context_->GetFieldGeneratorInfo(field); + printer->Print( + "case $number$:\n" + " return internalGetMutable$capitalized_name$();\n", + "number", SimpleItoa(field->number()), + "capitalized_name", info->capitalized_name); + } + printer->Print( + "default:\n" + " throw new RuntimeException(\n" + " \"Invalid map field number: \" + number);\n"); + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" + "}\n"); + } } printer->Print( "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" @@ -959,7 +1062,7 @@ GenerateCommonBuilderMethods(io::Printer* printer) { "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { // LITE runtime passes along the default instance to implement - // getDefaultInstanceForType() at the GneratedMessageLite level. + // getDefaultInstanceForType() at the GeneratedMessageLite level. printer->Print( "// Construct using $classname$.newBuilder()\n" "private Builder() {\n" @@ -1062,22 +1165,17 @@ GenerateCommonBuilderMethods(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public $classname$ buildPartial() {\n" - " $classname$ result = new $classname$(this);\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + " $classname$ result = new $classname$(this);\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { // LITE_RUNTIME only provides a single message constructor. printer->Print( "public $classname$ buildPartial() {\n" - " $classname$ result = null;\n" - " try {\n" - " result = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw new RuntimeException(e);\n" - " }\n" + " $classname$ result = new $classname$(\n" + " com.google.protobuf.Internal\n" + " .EMPTY_CODED_INPUT_STREAM,\n" + " com.google.protobuf.ExtensionRegistryLite\n" + " .getEmptyRegistry());\n" " result.unknownFields = this.unknownFields;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); @@ -1271,6 +1369,12 @@ GenerateBuilderParsingMethods(io::Printer* printer) { void ImmutableMessageGenerator::GenerateIsInitialized( io::Printer* printer, UseMemoization useMemoization) { + // LITE_RUNTIME avoids generating isInitialized if it's not needed. + if (!HasDescriptorMethods(descriptor_) + && !HasRequiredFields(descriptor_)) { + return; + } + bool memoization = useMemoization == MEMOIZE; if (memoization) { // Memoizes whether the protocol buffer is fully initialized (has all @@ -1558,8 +1662,7 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Print( "private $classname$(\n" " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws com.google.protobuf.InvalidProtocolBufferException {\n", + " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", "classname", descriptor_->name()); printer->Indent(); @@ -1695,10 +1798,11 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Outdent(); printer->Print( "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " throw e.setUnfinishedMessage(this);\n" + " throw new RuntimeException(e.setUnfinishedMessage(this));\n" "} catch (java.io.IOException e) {\n" - " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " e.getMessage()).setUnfinishedMessage(this);\n" + " throw new RuntimeException(\n" + " new com.google.protobuf.InvalidProtocolBufferException(\n" + " e.getMessage()).setUnfinishedMessage(this));\n" "} finally {\n"); printer->Indent(); @@ -1747,8 +1851,19 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { " throws com.google.protobuf.InvalidProtocolBufferException {\n", "classname", descriptor_->name()); if (HasGeneratedMethods(descriptor_)) { + // The parsing constructor throws an InvalidProtocolBufferException via a + // RuntimeException to aid in method pruning. We unwrap it here. printer->Print( - " return new $classname$(input, extensionRegistry);\n", + " try {\n" + " return new $classname$(input, extensionRegistry);\n" + " } catch (RuntimeException e) {\n" + " if (e.getCause() instanceof\n" + " com.google.protobuf.InvalidProtocolBufferException) {\n" + " throw (com.google.protobuf.InvalidProtocolBufferException)\n" + " e.getCause();\n" + " }\n" + " throw e;\n" + " }\n", "classname", descriptor_->name()); } else { // When parsing constructor isn't generated, use builder to parse messages. @@ -1775,13 +1890,16 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { "};\n" "\n"); - printer->Print( - "@java.lang.Override\n" - "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" - " return PARSER;\n" - "}\n" - "\n", - "classname", descriptor_->name()); + if (HasDescriptorMethods(descriptor_)) { + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( + "@java.lang.Override\n" + "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" + " return PARSER;\n" + "}\n" + "\n", + "classname", descriptor_->name()); + } } // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index 91eb2876..016fdd5d 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -117,7 +117,7 @@ class ImmutableMessageGenerator : public MessageGenerator { void GenerateBuilder(io::Printer* printer); void GenerateCommonBuilderMethods(io::Printer* printer); - void GenerateDescriptorMethods(io::Printer* printer); + void GenerateDescriptorMethods(io::Printer* printer, bool is_builder); void GenerateBuilderParsingMethods(io::Printer* printer); void GenerateIsInitialized(io::Printer* printer, UseMemoization useMemoization); diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index e331d7a4..48757c60 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -772,6 +772,9 @@ GenerateParsingDoneCode(io::Printer* printer) const { void RepeatedImmutablePrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { + // We invoke getSerializedSize in writeTo for messages that have packed + // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods. + // That makes it safe to rely on the memoized size here. printer->Print(variables_, "if (get$capitalized_name$List().size() > 0) {\n" " output.writeRawVarint32($tag$);\n" diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc index 2e61ea8a..70177367 100644 --- a/src/google/protobuf/compiler/java/java_shared_code_generator.cc +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc @@ -171,7 +171,7 @@ void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { string classname = FileJavaPackage(file_->dependency(i)) + "." + name_resolver_->GetDescriptorClassName( file_->dependency(i)); - dependencies.push_back(make_pair(filename, classname)); + dependencies.push_back(std::make_pair(filename, classname)); } } diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 1c9302af..8aa5699c 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -667,7 +667,7 @@ GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "String s = input.readStringRequireUtf8();\n" "$set_oneof_case_message$;\n" - "$oneof_name$_ = s;\n}\n"); + "$oneof_name$_ = s;\n"); } else if (!HasDescriptorMethods(descriptor_->file())) { // Lite runtime should attempt to reduce allocations by attempting to // construct the string directly from the input stream buffer. This avoids diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index e7d5117e..98261431 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -133,10 +133,10 @@ bool MockCodeGenerator::Generate( *error = "Saw message type MockCodeGenerator_Error."; return false; } else if (command == "Exit") { - cerr << "Saw message type MockCodeGenerator_Exit." << endl; + std::cerr << "Saw message type MockCodeGenerator_Exit." << std::endl; exit(123); } else if (command == "Abort") { - cerr << "Saw message type MockCodeGenerator_Abort." << endl; + std::cerr << "Saw message type MockCodeGenerator_Abort." << std::endl; abort(); } else if (command == "HasSourceCodeInfo") { FileDescriptorProto file_descriptor_proto; @@ -144,8 +144,8 @@ bool MockCodeGenerator::Generate( bool has_source_code_info = file_descriptor_proto.has_source_code_info() && file_descriptor_proto.source_code_info().location_size() > 0; - cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: " - << has_source_code_info << "." << endl; + std::cerr << "Saw message type MockCodeGenerator_HasSourceCodeInfo: " + << has_source_code_info << "." << std::endl; abort(); } else { GOOGLE_LOG(FATAL) << "Unknown MockCodeGenerator command: " << command; diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index fe697acf..c50cdf54 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -277,27 +277,39 @@ bool Parser::ConsumeString(string* output, const char* error) { } } -bool Parser::TryConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location) { +bool Parser::TryConsumeEndOfDeclaration( + const char* text, const LocationRecorder* location) { if (LookingAt(text)) { string leading, trailing; - input_->NextWithComments(&trailing, NULL, &leading); + vector detached; + input_->NextWithComments(&trailing, &detached, &leading); // Save the leading comments for next time, and recall the leading comments // from last time. leading.swap(upcoming_doc_comments_); if (location != NULL) { - location->AttachComments(&leading, &trailing); + upcoming_detached_comments_.swap(detached); + location->AttachComments(&leading, &trailing, &detached); + } else if (strcmp(text, "}") == 0) { + // If the current location is null and we are finishing the current scope, + // drop pending upcoming detached comments. + upcoming_detached_comments_.swap(detached); + } else { + // Otherwise, append the new detached comments to the existing upcoming + // detached comments. + upcoming_detached_comments_.insert(upcoming_detached_comments_.end(), + detached.begin(), detached.end()); } + return true; } else { return false; } } -bool Parser::ConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location) { +bool Parser::ConsumeEndOfDeclaration( + const char* text, const LocationRecorder* location) { if (TryConsumeEndOfDeclaration(text, location)) { return true; } else { @@ -390,7 +402,8 @@ void Parser::LocationRecorder::RecordLegacyLocation(const Message* descriptor, } void Parser::LocationRecorder::AttachComments( - string* leading, string* trailing) const { + string* leading, string* trailing, + vector* detached_comments) const { GOOGLE_CHECK(!location_->has_leading_comments()); GOOGLE_CHECK(!location_->has_trailing_comments()); @@ -400,6 +413,11 @@ void Parser::LocationRecorder::AttachComments( if (!trailing->empty()) { location_->mutable_trailing_comments()->swap(*trailing); } + for (int i = 0; i < detached_comments->size(); ++i) { + location_->add_leading_detached_comments()->swap( + (*detached_comments)[i]); + } + detached_comments->clear(); } // ------------------------------------------------------------------- @@ -451,16 +469,18 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { SourceCodeInfo source_code_info; source_code_info_ = &source_code_info; + vector top_doc_comments; if (LookingAtType(io::Tokenizer::TYPE_START)) { // Advance to first token. - input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); + input_->NextWithComments(NULL, &upcoming_detached_comments_, + &upcoming_doc_comments_); } { LocationRecorder root_location(this); if (require_syntax_identifier_ || LookingAt("syntax")) { - if (!ParseSyntaxIdentifier()) { + if (!ParseSyntaxIdentifier(root_location)) { // Don't attempt to parse the file if we didn't recognize the syntax // identifier. return false; @@ -469,9 +489,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { if (file != NULL) file->set_syntax(syntax_identifier_); } else if (!stop_after_syntax_identifier_) { GOOGLE_LOG(WARNING) << "No syntax specified for the proto file. " - << "Please use 'syntax = \"proto2\";' or " - << "'syntax = \"proto3\";' to specify a syntax " - << "version. (Defaulted to proto2 syntax.)"; + << "Please use 'syntax = \"proto2\";' or " + << "'syntax = \"proto3\";' to specify a syntax " + << "version. (Defaulted to proto2 syntax.)"; syntax_identifier_ = "proto2"; } @@ -486,7 +506,8 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { if (LookingAt("}")) { AddError("Unmatched \"}\"."); - input_->NextWithComments(NULL, NULL, &upcoming_doc_comments_); + input_->NextWithComments(NULL, &upcoming_detached_comments_, + &upcoming_doc_comments_); } } } @@ -498,7 +519,9 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { return !had_errors_; } -bool Parser::ParseSyntaxIdentifier() { +bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) { + LocationRecorder syntax_location(parent, + FileDescriptorProto::kSyntaxFieldNumber); DO(Consume( "syntax", "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'.")); @@ -506,7 +529,7 @@ bool Parser::ParseSyntaxIdentifier() { io::Tokenizer::Token syntax_token = input_->current(); string syntax; DO(ConsumeString(&syntax, "Expected syntax identifier.")); - DO(ConsumeEndOfDeclaration(";", NULL)); + DO(ConsumeEndOfDeclaration(";", &syntax_location)); syntax_identifier_ = syntax; @@ -1271,7 +1294,6 @@ bool Parser::ParseOption(Message* options, DO(ConsumeEndOfDeclaration(";", &location)); } - return true; } @@ -1636,8 +1658,14 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, // Parse input type. DO(Consume("(")); { - if (TryConsume("stream")) { + if (LookingAt("stream")) { + LocationRecorder location( + method_location, MethodDescriptorProto::kClientStreamingFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::OTHER); method->set_client_streaming(true); + DO(Consume("stream")); + } LocationRecorder location(method_location, MethodDescriptorProto::kInputTypeFieldNumber); @@ -1651,8 +1679,14 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, DO(Consume("returns")); DO(Consume("(")); { - if (TryConsume("stream")) { + if (LookingAt("stream")) { + LocationRecorder location( + method_location, MethodDescriptorProto::kServerStreamingFieldNumber); + location.RecordLegacyLocation( + method, DescriptorPool::ErrorCollector::OTHER); + DO(Consume("stream")); method->set_server_streaming(true); + } LocationRecorder location(method_location, MethodDescriptorProto::kOutputTypeFieldNumber); @@ -1664,10 +1698,9 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, if (LookingAt("{")) { // Options! - DO(ParseOptions(method_location, - containing_file, - MethodDescriptorProto::kOptionsFieldNumber, - method->mutable_options())); + DO(ParseMethodOptions(method_location, containing_file, + MethodDescriptorProto::kOptionsFieldNumber, + method->mutable_options())); } else { DO(ConsumeEndOfDeclaration(";", &method_location)); } @@ -1676,10 +1709,10 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, } -bool Parser::ParseOptions(const LocationRecorder& parent_location, - const FileDescriptorProto* containing_file, - const int optionsFieldNumber, - Message* mutable_options) { +bool Parser::ParseMethodOptions(const LocationRecorder& parent_location, + const FileDescriptorProto* containing_file, + const int optionsFieldNumber, + Message* mutable_options) { // Options! ConsumeEndOfDeclaration("{", &parent_location); while (!TryConsumeEndOfDeclaration("}", NULL)) { @@ -1693,8 +1726,8 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location, } else { LocationRecorder location(parent_location, optionsFieldNumber); - if (!ParseOption(mutable_options, location, containing_file, - OPTION_STATEMENT)) { + if (!ParseOption(mutable_options, location, + containing_file, OPTION_STATEMENT)) { // This statement failed to parse. Skip it, but keep looping to // parse other statements. SkipStatement(); @@ -1847,7 +1880,7 @@ bool SourceLocationTable::Find( DescriptorPool::ErrorCollector::ErrorLocation location, int* line, int* column) const { const pair* result = - FindOrNull(location_map_, make_pair(descriptor, location)); + FindOrNull(location_map_, std::make_pair(descriptor, location)); if (result == NULL) { *line = -1; *column = 0; @@ -1863,7 +1896,8 @@ void SourceLocationTable::Add( const Message* descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, int line, int column) { - location_map_[make_pair(descriptor, location)] = make_pair(line, column); + location_map_[std::make_pair(descriptor, location)] = + std::make_pair(line, column); } void SourceLocationTable::Clear() { diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index a15cc705..7cb1678a 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -185,10 +185,13 @@ class LIBPROTOBUF_EXPORT Parser { // have been passed around by const reference, for no particularly good // reason. We should probably go through and change them all to mutable // pointer to make this more intuitive. - bool TryConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location); - bool ConsumeEndOfDeclaration(const char* text, - const LocationRecorder* location); + bool TryConsumeEndOfDeclaration( + const char* text, const LocationRecorder* location); + bool TryConsumeEndOfDeclarationFinishScope( + const char* text, const LocationRecorder* location); + + bool ConsumeEndOfDeclaration( + const char* text, const LocationRecorder* location); // ----------------------------------------------------------------- // Error logging helpers @@ -253,9 +256,13 @@ class LIBPROTOBUF_EXPORT Parser { // // TODO(kenton): See comment on TryConsumeEndOfDeclaration(), above, for // why this is const. - void AttachComments(string* leading, string* trailing) const; + void AttachComments(string* leading, string* trailing, + vector* detached_comments) const; private: + // Indexes of parent and current location in the parent + // SourceCodeInfo.location repeated field. For top-level elements, + // parent_index_ is -1. Parser* parser_; SourceCodeInfo::Location* location_; @@ -268,7 +275,7 @@ class LIBPROTOBUF_EXPORT Parser { // Parses the "syntax = \"proto2\";" line at the top of the file. Returns // false if it failed to parse or if the syntax identifier was not // recognized. - bool ParseSyntaxIdentifier(); + bool ParseSyntaxIdentifier(const LocationRecorder& parent); // These methods parse various individual bits of code. They return // false if they completely fail to parse the construct. In this case, @@ -302,9 +309,6 @@ class LIBPROTOBUF_EXPORT Parser { RepeatedField* weak_dependency, const LocationRecorder& root_location, const FileDescriptorProto* containing_file); - bool ParseOption(Message* options, - const LocationRecorder& options_location, - const FileDescriptorProto* containing_file); // These methods parse the contents of a message, enum, or service type and // add them to the given object. They consume the entire block including @@ -397,10 +401,10 @@ class LIBPROTOBUF_EXPORT Parser { // Parse options of a single method or stream. - bool ParseOptions(const LocationRecorder& parent_location, - const FileDescriptorProto* containing_file, - const int optionsFieldNumber, - Message* mutable_options); + bool ParseMethodOptions(const LocationRecorder& parent_location, + const FileDescriptorProto* containing_file, + const int optionsFieldNumber, + Message* mutable_options); // Parse "required", "optional", or "repeated" and fill in "label" // with the value. Returns true if shuch a label is consumed. @@ -497,6 +501,13 @@ class LIBPROTOBUF_EXPORT Parser { // yet; use ConsumeEndOfDeclaration() to get the complete comments. string upcoming_doc_comments_; + // Detached comments are not connected to any syntax entities. Elements in + // this vector are paragraphs of comments separated by empty lines. The + // detached comments will be put into the leading_detached_comments field for + // the next element (See SourceCodeInfo.Location in descriptor.proto), when + // ConsumeEndOfDeclaration() is called. + vector upcoming_detached_comments_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser); }; diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index fe0719f8..1684bebe 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -1571,7 +1571,7 @@ void SortMessages(DescriptorProto *descriptor_proto) { } DescriptorProto **data = descriptor_proto->mutable_nested_type()->mutable_data(); - sort(data, data + size, CompareDescriptorNames()); + std::sort(data, data + size, CompareDescriptorNames()); } // Sorts DescriptorProtos belonging to a FileDescriptorProto, by name. @@ -1583,7 +1583,7 @@ void SortMessages(FileDescriptorProto *file_descriptor_proto) { } DescriptorProto **data = file_descriptor_proto->mutable_message_type()->mutable_data(); - sort(data, data + size, CompareDescriptorNames()); + std::sort(data, data + size, CompareDescriptorNames()); } // Strips the message and enum field type names for comparison purpose only. @@ -1703,25 +1703,52 @@ TEST_F(ParseDescriptorDebugTest, TestCustomOptions) { // places. TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) { SetupParser( + "// Detached comment before syntax.\n" + "\n" + "// Syntax comment.\n" + "syntax = \"proto2\";\n" + "\n" + "// Detached comment before package.\n" + "\n" + "// Package comment.\n" + "package comment_test;\n" + "\n" + "// Detached comment before TestMessage1.\n" + "\n" "// Message comment.\n" "message TestMessage1 {\n" + "\n" + " // Detached comment before foo.\n" + "\n" " // Field comment.\n" " optional int32 foo = 1;\n" "\n" + " // Detached comment before NestedMessage.\n" + "\n" " // Nested-message comment.\n" " message NestedMessage {\n" " optional int32 bar = 1;\n" " }\n" "}\n" "\n" + "// Detached comment before MyEnumType.\n" + "\n" "// Enum comment.\n" "enum MyEnumType {\n" + "\n" + " // Detached comment before ASDF.\n" + "\n" " // Enum-value comment.\n" " ASDF = 1;\n" "}\n" "\n" + "// Detached comment before MyService.\n" + "\n" "// Service comment.\n" "service MyService {\n" + "\n" + " // Detached comment before MyRPCCall.\n" + "\n" " // RPC comment.\n" " rpc MyRPCCall(TestMessage1) returns (TestMessage1) { }\n" "}\n"); @@ -1745,22 +1772,34 @@ TEST_F(ParseDescriptorDebugTest, TestCommentsInDebugString) { const string debug_string = descriptor->DebugStringWithOptions(debug_string_options); - // Ensure that each of the comments appears somewhere in the DebugString(), - // and that these comments appear in order. We don't test the exact comment - // placement or formatting, because we do not want to be too fragile here. + // Ensure that each of the comments appears somewhere in the DebugString(). + // We don't test the exact comment placement or formatting, because we do not + // want to be too fragile here. const char* expected_comments[] = { + "Detached comment before syntax.", + "Syntax comment.", + "Detached comment before package.", + "Package comment.", + "Detached comment before TestMessage1.", "Message comment.", + "Detached comment before foo.", "Field comment", + "Detached comment before NestedMessage.", "Nested-message comment", + "Detached comment before MyEnumType.", "Enum comment", + "Detached comment before ASDF.", "Enum-value comment", + "Detached comment before MyService.", "Service comment", + "Detached comment before MyRPCCall.", "RPC comment", }; for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) { string::size_type found_pos = debug_string.find(expected_comments[i]); - ASSERT_TRUE(found_pos != string::npos); + EXPECT_TRUE(found_pos != string::npos) + << "\"" << expected_comments[i] << "\" not found."; } } @@ -1930,8 +1969,8 @@ class SourceInfoTest : public ParserTest { return false; } - spans_.insert(make_pair(SpanKey(*descriptor_proto, field, index), - &location)); + spans_.insert( + std::make_pair(SpanKey(*descriptor_proto, field, index), &location)); } return true; @@ -1952,16 +1991,18 @@ class SourceInfoTest : public ParserTest { bool HasSpan(char start_marker, char end_marker, const Message& descriptor_proto) { return HasSpanWithComment( - start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL); + start_marker, end_marker, descriptor_proto, NULL, -1, NULL, NULL, NULL); } bool HasSpanWithComment(char start_marker, char end_marker, const Message& descriptor_proto, const char* expected_leading_comments, - const char* expected_trailing_comments) { + const char* expected_trailing_comments, + const char* expected_leading_detached_comments) { return HasSpanWithComment( start_marker, end_marker, descriptor_proto, NULL, -1, - expected_leading_comments, expected_trailing_comments); + expected_leading_comments, expected_trailing_comments, + expected_leading_detached_comments); } bool HasSpan(char start_marker, char end_marker, @@ -1973,14 +2014,15 @@ class SourceInfoTest : public ParserTest { const Message& descriptor_proto, const string& field_name, int index) { return HasSpan(start_marker, end_marker, descriptor_proto, - field_name, index, NULL, NULL); + field_name, index, NULL, NULL, NULL); } bool HasSpan(char start_marker, char end_marker, const Message& descriptor_proto, const string& field_name, int index, const char* expected_leading_comments, - const char* expected_trailing_comments) { + const char* expected_trailing_comments, + const char* expected_leading_detached_comments) { const FieldDescriptor* field = descriptor_proto.GetDescriptor()->FindFieldByName(field_name); if (field == NULL) { @@ -1991,12 +2033,13 @@ class SourceInfoTest : public ParserTest { return HasSpanWithComment( start_marker, end_marker, descriptor_proto, field, index, - expected_leading_comments, expected_trailing_comments); + expected_leading_comments, expected_trailing_comments, + expected_leading_detached_comments); } bool HasSpan(const Message& descriptor_proto) { return HasSpanWithComment( - '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL); + '\0', '\0', descriptor_proto, NULL, -1, NULL, NULL, NULL); } bool HasSpan(const Message& descriptor_proto, const string& field_name) { @@ -2008,11 +2051,12 @@ class SourceInfoTest : public ParserTest { return HasSpan('\0', '\0', descriptor_proto, field_name, index); } - bool HasSpanWithComment(char start_marker, char end_marker, - const Message& descriptor_proto, - const FieldDescriptor* field, int index, - const char* expected_leading_comments, - const char* expected_trailing_comments) { + bool HasSpanWithComment( + char start_marker, char end_marker, const Message& descriptor_proto, + const FieldDescriptor* field, int index, + const char* expected_leading_comments, + const char* expected_trailing_comments, + const char* expected_leading_detached_comments) { pair range = spans_.equal_range(SpanKey(descriptor_proto, field, index)); @@ -2051,6 +2095,13 @@ class SourceInfoTest : public ParserTest { EXPECT_EQ(expected_trailing_comments, iter->second->trailing_comments()); } + if (expected_leading_detached_comments == NULL) { + EXPECT_EQ(0, iter->second->leading_detached_comments_size()); + } else { + EXPECT_EQ( + expected_leading_detached_comments, + Join(iter->second->leading_detached_comments(), "\n")); + } spans_.erase(iter); return true; @@ -2101,7 +2152,7 @@ class SourceInfoTest : public ParserTest { text_without_markers_ += '$'; ++column; } else { - markers_[*text] = make_pair(line, column); + markers_[*text] = std::make_pair(line, column); ++text; GOOGLE_CHECK_EQ('$', *text); } @@ -2120,7 +2171,7 @@ class SourceInfoTest : public ParserTest { TEST_F(SourceInfoTest, BasicFileDecls) { EXPECT_TRUE(Parse( - "$a$syntax = \"proto2\";\n" + "$a$syntax = \"proto2\";$i$\n" "package $b$foo.bar$c$;\n" "import $d$\"baz.proto\"$e$;\n" "import $f$\"qux.proto\"$g$;$h$\n" @@ -2131,6 +2182,7 @@ TEST_F(SourceInfoTest, BasicFileDecls) { EXPECT_TRUE(HasSpan('b', 'c', file_, "package")); EXPECT_TRUE(HasSpan('d', 'e', file_, "dependency", 0)); EXPECT_TRUE(HasSpan('f', 'g', file_, "dependency", 1)); + EXPECT_TRUE(HasSpan('a', 'i', file_, "syntax")); } TEST_F(SourceInfoTest, Messages) { @@ -2561,6 +2613,9 @@ TEST_F(SourceInfoTest, ScopedOptions) { " rpc M(X) returns(Y) {\n" " $g$option mopt = 1;$h$\n" " }\n" + " rpc MS4($1$stream$2$ X) returns($3$stream$4$ Y) {\n" + " $k$option mopt = 1;$l$\n" + " }\n" "}\n")); EXPECT_TRUE(HasSpan('a', 'b', file_.message_type(0).options())); @@ -2620,6 +2675,26 @@ TEST_F(SourceInfoTest, ScopedOptions) { .uninterpreted_option(0).name(0), "name_part")); EXPECT_TRUE(HasSpan(file_.service(0).method(0).options() .uninterpreted_option(0), "positive_int_value")); + + EXPECT_TRUE(HasSpan('k', 'l', file_.service(0).method(1).options())); + EXPECT_TRUE(HasSpan(file_.service(0).method(1))); + EXPECT_TRUE(HasSpan(file_.service(0).method(1), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1), "input_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1), "output_type")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0), "name")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0).name(0))); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0).name(0), "name_part")); + EXPECT_TRUE(HasSpan(file_.service(0).method(1).options() + .uninterpreted_option(0), "positive_int_value")); + EXPECT_TRUE(HasSpan('1', '2', file_.service(0).method(1), + "client_streaming")); + EXPECT_TRUE(HasSpan('3', '4', file_.service(0).method(1), + "server_streaming")); } TEST_F(SourceInfoTest, FieldOptions) { @@ -2705,7 +2780,7 @@ TEST_F(SourceInfoTest, DocComments) { " // Foo trailing\n" " // line 2\n" "\n" - " // ignored\n" + " // detached\n" "\n" " // bar leading\n" " $b$optional int32 bar = 1;$c$\n" @@ -2719,10 +2794,12 @@ TEST_F(SourceInfoTest, DocComments) { EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n", - " Foo trailing\n line 2\n")); + " Foo trailing\n line 2\n", + NULL)); EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", - " bar trailing\n")); + " bar trailing\n", + " detached\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -2735,21 +2812,23 @@ TEST_F(SourceInfoTest, DocComments) { TEST_F(SourceInfoTest, DocComments2) { EXPECT_TRUE(Parse( - "// ignored\n" - "syntax = \"proto2\";\n" + "// detached before message.\n" + "\n" "// Foo leading\n" "// line 2\n" "$a$message Foo {\n" " /* Foo trailing\n" " * line 2 */\n" - " // ignored\n" + " // detached\n" " /* bar leading\n" " */" " $b$optional int32 bar = 1;$c$ // bar trailing\n" - " // ignored\n" + " // ignored detached\n" "}$d$\n" "// ignored\n" "\n" + "// detached before option\n" + "\n" "// option leading\n" "$e$option baz = 123;$f$\n" "// option trailing\n" @@ -2761,13 +2840,16 @@ TEST_F(SourceInfoTest, DocComments2) { EXPECT_TRUE(HasSpanWithComment('a', 'd', foo, " Foo leading\n line 2\n", - " Foo trailing\n line 2 ")); + " Foo trailing\n line 2 ", + " detached before message.\n")); EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", - " bar trailing\n")); + " bar trailing\n", + " detached\n")); EXPECT_TRUE(HasSpanWithComment('e', 'f', baz, " option leading\n", - " option trailing\n")); + " option trailing\n", + " detached before option\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -2798,7 +2880,8 @@ TEST_F(SourceInfoTest, DocComments3) { EXPECT_TRUE(HasSpanWithComment('b', 'c', bar, " bar leading\n", - " bar trailing\n")); + " bar trailing\n", + NULL)); // Ignore these. EXPECT_TRUE(HasSpan(file_)); @@ -2818,25 +2901,63 @@ TEST_F(SourceInfoTest, DocComments3) { bar.options().uninterpreted_option(0), "aggregate_value")); } +TEST_F(SourceInfoTest, DocCommentsTopLevel) { + EXPECT_TRUE(Parse( + "// detached before syntax paragraph 1\n" + "\n" + "// detached before syntax paragraph 2\n" + "\n" + "// syntax leading\n" + "$a$syntax = \"proto2\";$b$\n" + "// syntax trailing\n" + "\n" + "// syntax-package detached comments\n" + "\n" + ";\n" + "\n" + "// detached after empty before package\n" + "\n" + "// package leading\n" + "package $c$foo$d$;\n" + "// package trailing\n" + "\n" + "// ignored detach\n" + "\n")); + + EXPECT_TRUE(HasSpan('a', 'b', file_, "syntax", -1, + " syntax leading\n", + " syntax trailing\n", + " detached before syntax paragraph 1\n" + "\n" + " detached before syntax paragraph 2\n")); + EXPECT_TRUE(HasSpan('c', 'd', file_, "package", -1, + " package leading\n", + " package trailing\n", + " syntax-package detached comments\n" + "\n" + " detached after empty before package\n")); + + // ignore these. + EXPECT_TRUE(HasSpan(file_)); +} + TEST_F(SourceInfoTest, DocCommentsOneof) { EXPECT_TRUE(Parse( - "// ignored\n" - "syntax = \"proto2\";\n" "// Foo leading\n" "$a$message Foo {\n" " /* Foo trailing\n" " */\n" - " // ignored\n" + " // detached before oneof\n" " /* bar leading\n" " * line 2 */\n" " $b$oneof bar {\n" " /* bar trailing\n" " * line 2 */\n" - " // ignored\n" + " // detached before bar_int\n" " /* bar_int leading\n" " */\n" " $c$int32 bar_int = 1;$d$ // bar_int trailing\n" - " // ignored\n" + " // detach comment ignored\n" " }$e$\n" "}$f$\n")); @@ -2846,13 +2967,16 @@ TEST_F(SourceInfoTest, DocCommentsOneof) { EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, " Foo leading\n", - " Foo trailing\n")); + " Foo trailing\n", + NULL)); EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, " bar leading\n line 2 ", - " bar trailing\n line 2 ")); + " bar trailing\n line 2 ", + " detached before oneof\n")); EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, " bar_int leading\n", - " bar_int trailing\n")); + " bar_int trailing\n", + " detached before bar_int\n")); // Ignore these. EXPECT_TRUE(HasSpan(file_)); diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index 9011a6bd..ad501acf 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -95,7 +95,7 @@ class GeneratorResponseContext : public GeneratorContext { int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { if (argc > 1) { - cerr << argv[0] << ": Unknown option: " << argv[1] << endl; + std::cerr << argv[0] << ": Unknown option: " << argv[1] << std::endl; return 1; } @@ -106,7 +106,8 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { CodeGeneratorRequest request; if (!request.ParseFromFileDescriptor(STDIN_FILENO)) { - cerr << argv[0] << ": protoc sent unparseable request to plugin." << endl; + std::cerr << argv[0] << ": protoc sent unparseable request to plugin." + << std::endl; return 1; } @@ -123,9 +124,9 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { for (int i = 0; i < request.file_to_generate_size(); i++) { parsed_files.push_back(pool.FindFileByName(request.file_to_generate(i))); if (parsed_files.back() == NULL) { - cerr << argv[0] << ": protoc asked plugin to generate a file but " - "did not provide a descriptor for the file: " - << request.file_to_generate(i) << endl; + std::cerr << argv[0] << ": protoc asked plugin to generate a file but " + "did not provide a descriptor for the file: " + << request.file_to_generate(i) << std::endl; return 1; } } @@ -151,7 +152,7 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { } if (!response.SerializeToFileDescriptor(STDOUT_FILENO)) { - cerr << argv[0] << ": Error writing to stdout." << endl; + std::cerr << argv[0] << ": Error writing to stdout." << std::endl; return 1; } diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 5118de15..fed1726a 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -140,8 +140,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { "\01324.google.protobuf.compiler.CodeGenerat" "orResponse.File\032>\n\004File\022\014\n\004name\030\001 \001(\t\022\027\n" "\017insertion_point\030\002 \001(\t\022\017\n\007content\030\017 \001(\tB" - ",\n\034com.google.protobuf.compilerB\014PluginP" - "rotos", 445); + "7\n\034com.google.protobuf.compilerB\014PluginP" + "rotosZ\tplugin_go", 456); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/compiler/plugin.proto", &protobuf_RegisterTypes); CodeGeneratorRequest::default_instance_ = new CodeGeneratorRequest(); @@ -509,6 +509,147 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// CodeGeneratorRequest + +// repeated string file_to_generate = 1; + int CodeGeneratorRequest::file_to_generate_size() const { + return file_to_generate_.size(); +} + void CodeGeneratorRequest::clear_file_to_generate() { + file_to_generate_.Clear(); +} + const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return file_to_generate_.Get(index); +} + ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return file_to_generate_.Mutable(index); +} + void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + file_to_generate_.Mutable(index)->assign(value); +} + void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { + file_to_generate_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) { + file_to_generate_.Mutable(index)->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + ::std::string* CodeGeneratorRequest::add_file_to_generate() { + return file_to_generate_.Add(); +} + void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { + file_to_generate_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + void CodeGeneratorRequest::add_file_to_generate(const char* value) { + file_to_generate_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) { + file_to_generate_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) +} + const ::google::protobuf::RepeatedPtrField< ::std::string>& +CodeGeneratorRequest::file_to_generate() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return file_to_generate_; +} + ::google::protobuf::RepeatedPtrField< ::std::string>* +CodeGeneratorRequest::mutable_file_to_generate() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) + return &file_to_generate_; +} + +// optional string parameter = 2; + bool CodeGeneratorRequest::has_parameter() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void CodeGeneratorRequest::set_has_parameter() { + _has_bits_[0] |= 0x00000002u; +} + void CodeGeneratorRequest::clear_has_parameter() { + _has_bits_[0] &= ~0x00000002u; +} + void CodeGeneratorRequest::clear_parameter() { + parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_parameter(); +} + const ::std::string& CodeGeneratorRequest::parameter() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) + return parameter_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorRequest::set_parameter(const ::std::string& value) { + set_has_parameter(); + parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} + void CodeGeneratorRequest::set_parameter(const char* value) { + set_has_parameter(); + parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} + void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { + set_has_parameter(); + parameter_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} + ::std::string* CodeGeneratorRequest::mutable_parameter() { + set_has_parameter(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) + return parameter_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorRequest::release_parameter() { + clear_has_parameter(); + return parameter_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { + if (parameter != NULL) { + set_has_parameter(); + } else { + clear_has_parameter(); + } + parameter_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), parameter); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) +} + +// repeated .google.protobuf.FileDescriptorProto proto_file = 15; + int CodeGeneratorRequest::proto_file_size() const { + return proto_file_.size(); +} + void CodeGeneratorRequest::clear_proto_file() { + proto_file_.Clear(); +} + const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_.Get(index); +} + ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_.Mutable(index); +} + ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +CodeGeneratorRequest::proto_file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return proto_file_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* +CodeGeneratorRequest::mutable_proto_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) + return &proto_file_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -1162,6 +1303,256 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// CodeGeneratorResponse_File + +// optional string name = 1; + bool CodeGeneratorResponse_File::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void CodeGeneratorResponse_File::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void CodeGeneratorResponse_File::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void CodeGeneratorResponse_File::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& CodeGeneratorResponse_File::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} + void CodeGeneratorResponse_File::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} + void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} + ::std::string* CodeGeneratorResponse_File::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorResponse_File::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) +} + +// optional string insertion_point = 2; + bool CodeGeneratorResponse_File::has_insertion_point() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void CodeGeneratorResponse_File::set_has_insertion_point() { + _has_bits_[0] |= 0x00000002u; +} + void CodeGeneratorResponse_File::clear_has_insertion_point() { + _has_bits_[0] &= ~0x00000002u; +} + void CodeGeneratorResponse_File::clear_insertion_point() { + insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_insertion_point(); +} + const ::std::string& CodeGeneratorResponse_File::insertion_point() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) + return insertion_point_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { + set_has_insertion_point(); + insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} + void CodeGeneratorResponse_File::set_insertion_point(const char* value) { + set_has_insertion_point(); + insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} + void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { + set_has_insertion_point(); + insertion_point_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} + ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { + set_has_insertion_point(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) + return insertion_point_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorResponse_File::release_insertion_point() { + clear_has_insertion_point(); + return insertion_point_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { + if (insertion_point != NULL) { + set_has_insertion_point(); + } else { + clear_has_insertion_point(); + } + insertion_point_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), insertion_point); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) +} + +// optional string content = 15; + bool CodeGeneratorResponse_File::has_content() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void CodeGeneratorResponse_File::set_has_content() { + _has_bits_[0] |= 0x00000004u; +} + void CodeGeneratorResponse_File::clear_has_content() { + _has_bits_[0] &= ~0x00000004u; +} + void CodeGeneratorResponse_File::clear_content() { + content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_content(); +} + const ::std::string& CodeGeneratorResponse_File::content() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) + return content_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_content(const ::std::string& value) { + set_has_content(); + content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} + void CodeGeneratorResponse_File::set_content(const char* value) { + set_has_content(); + content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} + void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { + set_has_content(); + content_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} + ::std::string* CodeGeneratorResponse_File::mutable_content() { + set_has_content(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) + return content_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorResponse_File::release_content() { + clear_has_content(); + return content_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { + if (content != NULL) { + set_has_content(); + } else { + clear_has_content(); + } + content_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), content); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) +} + +// ------------------------------------------------------------------- + +// CodeGeneratorResponse + +// optional string error = 1; + bool CodeGeneratorResponse::has_error() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void CodeGeneratorResponse::set_has_error() { + _has_bits_[0] |= 0x00000001u; +} + void CodeGeneratorResponse::clear_has_error() { + _has_bits_[0] &= ~0x00000001u; +} + void CodeGeneratorResponse::clear_error() { + error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_error(); +} + const ::std::string& CodeGeneratorResponse::error() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) + return error_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse::set_error(const ::std::string& value) { + set_has_error(); + error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) +} + void CodeGeneratorResponse::set_error(const char* value) { + set_has_error(); + error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) +} + void CodeGeneratorResponse::set_error(const char* value, size_t size) { + set_has_error(); + error_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) +} + ::std::string* CodeGeneratorResponse::mutable_error() { + set_has_error(); + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) + return error_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* CodeGeneratorResponse::release_error() { + clear_has_error(); + return error_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void CodeGeneratorResponse::set_allocated_error(::std::string* error) { + if (error != NULL) { + set_has_error(); + } else { + clear_has_error(); + } + error_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), error); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) +} + +// repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; + int CodeGeneratorResponse::file_size() const { + return file_.size(); +} + void CodeGeneratorResponse::clear_file() { + file_.Clear(); +} + const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_.Get(index); +} + ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_.Mutable(index); +} + ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& +CodeGeneratorResponse::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) + return file_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* +CodeGeneratorResponse::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) + return &file_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index ad017005..ea48b8b5 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -110,43 +110,43 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message // accessors ------------------------------------------------------- // repeated string file_to_generate = 1; - inline int file_to_generate_size() const; - inline void clear_file_to_generate(); + int file_to_generate_size() const; + void clear_file_to_generate(); static const int kFileToGenerateFieldNumber = 1; - inline const ::std::string& file_to_generate(int index) const; - inline ::std::string* mutable_file_to_generate(int index); - inline void set_file_to_generate(int index, const ::std::string& value); - inline void set_file_to_generate(int index, const char* value); - inline void set_file_to_generate(int index, const char* value, size_t size); - inline ::std::string* add_file_to_generate(); - inline void add_file_to_generate(const ::std::string& value); - inline void add_file_to_generate(const char* value); - inline void add_file_to_generate(const char* value, size_t size); - inline const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; - inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); + const ::std::string& file_to_generate(int index) const; + ::std::string* mutable_file_to_generate(int index); + void set_file_to_generate(int index, const ::std::string& value); + void set_file_to_generate(int index, const char* value); + void set_file_to_generate(int index, const char* value, size_t size); + ::std::string* add_file_to_generate(); + void add_file_to_generate(const ::std::string& value); + void add_file_to_generate(const char* value); + void add_file_to_generate(const char* value, size_t size); + const ::google::protobuf::RepeatedPtrField< ::std::string>& file_to_generate() const; + ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_file_to_generate(); // optional string parameter = 2; - inline bool has_parameter() const; - inline void clear_parameter(); + bool has_parameter() const; + void clear_parameter(); static const int kParameterFieldNumber = 2; - inline const ::std::string& parameter() const; - inline void set_parameter(const ::std::string& value); - inline void set_parameter(const char* value); - inline void set_parameter(const char* value, size_t size); - inline ::std::string* mutable_parameter(); - inline ::std::string* release_parameter(); - inline void set_allocated_parameter(::std::string* parameter); + const ::std::string& parameter() const; + void set_parameter(const ::std::string& value); + void set_parameter(const char* value); + void set_parameter(const char* value, size_t size); + ::std::string* mutable_parameter(); + ::std::string* release_parameter(); + void set_allocated_parameter(::std::string* parameter); // repeated .google.protobuf.FileDescriptorProto proto_file = 15; - inline int proto_file_size() const; - inline void clear_proto_file(); + int proto_file_size() const; + void clear_proto_file(); static const int kProtoFileFieldNumber = 15; - inline const ::google::protobuf::FileDescriptorProto& proto_file(int index) const; - inline ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index); - inline ::google::protobuf::FileDescriptorProto* add_proto_file(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + const ::google::protobuf::FileDescriptorProto& proto_file(int index) const; + ::google::protobuf::FileDescriptorProto* mutable_proto_file(int index); + ::google::protobuf::FileDescriptorProto* add_proto_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& proto_file() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_proto_file(); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) @@ -234,40 +234,40 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional string insertion_point = 2; - inline bool has_insertion_point() const; - inline void clear_insertion_point(); + bool has_insertion_point() const; + void clear_insertion_point(); static const int kInsertionPointFieldNumber = 2; - inline const ::std::string& insertion_point() const; - inline void set_insertion_point(const ::std::string& value); - inline void set_insertion_point(const char* value); - inline void set_insertion_point(const char* value, size_t size); - inline ::std::string* mutable_insertion_point(); - inline ::std::string* release_insertion_point(); - inline void set_allocated_insertion_point(::std::string* insertion_point); + const ::std::string& insertion_point() const; + void set_insertion_point(const ::std::string& value); + void set_insertion_point(const char* value); + void set_insertion_point(const char* value, size_t size); + ::std::string* mutable_insertion_point(); + ::std::string* release_insertion_point(); + void set_allocated_insertion_point(::std::string* insertion_point); // optional string content = 15; - inline bool has_content() const; - inline void clear_content(); + bool has_content() const; + void clear_content(); static const int kContentFieldNumber = 15; - inline const ::std::string& content() const; - inline void set_content(const ::std::string& value); - inline void set_content(const char* value); - inline void set_content(const char* value, size_t size); - inline ::std::string* mutable_content(); - inline ::std::string* release_content(); - inline void set_allocated_content(::std::string* content); + const ::std::string& content() const; + void set_content(const ::std::string& value); + void set_content(const char* value); + void set_content(const char* value, size_t size); + ::std::string* mutable_content(); + ::std::string* release_content(); + void set_allocated_content(::std::string* content); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) private: @@ -360,27 +360,27 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag // accessors ------------------------------------------------------- // optional string error = 1; - inline bool has_error() const; - inline void clear_error(); + bool has_error() const; + void clear_error(); static const int kErrorFieldNumber = 1; - inline const ::std::string& error() const; - inline void set_error(const ::std::string& value); - inline void set_error(const char* value); - inline void set_error(const char* value, size_t size); - inline ::std::string* mutable_error(); - inline ::std::string* release_error(); - inline void set_allocated_error(::std::string* error); + const ::std::string& error() const; + void set_error(const ::std::string& value); + void set_error(const char* value); + void set_error(const char* value, size_t size); + ::std::string* mutable_error(); + ::std::string* release_error(); + void set_allocated_error(::std::string* error); // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; - inline int file_size() const; - inline void clear_file(); + int file_size() const; + void clear_file(); static const int kFileFieldNumber = 15; - inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const; - inline ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index); - inline ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& + const ::google::protobuf::compiler::CodeGeneratorResponse_File& file(int index) const; + ::google::protobuf::compiler::CodeGeneratorResponse_File* mutable_file(int index); + ::google::protobuf::compiler::CodeGeneratorResponse_File* add_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& file() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* mutable_file(); // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) @@ -405,6 +405,7 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag // =================================================================== +#if !PROTOBUF_INLINE_NOT_IN_HEADERS // CodeGeneratorRequest // repeated string file_to_generate = 1; @@ -794,6 +795,7 @@ CodeGeneratorResponse::mutable_file() { return &file_; } +#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) @@ -801,15 +803,6 @@ CodeGeneratorResponse::mutable_file() { } // namespace protobuf } // namespace google -#ifndef SWIG -namespace google { -namespace protobuf { - - -} // namespace protobuf -} // namespace google -#endif // SWIG - // @@protoc_insertion_point(global_scope) #endif // PROTOBUF_google_2fprotobuf_2fcompiler_2fplugin_2eproto__INCLUDED diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto index e627289b..acaee1f4 100644 --- a/src/google/protobuf/compiler/plugin.proto +++ b/src/google/protobuf/compiler/plugin.proto @@ -49,6 +49,8 @@ package google.protobuf.compiler; option java_package = "com.google.protobuf.compiler"; option java_outer_classname = "PluginProtos"; +option go_package = "plugin_go"; + import "google/protobuf/descriptor.proto"; // An encoded CodeGeneratorRequest is written to the plugin's stdin. diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index b8dd198d..bfdacd95 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -783,7 +783,7 @@ inline const FileDescriptor* DescriptorPool::Tables::FindFile( inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber( const Descriptor* parent, int number) const { - return FindPtrOrNull(fields_by_number_, make_pair(parent, number)); + return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number)); } inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName( @@ -800,7 +800,7 @@ inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName( inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber( const EnumDescriptor* parent, int number) const { - return FindPtrOrNull(enum_values_by_number_, make_pair(parent, number)); + return FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number)); } inline const EnumValueDescriptor* @@ -808,8 +808,8 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( const EnumDescriptor* parent, int number) const { // First try, with map of compiled-in values. { - const EnumValueDescriptor* desc = FindPtrOrNull( - enum_values_by_number_, make_pair(parent, number)); + const EnumValueDescriptor* desc = + FindPtrOrNull(enum_values_by_number_, std::make_pair(parent, number)); if (desc != NULL) { return desc; } @@ -818,7 +818,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( { ReaderMutexLock l(&unknown_enum_values_mu_); const EnumValueDescriptor* desc = FindPtrOrNull( - unknown_enum_values_by_number_, make_pair(parent, number)); + unknown_enum_values_by_number_, std::make_pair(parent, number)); if (desc != NULL) { return desc; } @@ -828,7 +828,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( { WriterMutexLock l(&unknown_enum_values_mu_); const EnumValueDescriptor* desc = FindPtrOrNull( - unknown_enum_values_by_number_, make_pair(parent, number)); + unknown_enum_values_by_number_, std::make_pair(parent, number)); if (desc != NULL) { return desc; } @@ -850,8 +850,7 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( result->type_ = parent; result->options_ = &EnumValueOptions::default_instance(); InsertIfNotPresent(&unknown_enum_values_by_number_, - make_pair(parent, number), - result); + std::make_pair(parent, number), result); return result; } } @@ -859,13 +858,13 @@ FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown( inline const FieldDescriptor* DescriptorPool::Tables::FindExtension( const Descriptor* extendee, int number) { - return FindPtrOrNull(extensions_, make_pair(extendee, number)); + return FindPtrOrNull(extensions_, std::make_pair(extendee, number)); } inline void DescriptorPool::Tables::FindAllExtensions( const Descriptor* extendee, vector* out) const { ExtensionsGroupedByDescriptorMap::const_iterator it = - extensions_.lower_bound(make_pair(extendee, 0)); + extensions_.lower_bound(std::make_pair(extendee, 0)); for (; it != extensions_.end() && it->first.first == extendee; ++it) { out->push_back(it->second); } @@ -993,7 +992,7 @@ void FileDescriptorTables::BuildLocationsByPath( const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation( const vector& path, const SourceCodeInfo* info) const { pair p( - make_pair(this, info)); + std::make_pair(this, info)); locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p); return FindPtrOrNull(locations_by_path_, Join(path, ",")); } @@ -1929,9 +1928,9 @@ bool FormatLineOptions(int depth, const Message &options, string *output) { return !all_options.empty(); } -template class SourceLocationCommentPrinter { public: + template SourceLocationCommentPrinter(const DescType* desc, const string& prefix, const DebugStringOptions& options) @@ -1941,9 +1940,27 @@ class SourceLocationCommentPrinter { have_source_loc_ = options.include_comments && desc->GetSourceLocation(&source_loc_); } + SourceLocationCommentPrinter(const FileDescriptor* file, + const vector& path, + const string& prefix, + const DebugStringOptions& options) + : options_(options), prefix_(prefix) { + // Perform the SourceLocation lookup only if we're including user comments, + // because the lookup is fairly expensive. + have_source_loc_ = options.include_comments && + file->GetSourceLocation(path, &source_loc_); + } void AddPreComment(string* output) { - if (have_source_loc_ && source_loc_.leading_comments.size() > 0) { - *output += FormatComment(source_loc_.leading_comments); + if (have_source_loc_) { + // Detached leading comments. + for (int i = 0 ; i < source_loc_.leading_detached_comments.size(); ++i) { + *output += FormatComment(source_loc_.leading_detached_comments[i]); + *output += "\n"; + } + // Attached leading comments. + if (!source_loc_.leading_comments.empty()) { + *output += FormatComment(source_loc_.leading_comments); + } } } void AddPostComment(string* output) { @@ -1967,7 +1984,6 @@ class SourceLocationCommentPrinter { } private: - const DescType* desc_; bool have_source_loc_; SourceLocation source_loc_; DebugStringOptions options_; @@ -1984,10 +2000,18 @@ string FileDescriptor::DebugString() const { string FileDescriptor::DebugStringWithOptions( const DebugStringOptions& debug_string_options) const { string contents; - strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n", - SyntaxName(syntax())); + { + vector path; + path.push_back(FileDescriptorProto::kSyntaxFieldNumber); + SourceLocationCommentPrinter syntax_comment( + this, path, "", debug_string_options); + syntax_comment.AddPreComment(&contents); + strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n", + SyntaxName(syntax())); + syntax_comment.AddPostComment(&contents); + } - SourceLocationCommentPrinter + SourceLocationCommentPrinter comment_printer(this, "", debug_string_options); comment_printer.AddPreComment(&contents); @@ -2012,7 +2036,13 @@ string FileDescriptor::DebugStringWithOptions( } if (!package().empty()) { + vector path; + path.push_back(FileDescriptorProto::kPackageFieldNumber); + SourceLocationCommentPrinter package_comment( + this, path, "", debug_string_options); + package_comment.AddPreComment(&contents); strings::SubstituteAndAppend(&contents, "package $0;\n\n", package()); + package_comment.AddPostComment(&contents); } if (FormatLineOptions(0, options(), &contents)) { @@ -2087,7 +2117,7 @@ void Descriptor::DebugString(int depth, string *contents, string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2217,7 +2247,7 @@ void FieldDescriptor::DebugString(int depth, label.push_back(' '); } - SourceLocationCommentPrinter + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2274,7 +2304,7 @@ void OneofDescriptor::DebugString(int depth, string* contents, debug_string_options) const { string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); strings::SubstituteAndAppend( @@ -2305,7 +2335,7 @@ void EnumDescriptor::DebugString(int depth, string *contents, string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2339,7 +2369,7 @@ void EnumValueDescriptor::DebugString(int depth, string *contents, debug_string_options) const { string prefix(depth * 2, ' '); - SourceLocationCommentPrinter + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2370,7 +2400,7 @@ string ServiceDescriptor::DebugStringWithOptions( void ServiceDescriptor::DebugString(string *contents, const DebugStringOptions& debug_string_options) const { - SourceLocationCommentPrinter + SourceLocationCommentPrinter comment_printer(this, /* prefix */ "", debug_string_options); comment_printer.AddPreComment(contents); @@ -2405,7 +2435,7 @@ void MethodDescriptor::DebugString(int depth, string *contents, string prefix(depth * 2, ' '); ++depth; - SourceLocationCommentPrinter + SourceLocationCommentPrinter comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); @@ -2445,6 +2475,9 @@ bool FileDescriptor::GetSourceLocation(const vector& path, out_location->leading_comments = loc->leading_comments(); out_location->trailing_comments = loc->trailing_comments(); + out_location->leading_detached_comments.assign( + loc->leading_detached_comments().begin(), + loc->leading_detached_comments().end()); return true; } } @@ -3697,7 +3730,6 @@ const FileDescriptor* DescriptorBuilder::BuildFile( "Unrecognized syntax: " + proto.syntax()); } - result->name_ = tables_->AllocateString(proto.name()); if (proto.has_package()) { result->package_ = tables_->AllocateString(proto.package()); @@ -5110,7 +5142,7 @@ bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field, case FieldDescriptor::TYPE_SFIXED64: // Legal cases break; - // Do not add a default, so that the compiler will complian when new types + // Do not add a default, so that the compiler will complain when new types // are added. } @@ -5123,7 +5155,7 @@ void DescriptorBuilder::DetectMapConflicts(const Descriptor* message, for (int i = 0; i < message->nested_type_count(); ++i) { const Descriptor* nested = message->nested_type(i); pair::iterator, bool> result = - seen_types.insert(make_pair(nested->name(), nested)); + seen_types.insert(std::make_pair(nested->name(), nested)); if (!result.second) { if (result.first->second->options().map_entry() || nested->options().map_entry()) { diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 52df47f3..0e264f54 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -117,8 +117,10 @@ struct SourceLocation { int end_column; // Doc comments found at the source location. + // See the comments in SourceCodeInfo.Location (descriptor.proto) for details. string leading_comments; string trailing_comments; + vector leading_detached_comments; }; // Options when generating machine-parsable output from a descriptor with @@ -312,7 +314,7 @@ class LIBPROTOBUF_EXPORT Descriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector* output) const; + void GetLocationPath(std::vector* output) const; const string* name_; const string* full_name_; @@ -594,7 +596,7 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector* output) const; + void GetLocationPath(std::vector* output) const; const string* name_; const string* full_name_; @@ -688,7 +690,7 @@ class LIBPROTOBUF_EXPORT OneofDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector* output) const; + void GetLocationPath(std::vector* output) const; const string* name_; const string* full_name_; @@ -790,7 +792,7 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector* output) const; + void GetLocationPath(std::vector* output) const; const string* name_; const string* full_name_; @@ -874,7 +876,7 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector* output) const; + void GetLocationPath(std::vector* output) const; const string* name_; const string* full_name_; @@ -949,7 +951,7 @@ class LIBPROTOBUF_EXPORT ServiceDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector* output) const; + void GetLocationPath(std::vector* output) const; const string* name_; const string* full_name_; @@ -1028,7 +1030,7 @@ class LIBPROTOBUF_EXPORT MethodDescriptor { // Walks up the descriptor tree to generate the source location path // to this descriptor from the file root. - void GetLocationPath(vector* output) const; + void GetLocationPath(std::vector* output) const; const string* name_; const string* full_name_; @@ -1173,17 +1175,15 @@ class LIBPROTOBUF_EXPORT FileDescriptor { // this file declaration (namely, the empty path). bool GetSourceLocation(SourceLocation* out_location) const; - private: - // Source Location --------------------------------------------------- - // Updates |*out_location| to the source location of the complete // extent of the declaration or declaration-part denoted by |path|. // Returns false and leaves |*out_location| unchanged iff location // information was not available. (See SourceCodeInfo for // description of path encoding.) - bool GetSourceLocation(const vector& path, + bool GetSourceLocation(const std::vector& path, SourceLocation* out_location) const; + private: typedef FileOptions OptionsType; const string* name_; @@ -1326,7 +1326,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // found: extensions defined in the fallback database might not be found // depending on the database implementation. void FindAllExtensions(const Descriptor* extendee, - vector* out) const; + std::vector* out) const; // Building descriptors -------------------------------------------- diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 97121fa9..9556206c 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -289,7 +289,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_), -1); FileOptions_descriptor_ = file->message_type(9); - static const int FileOptions_offsets_[13] = { + static const int FileOptions_offsets_[14] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), @@ -302,6 +302,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), }; FileOptions_reflection_ = @@ -474,11 +475,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, _internal_metadata_), -1); SourceCodeInfo_Location_descriptor_ = SourceCodeInfo_descriptor_->nested_type(0); - static const int SourceCodeInfo_Location_offsets_[4] = { + static const int SourceCodeInfo_Location_offsets_[5] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, path_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, span_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_comments_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, trailing_comments_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo_Location, leading_detached_comments_), }; SourceCodeInfo_Location_reflection_ = ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( @@ -661,7 +663,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "t_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.p" "rotobuf.MethodOptions\022\037\n\020client_streamin" "g\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010" - ":\005false\"\314\004\n\013FileOptions\022\024\n\014java_package\030" + ":\005false\"\347\004\n\013FileOptions\022\024\n\014java_package\030" "\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023j" "ava_multiple_files\030\n \001(\010:\005false\022,\n\035java_" "generate_equals_and_hash\030\024 \001(\010:\005false\022%\n" @@ -672,49 +674,51 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal" "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031" "\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_a" - "renas\030\037 \001(\010:\005false\022C\n\024uninterpreted_opti" + "renas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030" + "$ \001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g" + "oogle.protobuf.UninterpretedOption\":\n\014Op" + "timizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014" + "LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOpt" + "ions\022&\n\027message_set_wire_format\030\001 \001(\010:\005f" + "alse\022.\n\037no_standard_descriptor_accessor\030" + "\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" + "\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpreted_opti" "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete" - "dOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCO" - "DE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346" - "\001\n\016MessageOptions\022&\n\027message_set_wire_fo" - "rmat\030\001 \001(\010:\005false\022.\n\037no_standard_descrip" - "tor_accessor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030" - "\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024unint" - "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014Fiel" - "dOptions\022:\n\005ctype\030\001 \001(\0162#.google.protobu" - "f.FieldOptions.CType:\006STRING\022\016\n\006packed\030\002" - " \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndeprecated\030" - "\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005false\022C\n\024uni" - "nterpreted_option\030\347\007 \003(\0132$.google.protob" - "uf.UninterpretedOption\"/\n\005CType\022\n\n\006STRIN" - "G\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200" - "\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022" - "\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024uninterpre" - "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin" - "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueO" - "ptions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uni" - "nterpreted_option\030\347\007 \003(\0132$.google.protob" - "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016Ser" - "viceOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C" - "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p" - "rotobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z" - "\n\rMethodOptions\022\031\n\ndeprecated\030! \001(\010:\005fal" - "se\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goog" - "le.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200" - "\200\002\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\013" - "2-.google.protobuf.UninterpretedOption.N" - "amePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022pos" - "itive_int_value\030\004 \001(\004\022\032\n\022negative_int_va" - "lue\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014strin" - "g_value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323" - "\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_exte" - "nsion\030\002 \002(\010\"\261\001\n\016SourceCodeInfo\022:\n\010locati" - "on\030\001 \003(\0132(.google.protobuf.SourceCodeInf" - "o.Location\032c\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001" - "\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003" - " \001(\t\022\031\n\021trailing_comments\030\004 \001(\tB)\n\023com.g" - "oogle.protobufB\020DescriptorProtosH\001", 4554); + "dOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005c" + "type\030\001 \001(\0162#.google.protobuf.FieldOption" + "s.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030" + "\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" + "\023\n\004weak\030\n \001(\010:\005false\022C\n\024uninterpreted_op" + "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" + "tedOption\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001" + "\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOp" + "tions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated" + "\030\003 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007" + " \003(\0132$.google.protobuf.UninterpretedOpti" + "on*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndep" + "recated\030\001 \001(\010:\005false\022C\n\024uninterpreted_op" + "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" + "tedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031" + "\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninterpret" + "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint" + "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptio" + "ns\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninter" + "preted_option\030\347\007 \003(\0132$.google.protobuf.U" + "ninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninte" + "rpretedOption\022;\n\004name\030\002 \003(\0132-.google.pro" + "tobuf.UninterpretedOption.NamePart\022\030\n\020id" + "entifier_value\030\003 \001(\t\022\032\n\022positive_int_val" + "ue\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014" + "double_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014" + "\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n" + "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325" + "\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003(\0132(.go" + "ogle.protobuf.SourceCodeInfo.Location\032\206\001" + "\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003" + "(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trai" + "ling_comments\030\004 \001(\t\022!\n\031leading_detached_" + "comments\030\006 \003(\tB)\n\023com.google.protobufB\020D" + "escriptorProtosH\001", 4617); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -1009,6 +1013,40 @@ void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FileDescriptorSet + +// repeated .google.protobuf.FileDescriptorProto file = 1; + int FileDescriptorSet::file_size() const { + return file_.size(); +} + void FileDescriptorSet::clear_file() { + file_.Clear(); +} + const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file) + return file_.Get(index); +} + ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file) + return file_.Mutable(index); +} + ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) + return file_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& +FileDescriptorSet::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) + return file_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* +FileDescriptorSet::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) + return &file_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -1771,6 +1809,489 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FileDescriptorProto + +// optional string name = 1; + bool FileDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void FileDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void FileDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void FileDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& FileDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name) +} + void FileDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name) +} + void FileDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name) +} + ::std::string* FileDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name) +} + +// optional string package = 2; + bool FileDescriptorProto::has_package() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void FileDescriptorProto::set_has_package() { + _has_bits_[0] |= 0x00000002u; +} + void FileDescriptorProto::clear_has_package() { + _has_bits_[0] &= ~0x00000002u; +} + void FileDescriptorProto::clear_package() { + package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_package(); +} + const ::std::string& FileDescriptorProto::package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package) + return package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_package(const ::std::string& value) { + set_has_package(); + package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package) +} + void FileDescriptorProto::set_package(const char* value) { + set_has_package(); + package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package) +} + void FileDescriptorProto::set_package(const char* value, size_t size) { + set_has_package(); + package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package) +} + ::std::string* FileDescriptorProto::mutable_package() { + set_has_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package) + return package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileDescriptorProto::release_package() { + clear_has_package(); + return package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_allocated_package(::std::string* package) { + if (package != NULL) { + set_has_package(); + } else { + clear_has_package(); + } + package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), package); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package) +} + +// repeated string dependency = 3; + int FileDescriptorProto::dependency_size() const { + return dependency_.size(); +} + void FileDescriptorProto::clear_dependency() { + dependency_.Clear(); +} + const ::std::string& FileDescriptorProto::dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency) + return dependency_.Get(index); +} + ::std::string* FileDescriptorProto::mutable_dependency(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency) + return dependency_.Mutable(index); +} + void FileDescriptorProto::set_dependency(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) + dependency_.Mutable(index)->assign(value); +} + void FileDescriptorProto::set_dependency(int index, const char* value) { + dependency_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency) +} + void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) { + dependency_.Mutable(index)->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) +} + ::std::string* FileDescriptorProto::add_dependency() { + return dependency_.Add(); +} + void FileDescriptorProto::add_dependency(const ::std::string& value) { + dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) +} + void FileDescriptorProto::add_dependency(const char* value) { + dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency) +} + void FileDescriptorProto::add_dependency(const char* value, size_t size) { + dependency_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency) +} + const ::google::protobuf::RepeatedPtrField< ::std::string>& +FileDescriptorProto::dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency) + return dependency_; +} + ::google::protobuf::RepeatedPtrField< ::std::string>* +FileDescriptorProto::mutable_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency) + return &dependency_; +} + +// repeated int32 public_dependency = 10; + int FileDescriptorProto::public_dependency_size() const { + return public_dependency_.size(); +} + void FileDescriptorProto::clear_public_dependency() { + public_dependency_.Clear(); +} + ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency) + return public_dependency_.Get(index); +} + void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) { + public_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency) +} + void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) { + public_dependency_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +FileDescriptorProto::public_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency) + return public_dependency_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +FileDescriptorProto::mutable_public_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency) + return &public_dependency_; +} + +// repeated int32 weak_dependency = 11; + int FileDescriptorProto::weak_dependency_size() const { + return weak_dependency_.size(); +} + void FileDescriptorProto::clear_weak_dependency() { + weak_dependency_.Clear(); +} + ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency) + return weak_dependency_.Get(index); +} + void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) { + weak_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency) +} + void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) { + weak_dependency_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +FileDescriptorProto::weak_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency) + return weak_dependency_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +FileDescriptorProto::mutable_weak_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency) + return &weak_dependency_; +} + +// repeated .google.protobuf.DescriptorProto message_type = 4; + int FileDescriptorProto::message_type_size() const { + return message_type_.size(); +} + void FileDescriptorProto::clear_message_type() { + message_type_.Clear(); +} + const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type) + return message_type_.Get(index); +} + ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type) + return message_type_.Mutable(index); +} + ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) + return message_type_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +FileDescriptorProto::message_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) + return message_type_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* +FileDescriptorProto::mutable_message_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) + return &message_type_; +} + +// repeated .google.protobuf.EnumDescriptorProto enum_type = 5; + int FileDescriptorProto::enum_type_size() const { + return enum_type_.size(); +} + void FileDescriptorProto::clear_enum_type() { + enum_type_.Clear(); +} + const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_.Get(index); +} + ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_.Mutable(index); +} + ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +FileDescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) + return enum_type_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* +FileDescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) + return &enum_type_; +} + +// repeated .google.protobuf.ServiceDescriptorProto service = 6; + int FileDescriptorProto::service_size() const { + return service_.size(); +} + void FileDescriptorProto::clear_service() { + service_.Clear(); +} + const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service) + return service_.Get(index); +} + ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service) + return service_.Mutable(index); +} + ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) + return service_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& +FileDescriptorProto::service() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) + return service_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* +FileDescriptorProto::mutable_service() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) + return &service_; +} + +// repeated .google.protobuf.FieldDescriptorProto extension = 7; + int FileDescriptorProto::extension_size() const { + return extension_.size(); +} + void FileDescriptorProto::clear_extension() { + extension_.Clear(); +} + const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension) + return extension_.Get(index); +} + ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension) + return extension_.Mutable(index); +} + ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) + return extension_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +FileDescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) + return extension_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +FileDescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) + return &extension_; +} + +// optional .google.protobuf.FileOptions options = 8; + bool FileDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} + void FileDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000200u; +} + void FileDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000200u; +} + void FileDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::FileOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) + return options_; +} + ::google::protobuf::FileOptions* FileDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FileOptions* temp = options_; + options_ = NULL; + return temp; +} + void FileDescriptorProto::set_allocated_options(::google::protobuf::FileOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options) +} + +// optional .google.protobuf.SourceCodeInfo source_code_info = 9; + bool FileDescriptorProto::has_source_code_info() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} + void FileDescriptorProto::set_has_source_code_info() { + _has_bits_[0] |= 0x00000400u; +} + void FileDescriptorProto::clear_has_source_code_info() { + _has_bits_[0] &= ~0x00000400u; +} + void FileDescriptorProto::clear_source_code_info() { + if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); + clear_has_source_code_info(); +} + const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info) + return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_; +} + ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { + set_has_source_code_info(); + if (source_code_info_ == NULL) { + source_code_info_ = new ::google::protobuf::SourceCodeInfo; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) + return source_code_info_; +} + ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { + clear_has_source_code_info(); + ::google::protobuf::SourceCodeInfo* temp = source_code_info_; + source_code_info_ = NULL; + return temp; +} + void FileDescriptorProto::set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info) { + delete source_code_info_; + source_code_info_ = source_code_info; + if (source_code_info) { + set_has_source_code_info(); + } else { + clear_has_source_code_info(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) +} + +// optional string syntax = 12; + bool FileDescriptorProto::has_syntax() const { + return (_has_bits_[0] & 0x00000800u) != 0; +} + void FileDescriptorProto::set_has_syntax() { + _has_bits_[0] |= 0x00000800u; +} + void FileDescriptorProto::clear_has_syntax() { + _has_bits_[0] &= ~0x00000800u; +} + void FileDescriptorProto::clear_syntax() { + syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_syntax(); +} + const ::std::string& FileDescriptorProto::syntax() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.syntax) + return syntax_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_syntax(const ::std::string& value) { + set_has_syntax(); + syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.syntax) +} + void FileDescriptorProto::set_syntax(const char* value) { + set_has_syntax(); + syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.syntax) +} + void FileDescriptorProto::set_syntax(const char* value, size_t size) { + set_has_syntax(); + syntax_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.syntax) +} + ::std::string* FileDescriptorProto::mutable_syntax() { + set_has_syntax(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.syntax) + return syntax_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileDescriptorProto::release_syntax() { + clear_has_syntax(); + return syntax_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileDescriptorProto::set_allocated_syntax(::std::string* syntax) { + if (syntax != NULL) { + set_has_syntax(); + } else { + clear_has_syntax(); + } + syntax_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), syntax); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -1839,19 +2360,17 @@ DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New(::google::pr } void DescriptorProto_ExtensionRange::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(start_, end_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -2594,6 +3113,338 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// DescriptorProto_ExtensionRange + +// optional int32 start = 1; + bool DescriptorProto_ExtensionRange::has_start() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void DescriptorProto_ExtensionRange::set_has_start() { + _has_bits_[0] |= 0x00000001u; +} + void DescriptorProto_ExtensionRange::clear_has_start() { + _has_bits_[0] &= ~0x00000001u; +} + void DescriptorProto_ExtensionRange::clear_start() { + start_ = 0; + clear_has_start(); +} + ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start) + return start_; +} + void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) { + set_has_start(); + start_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start) +} + +// optional int32 end = 2; + bool DescriptorProto_ExtensionRange::has_end() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void DescriptorProto_ExtensionRange::set_has_end() { + _has_bits_[0] |= 0x00000002u; +} + void DescriptorProto_ExtensionRange::clear_has_end() { + _has_bits_[0] &= ~0x00000002u; +} + void DescriptorProto_ExtensionRange::clear_end() { + end_ = 0; + clear_has_end(); +} + ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end) + return end_; +} + void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) { + set_has_end(); + end_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end) +} + +// ------------------------------------------------------------------- + +// DescriptorProto + +// optional string name = 1; + bool DescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void DescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void DescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void DescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& DescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void DescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name) +} + void DescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name) +} + void DescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name) +} + ::std::string* DescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* DescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void DescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name) +} + +// repeated .google.protobuf.FieldDescriptorProto field = 2; + int DescriptorProto::field_size() const { + return field_.size(); +} + void DescriptorProto::clear_field() { + field_.Clear(); +} + const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field) + return field_.Get(index); +} + ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field) + return field_.Mutable(index); +} + ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) + return field_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::field() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) + return field_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +DescriptorProto::mutable_field() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) + return &field_; +} + +// repeated .google.protobuf.FieldDescriptorProto extension = 6; + int DescriptorProto::extension_size() const { + return extension_.size(); +} + void DescriptorProto::clear_extension() { + extension_.Clear(); +} + const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension) + return extension_.Get(index); +} + ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension) + return extension_.Mutable(index); +} + ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) + return extension_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& +DescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) + return extension_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* +DescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) + return &extension_; +} + +// repeated .google.protobuf.DescriptorProto nested_type = 3; + int DescriptorProto::nested_type_size() const { + return nested_type_.size(); +} + void DescriptorProto::clear_nested_type() { + nested_type_.Clear(); +} + const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type) + return nested_type_.Get(index); +} + ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type) + return nested_type_.Mutable(index); +} + ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) + return nested_type_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& +DescriptorProto::nested_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) + return nested_type_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* +DescriptorProto::mutable_nested_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) + return &nested_type_; +} + +// repeated .google.protobuf.EnumDescriptorProto enum_type = 4; + int DescriptorProto::enum_type_size() const { + return enum_type_.size(); +} + void DescriptorProto::clear_enum_type() { + enum_type_.Clear(); +} + const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type) + return enum_type_.Get(index); +} + ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type) + return enum_type_.Mutable(index); +} + ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) + return enum_type_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& +DescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) + return enum_type_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* +DescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) + return &enum_type_; +} + +// repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; + int DescriptorProto::extension_range_size() const { + return extension_range_.size(); +} + void DescriptorProto::clear_extension_range() { + extension_range_.Clear(); +} + const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range) + return extension_range_.Get(index); +} + ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range) + return extension_range_.Mutable(index); +} + ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) + return extension_range_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& +DescriptorProto::extension_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range) + return extension_range_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* +DescriptorProto::mutable_extension_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range) + return &extension_range_; +} + +// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + int DescriptorProto::oneof_decl_size() const { + return oneof_decl_.size(); +} + void DescriptorProto::clear_oneof_decl() { + oneof_decl_.Clear(); +} + const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Get(index); +} + ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Mutable(index); +} + ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& +DescriptorProto::oneof_decl() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* +DescriptorProto::mutable_oneof_decl() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) + return &oneof_decl_; +} + +// optional .google.protobuf.MessageOptions options = 7; + bool DescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} + void DescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000080u; +} + void DescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000080u; +} + void DescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::MessageOptions& DescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::MessageOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) + return options_; +} + ::google::protobuf::MessageOptions* DescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MessageOptions* temp = options_; + options_ = NULL; + return temp; +} + void DescriptorProto::set_allocated_options(::google::protobuf::MessageOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -3308,14 +4159,371 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FieldDescriptorProto -// =================================================================== - -#ifndef _MSC_VER -const int OneofDescriptorProto::kNameFieldNumber; -#endif // !_MSC_VER - -OneofDescriptorProto::OneofDescriptorProto() +// optional string name = 1; + bool FieldDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void FieldDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void FieldDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void FieldDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& FieldDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name) +} + void FieldDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name) +} + void FieldDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name) +} + ::std::string* FieldDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FieldDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name) +} + +// optional int32 number = 3; + bool FieldDescriptorProto::has_number() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void FieldDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} + void FieldDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; +} + void FieldDescriptorProto::clear_number() { + number_ = 0; + clear_has_number(); +} + ::google::protobuf::int32 FieldDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number) + return number_; +} + void FieldDescriptorProto::set_number(::google::protobuf::int32 value) { + set_has_number(); + number_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number) +} + +// optional .google.protobuf.FieldDescriptorProto.Label label = 4; + bool FieldDescriptorProto::has_label() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void FieldDescriptorProto::set_has_label() { + _has_bits_[0] |= 0x00000004u; +} + void FieldDescriptorProto::clear_has_label() { + _has_bits_[0] &= ~0x00000004u; +} + void FieldDescriptorProto::clear_label() { + label_ = 1; + clear_has_label(); +} + ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label) + return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_); +} + void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) { + assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); + set_has_label(); + label_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label) +} + +// optional .google.protobuf.FieldDescriptorProto.Type type = 5; + bool FieldDescriptorProto::has_type() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void FieldDescriptorProto::set_has_type() { + _has_bits_[0] |= 0x00000008u; +} + void FieldDescriptorProto::clear_has_type() { + _has_bits_[0] &= ~0x00000008u; +} + void FieldDescriptorProto::clear_type() { + type_ = 1; + clear_has_type(); +} + ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type) + return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_); +} + void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) { + assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); + set_has_type(); + type_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type) +} + +// optional string type_name = 6; + bool FieldDescriptorProto::has_type_name() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void FieldDescriptorProto::set_has_type_name() { + _has_bits_[0] |= 0x00000010u; +} + void FieldDescriptorProto::clear_has_type_name() { + _has_bits_[0] &= ~0x00000010u; +} + void FieldDescriptorProto::clear_type_name() { + type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_type_name(); +} + const ::std::string& FieldDescriptorProto::type_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name) + return type_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_type_name(const ::std::string& value) { + set_has_type_name(); + type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name) +} + void FieldDescriptorProto::set_type_name(const char* value) { + set_has_type_name(); + type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name) +} + void FieldDescriptorProto::set_type_name(const char* value, size_t size) { + set_has_type_name(); + type_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name) +} + ::std::string* FieldDescriptorProto::mutable_type_name() { + set_has_type_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name) + return type_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FieldDescriptorProto::release_type_name() { + clear_has_type_name(); + return type_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) { + if (type_name != NULL) { + set_has_type_name(); + } else { + clear_has_type_name(); + } + type_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), type_name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name) +} + +// optional string extendee = 2; + bool FieldDescriptorProto::has_extendee() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} + void FieldDescriptorProto::set_has_extendee() { + _has_bits_[0] |= 0x00000020u; +} + void FieldDescriptorProto::clear_has_extendee() { + _has_bits_[0] &= ~0x00000020u; +} + void FieldDescriptorProto::clear_extendee() { + extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_extendee(); +} + const ::std::string& FieldDescriptorProto::extendee() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee) + return extendee_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_extendee(const ::std::string& value) { + set_has_extendee(); + extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee) +} + void FieldDescriptorProto::set_extendee(const char* value) { + set_has_extendee(); + extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee) +} + void FieldDescriptorProto::set_extendee(const char* value, size_t size) { + set_has_extendee(); + extendee_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee) +} + ::std::string* FieldDescriptorProto::mutable_extendee() { + set_has_extendee(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee) + return extendee_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FieldDescriptorProto::release_extendee() { + clear_has_extendee(); + return extendee_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) { + if (extendee != NULL) { + set_has_extendee(); + } else { + clear_has_extendee(); + } + extendee_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), extendee); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee) +} + +// optional string default_value = 7; + bool FieldDescriptorProto::has_default_value() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} + void FieldDescriptorProto::set_has_default_value() { + _has_bits_[0] |= 0x00000040u; +} + void FieldDescriptorProto::clear_has_default_value() { + _has_bits_[0] &= ~0x00000040u; +} + void FieldDescriptorProto::clear_default_value() { + default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_default_value(); +} + const ::std::string& FieldDescriptorProto::default_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value) + return default_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_default_value(const ::std::string& value) { + set_has_default_value(); + default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value) +} + void FieldDescriptorProto::set_default_value(const char* value) { + set_has_default_value(); + default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value) +} + void FieldDescriptorProto::set_default_value(const char* value, size_t size) { + set_has_default_value(); + default_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value) +} + ::std::string* FieldDescriptorProto::mutable_default_value() { + set_has_default_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value) + return default_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FieldDescriptorProto::release_default_value() { + clear_has_default_value(); + return default_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) { + if (default_value != NULL) { + set_has_default_value(); + } else { + clear_has_default_value(); + } + default_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), default_value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value) +} + +// optional int32 oneof_index = 9; + bool FieldDescriptorProto::has_oneof_index() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} + void FieldDescriptorProto::set_has_oneof_index() { + _has_bits_[0] |= 0x00000080u; +} + void FieldDescriptorProto::clear_has_oneof_index() { + _has_bits_[0] &= ~0x00000080u; +} + void FieldDescriptorProto::clear_oneof_index() { + oneof_index_ = 0; + clear_has_oneof_index(); +} + ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index) + return oneof_index_; +} + void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) { + set_has_oneof_index(); + oneof_index_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index) +} + +// optional .google.protobuf.FieldOptions options = 8; + bool FieldDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} + void FieldDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000100u; +} + void FieldDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000100u; +} + void FieldDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::FieldOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) + return options_; +} + ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::FieldOptions* temp = options_; + options_ = NULL; + return temp; +} + void FieldDescriptorProto::set_allocated_options(::google::protobuf::FieldOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS + +// =================================================================== + +#ifndef _MSC_VER +const int OneofDescriptorProto::kNameFieldNumber; +#endif // !_MSC_VER + +OneofDescriptorProto::OneofDescriptorProto() : ::google::protobuf::Message() , _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto) @@ -3557,6 +4765,63 @@ void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// OneofDescriptorProto + +// optional string name = 1; + bool OneofDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void OneofDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void OneofDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void OneofDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& OneofDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void OneofDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name) +} + void OneofDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name) +} + void OneofDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name) +} + ::std::string* OneofDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* OneofDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void OneofDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -3897,6 +5162,136 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EnumDescriptorProto + +// optional string name = 1; + bool EnumDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void EnumDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void EnumDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void EnumDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& EnumDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EnumDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name) +} + void EnumDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name) +} + void EnumDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name) +} + ::std::string* EnumDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* EnumDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EnumDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) +} + +// repeated .google.protobuf.EnumValueDescriptorProto value = 2; + int EnumDescriptorProto::value_size() const { + return value_.size(); +} + void EnumDescriptorProto::clear_value() { + value_.Clear(); +} + const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value) + return value_.Get(index); +} + ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value) + return value_.Mutable(index); +} + ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) + return value_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& +EnumDescriptorProto::value() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) + return value_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* +EnumDescriptorProto::mutable_value() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) + return &value_; +} + +// optional .google.protobuf.EnumOptions options = 3; + bool EnumDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void EnumDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} + void EnumDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} + void EnumDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::EnumOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) + return options_; +} + ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumOptions* temp = options_; + options_ = NULL; + return temp; +} + void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -4236,6 +5631,130 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EnumValueDescriptorProto + +// optional string name = 1; + bool EnumValueDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void EnumValueDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void EnumValueDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void EnumValueDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& EnumValueDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EnumValueDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name) +} + void EnumValueDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name) +} + void EnumValueDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name) +} + ::std::string* EnumValueDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* EnumValueDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void EnumValueDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name) +} + +// optional int32 number = 2; + bool EnumValueDescriptorProto::has_number() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void EnumValueDescriptorProto::set_has_number() { + _has_bits_[0] |= 0x00000002u; +} + void EnumValueDescriptorProto::clear_has_number() { + _has_bits_[0] &= ~0x00000002u; +} + void EnumValueDescriptorProto::clear_number() { + number_ = 0; + clear_has_number(); +} + ::google::protobuf::int32 EnumValueDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number) + return number_; +} + void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) { + set_has_number(); + number_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number) +} + +// optional .google.protobuf.EnumValueOptions options = 3; + bool EnumValueDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void EnumValueDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} + void EnumValueDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} + void EnumValueDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::EnumValueOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) + return options_; +} + ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::EnumValueOptions* temp = options_; + options_ = NULL; + return temp; +} + void EnumValueDescriptorProto::set_allocated_options(::google::protobuf::EnumValueOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -4576,6 +6095,136 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// ServiceDescriptorProto + +// optional string name = 1; + bool ServiceDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void ServiceDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} + void ServiceDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void ServiceDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& ServiceDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void ServiceDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name) +} + void ServiceDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name) +} + void ServiceDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name) +} + ::std::string* ServiceDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* ServiceDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void ServiceDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name) +} + +// repeated .google.protobuf.MethodDescriptorProto method = 2; + int ServiceDescriptorProto::method_size() const { + return method_.size(); +} + void ServiceDescriptorProto::clear_method() { + method_.Clear(); +} + const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method) + return method_.Get(index); +} + ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method) + return method_.Mutable(index); +} + ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) + return method_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& +ServiceDescriptorProto::method() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) + return method_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* +ServiceDescriptorProto::mutable_method() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) + return &method_; +} + +// optional .google.protobuf.ServiceOptions options = 3; + bool ServiceDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void ServiceDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000004u; +} + void ServiceDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000004u; +} + void ServiceDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::ServiceOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) + return options_; +} + ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::ServiceOptions* temp = options_; + options_ = NULL; + return temp; +} + void ServiceDescriptorProto::set_allocated_options(::google::protobuf::ServiceOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -4658,15 +6307,13 @@ MethodDescriptorProto* MethodDescriptorProto::New(::google::protobuf::Arena* are } void MethodDescriptorProto::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) if (_has_bits_[0 / 32] & 63) { ZR_(client_streaming_, server_streaming_); @@ -4684,7 +6331,7 @@ void MethodDescriptorProto::Clear() { } } -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ ::memset(_has_bits_, 0, sizeof(_has_bits_)); @@ -5075,31 +6722,285 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MethodDescriptorProto -// =================================================================== - -const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor() { - protobuf_AssignDescriptorsOnce(); - return FileOptions_OptimizeMode_descriptor_; +// optional string name = 1; + bool MethodDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; } -bool FileOptions_OptimizeMode_IsValid(int value) { - switch(value) { - case 1: - case 2: - case 3: - return true; - default: - return false; - } + void MethodDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; } - -#ifndef _MSC_VER -const FileOptions_OptimizeMode FileOptions::SPEED; -const FileOptions_OptimizeMode FileOptions::CODE_SIZE; -const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME; -const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; -const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; -const int FileOptions::OptimizeMode_ARRAYSIZE; + void MethodDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} + void MethodDescriptorProto::clear_name() { + name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name(); +} + const ::std::string& MethodDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name) + return name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name) +} + void MethodDescriptorProto::set_name(const char* value) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name) +} + void MethodDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name) +} + ::std::string* MethodDescriptorProto::mutable_name() { + set_has_name(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name) + return name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* MethodDescriptorProto::release_name() { + clear_has_name(); + return name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_allocated_name(::std::string* name) { + if (name != NULL) { + set_has_name(); + } else { + clear_has_name(); + } + name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name) +} + +// optional string input_type = 2; + bool MethodDescriptorProto::has_input_type() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void MethodDescriptorProto::set_has_input_type() { + _has_bits_[0] |= 0x00000002u; +} + void MethodDescriptorProto::clear_has_input_type() { + _has_bits_[0] &= ~0x00000002u; +} + void MethodDescriptorProto::clear_input_type() { + input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_input_type(); +} + const ::std::string& MethodDescriptorProto::input_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type) + return input_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_input_type(const ::std::string& value) { + set_has_input_type(); + input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type) +} + void MethodDescriptorProto::set_input_type(const char* value) { + set_has_input_type(); + input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type) +} + void MethodDescriptorProto::set_input_type(const char* value, size_t size) { + set_has_input_type(); + input_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type) +} + ::std::string* MethodDescriptorProto::mutable_input_type() { + set_has_input_type(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type) + return input_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* MethodDescriptorProto::release_input_type() { + clear_has_input_type(); + return input_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) { + if (input_type != NULL) { + set_has_input_type(); + } else { + clear_has_input_type(); + } + input_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), input_type); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type) +} + +// optional string output_type = 3; + bool MethodDescriptorProto::has_output_type() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void MethodDescriptorProto::set_has_output_type() { + _has_bits_[0] |= 0x00000004u; +} + void MethodDescriptorProto::clear_has_output_type() { + _has_bits_[0] &= ~0x00000004u; +} + void MethodDescriptorProto::clear_output_type() { + output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_output_type(); +} + const ::std::string& MethodDescriptorProto::output_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type) + return output_type_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_output_type(const ::std::string& value) { + set_has_output_type(); + output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type) +} + void MethodDescriptorProto::set_output_type(const char* value) { + set_has_output_type(); + output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type) +} + void MethodDescriptorProto::set_output_type(const char* value, size_t size) { + set_has_output_type(); + output_type_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type) +} + ::std::string* MethodDescriptorProto::mutable_output_type() { + set_has_output_type(); + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type) + return output_type_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* MethodDescriptorProto::release_output_type() { + clear_has_output_type(); + return output_type_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) { + if (output_type != NULL) { + set_has_output_type(); + } else { + clear_has_output_type(); + } + output_type_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), output_type); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type) +} + +// optional .google.protobuf.MethodOptions options = 4; + bool MethodDescriptorProto::has_options() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void MethodDescriptorProto::set_has_options() { + _has_bits_[0] |= 0x00000008u; +} + void MethodDescriptorProto::clear_has_options() { + _has_bits_[0] &= ~0x00000008u; +} + void MethodDescriptorProto::clear_options() { + if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); + clear_has_options(); +} + const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options) + return options_ != NULL ? *options_ : *default_instance_->options_; +} + ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { + set_has_options(); + if (options_ == NULL) { + options_ = new ::google::protobuf::MethodOptions; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) + return options_; +} + ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() { + clear_has_options(); + ::google::protobuf::MethodOptions* temp = options_; + options_ = NULL; + return temp; +} + void MethodDescriptorProto::set_allocated_options(::google::protobuf::MethodOptions* options) { + delete options_; + options_ = options; + if (options) { + set_has_options(); + } else { + clear_has_options(); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options) +} + +// optional bool client_streaming = 5 [default = false]; + bool MethodDescriptorProto::has_client_streaming() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void MethodDescriptorProto::set_has_client_streaming() { + _has_bits_[0] |= 0x00000010u; +} + void MethodDescriptorProto::clear_has_client_streaming() { + _has_bits_[0] &= ~0x00000010u; +} + void MethodDescriptorProto::clear_client_streaming() { + client_streaming_ = false; + clear_has_client_streaming(); +} + bool MethodDescriptorProto::client_streaming() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.client_streaming) + return client_streaming_; +} + void MethodDescriptorProto::set_client_streaming(bool value) { + set_has_client_streaming(); + client_streaming_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.client_streaming) +} + +// optional bool server_streaming = 6 [default = false]; + bool MethodDescriptorProto::has_server_streaming() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} + void MethodDescriptorProto::set_has_server_streaming() { + _has_bits_[0] |= 0x00000020u; +} + void MethodDescriptorProto::clear_has_server_streaming() { + _has_bits_[0] &= ~0x00000020u; +} + void MethodDescriptorProto::clear_server_streaming() { + server_streaming_ = false; + clear_has_server_streaming(); +} + bool MethodDescriptorProto::server_streaming() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.server_streaming) + return server_streaming_; +} + void MethodDescriptorProto::set_server_streaming(bool value) { + set_has_server_streaming(); + server_streaming_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.server_streaming) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS + +// =================================================================== + +const ::google::protobuf::EnumDescriptor* FileOptions_OptimizeMode_descriptor() { + protobuf_AssignDescriptorsOnce(); + return FileOptions_OptimizeMode_descriptor_; +} +bool FileOptions_OptimizeMode_IsValid(int value) { + switch(value) { + case 1: + case 2: + case 3: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const FileOptions_OptimizeMode FileOptions::SPEED; +const FileOptions_OptimizeMode FileOptions::CODE_SIZE; +const FileOptions_OptimizeMode FileOptions::LITE_RUNTIME; +const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; +const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; +const int FileOptions::OptimizeMode_ARRAYSIZE; #endif // _MSC_VER #ifndef _MSC_VER const int FileOptions::kJavaPackageFieldNumber; @@ -5114,6 +7015,7 @@ const int FileOptions::kJavaGenericServicesFieldNumber; const int FileOptions::kPyGenericServicesFieldNumber; const int FileOptions::kDeprecatedFieldNumber; const int FileOptions::kCcEnableArenasFieldNumber; +const int FileOptions::kObjcClassPrefixFieldNumber; const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER @@ -5149,6 +7051,7 @@ void FileOptions::SharedCtor() { py_generic_services_ = false; deprecated_ = false; cc_enable_arenas_ = false; + objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -5161,6 +7064,7 @@ void FileOptions::SharedDtor() { java_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); java_outer_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (this != default_instance_) { } } @@ -5192,15 +7096,13 @@ FileOptions* FileOptions::New(::google::protobuf::Arena* arena) const { void FileOptions::Clear() { _extensions_.Clear(); -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) if (_has_bits_[0 / 32] & 255) { ZR_(java_multiple_files_, cc_generic_services_); @@ -5215,9 +7117,14 @@ void FileOptions::Clear() { go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } } - ZR_(java_generic_services_, cc_enable_arenas_); + if (_has_bits_[8 / 32] & 7936) { + ZR_(java_generic_services_, cc_enable_arenas_); + if (has_objc_class_prefix()) { + objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + } -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ uninterpreted_option_.Clear(); @@ -5423,6 +7330,23 @@ bool FileOptions::MergePartialFromCodedStream( } else { goto handle_unusual; } + if (input->ExpectTag(290)) goto parse_objc_class_prefix; + break; + } + + // optional string objc_class_prefix = 36; + case 36: { + if (tag == 290) { + parse_objc_class_prefix: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_objc_class_prefix())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->objc_class_prefix().data(), this->objc_class_prefix().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.FileOptions.objc_class_prefix"); + } else { + goto handle_unusual; + } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } @@ -5547,6 +7471,16 @@ void FileOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteBool(31, this->cc_enable_arenas(), output); } + // optional string objc_class_prefix = 36; + if (has_objc_class_prefix()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->objc_class_prefix().data(), this->objc_class_prefix().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.objc_class_prefix"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 36, this->objc_class_prefix(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -5646,6 +7580,17 @@ void FileOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(31, this->cc_enable_arenas(), target); } + // optional string objc_class_prefix = 36; + if (has_objc_class_prefix()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->objc_class_prefix().data(), this->objc_class_prefix().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.objc_class_prefix"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 36, this->objc_class_prefix(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -5717,7 +7662,7 @@ int FileOptions::ByteSize() const { } } - if (_has_bits_[8 / 32] & 3840) { + if (_has_bits_[8 / 32] & 7936) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; @@ -5738,6 +7683,13 @@ int FileOptions::ByteSize() const { total_size += 2 + 1; } + // optional string objc_class_prefix = 36; + if (has_objc_class_prefix()) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->objc_class_prefix()); + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -5817,6 +7769,10 @@ void FileOptions::MergeFrom(const FileOptions& from) { if (from.has_cc_enable_arenas()) { set_cc_enable_arenas(from.cc_enable_arenas()); } + if (from.has_objc_class_prefix()) { + set_has_objc_class_prefix(); + objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_); + } } _extensions_.MergeFrom(from._extensions_); if (from._internal_metadata_.have_unknown_fields()) { @@ -5860,6 +7816,7 @@ void FileOptions::InternalSwap(FileOptions* other) { std::swap(py_generic_services_, other->py_generic_services_); std::swap(deprecated_, other->deprecated_); std::swap(cc_enable_arenas_, other->cc_enable_arenas_); + objc_class_prefix_.Swap(&other->objc_class_prefix_); uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); @@ -5875,6 +7832,469 @@ void FileOptions::InternalSwap(FileOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FileOptions + +// optional string java_package = 1; + bool FileOptions::has_java_package() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void FileOptions::set_has_java_package() { + _has_bits_[0] |= 0x00000001u; +} + void FileOptions::clear_has_java_package() { + _has_bits_[0] &= ~0x00000001u; +} + void FileOptions::clear_java_package() { + java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_java_package(); +} + const ::std::string& FileOptions::java_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package) + return java_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_java_package(const ::std::string& value) { + set_has_java_package(); + java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package) +} + void FileOptions::set_java_package(const char* value) { + set_has_java_package(); + java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package) +} + void FileOptions::set_java_package(const char* value, size_t size) { + set_has_java_package(); + java_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package) +} + ::std::string* FileOptions::mutable_java_package() { + set_has_java_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package) + return java_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_java_package() { + clear_has_java_package(); + return java_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_java_package(::std::string* java_package) { + if (java_package != NULL) { + set_has_java_package(); + } else { + clear_has_java_package(); + } + java_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_package); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package) +} + +// optional string java_outer_classname = 8; + bool FileOptions::has_java_outer_classname() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void FileOptions::set_has_java_outer_classname() { + _has_bits_[0] |= 0x00000002u; +} + void FileOptions::clear_has_java_outer_classname() { + _has_bits_[0] &= ~0x00000002u; +} + void FileOptions::clear_java_outer_classname() { + java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_java_outer_classname(); +} + const ::std::string& FileOptions::java_outer_classname() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname) + return java_outer_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_java_outer_classname(const ::std::string& value) { + set_has_java_outer_classname(); + java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname) +} + void FileOptions::set_java_outer_classname(const char* value) { + set_has_java_outer_classname(); + java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname) +} + void FileOptions::set_java_outer_classname(const char* value, size_t size) { + set_has_java_outer_classname(); + java_outer_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname) +} + ::std::string* FileOptions::mutable_java_outer_classname() { + set_has_java_outer_classname(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname) + return java_outer_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_java_outer_classname() { + clear_has_java_outer_classname(); + return java_outer_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) { + if (java_outer_classname != NULL) { + set_has_java_outer_classname(); + } else { + clear_has_java_outer_classname(); + } + java_outer_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), java_outer_classname); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname) +} + +// optional bool java_multiple_files = 10 [default = false]; + bool FileOptions::has_java_multiple_files() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void FileOptions::set_has_java_multiple_files() { + _has_bits_[0] |= 0x00000004u; +} + void FileOptions::clear_has_java_multiple_files() { + _has_bits_[0] &= ~0x00000004u; +} + void FileOptions::clear_java_multiple_files() { + java_multiple_files_ = false; + clear_has_java_multiple_files(); +} + bool FileOptions::java_multiple_files() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files) + return java_multiple_files_; +} + void FileOptions::set_java_multiple_files(bool value) { + set_has_java_multiple_files(); + java_multiple_files_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files) +} + +// optional bool java_generate_equals_and_hash = 20 [default = false]; + bool FileOptions::has_java_generate_equals_and_hash() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void FileOptions::set_has_java_generate_equals_and_hash() { + _has_bits_[0] |= 0x00000008u; +} + void FileOptions::clear_has_java_generate_equals_and_hash() { + _has_bits_[0] &= ~0x00000008u; +} + void FileOptions::clear_java_generate_equals_and_hash() { + java_generate_equals_and_hash_ = false; + clear_has_java_generate_equals_and_hash(); +} + bool FileOptions::java_generate_equals_and_hash() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash) + return java_generate_equals_and_hash_; +} + void FileOptions::set_java_generate_equals_and_hash(bool value) { + set_has_java_generate_equals_and_hash(); + java_generate_equals_and_hash_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash) +} + +// optional bool java_string_check_utf8 = 27 [default = false]; + bool FileOptions::has_java_string_check_utf8() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void FileOptions::set_has_java_string_check_utf8() { + _has_bits_[0] |= 0x00000010u; +} + void FileOptions::clear_has_java_string_check_utf8() { + _has_bits_[0] &= ~0x00000010u; +} + void FileOptions::clear_java_string_check_utf8() { + java_string_check_utf8_ = false; + clear_has_java_string_check_utf8(); +} + bool FileOptions::java_string_check_utf8() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8) + return java_string_check_utf8_; +} + void FileOptions::set_java_string_check_utf8(bool value) { + set_has_java_string_check_utf8(); + java_string_check_utf8_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8) +} + +// optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; + bool FileOptions::has_optimize_for() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} + void FileOptions::set_has_optimize_for() { + _has_bits_[0] |= 0x00000020u; +} + void FileOptions::clear_has_optimize_for() { + _has_bits_[0] &= ~0x00000020u; +} + void FileOptions::clear_optimize_for() { + optimize_for_ = 1; + clear_has_optimize_for(); +} + ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for) + return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_); +} + void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) { + assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); + set_has_optimize_for(); + optimize_for_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for) +} + +// optional string go_package = 11; + bool FileOptions::has_go_package() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} + void FileOptions::set_has_go_package() { + _has_bits_[0] |= 0x00000040u; +} + void FileOptions::clear_has_go_package() { + _has_bits_[0] &= ~0x00000040u; +} + void FileOptions::clear_go_package() { + go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_go_package(); +} + const ::std::string& FileOptions::go_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package) + return go_package_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_go_package(const ::std::string& value) { + set_has_go_package(); + go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package) +} + void FileOptions::set_go_package(const char* value) { + set_has_go_package(); + go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package) +} + void FileOptions::set_go_package(const char* value, size_t size) { + set_has_go_package(); + go_package_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package) +} + ::std::string* FileOptions::mutable_go_package() { + set_has_go_package(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package) + return go_package_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_go_package() { + clear_has_go_package(); + return go_package_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_go_package(::std::string* go_package) { + if (go_package != NULL) { + set_has_go_package(); + } else { + clear_has_go_package(); + } + go_package_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), go_package); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package) +} + +// optional bool cc_generic_services = 16 [default = false]; + bool FileOptions::has_cc_generic_services() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} + void FileOptions::set_has_cc_generic_services() { + _has_bits_[0] |= 0x00000080u; +} + void FileOptions::clear_has_cc_generic_services() { + _has_bits_[0] &= ~0x00000080u; +} + void FileOptions::clear_cc_generic_services() { + cc_generic_services_ = false; + clear_has_cc_generic_services(); +} + bool FileOptions::cc_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services) + return cc_generic_services_; +} + void FileOptions::set_cc_generic_services(bool value) { + set_has_cc_generic_services(); + cc_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services) +} + +// optional bool java_generic_services = 17 [default = false]; + bool FileOptions::has_java_generic_services() const { + return (_has_bits_[0] & 0x00000100u) != 0; +} + void FileOptions::set_has_java_generic_services() { + _has_bits_[0] |= 0x00000100u; +} + void FileOptions::clear_has_java_generic_services() { + _has_bits_[0] &= ~0x00000100u; +} + void FileOptions::clear_java_generic_services() { + java_generic_services_ = false; + clear_has_java_generic_services(); +} + bool FileOptions::java_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services) + return java_generic_services_; +} + void FileOptions::set_java_generic_services(bool value) { + set_has_java_generic_services(); + java_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services) +} + +// optional bool py_generic_services = 18 [default = false]; + bool FileOptions::has_py_generic_services() const { + return (_has_bits_[0] & 0x00000200u) != 0; +} + void FileOptions::set_has_py_generic_services() { + _has_bits_[0] |= 0x00000200u; +} + void FileOptions::clear_has_py_generic_services() { + _has_bits_[0] &= ~0x00000200u; +} + void FileOptions::clear_py_generic_services() { + py_generic_services_ = false; + clear_has_py_generic_services(); +} + bool FileOptions::py_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services) + return py_generic_services_; +} + void FileOptions::set_py_generic_services(bool value) { + set_has_py_generic_services(); + py_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services) +} + +// optional bool deprecated = 23 [default = false]; + bool FileOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} + void FileOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000400u; +} + void FileOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000400u; +} + void FileOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool FileOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated) + return deprecated_; +} + void FileOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated) +} + +// optional bool cc_enable_arenas = 31 [default = false]; + bool FileOptions::has_cc_enable_arenas() const { + return (_has_bits_[0] & 0x00000800u) != 0; +} + void FileOptions::set_has_cc_enable_arenas() { + _has_bits_[0] |= 0x00000800u; +} + void FileOptions::clear_has_cc_enable_arenas() { + _has_bits_[0] &= ~0x00000800u; +} + void FileOptions::clear_cc_enable_arenas() { + cc_enable_arenas_ = false; + clear_has_cc_enable_arenas(); +} + bool FileOptions::cc_enable_arenas() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_enable_arenas) + return cc_enable_arenas_; +} + void FileOptions::set_cc_enable_arenas(bool value) { + set_has_cc_enable_arenas(); + cc_enable_arenas_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas) +} + +// optional string objc_class_prefix = 36; + bool FileOptions::has_objc_class_prefix() const { + return (_has_bits_[0] & 0x00001000u) != 0; +} + void FileOptions::set_has_objc_class_prefix() { + _has_bits_[0] |= 0x00001000u; +} + void FileOptions::clear_has_objc_class_prefix() { + _has_bits_[0] &= ~0x00001000u; +} + void FileOptions::clear_objc_class_prefix() { + objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_objc_class_prefix(); +} + const ::std::string& FileOptions::objc_class_prefix() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix) + return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_objc_class_prefix(const ::std::string& value) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix) +} + void FileOptions::set_objc_class_prefix(const char* value) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix) +} + void FileOptions::set_objc_class_prefix(const char* value, size_t size) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix) +} + ::std::string* FileOptions::mutable_objc_class_prefix() { + set_has_objc_class_prefix(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix) + return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_objc_class_prefix() { + clear_has_objc_class_prefix(); + return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) { + if (objc_class_prefix != NULL) { + set_has_objc_class_prefix(); + } else { + clear_has_objc_class_prefix(); + } + objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int FileOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void FileOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FileOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +FileOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -5949,19 +8369,17 @@ MessageOptions* MessageOptions::New(::google::protobuf::Arena* arena) const { void MessageOptions::Clear() { _extensions_.Clear(); -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(message_set_wire_format_, map_entry_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ uninterpreted_option_.Clear(); @@ -6287,6 +8705,136 @@ void MessageOptions::InternalSwap(MessageOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MessageOptions + +// optional bool message_set_wire_format = 1 [default = false]; + bool MessageOptions::has_message_set_wire_format() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void MessageOptions::set_has_message_set_wire_format() { + _has_bits_[0] |= 0x00000001u; +} + void MessageOptions::clear_has_message_set_wire_format() { + _has_bits_[0] &= ~0x00000001u; +} + void MessageOptions::clear_message_set_wire_format() { + message_set_wire_format_ = false; + clear_has_message_set_wire_format(); +} + bool MessageOptions::message_set_wire_format() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format) + return message_set_wire_format_; +} + void MessageOptions::set_message_set_wire_format(bool value) { + set_has_message_set_wire_format(); + message_set_wire_format_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format) +} + +// optional bool no_standard_descriptor_accessor = 2 [default = false]; + bool MessageOptions::has_no_standard_descriptor_accessor() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void MessageOptions::set_has_no_standard_descriptor_accessor() { + _has_bits_[0] |= 0x00000002u; +} + void MessageOptions::clear_has_no_standard_descriptor_accessor() { + _has_bits_[0] &= ~0x00000002u; +} + void MessageOptions::clear_no_standard_descriptor_accessor() { + no_standard_descriptor_accessor_ = false; + clear_has_no_standard_descriptor_accessor(); +} + bool MessageOptions::no_standard_descriptor_accessor() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor) + return no_standard_descriptor_accessor_; +} + void MessageOptions::set_no_standard_descriptor_accessor(bool value) { + set_has_no_standard_descriptor_accessor(); + no_standard_descriptor_accessor_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor) +} + +// optional bool deprecated = 3 [default = false]; + bool MessageOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void MessageOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000004u; +} + void MessageOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000004u; +} + void MessageOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool MessageOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated) + return deprecated_; +} + void MessageOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated) +} + +// optional bool map_entry = 7; + bool MessageOptions::has_map_entry() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void MessageOptions::set_has_map_entry() { + _has_bits_[0] |= 0x00000008u; +} + void MessageOptions::clear_has_map_entry() { + _has_bits_[0] &= ~0x00000008u; +} + void MessageOptions::clear_map_entry() { + map_entry_ = false; + clear_has_map_entry(); +} + bool MessageOptions::map_entry() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.map_entry) + return map_entry_; +} + void MessageOptions::set_map_entry(bool value) { + set_has_map_entry(); + map_entry_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.map_entry) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int MessageOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void MessageOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MessageOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +MessageOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -6386,21 +8934,19 @@ FieldOptions* FieldOptions::New(::google::protobuf::Arena* arena) const { void FieldOptions::Clear() { _extensions_.Clear(); -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) if (_has_bits_[0 / 32] & 31) { ZR_(ctype_, weak_); } -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ uninterpreted_option_.Clear(); @@ -6768,6 +9314,161 @@ void FieldOptions::InternalSwap(FieldOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// FieldOptions + +// optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; + bool FieldOptions::has_ctype() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void FieldOptions::set_has_ctype() { + _has_bits_[0] |= 0x00000001u; +} + void FieldOptions::clear_has_ctype() { + _has_bits_[0] &= ~0x00000001u; +} + void FieldOptions::clear_ctype() { + ctype_ = 0; + clear_has_ctype(); +} + ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype) + return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_); +} + void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) { + assert(::google::protobuf::FieldOptions_CType_IsValid(value)); + set_has_ctype(); + ctype_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype) +} + +// optional bool packed = 2; + bool FieldOptions::has_packed() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void FieldOptions::set_has_packed() { + _has_bits_[0] |= 0x00000002u; +} + void FieldOptions::clear_has_packed() { + _has_bits_[0] &= ~0x00000002u; +} + void FieldOptions::clear_packed() { + packed_ = false; + clear_has_packed(); +} + bool FieldOptions::packed() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed) + return packed_; +} + void FieldOptions::set_packed(bool value) { + set_has_packed(); + packed_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) +} + +// optional bool lazy = 5 [default = false]; + bool FieldOptions::has_lazy() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void FieldOptions::set_has_lazy() { + _has_bits_[0] |= 0x00000004u; +} + void FieldOptions::clear_has_lazy() { + _has_bits_[0] &= ~0x00000004u; +} + void FieldOptions::clear_lazy() { + lazy_ = false; + clear_has_lazy(); +} + bool FieldOptions::lazy() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy) + return lazy_; +} + void FieldOptions::set_lazy(bool value) { + set_has_lazy(); + lazy_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy) +} + +// optional bool deprecated = 3 [default = false]; + bool FieldOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void FieldOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000008u; +} + void FieldOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000008u; +} + void FieldOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool FieldOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated) + return deprecated_; +} + void FieldOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated) +} + +// optional bool weak = 10 [default = false]; + bool FieldOptions::has_weak() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void FieldOptions::set_has_weak() { + _has_bits_[0] |= 0x00000010u; +} + void FieldOptions::clear_has_weak() { + _has_bits_[0] &= ~0x00000010u; +} + void FieldOptions::clear_weak() { + weak_ = false; + clear_has_weak(); +} + bool FieldOptions::weak() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak) + return weak_; +} + void FieldOptions::set_weak(bool value) { + set_has_weak(); + weak_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int FieldOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void FieldOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +FieldOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +FieldOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -6838,19 +9539,17 @@ EnumOptions* EnumOptions::New(::google::protobuf::Arena* arena) const { void EnumOptions::Clear() { _extensions_.Clear(); -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) ZR_(allow_alias_, deprecated_); -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ uninterpreted_option_.Clear(); @@ -7108,6 +9807,88 @@ void EnumOptions::InternalSwap(EnumOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EnumOptions + +// optional bool allow_alias = 2; + bool EnumOptions::has_allow_alias() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void EnumOptions::set_has_allow_alias() { + _has_bits_[0] |= 0x00000001u; +} + void EnumOptions::clear_has_allow_alias() { + _has_bits_[0] &= ~0x00000001u; +} + void EnumOptions::clear_allow_alias() { + allow_alias_ = false; + clear_has_allow_alias(); +} + bool EnumOptions::allow_alias() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias) + return allow_alias_; +} + void EnumOptions::set_allow_alias(bool value) { + set_has_allow_alias(); + allow_alias_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias) +} + +// optional bool deprecated = 3 [default = false]; + bool EnumOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void EnumOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000002u; +} + void EnumOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000002u; +} + void EnumOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool EnumOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated) + return deprecated_; +} + void EnumOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int EnumOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void EnumOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +EnumOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -7396,6 +10177,64 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// EnumValueOptions + +// optional bool deprecated = 1 [default = false]; + bool EnumValueOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void EnumValueOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} + void EnumValueOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} + void EnumValueOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool EnumValueOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated) + return deprecated_; +} + void EnumValueOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int EnumValueOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void EnumValueOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +EnumValueOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +EnumValueOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -7684,6 +10523,64 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// ServiceOptions + +// optional bool deprecated = 33 [default = false]; + bool ServiceOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void ServiceOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} + void ServiceOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} + void ServiceOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool ServiceOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated) + return deprecated_; +} + void ServiceOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int ServiceOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void ServiceOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +ServiceOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +ServiceOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -7972,6 +10869,64 @@ void MethodOptions::InternalSwap(MethodOptions* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// MethodOptions + +// optional bool deprecated = 33 [default = false]; + bool MethodOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void MethodOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} + void MethodOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} + void MethodOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} + bool MethodOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated) + return deprecated_; +} + void MethodOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated) +} + +// repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; + int MethodOptions::uninterpreted_option_size() const { + return uninterpreted_option_.size(); +} + void MethodOptions::clear_uninterpreted_option() { + uninterpreted_option_.Clear(); +} + const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_.Get(index); +} + ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_.Mutable(index); +} + ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& +MethodOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) + return uninterpreted_option_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* +MethodOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) + return &uninterpreted_option_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -8359,15 +11314,13 @@ UninterpretedOption* UninterpretedOption::New(::google::protobuf::Arena* arena) } void UninterpretedOption::Clear() { -#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ - &reinterpret_cast(16)->f) - \ - reinterpret_cast(16)) +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) -#define ZR_(first, last) do { \ - size_t f = OFFSET_OF_FIELD_(first); \ - size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ - ::memset(&first, 0, n); \ - } while (0) +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) if (_has_bits_[0 / 32] & 126) { ZR_(positive_int_value_, double_value_); @@ -8382,7 +11335,7 @@ void UninterpretedOption::Clear() { } } -#undef OFFSET_OF_FIELD_ +#undef ZR_HELPER_ #undef ZR_ name_.Clear(); @@ -8799,6 +11752,352 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// UninterpretedOption_NamePart + +// required string name_part = 1; + bool UninterpretedOption_NamePart::has_name_part() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} + void UninterpretedOption_NamePart::set_has_name_part() { + _has_bits_[0] |= 0x00000001u; +} + void UninterpretedOption_NamePart::clear_has_name_part() { + _has_bits_[0] &= ~0x00000001u; +} + void UninterpretedOption_NamePart::clear_name_part() { + name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_name_part(); +} + const ::std::string& UninterpretedOption_NamePart::name_part() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part) + return name_part_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) { + set_has_name_part(); + name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part) +} + void UninterpretedOption_NamePart::set_name_part(const char* value) { + set_has_name_part(); + name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part) +} + void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { + set_has_name_part(); + name_part_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part) +} + ::std::string* UninterpretedOption_NamePart::mutable_name_part() { + set_has_name_part(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part) + return name_part_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* UninterpretedOption_NamePart::release_name_part() { + clear_has_name_part(); + return name_part_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) { + if (name_part != NULL) { + set_has_name_part(); + } else { + clear_has_name_part(); + } + name_part_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), name_part); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part) +} + +// required bool is_extension = 2; + bool UninterpretedOption_NamePart::has_is_extension() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void UninterpretedOption_NamePart::set_has_is_extension() { + _has_bits_[0] |= 0x00000002u; +} + void UninterpretedOption_NamePart::clear_has_is_extension() { + _has_bits_[0] &= ~0x00000002u; +} + void UninterpretedOption_NamePart::clear_is_extension() { + is_extension_ = false; + clear_has_is_extension(); +} + bool UninterpretedOption_NamePart::is_extension() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension) + return is_extension_; +} + void UninterpretedOption_NamePart::set_is_extension(bool value) { + set_has_is_extension(); + is_extension_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension) +} + +// ------------------------------------------------------------------- + +// UninterpretedOption + +// repeated .google.protobuf.UninterpretedOption.NamePart name = 2; + int UninterpretedOption::name_size() const { + return name_.size(); +} + void UninterpretedOption::clear_name() { + name_.Clear(); +} + const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name) + return name_.Get(index); +} + ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name) + return name_.Mutable(index); +} + ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() { + // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) + return name_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& +UninterpretedOption::name() const { + // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) + return name_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* +UninterpretedOption::mutable_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) + return &name_; +} + +// optional string identifier_value = 3; + bool UninterpretedOption::has_identifier_value() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} + void UninterpretedOption::set_has_identifier_value() { + _has_bits_[0] |= 0x00000002u; +} + void UninterpretedOption::clear_has_identifier_value() { + _has_bits_[0] &= ~0x00000002u; +} + void UninterpretedOption::clear_identifier_value() { + identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_identifier_value(); +} + const ::std::string& UninterpretedOption::identifier_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value) + return identifier_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_identifier_value(const ::std::string& value) { + set_has_identifier_value(); + identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value) +} + void UninterpretedOption::set_identifier_value(const char* value) { + set_has_identifier_value(); + identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value) +} + void UninterpretedOption::set_identifier_value(const char* value, size_t size) { + set_has_identifier_value(); + identifier_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value) +} + ::std::string* UninterpretedOption::mutable_identifier_value() { + set_has_identifier_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value) + return identifier_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* UninterpretedOption::release_identifier_value() { + clear_has_identifier_value(); + return identifier_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) { + if (identifier_value != NULL) { + set_has_identifier_value(); + } else { + clear_has_identifier_value(); + } + identifier_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), identifier_value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value) +} + +// optional uint64 positive_int_value = 4; + bool UninterpretedOption::has_positive_int_value() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void UninterpretedOption::set_has_positive_int_value() { + _has_bits_[0] |= 0x00000004u; +} + void UninterpretedOption::clear_has_positive_int_value() { + _has_bits_[0] &= ~0x00000004u; +} + void UninterpretedOption::clear_positive_int_value() { + positive_int_value_ = GOOGLE_ULONGLONG(0); + clear_has_positive_int_value(); +} + ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value) + return positive_int_value_; +} + void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) { + set_has_positive_int_value(); + positive_int_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value) +} + +// optional int64 negative_int_value = 5; + bool UninterpretedOption::has_negative_int_value() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void UninterpretedOption::set_has_negative_int_value() { + _has_bits_[0] |= 0x00000008u; +} + void UninterpretedOption::clear_has_negative_int_value() { + _has_bits_[0] &= ~0x00000008u; +} + void UninterpretedOption::clear_negative_int_value() { + negative_int_value_ = GOOGLE_LONGLONG(0); + clear_has_negative_int_value(); +} + ::google::protobuf::int64 UninterpretedOption::negative_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value) + return negative_int_value_; +} + void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) { + set_has_negative_int_value(); + negative_int_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value) +} + +// optional double double_value = 6; + bool UninterpretedOption::has_double_value() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} + void UninterpretedOption::set_has_double_value() { + _has_bits_[0] |= 0x00000010u; +} + void UninterpretedOption::clear_has_double_value() { + _has_bits_[0] &= ~0x00000010u; +} + void UninterpretedOption::clear_double_value() { + double_value_ = 0; + clear_has_double_value(); +} + double UninterpretedOption::double_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value) + return double_value_; +} + void UninterpretedOption::set_double_value(double value) { + set_has_double_value(); + double_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value) +} + +// optional bytes string_value = 7; + bool UninterpretedOption::has_string_value() const { + return (_has_bits_[0] & 0x00000020u) != 0; +} + void UninterpretedOption::set_has_string_value() { + _has_bits_[0] |= 0x00000020u; +} + void UninterpretedOption::clear_has_string_value() { + _has_bits_[0] &= ~0x00000020u; +} + void UninterpretedOption::clear_string_value() { + string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_string_value(); +} + const ::std::string& UninterpretedOption::string_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value) + return string_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_string_value(const ::std::string& value) { + set_has_string_value(); + string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value) +} + void UninterpretedOption::set_string_value(const char* value) { + set_has_string_value(); + string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value) +} + void UninterpretedOption::set_string_value(const void* value, size_t size) { + set_has_string_value(); + string_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value) +} + ::std::string* UninterpretedOption::mutable_string_value() { + set_has_string_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value) + return string_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* UninterpretedOption::release_string_value() { + clear_has_string_value(); + return string_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_allocated_string_value(::std::string* string_value) { + if (string_value != NULL) { + set_has_string_value(); + } else { + clear_has_string_value(); + } + string_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value) +} + +// optional string aggregate_value = 8; + bool UninterpretedOption::has_aggregate_value() const { + return (_has_bits_[0] & 0x00000040u) != 0; +} + void UninterpretedOption::set_has_aggregate_value() { + _has_bits_[0] |= 0x00000040u; +} + void UninterpretedOption::clear_has_aggregate_value() { + _has_bits_[0] &= ~0x00000040u; +} + void UninterpretedOption::clear_aggregate_value() { + aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_aggregate_value(); +} + const ::std::string& UninterpretedOption::aggregate_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value) + return aggregate_value_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_aggregate_value(const ::std::string& value) { + set_has_aggregate_value(); + aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value) +} + void UninterpretedOption::set_aggregate_value(const char* value) { + set_has_aggregate_value(); + aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value) +} + void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { + set_has_aggregate_value(); + aggregate_value_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value) +} + ::std::string* UninterpretedOption::mutable_aggregate_value() { + set_has_aggregate_value(); + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value) + return aggregate_value_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* UninterpretedOption::release_aggregate_value() { + clear_has_aggregate_value(); + return aggregate_value_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) { + if (aggregate_value != NULL) { + set_has_aggregate_value(); + } else { + clear_has_aggregate_value(); + } + aggregate_value_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), aggregate_value); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value) +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -8807,6 +12106,7 @@ const int SourceCodeInfo_Location::kPathFieldNumber; const int SourceCodeInfo_Location::kSpanFieldNumber; const int SourceCodeInfo_Location::kLeadingCommentsFieldNumber; const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber; +const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber; #endif // !_MSC_VER SourceCodeInfo_Location::SourceCodeInfo_Location() @@ -8882,6 +12182,7 @@ void SourceCodeInfo_Location::Clear() { } path_.Clear(); span_.Clear(); + leading_detached_comments_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); if (_internal_metadata_.have_unknown_fields()) { mutable_unknown_fields()->Clear(); @@ -8963,6 +12264,25 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream( } else { goto handle_unusual; } + if (input->ExpectTag(50)) goto parse_leading_detached_comments; + break; + } + + // repeated string leading_detached_comments = 6; + case 6: { + if (tag == 50) { + parse_leading_detached_comments: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_leading_detached_comments())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_detached_comments(this->leading_detached_comments_size() - 1).data(), + this->leading_detached_comments(this->leading_detached_comments_size() - 1).length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(50)) goto parse_leading_detached_comments; if (input->ExpectAtEnd()) goto success; break; } @@ -9032,6 +12352,16 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( 4, this->trailing_comments(), output); } + // repeated string leading_detached_comments = 6; + for (int i = 0; i < this->leading_detached_comments_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + ::google::protobuf::internal::WireFormatLite::WriteString( + 6, this->leading_detached_comments(i), output); + } + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); @@ -9092,6 +12422,16 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( 4, this->trailing_comments(), target); } + // repeated string leading_detached_comments = 6; + for (int i = 0; i < this->leading_detached_comments_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->leading_detached_comments(i).data(), this->leading_detached_comments(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.SourceCodeInfo.Location.leading_detached_comments"); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(6, this->leading_detached_comments(i), target); + } + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); @@ -9153,6 +12493,13 @@ int SourceCodeInfo_Location::ByteSize() const { total_size += data_size; } + // repeated string leading_detached_comments = 6; + total_size += 1 * this->leading_detached_comments_size(); + for (int i = 0; i < this->leading_detached_comments_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->leading_detached_comments(i)); + } + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -9180,6 +12527,7 @@ void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); path_.MergeFrom(from.path_); span_.MergeFrom(from.span_); + leading_detached_comments_.MergeFrom(from.leading_detached_comments_); if (from._has_bits_[2 / 32] & (0xffu << (2 % 32))) { if (from.has_leading_comments()) { set_has_leading_comments(); @@ -9221,6 +12569,7 @@ void SourceCodeInfo_Location::InternalSwap(SourceCodeInfo_Location* other) { span_.UnsafeArenaSwap(&other->span_); leading_comments_.Swap(&other->leading_comments_); trailing_comments_.Swap(&other->trailing_comments_); + leading_detached_comments_.UnsafeArenaSwap(&other->leading_detached_comments_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); std::swap(_cached_size_, other->_cached_size_); @@ -9464,6 +12813,264 @@ void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) { return metadata; } +#if PROTOBUF_INLINE_NOT_IN_HEADERS +// SourceCodeInfo_Location + +// repeated int32 path = 1 [packed = true]; + int SourceCodeInfo_Location::path_size() const { + return path_.size(); +} + void SourceCodeInfo_Location::clear_path() { + path_.Clear(); +} + ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path) + return path_.Get(index); +} + void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) { + path_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path) +} + void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) { + path_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::path() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path) + return path_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_path() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path) + return &path_; +} + +// repeated int32 span = 2 [packed = true]; + int SourceCodeInfo_Location::span_size() const { + return span_.size(); +} + void SourceCodeInfo_Location::clear_span() { + span_.Clear(); +} + ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span) + return span_.Get(index); +} + void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) { + span_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span) +} + void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) { + span_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span) +} + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& +SourceCodeInfo_Location::span() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span) + return span_; +} + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* +SourceCodeInfo_Location::mutable_span() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span) + return &span_; +} + +// optional string leading_comments = 3; + bool SourceCodeInfo_Location::has_leading_comments() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} + void SourceCodeInfo_Location::set_has_leading_comments() { + _has_bits_[0] |= 0x00000004u; +} + void SourceCodeInfo_Location::clear_has_leading_comments() { + _has_bits_[0] &= ~0x00000004u; +} + void SourceCodeInfo_Location::clear_leading_comments() { + leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_leading_comments(); +} + const ::std::string& SourceCodeInfo_Location::leading_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments) + return leading_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) { + set_has_leading_comments(); + leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + void SourceCodeInfo_Location::set_leading_comments(const char* value) { + set_has_leading_comments(); + leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) { + set_has_leading_comments(); + leading_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + ::std::string* SourceCodeInfo_Location::mutable_leading_comments() { + set_has_leading_comments(); + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments) + return leading_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* SourceCodeInfo_Location::release_leading_comments() { + clear_has_leading_comments(); + return leading_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) { + if (leading_comments != NULL) { + set_has_leading_comments(); + } else { + clear_has_leading_comments(); + } + leading_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), leading_comments); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments) +} + +// optional string trailing_comments = 4; + bool SourceCodeInfo_Location::has_trailing_comments() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} + void SourceCodeInfo_Location::set_has_trailing_comments() { + _has_bits_[0] |= 0x00000008u; +} + void SourceCodeInfo_Location::clear_has_trailing_comments() { + _has_bits_[0] &= ~0x00000008u; +} + void SourceCodeInfo_Location::clear_trailing_comments() { + trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_trailing_comments(); +} + const ::std::string& SourceCodeInfo_Location::trailing_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return trailing_comments_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) { + set_has_trailing_comments(); + trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + void SourceCodeInfo_Location::set_trailing_comments(const char* value) { + set_has_trailing_comments(); + trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) { + set_has_trailing_comments(); + trailing_comments_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() { + set_has_trailing_comments(); + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments) + return trailing_comments_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* SourceCodeInfo_Location::release_trailing_comments() { + clear_has_trailing_comments(); + return trailing_comments_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) { + if (trailing_comments != NULL) { + set_has_trailing_comments(); + } else { + clear_has_trailing_comments(); + } + trailing_comments_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), trailing_comments); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) +} + +// repeated string leading_detached_comments = 6; + int SourceCodeInfo_Location::leading_detached_comments_size() const { + return leading_detached_comments_.size(); +} + void SourceCodeInfo_Location::clear_leading_detached_comments() { + leading_detached_comments_.Clear(); +} + const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_.Get(index); +} + ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_.Mutable(index); +} + void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + leading_detached_comments_.Mutable(index)->assign(value); +} + void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) { + leading_detached_comments_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) { + leading_detached_comments_.Mutable(index)->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() { + return leading_detached_comments_.Add(); +} + void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) { + leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) { + leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) { + leading_detached_comments_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} + const ::google::protobuf::RepeatedPtrField< ::std::string>& +SourceCodeInfo_Location::leading_detached_comments() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_; +} + ::google::protobuf::RepeatedPtrField< ::std::string>* +SourceCodeInfo_Location::mutable_leading_detached_comments() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return &leading_detached_comments_; +} + +// ------------------------------------------------------------------- + +// SourceCodeInfo + +// repeated .google.protobuf.SourceCodeInfo.Location location = 1; + int SourceCodeInfo::location_size() const { + return location_.size(); +} + void SourceCodeInfo::clear_location() { + location_.Clear(); +} + const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location) + return location_.Get(index); +} + ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location) + return location_.Mutable(index); +} + ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() { + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) + return location_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& +SourceCodeInfo::location() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) + return location_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* +SourceCodeInfo::mutable_location() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) + return &location_; +} + +#endif // PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index cda25982..d8cba659 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -222,15 +222,15 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message // accessors ------------------------------------------------------- // repeated .google.protobuf.FileDescriptorProto file = 1; - inline int file_size() const; - inline void clear_file(); + int file_size() const; + void clear_file(); static const int kFileFieldNumber = 1; - inline const ::google::protobuf::FileDescriptorProto& file(int index) const; - inline ::google::protobuf::FileDescriptorProto* mutable_file(int index); - inline ::google::protobuf::FileDescriptorProto* add_file(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& + const ::google::protobuf::FileDescriptorProto& file(int index) const; + ::google::protobuf::FileDescriptorProto* mutable_file(int index); + ::google::protobuf::FileDescriptorProto* add_file(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& file() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* mutable_file(); // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorSet) @@ -314,146 +314,146 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional string package = 2; - inline bool has_package() const; - inline void clear_package(); + bool has_package() const; + void clear_package(); static const int kPackageFieldNumber = 2; - inline const ::std::string& package() const; - inline void set_package(const ::std::string& value); - inline void set_package(const char* value); - inline void set_package(const char* value, size_t size); - inline ::std::string* mutable_package(); - inline ::std::string* release_package(); - inline void set_allocated_package(::std::string* package); + const ::std::string& package() const; + void set_package(const ::std::string& value); + void set_package(const char* value); + void set_package(const char* value, size_t size); + ::std::string* mutable_package(); + ::std::string* release_package(); + void set_allocated_package(::std::string* package); // repeated string dependency = 3; - inline int dependency_size() const; - inline void clear_dependency(); + int dependency_size() const; + void clear_dependency(); static const int kDependencyFieldNumber = 3; - inline const ::std::string& dependency(int index) const; - inline ::std::string* mutable_dependency(int index); - inline void set_dependency(int index, const ::std::string& value); - inline void set_dependency(int index, const char* value); - inline void set_dependency(int index, const char* value, size_t size); - inline ::std::string* add_dependency(); - inline void add_dependency(const ::std::string& value); - inline void add_dependency(const char* value); - inline void add_dependency(const char* value, size_t size); - inline const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const; - inline ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency(); + const ::std::string& dependency(int index) const; + ::std::string* mutable_dependency(int index); + void set_dependency(int index, const ::std::string& value); + void set_dependency(int index, const char* value); + void set_dependency(int index, const char* value, size_t size); + ::std::string* add_dependency(); + void add_dependency(const ::std::string& value); + void add_dependency(const char* value); + void add_dependency(const char* value, size_t size); + const ::google::protobuf::RepeatedPtrField< ::std::string>& dependency() const; + ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_dependency(); // repeated int32 public_dependency = 10; - inline int public_dependency_size() const; - inline void clear_public_dependency(); + int public_dependency_size() const; + void clear_public_dependency(); static const int kPublicDependencyFieldNumber = 10; - inline ::google::protobuf::int32 public_dependency(int index) const; - inline void set_public_dependency(int index, ::google::protobuf::int32 value); - inline void add_public_dependency(::google::protobuf::int32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + ::google::protobuf::int32 public_dependency(int index) const; + void set_public_dependency(int index, ::google::protobuf::int32 value); + void add_public_dependency(::google::protobuf::int32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& public_dependency() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* mutable_public_dependency(); // repeated int32 weak_dependency = 11; - inline int weak_dependency_size() const; - inline void clear_weak_dependency(); + int weak_dependency_size() const; + void clear_weak_dependency(); static const int kWeakDependencyFieldNumber = 11; - inline ::google::protobuf::int32 weak_dependency(int index) const; - inline void set_weak_dependency(int index, ::google::protobuf::int32 value); - inline void add_weak_dependency(::google::protobuf::int32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + ::google::protobuf::int32 weak_dependency(int index) const; + void set_weak_dependency(int index, ::google::protobuf::int32 value); + void add_weak_dependency(::google::protobuf::int32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& weak_dependency() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* mutable_weak_dependency(); // repeated .google.protobuf.DescriptorProto message_type = 4; - inline int message_type_size() const; - inline void clear_message_type(); + int message_type_size() const; + void clear_message_type(); static const int kMessageTypeFieldNumber = 4; - inline const ::google::protobuf::DescriptorProto& message_type(int index) const; - inline ::google::protobuf::DescriptorProto* mutable_message_type(int index); - inline ::google::protobuf::DescriptorProto* add_message_type(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + const ::google::protobuf::DescriptorProto& message_type(int index) const; + ::google::protobuf::DescriptorProto* mutable_message_type(int index); + ::google::protobuf::DescriptorProto* add_message_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& message_type() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_message_type(); // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; - inline int enum_type_size() const; - inline void clear_enum_type(); + int enum_type_size() const; + void clear_enum_type(); static const int kEnumTypeFieldNumber = 5; - inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; - inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); - inline ::google::protobuf::EnumDescriptorProto* add_enum_type(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; + ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); + ::google::protobuf::EnumDescriptorProto* add_enum_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& enum_type() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type(); // repeated .google.protobuf.ServiceDescriptorProto service = 6; - inline int service_size() const; - inline void clear_service(); + int service_size() const; + void clear_service(); static const int kServiceFieldNumber = 6; - inline const ::google::protobuf::ServiceDescriptorProto& service(int index) const; - inline ::google::protobuf::ServiceDescriptorProto* mutable_service(int index); - inline ::google::protobuf::ServiceDescriptorProto* add_service(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& + const ::google::protobuf::ServiceDescriptorProto& service(int index) const; + ::google::protobuf::ServiceDescriptorProto* mutable_service(int index); + ::google::protobuf::ServiceDescriptorProto* add_service(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& service() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* mutable_service(); // repeated .google.protobuf.FieldDescriptorProto extension = 7; - inline int extension_size() const; - inline void clear_extension(); + int extension_size() const; + void clear_extension(); static const int kExtensionFieldNumber = 7; - inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const; - inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); - inline ::google::protobuf::FieldDescriptorProto* add_extension(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + const ::google::protobuf::FieldDescriptorProto& extension(int index) const; + ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); + ::google::protobuf::FieldDescriptorProto* add_extension(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& extension() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension(); // optional .google.protobuf.FileOptions options = 8; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 8; - inline const ::google::protobuf::FileOptions& options() const; - inline ::google::protobuf::FileOptions* mutable_options(); - inline ::google::protobuf::FileOptions* release_options(); - inline void set_allocated_options(::google::protobuf::FileOptions* options); + const ::google::protobuf::FileOptions& options() const; + ::google::protobuf::FileOptions* mutable_options(); + ::google::protobuf::FileOptions* release_options(); + void set_allocated_options(::google::protobuf::FileOptions* options); // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - inline bool has_source_code_info() const; - inline void clear_source_code_info(); + bool has_source_code_info() const; + void clear_source_code_info(); static const int kSourceCodeInfoFieldNumber = 9; - inline const ::google::protobuf::SourceCodeInfo& source_code_info() const; - inline ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); - inline ::google::protobuf::SourceCodeInfo* release_source_code_info(); - inline void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info); + const ::google::protobuf::SourceCodeInfo& source_code_info() const; + ::google::protobuf::SourceCodeInfo* mutable_source_code_info(); + ::google::protobuf::SourceCodeInfo* release_source_code_info(); + void set_allocated_source_code_info(::google::protobuf::SourceCodeInfo* source_code_info); // optional string syntax = 12; - inline bool has_syntax() const; - inline void clear_syntax(); + bool has_syntax() const; + void clear_syntax(); static const int kSyntaxFieldNumber = 12; - inline const ::std::string& syntax() const; - inline void set_syntax(const ::std::string& value); - inline void set_syntax(const char* value); - inline void set_syntax(const char* value, size_t size); - inline ::std::string* mutable_syntax(); - inline ::std::string* release_syntax(); - inline void set_allocated_syntax(::std::string* syntax); + const ::std::string& syntax() const; + void set_syntax(const ::std::string& value); + void set_syntax(const char* value); + void set_syntax(const char* value, size_t size); + ::std::string* mutable_syntax(); + ::std::string* release_syntax(); + void set_allocated_syntax(::std::string* syntax); // @@protoc_insertion_point(class_scope:google.protobuf.FileDescriptorProto) private: @@ -557,18 +557,18 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto // accessors ------------------------------------------------------- // optional int32 start = 1; - inline bool has_start() const; - inline void clear_start(); + bool has_start() const; + void clear_start(); static const int kStartFieldNumber = 1; - inline ::google::protobuf::int32 start() const; - inline void set_start(::google::protobuf::int32 value); + ::google::protobuf::int32 start() const; + void set_start(::google::protobuf::int32 value); // optional int32 end = 2; - inline bool has_end() const; - inline void clear_end(); + bool has_end() const; + void clear_end(); static const int kEndFieldNumber = 2; - inline ::google::protobuf::int32 end() const; - inline void set_end(::google::protobuf::int32 value); + ::google::protobuf::int32 end() const; + void set_end(::google::protobuf::int32 value); // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange) private: @@ -658,97 +658,97 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // repeated .google.protobuf.FieldDescriptorProto field = 2; - inline int field_size() const; - inline void clear_field(); + int field_size() const; + void clear_field(); static const int kFieldFieldNumber = 2; - inline const ::google::protobuf::FieldDescriptorProto& field(int index) const; - inline ::google::protobuf::FieldDescriptorProto* mutable_field(int index); - inline ::google::protobuf::FieldDescriptorProto* add_field(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + const ::google::protobuf::FieldDescriptorProto& field(int index) const; + ::google::protobuf::FieldDescriptorProto* mutable_field(int index); + ::google::protobuf::FieldDescriptorProto* add_field(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& field() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_field(); // repeated .google.protobuf.FieldDescriptorProto extension = 6; - inline int extension_size() const; - inline void clear_extension(); + int extension_size() const; + void clear_extension(); static const int kExtensionFieldNumber = 6; - inline const ::google::protobuf::FieldDescriptorProto& extension(int index) const; - inline ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); - inline ::google::protobuf::FieldDescriptorProto* add_extension(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& + const ::google::protobuf::FieldDescriptorProto& extension(int index) const; + ::google::protobuf::FieldDescriptorProto* mutable_extension(int index); + ::google::protobuf::FieldDescriptorProto* add_extension(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& extension() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* mutable_extension(); // repeated .google.protobuf.DescriptorProto nested_type = 3; - inline int nested_type_size() const; - inline void clear_nested_type(); + int nested_type_size() const; + void clear_nested_type(); static const int kNestedTypeFieldNumber = 3; - inline const ::google::protobuf::DescriptorProto& nested_type(int index) const; - inline ::google::protobuf::DescriptorProto* mutable_nested_type(int index); - inline ::google::protobuf::DescriptorProto* add_nested_type(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& + const ::google::protobuf::DescriptorProto& nested_type(int index) const; + ::google::protobuf::DescriptorProto* mutable_nested_type(int index); + ::google::protobuf::DescriptorProto* add_nested_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& nested_type() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* mutable_nested_type(); // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; - inline int enum_type_size() const; - inline void clear_enum_type(); + int enum_type_size() const; + void clear_enum_type(); static const int kEnumTypeFieldNumber = 4; - inline const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; - inline ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); - inline ::google::protobuf::EnumDescriptorProto* add_enum_type(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& + const ::google::protobuf::EnumDescriptorProto& enum_type(int index) const; + ::google::protobuf::EnumDescriptorProto* mutable_enum_type(int index); + ::google::protobuf::EnumDescriptorProto* add_enum_type(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& enum_type() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* mutable_enum_type(); // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - inline int extension_range_size() const; - inline void clear_extension_range(); + int extension_range_size() const; + void clear_extension_range(); static const int kExtensionRangeFieldNumber = 5; - inline const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const; - inline ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index); - inline ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& + const ::google::protobuf::DescriptorProto_ExtensionRange& extension_range(int index) const; + ::google::protobuf::DescriptorProto_ExtensionRange* mutable_extension_range(int index); + ::google::protobuf::DescriptorProto_ExtensionRange* add_extension_range(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& extension_range() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* mutable_extension_range(); // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; - inline int oneof_decl_size() const; - inline void clear_oneof_decl(); + int oneof_decl_size() const; + void clear_oneof_decl(); static const int kOneofDeclFieldNumber = 8; - inline const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const; - inline ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index); - inline ::google::protobuf::OneofDescriptorProto* add_oneof_decl(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& + const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const; + ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index); + ::google::protobuf::OneofDescriptorProto* add_oneof_decl(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& oneof_decl() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* mutable_oneof_decl(); // optional .google.protobuf.MessageOptions options = 7; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 7; - inline const ::google::protobuf::MessageOptions& options() const; - inline ::google::protobuf::MessageOptions* mutable_options(); - inline ::google::protobuf::MessageOptions* release_options(); - inline void set_allocated_options(::google::protobuf::MessageOptions* options); + const ::google::protobuf::MessageOptions& options() const; + ::google::protobuf::MessageOptions* mutable_options(); + ::google::protobuf::MessageOptions* release_options(); + void set_allocated_options(::google::protobuf::MessageOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) private: @@ -907,89 +907,89 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional int32 number = 3; - inline bool has_number() const; - inline void clear_number(); + bool has_number() const; + void clear_number(); static const int kNumberFieldNumber = 3; - inline ::google::protobuf::int32 number() const; - inline void set_number(::google::protobuf::int32 value); + ::google::protobuf::int32 number() const; + void set_number(::google::protobuf::int32 value); // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - inline bool has_label() const; - inline void clear_label(); + bool has_label() const; + void clear_label(); static const int kLabelFieldNumber = 4; - inline ::google::protobuf::FieldDescriptorProto_Label label() const; - inline void set_label(::google::protobuf::FieldDescriptorProto_Label value); + ::google::protobuf::FieldDescriptorProto_Label label() const; + void set_label(::google::protobuf::FieldDescriptorProto_Label value); // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - inline bool has_type() const; - inline void clear_type(); + bool has_type() const; + void clear_type(); static const int kTypeFieldNumber = 5; - inline ::google::protobuf::FieldDescriptorProto_Type type() const; - inline void set_type(::google::protobuf::FieldDescriptorProto_Type value); + ::google::protobuf::FieldDescriptorProto_Type type() const; + void set_type(::google::protobuf::FieldDescriptorProto_Type value); // optional string type_name = 6; - inline bool has_type_name() const; - inline void clear_type_name(); + bool has_type_name() const; + void clear_type_name(); static const int kTypeNameFieldNumber = 6; - inline const ::std::string& type_name() const; - inline void set_type_name(const ::std::string& value); - inline void set_type_name(const char* value); - inline void set_type_name(const char* value, size_t size); - inline ::std::string* mutable_type_name(); - inline ::std::string* release_type_name(); - inline void set_allocated_type_name(::std::string* type_name); + const ::std::string& type_name() const; + void set_type_name(const ::std::string& value); + void set_type_name(const char* value); + void set_type_name(const char* value, size_t size); + ::std::string* mutable_type_name(); + ::std::string* release_type_name(); + void set_allocated_type_name(::std::string* type_name); // optional string extendee = 2; - inline bool has_extendee() const; - inline void clear_extendee(); + bool has_extendee() const; + void clear_extendee(); static const int kExtendeeFieldNumber = 2; - inline const ::std::string& extendee() const; - inline void set_extendee(const ::std::string& value); - inline void set_extendee(const char* value); - inline void set_extendee(const char* value, size_t size); - inline ::std::string* mutable_extendee(); - inline ::std::string* release_extendee(); - inline void set_allocated_extendee(::std::string* extendee); + const ::std::string& extendee() const; + void set_extendee(const ::std::string& value); + void set_extendee(const char* value); + void set_extendee(const char* value, size_t size); + ::std::string* mutable_extendee(); + ::std::string* release_extendee(); + void set_allocated_extendee(::std::string* extendee); // optional string default_value = 7; - inline bool has_default_value() const; - inline void clear_default_value(); + bool has_default_value() const; + void clear_default_value(); static const int kDefaultValueFieldNumber = 7; - inline const ::std::string& default_value() const; - inline void set_default_value(const ::std::string& value); - inline void set_default_value(const char* value); - inline void set_default_value(const char* value, size_t size); - inline ::std::string* mutable_default_value(); - inline ::std::string* release_default_value(); - inline void set_allocated_default_value(::std::string* default_value); + const ::std::string& default_value() const; + void set_default_value(const ::std::string& value); + void set_default_value(const char* value); + void set_default_value(const char* value, size_t size); + ::std::string* mutable_default_value(); + ::std::string* release_default_value(); + void set_allocated_default_value(::std::string* default_value); // optional int32 oneof_index = 9; - inline bool has_oneof_index() const; - inline void clear_oneof_index(); + bool has_oneof_index() const; + void clear_oneof_index(); static const int kOneofIndexFieldNumber = 9; - inline ::google::protobuf::int32 oneof_index() const; - inline void set_oneof_index(::google::protobuf::int32 value); + ::google::protobuf::int32 oneof_index() const; + void set_oneof_index(::google::protobuf::int32 value); // optional .google.protobuf.FieldOptions options = 8; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 8; - inline const ::google::protobuf::FieldOptions& options() const; - inline ::google::protobuf::FieldOptions* mutable_options(); - inline ::google::protobuf::FieldOptions* release_options(); - inline void set_allocated_options(::google::protobuf::FieldOptions* options); + const ::google::protobuf::FieldOptions& options() const; + ::google::protobuf::FieldOptions* mutable_options(); + ::google::protobuf::FieldOptions* release_options(); + void set_allocated_options(::google::protobuf::FieldOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.FieldDescriptorProto) private: @@ -1098,16 +1098,16 @@ class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Messa // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) private: @@ -1192,37 +1192,37 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // repeated .google.protobuf.EnumValueDescriptorProto value = 2; - inline int value_size() const; - inline void clear_value(); + int value_size() const; + void clear_value(); static const int kValueFieldNumber = 2; - inline const ::google::protobuf::EnumValueDescriptorProto& value(int index) const; - inline ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index); - inline ::google::protobuf::EnumValueDescriptorProto* add_value(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& + const ::google::protobuf::EnumValueDescriptorProto& value(int index) const; + ::google::protobuf::EnumValueDescriptorProto* mutable_value(int index); + ::google::protobuf::EnumValueDescriptorProto* add_value(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& value() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* mutable_value(); // optional .google.protobuf.EnumOptions options = 3; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 3; - inline const ::google::protobuf::EnumOptions& options() const; - inline ::google::protobuf::EnumOptions* mutable_options(); - inline ::google::protobuf::EnumOptions* release_options(); - inline void set_allocated_options(::google::protobuf::EnumOptions* options); + const ::google::protobuf::EnumOptions& options() const; + ::google::protobuf::EnumOptions* mutable_options(); + ::google::protobuf::EnumOptions* release_options(); + void set_allocated_options(::google::protobuf::EnumOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto) private: @@ -1311,32 +1311,32 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional int32 number = 2; - inline bool has_number() const; - inline void clear_number(); + bool has_number() const; + void clear_number(); static const int kNumberFieldNumber = 2; - inline ::google::protobuf::int32 number() const; - inline void set_number(::google::protobuf::int32 value); + ::google::protobuf::int32 number() const; + void set_number(::google::protobuf::int32 value); // optional .google.protobuf.EnumValueOptions options = 3; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 3; - inline const ::google::protobuf::EnumValueOptions& options() const; - inline ::google::protobuf::EnumValueOptions* mutable_options(); - inline ::google::protobuf::EnumValueOptions* release_options(); - inline void set_allocated_options(::google::protobuf::EnumValueOptions* options); + const ::google::protobuf::EnumValueOptions& options() const; + ::google::protobuf::EnumValueOptions* mutable_options(); + ::google::protobuf::EnumValueOptions* release_options(); + void set_allocated_options(::google::protobuf::EnumValueOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto) private: @@ -1427,37 +1427,37 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // repeated .google.protobuf.MethodDescriptorProto method = 2; - inline int method_size() const; - inline void clear_method(); + int method_size() const; + void clear_method(); static const int kMethodFieldNumber = 2; - inline const ::google::protobuf::MethodDescriptorProto& method(int index) const; - inline ::google::protobuf::MethodDescriptorProto* mutable_method(int index); - inline ::google::protobuf::MethodDescriptorProto* add_method(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& + const ::google::protobuf::MethodDescriptorProto& method(int index) const; + ::google::protobuf::MethodDescriptorProto* mutable_method(int index); + ::google::protobuf::MethodDescriptorProto* add_method(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& method() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* mutable_method(); // optional .google.protobuf.ServiceOptions options = 3; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 3; - inline const ::google::protobuf::ServiceOptions& options() const; - inline ::google::protobuf::ServiceOptions* mutable_options(); - inline ::google::protobuf::ServiceOptions* release_options(); - inline void set_allocated_options(::google::protobuf::ServiceOptions* options); + const ::google::protobuf::ServiceOptions& options() const; + ::google::protobuf::ServiceOptions* mutable_options(); + ::google::protobuf::ServiceOptions* release_options(); + void set_allocated_options(::google::protobuf::ServiceOptions* options); // @@protoc_insertion_point(class_scope:google.protobuf.ServiceDescriptorProto) private: @@ -1546,63 +1546,63 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess // accessors ------------------------------------------------------- // optional string name = 1; - inline bool has_name() const; - inline void clear_name(); + bool has_name() const; + void clear_name(); static const int kNameFieldNumber = 1; - inline const ::std::string& name() const; - inline void set_name(const ::std::string& value); - inline void set_name(const char* value); - inline void set_name(const char* value, size_t size); - inline ::std::string* mutable_name(); - inline ::std::string* release_name(); - inline void set_allocated_name(::std::string* name); + const ::std::string& name() const; + void set_name(const ::std::string& value); + void set_name(const char* value); + void set_name(const char* value, size_t size); + ::std::string* mutable_name(); + ::std::string* release_name(); + void set_allocated_name(::std::string* name); // optional string input_type = 2; - inline bool has_input_type() const; - inline void clear_input_type(); + bool has_input_type() const; + void clear_input_type(); static const int kInputTypeFieldNumber = 2; - inline const ::std::string& input_type() const; - inline void set_input_type(const ::std::string& value); - inline void set_input_type(const char* value); - inline void set_input_type(const char* value, size_t size); - inline ::std::string* mutable_input_type(); - inline ::std::string* release_input_type(); - inline void set_allocated_input_type(::std::string* input_type); + const ::std::string& input_type() const; + void set_input_type(const ::std::string& value); + void set_input_type(const char* value); + void set_input_type(const char* value, size_t size); + ::std::string* mutable_input_type(); + ::std::string* release_input_type(); + void set_allocated_input_type(::std::string* input_type); // optional string output_type = 3; - inline bool has_output_type() const; - inline void clear_output_type(); + bool has_output_type() const; + void clear_output_type(); static const int kOutputTypeFieldNumber = 3; - inline const ::std::string& output_type() const; - inline void set_output_type(const ::std::string& value); - inline void set_output_type(const char* value); - inline void set_output_type(const char* value, size_t size); - inline ::std::string* mutable_output_type(); - inline ::std::string* release_output_type(); - inline void set_allocated_output_type(::std::string* output_type); + const ::std::string& output_type() const; + void set_output_type(const ::std::string& value); + void set_output_type(const char* value); + void set_output_type(const char* value, size_t size); + ::std::string* mutable_output_type(); + ::std::string* release_output_type(); + void set_allocated_output_type(::std::string* output_type); // optional .google.protobuf.MethodOptions options = 4; - inline bool has_options() const; - inline void clear_options(); + bool has_options() const; + void clear_options(); static const int kOptionsFieldNumber = 4; - inline const ::google::protobuf::MethodOptions& options() const; - inline ::google::protobuf::MethodOptions* mutable_options(); - inline ::google::protobuf::MethodOptions* release_options(); - inline void set_allocated_options(::google::protobuf::MethodOptions* options); + const ::google::protobuf::MethodOptions& options() const; + ::google::protobuf::MethodOptions* mutable_options(); + ::google::protobuf::MethodOptions* release_options(); + void set_allocated_options(::google::protobuf::MethodOptions* options); // optional bool client_streaming = 5 [default = false]; - inline bool has_client_streaming() const; - inline void clear_client_streaming(); + bool has_client_streaming() const; + void clear_client_streaming(); static const int kClientStreamingFieldNumber = 5; - inline bool client_streaming() const; - inline void set_client_streaming(bool value); + bool client_streaming() const; + void set_client_streaming(bool value); // optional bool server_streaming = 6 [default = false]; - inline bool has_server_streaming() const; - inline void clear_server_streaming(); + bool has_server_streaming() const; + void clear_server_streaming(); static const int kServerStreamingFieldNumber = 6; - inline bool server_streaming() const; - inline void set_server_streaming(bool value); + bool server_streaming() const; + void set_server_streaming(bool value); // @@protoc_insertion_point(class_scope:google.protobuf.MethodDescriptorProto) private: @@ -1727,114 +1727,126 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional string java_package = 1; - inline bool has_java_package() const; - inline void clear_java_package(); + bool has_java_package() const; + void clear_java_package(); static const int kJavaPackageFieldNumber = 1; - inline const ::std::string& java_package() const; - inline void set_java_package(const ::std::string& value); - inline void set_java_package(const char* value); - inline void set_java_package(const char* value, size_t size); - inline ::std::string* mutable_java_package(); - inline ::std::string* release_java_package(); - inline void set_allocated_java_package(::std::string* java_package); + const ::std::string& java_package() const; + void set_java_package(const ::std::string& value); + void set_java_package(const char* value); + void set_java_package(const char* value, size_t size); + ::std::string* mutable_java_package(); + ::std::string* release_java_package(); + void set_allocated_java_package(::std::string* java_package); // optional string java_outer_classname = 8; - inline bool has_java_outer_classname() const; - inline void clear_java_outer_classname(); + bool has_java_outer_classname() const; + void clear_java_outer_classname(); static const int kJavaOuterClassnameFieldNumber = 8; - inline const ::std::string& java_outer_classname() const; - inline void set_java_outer_classname(const ::std::string& value); - inline void set_java_outer_classname(const char* value); - inline void set_java_outer_classname(const char* value, size_t size); - inline ::std::string* mutable_java_outer_classname(); - inline ::std::string* release_java_outer_classname(); - inline void set_allocated_java_outer_classname(::std::string* java_outer_classname); + const ::std::string& java_outer_classname() const; + void set_java_outer_classname(const ::std::string& value); + void set_java_outer_classname(const char* value); + void set_java_outer_classname(const char* value, size_t size); + ::std::string* mutable_java_outer_classname(); + ::std::string* release_java_outer_classname(); + void set_allocated_java_outer_classname(::std::string* java_outer_classname); // optional bool java_multiple_files = 10 [default = false]; - inline bool has_java_multiple_files() const; - inline void clear_java_multiple_files(); + bool has_java_multiple_files() const; + void clear_java_multiple_files(); static const int kJavaMultipleFilesFieldNumber = 10; - inline bool java_multiple_files() const; - inline void set_java_multiple_files(bool value); + bool java_multiple_files() const; + void set_java_multiple_files(bool value); // optional bool java_generate_equals_and_hash = 20 [default = false]; - inline bool has_java_generate_equals_and_hash() const; - inline void clear_java_generate_equals_and_hash(); + bool has_java_generate_equals_and_hash() const; + void clear_java_generate_equals_and_hash(); static const int kJavaGenerateEqualsAndHashFieldNumber = 20; - inline bool java_generate_equals_and_hash() const; - inline void set_java_generate_equals_and_hash(bool value); + bool java_generate_equals_and_hash() const; + void set_java_generate_equals_and_hash(bool value); // optional bool java_string_check_utf8 = 27 [default = false]; - inline bool has_java_string_check_utf8() const; - inline void clear_java_string_check_utf8(); + bool has_java_string_check_utf8() const; + void clear_java_string_check_utf8(); static const int kJavaStringCheckUtf8FieldNumber = 27; - inline bool java_string_check_utf8() const; - inline void set_java_string_check_utf8(bool value); + bool java_string_check_utf8() const; + void set_java_string_check_utf8(bool value); // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - inline bool has_optimize_for() const; - inline void clear_optimize_for(); + bool has_optimize_for() const; + void clear_optimize_for(); static const int kOptimizeForFieldNumber = 9; - inline ::google::protobuf::FileOptions_OptimizeMode optimize_for() const; - inline void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value); + ::google::protobuf::FileOptions_OptimizeMode optimize_for() const; + void set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value); // optional string go_package = 11; - inline bool has_go_package() const; - inline void clear_go_package(); + bool has_go_package() const; + void clear_go_package(); static const int kGoPackageFieldNumber = 11; - inline const ::std::string& go_package() const; - inline void set_go_package(const ::std::string& value); - inline void set_go_package(const char* value); - inline void set_go_package(const char* value, size_t size); - inline ::std::string* mutable_go_package(); - inline ::std::string* release_go_package(); - inline void set_allocated_go_package(::std::string* go_package); + const ::std::string& go_package() const; + void set_go_package(const ::std::string& value); + void set_go_package(const char* value); + void set_go_package(const char* value, size_t size); + ::std::string* mutable_go_package(); + ::std::string* release_go_package(); + void set_allocated_go_package(::std::string* go_package); // optional bool cc_generic_services = 16 [default = false]; - inline bool has_cc_generic_services() const; - inline void clear_cc_generic_services(); + bool has_cc_generic_services() const; + void clear_cc_generic_services(); static const int kCcGenericServicesFieldNumber = 16; - inline bool cc_generic_services() const; - inline void set_cc_generic_services(bool value); + bool cc_generic_services() const; + void set_cc_generic_services(bool value); // optional bool java_generic_services = 17 [default = false]; - inline bool has_java_generic_services() const; - inline void clear_java_generic_services(); + bool has_java_generic_services() const; + void clear_java_generic_services(); static const int kJavaGenericServicesFieldNumber = 17; - inline bool java_generic_services() const; - inline void set_java_generic_services(bool value); + bool java_generic_services() const; + void set_java_generic_services(bool value); // optional bool py_generic_services = 18 [default = false]; - inline bool has_py_generic_services() const; - inline void clear_py_generic_services(); + bool has_py_generic_services() const; + void clear_py_generic_services(); static const int kPyGenericServicesFieldNumber = 18; - inline bool py_generic_services() const; - inline void set_py_generic_services(bool value); + bool py_generic_services() const; + void set_py_generic_services(bool value); // optional bool deprecated = 23 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 23; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // optional bool cc_enable_arenas = 31 [default = false]; - inline bool has_cc_enable_arenas() const; - inline void clear_cc_enable_arenas(); + bool has_cc_enable_arenas() const; + void clear_cc_enable_arenas(); static const int kCcEnableArenasFieldNumber = 31; - inline bool cc_enable_arenas() const; - inline void set_cc_enable_arenas(bool value); + bool cc_enable_arenas() const; + void set_cc_enable_arenas(bool value); + + // optional string objc_class_prefix = 36; + bool has_objc_class_prefix() const; + void clear_objc_class_prefix(); + static const int kObjcClassPrefixFieldNumber = 36; + const ::std::string& objc_class_prefix() const; + void set_objc_class_prefix(const ::std::string& value); + void set_objc_class_prefix(const char* value); + void set_objc_class_prefix(const char* value, size_t size); + ::std::string* mutable_objc_class_prefix(); + ::std::string* release_objc_class_prefix(); + void set_allocated_objc_class_prefix(::std::string* objc_class_prefix); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FileOptions) @@ -1864,6 +1876,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void clear_has_deprecated(); inline void set_has_cc_enable_arenas(); inline void clear_has_cc_enable_arenas(); + inline void set_has_objc_class_prefix(); + inline void clear_has_objc_class_prefix(); ::google::protobuf::internal::ExtensionSet _extensions_; @@ -1878,6 +1892,7 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { bool cc_generic_services_; int optimize_for_; ::google::protobuf::internal::ArenaStringPtr go_package_; + ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool java_generic_services_; bool py_generic_services_; @@ -1957,43 +1972,43 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool message_set_wire_format = 1 [default = false]; - inline bool has_message_set_wire_format() const; - inline void clear_message_set_wire_format(); + bool has_message_set_wire_format() const; + void clear_message_set_wire_format(); static const int kMessageSetWireFormatFieldNumber = 1; - inline bool message_set_wire_format() const; - inline void set_message_set_wire_format(bool value); + bool message_set_wire_format() const; + void set_message_set_wire_format(bool value); // optional bool no_standard_descriptor_accessor = 2 [default = false]; - inline bool has_no_standard_descriptor_accessor() const; - inline void clear_no_standard_descriptor_accessor(); + bool has_no_standard_descriptor_accessor() const; + void clear_no_standard_descriptor_accessor(); static const int kNoStandardDescriptorAccessorFieldNumber = 2; - inline bool no_standard_descriptor_accessor() const; - inline void set_no_standard_descriptor_accessor(bool value); + bool no_standard_descriptor_accessor() const; + void set_no_standard_descriptor_accessor(bool value); // optional bool deprecated = 3 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 3; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // optional bool map_entry = 7; - inline bool has_map_entry() const; - inline void clear_map_entry(); + bool has_map_entry() const; + void clear_map_entry(); static const int kMapEntryFieldNumber = 7; - inline bool map_entry() const; - inline void set_map_entry(bool value); + bool map_entry() const; + void set_map_entry(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MessageOptions) @@ -2117,50 +2132,50 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - inline bool has_ctype() const; - inline void clear_ctype(); + bool has_ctype() const; + void clear_ctype(); static const int kCtypeFieldNumber = 1; - inline ::google::protobuf::FieldOptions_CType ctype() const; - inline void set_ctype(::google::protobuf::FieldOptions_CType value); + ::google::protobuf::FieldOptions_CType ctype() const; + void set_ctype(::google::protobuf::FieldOptions_CType value); // optional bool packed = 2; - inline bool has_packed() const; - inline void clear_packed(); + bool has_packed() const; + void clear_packed(); static const int kPackedFieldNumber = 2; - inline bool packed() const; - inline void set_packed(bool value); + bool packed() const; + void set_packed(bool value); // optional bool lazy = 5 [default = false]; - inline bool has_lazy() const; - inline void clear_lazy(); + bool has_lazy() const; + void clear_lazy(); static const int kLazyFieldNumber = 5; - inline bool lazy() const; - inline void set_lazy(bool value); + bool lazy() const; + void set_lazy(bool value); // optional bool deprecated = 3 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 3; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // optional bool weak = 10 [default = false]; - inline bool has_weak() const; - inline void clear_weak(); + bool has_weak() const; + void clear_weak(); static const int kWeakFieldNumber = 10; - inline bool weak() const; - inline void set_weak(bool value); + bool weak() const; + void set_weak(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(FieldOptions) @@ -2262,29 +2277,29 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool allow_alias = 2; - inline bool has_allow_alias() const; - inline void clear_allow_alias(); + bool has_allow_alias() const; + void clear_allow_alias(); static const int kAllowAliasFieldNumber = 2; - inline bool allow_alias() const; - inline void set_allow_alias(bool value); + bool allow_alias() const; + void set_allow_alias(bool value); // optional bool deprecated = 3 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 3; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumOptions) @@ -2377,22 +2392,22 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool deprecated = 1 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 1; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions) @@ -2482,22 +2497,22 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool deprecated = 33 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 33; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions) @@ -2587,22 +2602,22 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // optional bool deprecated = 33 [default = false]; - inline bool has_deprecated() const; - inline void clear_deprecated(); + bool has_deprecated() const; + void clear_deprecated(); static const int kDeprecatedFieldNumber = 33; - inline bool deprecated() const; - inline void set_deprecated(bool value); + bool deprecated() const; + void set_deprecated(bool value); // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - inline int uninterpreted_option_size() const; - inline void clear_uninterpreted_option(); + int uninterpreted_option_size() const; + void clear_uninterpreted_option(); static const int kUninterpretedOptionFieldNumber = 999; - inline const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; - inline ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); - inline ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& + const ::google::protobuf::UninterpretedOption& uninterpreted_option(int index) const; + ::google::protobuf::UninterpretedOption* mutable_uninterpreted_option(int index); + ::google::protobuf::UninterpretedOption* add_uninterpreted_option(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& uninterpreted_option() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* mutable_uninterpreted_option(); GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions) @@ -2692,23 +2707,23 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu // accessors ------------------------------------------------------- // required string name_part = 1; - inline bool has_name_part() const; - inline void clear_name_part(); + bool has_name_part() const; + void clear_name_part(); static const int kNamePartFieldNumber = 1; - inline const ::std::string& name_part() const; - inline void set_name_part(const ::std::string& value); - inline void set_name_part(const char* value); - inline void set_name_part(const char* value, size_t size); - inline ::std::string* mutable_name_part(); - inline ::std::string* release_name_part(); - inline void set_allocated_name_part(::std::string* name_part); + const ::std::string& name_part() const; + void set_name_part(const ::std::string& value); + void set_name_part(const char* value); + void set_name_part(const char* value, size_t size); + ::std::string* mutable_name_part(); + ::std::string* release_name_part(); + void set_allocated_name_part(::std::string* name_part); // required bool is_extension = 2; - inline bool has_is_extension() const; - inline void clear_is_extension(); + bool has_is_extension() const; + void clear_is_extension(); static const int kIsExtensionFieldNumber = 2; - inline bool is_extension() const; - inline void set_is_extension(bool value); + bool is_extension() const; + void set_is_extension(bool value); // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption.NamePart) private: @@ -2801,73 +2816,73 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag // accessors ------------------------------------------------------- // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - inline int name_size() const; - inline void clear_name(); + int name_size() const; + void clear_name(); static const int kNameFieldNumber = 2; - inline const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const; - inline ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index); - inline ::google::protobuf::UninterpretedOption_NamePart* add_name(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& + const ::google::protobuf::UninterpretedOption_NamePart& name(int index) const; + ::google::protobuf::UninterpretedOption_NamePart* mutable_name(int index); + ::google::protobuf::UninterpretedOption_NamePart* add_name(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& name() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* mutable_name(); // optional string identifier_value = 3; - inline bool has_identifier_value() const; - inline void clear_identifier_value(); + bool has_identifier_value() const; + void clear_identifier_value(); static const int kIdentifierValueFieldNumber = 3; - inline const ::std::string& identifier_value() const; - inline void set_identifier_value(const ::std::string& value); - inline void set_identifier_value(const char* value); - inline void set_identifier_value(const char* value, size_t size); - inline ::std::string* mutable_identifier_value(); - inline ::std::string* release_identifier_value(); - inline void set_allocated_identifier_value(::std::string* identifier_value); + const ::std::string& identifier_value() const; + void set_identifier_value(const ::std::string& value); + void set_identifier_value(const char* value); + void set_identifier_value(const char* value, size_t size); + ::std::string* mutable_identifier_value(); + ::std::string* release_identifier_value(); + void set_allocated_identifier_value(::std::string* identifier_value); // optional uint64 positive_int_value = 4; - inline bool has_positive_int_value() const; - inline void clear_positive_int_value(); + bool has_positive_int_value() const; + void clear_positive_int_value(); static const int kPositiveIntValueFieldNumber = 4; - inline ::google::protobuf::uint64 positive_int_value() const; - inline void set_positive_int_value(::google::protobuf::uint64 value); + ::google::protobuf::uint64 positive_int_value() const; + void set_positive_int_value(::google::protobuf::uint64 value); // optional int64 negative_int_value = 5; - inline bool has_negative_int_value() const; - inline void clear_negative_int_value(); + bool has_negative_int_value() const; + void clear_negative_int_value(); static const int kNegativeIntValueFieldNumber = 5; - inline ::google::protobuf::int64 negative_int_value() const; - inline void set_negative_int_value(::google::protobuf::int64 value); + ::google::protobuf::int64 negative_int_value() const; + void set_negative_int_value(::google::protobuf::int64 value); // optional double double_value = 6; - inline bool has_double_value() const; - inline void clear_double_value(); + bool has_double_value() const; + void clear_double_value(); static const int kDoubleValueFieldNumber = 6; - inline double double_value() const; - inline void set_double_value(double value); + double double_value() const; + void set_double_value(double value); // optional bytes string_value = 7; - inline bool has_string_value() const; - inline void clear_string_value(); + bool has_string_value() const; + void clear_string_value(); static const int kStringValueFieldNumber = 7; - inline const ::std::string& string_value() const; - inline void set_string_value(const ::std::string& value); - inline void set_string_value(const char* value); - inline void set_string_value(const void* value, size_t size); - inline ::std::string* mutable_string_value(); - inline ::std::string* release_string_value(); - inline void set_allocated_string_value(::std::string* string_value); + const ::std::string& string_value() const; + void set_string_value(const ::std::string& value); + void set_string_value(const char* value); + void set_string_value(const void* value, size_t size); + ::std::string* mutable_string_value(); + ::std::string* release_string_value(); + void set_allocated_string_value(::std::string* string_value); // optional string aggregate_value = 8; - inline bool has_aggregate_value() const; - inline void clear_aggregate_value(); + bool has_aggregate_value() const; + void clear_aggregate_value(); static const int kAggregateValueFieldNumber = 8; - inline const ::std::string& aggregate_value() const; - inline void set_aggregate_value(const ::std::string& value); - inline void set_aggregate_value(const char* value); - inline void set_aggregate_value(const char* value, size_t size); - inline ::std::string* mutable_aggregate_value(); - inline ::std::string* release_aggregate_value(); - inline void set_allocated_aggregate_value(::std::string* aggregate_value); + const ::std::string& aggregate_value() const; + void set_aggregate_value(const ::std::string& value); + void set_aggregate_value(const char* value); + void set_aggregate_value(const char* value, size_t size); + ::std::string* mutable_aggregate_value(); + ::std::string* release_aggregate_value(); + void set_allocated_aggregate_value(::std::string* aggregate_value); // @@protoc_insertion_point(class_scope:google.protobuf.UninterpretedOption) private: @@ -2968,52 +2983,68 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me // accessors ------------------------------------------------------- // repeated int32 path = 1 [packed = true]; - inline int path_size() const; - inline void clear_path(); + int path_size() const; + void clear_path(); static const int kPathFieldNumber = 1; - inline ::google::protobuf::int32 path(int index) const; - inline void set_path(int index, ::google::protobuf::int32 value); - inline void add_path(::google::protobuf::int32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + ::google::protobuf::int32 path(int index) const; + void set_path(int index, ::google::protobuf::int32 value); + void add_path(::google::protobuf::int32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& path() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* mutable_path(); // repeated int32 span = 2 [packed = true]; - inline int span_size() const; - inline void clear_span(); + int span_size() const; + void clear_span(); static const int kSpanFieldNumber = 2; - inline ::google::protobuf::int32 span(int index) const; - inline void set_span(int index, ::google::protobuf::int32 value); - inline void add_span(::google::protobuf::int32 value); - inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& + ::google::protobuf::int32 span(int index) const; + void set_span(int index, ::google::protobuf::int32 value); + void add_span(::google::protobuf::int32 value); + const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& span() const; - inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* + ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* mutable_span(); // optional string leading_comments = 3; - inline bool has_leading_comments() const; - inline void clear_leading_comments(); + bool has_leading_comments() const; + void clear_leading_comments(); static const int kLeadingCommentsFieldNumber = 3; - inline const ::std::string& leading_comments() const; - inline void set_leading_comments(const ::std::string& value); - inline void set_leading_comments(const char* value); - inline void set_leading_comments(const char* value, size_t size); - inline ::std::string* mutable_leading_comments(); - inline ::std::string* release_leading_comments(); - inline void set_allocated_leading_comments(::std::string* leading_comments); + const ::std::string& leading_comments() const; + void set_leading_comments(const ::std::string& value); + void set_leading_comments(const char* value); + void set_leading_comments(const char* value, size_t size); + ::std::string* mutable_leading_comments(); + ::std::string* release_leading_comments(); + void set_allocated_leading_comments(::std::string* leading_comments); // optional string trailing_comments = 4; - inline bool has_trailing_comments() const; - inline void clear_trailing_comments(); + bool has_trailing_comments() const; + void clear_trailing_comments(); static const int kTrailingCommentsFieldNumber = 4; - inline const ::std::string& trailing_comments() const; - inline void set_trailing_comments(const ::std::string& value); - inline void set_trailing_comments(const char* value); - inline void set_trailing_comments(const char* value, size_t size); - inline ::std::string* mutable_trailing_comments(); - inline ::std::string* release_trailing_comments(); - inline void set_allocated_trailing_comments(::std::string* trailing_comments); + const ::std::string& trailing_comments() const; + void set_trailing_comments(const ::std::string& value); + void set_trailing_comments(const char* value); + void set_trailing_comments(const char* value, size_t size); + ::std::string* mutable_trailing_comments(); + ::std::string* release_trailing_comments(); + void set_allocated_trailing_comments(::std::string* trailing_comments); + + // repeated string leading_detached_comments = 6; + int leading_detached_comments_size() const; + void clear_leading_detached_comments(); + static const int kLeadingDetachedCommentsFieldNumber = 6; + const ::std::string& leading_detached_comments(int index) const; + ::std::string* mutable_leading_detached_comments(int index); + void set_leading_detached_comments(int index, const ::std::string& value); + void set_leading_detached_comments(int index, const char* value); + void set_leading_detached_comments(int index, const char* value, size_t size); + ::std::string* add_leading_detached_comments(); + void add_leading_detached_comments(const ::std::string& value); + void add_leading_detached_comments(const char* value); + void add_leading_detached_comments(const char* value, size_t size); + const ::google::protobuf::RepeatedPtrField< ::std::string>& leading_detached_comments() const; + ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_leading_detached_comments(); // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo.Location) private: @@ -3031,6 +3062,7 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me mutable int _span_cached_byte_size_; ::google::protobuf::internal::ArenaStringPtr leading_comments_; ::google::protobuf::internal::ArenaStringPtr trailing_comments_; + ::google::protobuf::RepeatedPtrField< ::std::string> leading_detached_comments_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -3107,15 +3139,15 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { // accessors ------------------------------------------------------- // repeated .google.protobuf.SourceCodeInfo.Location location = 1; - inline int location_size() const; - inline void clear_location(); + int location_size() const; + void clear_location(); static const int kLocationFieldNumber = 1; - inline const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; - inline ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index); - inline ::google::protobuf::SourceCodeInfo_Location* add_location(); - inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& + const ::google::protobuf::SourceCodeInfo_Location& location(int index) const; + ::google::protobuf::SourceCodeInfo_Location* mutable_location(int index); + ::google::protobuf::SourceCodeInfo_Location* add_location(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& location() const; - inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* + ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* mutable_location(); // @@protoc_insertion_point(class_scope:google.protobuf.SourceCodeInfo) @@ -3137,6 +3169,7 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { // =================================================================== +#if !PROTOBUF_INLINE_NOT_IN_HEADERS // FileDescriptorSet // repeated .google.protobuf.FileDescriptorProto file = 1; @@ -5416,6 +5449,59 @@ inline void FileOptions::set_cc_enable_arenas(bool value) { // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_enable_arenas) } +// optional string objc_class_prefix = 36; +inline bool FileOptions::has_objc_class_prefix() const { + return (_has_bits_[0] & 0x00001000u) != 0; +} +inline void FileOptions::set_has_objc_class_prefix() { + _has_bits_[0] |= 0x00001000u; +} +inline void FileOptions::clear_has_objc_class_prefix() { + _has_bits_[0] &= ~0x00001000u; +} +inline void FileOptions::clear_objc_class_prefix() { + objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_objc_class_prefix(); +} +inline const ::std::string& FileOptions::objc_class_prefix() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.objc_class_prefix) + return objc_class_prefix_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_objc_class_prefix(const ::std::string& value) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.objc_class_prefix) +} +inline void FileOptions::set_objc_class_prefix(const char* value) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.objc_class_prefix) +} +inline void FileOptions::set_objc_class_prefix(const char* value, size_t size) { + set_has_objc_class_prefix(); + objc_class_prefix_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.objc_class_prefix) +} +inline ::std::string* FileOptions::mutable_objc_class_prefix() { + set_has_objc_class_prefix(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.objc_class_prefix) + return objc_class_prefix_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* FileOptions::release_objc_class_prefix() { + clear_has_objc_class_prefix(); + return objc_class_prefix_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_class_prefix) { + if (objc_class_prefix != NULL) { + set_has_objc_class_prefix(); + } else { + clear_has_objc_class_prefix(); + } + objc_class_prefix_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), objc_class_prefix); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -6503,6 +6589,60 @@ inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::stri // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) } +// repeated string leading_detached_comments = 6; +inline int SourceCodeInfo_Location::leading_detached_comments_size() const { + return leading_detached_comments_.size(); +} +inline void SourceCodeInfo_Location::clear_leading_detached_comments() { + leading_detached_comments_.Clear(); +} +inline const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_.Get(index); +} +inline ::std::string* SourceCodeInfo_Location::mutable_leading_detached_comments(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_.Mutable(index); +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + leading_detached_comments_.Mutable(index)->assign(value); +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value) { + leading_detached_comments_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) { + leading_detached_comments_.Mutable(index)->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline ::std::string* SourceCodeInfo_Location::add_leading_detached_comments() { + return leading_detached_comments_.Add(); +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const ::std::string& value) { + leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) { + leading_detached_comments_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) { + leading_detached_comments_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +SourceCodeInfo_Location::leading_detached_comments() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return leading_detached_comments_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +SourceCodeInfo_Location::mutable_leading_detached_comments() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.leading_detached_comments) + return &leading_detached_comments_; +} + // ------------------------------------------------------------------- // SourceCodeInfo @@ -6537,6 +6677,7 @@ SourceCodeInfo::mutable_location() { return &location_; } +#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index e17c0cc8..367b16e5 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -172,9 +172,7 @@ message FieldDescriptorProto { optional string default_value = 7; // If set, gives the index of a oneof in the containing type's oneof_decl - // list. This field is a member of that oneof. Extensions of a oneof should - // not set this since the oneof to which they belong will be inferred based - // on the extension range containing the extension's field number. + // list. This field is a member of that oneof. optional int32 oneof_index = 9; optional FieldOptions options = 8; @@ -344,12 +342,15 @@ message FileOptions { // least, this is a formalization for deprecating files. optional bool deprecated = 23 [default=false]; - // Enables the use of arenas for the proto messages in this file. This applies // only to generated classes for C++. optional bool cc_enable_arenas = 31 [default=false]; + // Sets the objective c class prefix which is prepended to all objective c + // generated classes from this .proto. There is no default. + optional string objc_class_prefix = 36; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -681,6 +682,11 @@ message SourceCodeInfo { // A series of line comments appearing on consecutive lines, with no other // tokens appearing on those lines, will be treated as a single comment. // + // leading_detached_comments will keep paragraphs of comments that appear + // before (but not connected to) the current element. Each paragraph, + // separated by empty lines, will be one comment element in the repeated + // field. + // // Only the comment content is provided; comment markers (e.g. //) are // stripped out. For block comments, leading whitespace and an asterisk // will be stripped from the beginning of each line other than the first. @@ -701,6 +707,12 @@ message SourceCodeInfo { // // Another line attached to qux. // optional double qux = 4; // + // // Detached comment for corge. This is not leading or trailing comments + // // to qux or corge because there are blank lines separating it from + // // both. + // + // // Detached comment for corge paragraph 2. + // // optional string corge = 5; // /* Block comment attached // * to corge. Leading asterisks @@ -708,7 +720,10 @@ message SourceCodeInfo { // /* Block comment attached to // * grault. */ // optional int32 grault = 6; + // + // // ignored detached comments. optional string leading_comments = 3; optional string trailing_comments = 4; + repeated string leading_detached_comments = 6; } } diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc index d024eab1..2117c020 100644 --- a/src/google/protobuf/descriptor_database.cc +++ b/src/google/protobuf/descriptor_database.cc @@ -153,10 +153,10 @@ bool SimpleDescriptorDatabase::DescriptorIndex::AddExtension( if (!field.extendee().empty() && field.extendee()[0] == '.') { // The extension is fully-qualified. We can use it as a lookup key in // the by_symbol_ table. - if (!InsertIfNotPresent(&by_extension_, - make_pair(field.extendee().substr(1), - field.number()), - value)) { + if (!InsertIfNotPresent( + &by_extension_, + std::make_pair(field.extendee().substr(1), field.number()), + value)) { GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: " "extend " << field.extendee() << " { " << field.name() << " = " << field.number() << " }"; @@ -189,17 +189,16 @@ template Value SimpleDescriptorDatabase::DescriptorIndex::FindExtension( const string& containing_type, int field_number) { - return FindWithDefault(by_extension_, - make_pair(containing_type, field_number), - Value()); + return FindWithDefault( + by_extension_, std::make_pair(containing_type, field_number), Value()); } template bool SimpleDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers( const string& containing_type, vector* output) { - typename map, Value >::const_iterator it = - by_extension_.lower_bound(make_pair(containing_type, 0)); + typename map, Value>::const_iterator it = + by_extension_.lower_bound(std::make_pair(containing_type, 0)); bool success = false; for (; it != by_extension_.end() && it->first.first == containing_type; @@ -310,7 +309,7 @@ bool EncodedDescriptorDatabase::Add( const void* encoded_file_descriptor, int size) { FileDescriptorProto file; if (file.ParseFromArray(encoded_file_descriptor, size)) { - return index_.AddFile(file, make_pair(encoded_file_descriptor, size)); + return index_.AddFile(file, std::make_pair(encoded_file_descriptor, size)); } else { GOOGLE_LOG(ERROR) << "Invalid file descriptor data passed to " "EncodedDescriptorDatabase::Add()."; @@ -525,15 +524,16 @@ bool MergedDescriptorDatabase::FindAllExtensionNumbers( for (int i = 0; i < sources_.size(); i++) { if (sources_[i]->FindAllExtensionNumbers(extendee_type, &results)) { - copy(results.begin(), results.end(), - insert_iterator >(merged_results, merged_results.begin())); + std::copy( + results.begin(), results.end(), + insert_iterator >(merged_results, merged_results.begin())); success = true; } results.clear(); } - copy(merged_results.begin(), merged_results.end(), - insert_iterator >(*output, output->end())); + std::copy(merged_results.begin(), merged_results.end(), + insert_iterator >(*output, output->end())); return success; } diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc index 6642d71b..1c03c443 100644 --- a/src/google/protobuf/descriptor_database_unittest.cc +++ b/src/google/protobuf/descriptor_database_unittest.cc @@ -408,7 +408,7 @@ TEST_P(DescriptorDatabaseTest, FindAllExtensionNumbers) { vector numbers; EXPECT_TRUE(database_->FindAllExtensionNumbers("Foo", &numbers)); ASSERT_EQ(2, numbers.size()); - sort(numbers.begin(), numbers.end()); + std::sort(numbers.begin(), numbers.end()); EXPECT_EQ(5, numbers[0]); EXPECT_EQ(32, numbers[1]); } @@ -722,7 +722,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) { vector numbers; EXPECT_TRUE(forward_merged_.FindAllExtensionNumbers("Baz", &numbers)); ASSERT_EQ(2, numbers.size()); - sort(numbers.begin(), numbers.end()); + std::sort(numbers.begin(), numbers.end()); EXPECT_EQ(12, numbers[0]); EXPECT_EQ(13, numbers[1]); } @@ -731,7 +731,7 @@ TEST_F(MergedDescriptorDatabaseTest, FindAllExtensionNumbers) { vector numbers; EXPECT_TRUE(reverse_merged_.FindAllExtensionNumbers("Baz", &numbers)); ASSERT_EQ(2, numbers.size()); - sort(numbers.begin(), numbers.end()); + std::sort(numbers.begin(), numbers.end()); EXPECT_EQ(12, numbers[0]); EXPECT_EQ(13, numbers[1]); } diff --git a/src/google/protobuf/descriptor_pb2_test.py b/src/google/protobuf/descriptor_pb2_test.py deleted file mode 100644 index c5a8d8a2..00000000 --- a/src/google/protobuf/descriptor_pb2_test.py +++ /dev/null @@ -1,54 +0,0 @@ -#! /usr/bin/python -# -# 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. - -# Verify that prebuild and checkedin version of descriptor_pb2.py is up to date. - -from google3.pyglib import resources -from google.apputils import basetest - -_DESC = 'google3/net/proto2/proto/descriptor_pb2.' -_OLD = _DESC + 'py-prebuilt' -_NEW = _DESC + 'compiled' - - -class PregeneratedFileChanged(basetest.TestCase): - - def testSameText(self): - generated = resources.GetResource(_NEW) - checkedin = resources.GetResource(_OLD) - self.assertMultiLineEqual( - generated, checkedin, 'It seems that protoc _pb2 generator changed. ' - 'Please run google/protobuf/generate_descriptor_proto.sh to ' - 'regnerate a new version of %s and add it to your CL' % _OLD) - -if __name__ == '__main__': - basetest.main() diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 2ceb41e5..fdce3d78 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -6104,9 +6104,9 @@ TEST_F(CopySourceCodeInfoToTest, CopySourceCodeInfoTo) { file_desc->CopySourceCodeInfoTo(&file_desc_proto); const SourceCodeInfo& info = file_desc_proto.source_code_info(); - ASSERT_EQ(3, info.location_size()); + ASSERT_EQ(4, info.location_size()); // Get the Foo message location - const SourceCodeInfo_Location& foo_location = info.location(1); + const SourceCodeInfo_Location& foo_location = info.location(2); ASSERT_EQ(2, foo_location.path_size()); EXPECT_EQ(FileDescriptorProto::kMessageTypeFieldNumber, foo_location.path(0)); EXPECT_EQ(0, foo_location.path(1)); // Foo is the first message defined diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 49087131..03b38dd0 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -97,7 +97,7 @@ void Register(const MessageLite* containing_type, int number, ExtensionInfo info) { ::google::protobuf::GoogleOnceInit(®istry_init_, &InitRegistry); - if (!InsertIfNotPresent(registry_, make_pair(containing_type, number), + if (!InsertIfNotPresent(registry_, std::make_pair(containing_type, number), info)) { GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \"" << containing_type->GetTypeName() @@ -107,8 +107,9 @@ void Register(const MessageLite* containing_type, const ExtensionInfo* FindRegisteredExtension( const MessageLite* containing_type, int number) { - return (registry_ == NULL) ? NULL : - FindOrNull(*registry_, make_pair(containing_type, number)); + return (registry_ == NULL) + ? NULL + : FindOrNull(*registry_, std::make_pair(containing_type, number)); } } // namespace @@ -1032,7 +1033,7 @@ void ExtensionSet::SwapExtension(ExtensionSet* other, if (this_iter == extensions_.end()) { if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - extensions_.insert(make_pair(number, other_iter->second)); + extensions_.insert(std::make_pair(number, other_iter->second)); } else { InternalExtensionMergeFrom(number, other_iter->second); } @@ -1042,7 +1043,7 @@ void ExtensionSet::SwapExtension(ExtensionSet* other, if (other_iter == other->extensions_.end()) { if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { - other->extensions_.insert(make_pair(number, this_iter->second)); + other->extensions_.insert(std::make_pair(number, this_iter->second)); } else { other->InternalExtensionMergeFrom(number, this_iter->second); } @@ -1175,6 +1176,9 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( extension.enum_validity_check.arg, value)) { AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, extension.descriptor); + } else { + // Invalid value. Treat as unknown. + field_skipper->SkipUnknownEnum(number, value); } } break; @@ -1337,7 +1341,7 @@ bool ExtensionSet::MaybeNewExtension(int number, const FieldDescriptor* descriptor, Extension** result) { pair::iterator, bool> insert_result = - extensions_.insert(make_pair(number, Extension())); + extensions_.insert(std::make_pair(number, Extension())); *result = &insert_result.first->second; (*result)->descriptor = descriptor; return insert_result.second; diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 5f4ca1c3..796e7a5f 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -91,9 +91,10 @@ class DescriptorPoolExtensionFinder : public ExtensionFinder { const Descriptor* containing_type_; }; -void ExtensionSet::AppendToList(const Descriptor* containing_type, - const DescriptorPool* pool, - vector* output) const { +void ExtensionSet::AppendToList( + const Descriptor* containing_type, + const DescriptorPool* pool, + std::vector* output) const { for (map::const_iterator iter = extensions_.begin(); iter != extensions_.end(); ++iter) { bool has = false; diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h index 3852cea5..fdcdc277 100644 --- a/src/google/protobuf/generated_enum_reflection.h +++ b/src/google/protobuf/generated_enum_reflection.h @@ -42,6 +42,7 @@ #include #include +#include namespace google { namespace protobuf { @@ -50,10 +51,6 @@ namespace protobuf { namespace protobuf { -// This type trait can be used to cause templates to only match proto2 enum -// types. -template struct is_proto_enum : ::google::protobuf::internal::false_type {}; - // Returns the EnumDescriptor for enum type E, which must be a // proto-declared enum type. Code generated by the protocol compiler // will include specializations of this template for each enum type declared. diff --git a/src/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h new file mode 100644 index 00000000..e4242055 --- /dev/null +++ b/src/google/protobuf/generated_enum_util.h @@ -0,0 +1,46 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ +#define GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ + +#include + +namespace google { +namespace protobuf { + +// This type trait can be used to cause templates to only match proto2 enum +// types. +template struct is_proto_enum : ::google::protobuf::internal::false_type {}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__ diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 34826801..412c48a1 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -995,6 +995,7 @@ void GeneratedMessageReflection::ListFields( // Optimization: The default instance never has any fields set. if (&message == default_instance_) return; + output->reserve(descriptor_->field_count()); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated()) { @@ -1018,7 +1019,7 @@ void GeneratedMessageReflection::ListFields( } // ListFields() must sort output by field number. - sort(output->begin(), output->end(), FieldNumberSorter()); + std::sort(output->begin(), output->end(), FieldNumberSorter()); } // ------------------------------------------------------------------- @@ -1434,6 +1435,8 @@ const Message& GeneratedMessageReflection::GetMessage( Message* GeneratedMessageReflection::MutableMessage( Message* message, const FieldDescriptor* field, MessageFactory* factory) const { + USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); + if (factory == NULL) factory = message_factory_; if (field->is_extension()) { @@ -1972,26 +1975,28 @@ inline void GeneratedMessageReflection::ClearOneof( uint32 oneof_case = GetOneofCase(*message, oneof_descriptor); if (oneof_case > 0) { const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case); - switch (field->cpp_type()) { - case FieldDescriptor::CPPTYPE_STRING: { - switch (field->options().ctype()) { - default: // TODO(kenton): Support other string reps. - case FieldOptions::STRING: { - const string* default_ptr = - &DefaultRaw(field).Get(NULL); - MutableField(message, field)-> - Destroy(default_ptr, GetArena(message)); - break; + if (GetArena(message) == NULL) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: { + const string* default_ptr = + &DefaultRaw(field).Get(NULL); + MutableField(message, field)-> + Destroy(default_ptr, GetArena(message)); + break; + } } + break; } - break; - } - case FieldDescriptor::CPPTYPE_MESSAGE: - delete *MutableRaw(message, field); - break; - default: - break; + case FieldDescriptor::CPPTYPE_MESSAGE: + delete *MutableRaw(message, field); + break; + default: + break; + } } *MutableOneofCase(message, oneof_descriptor) = 0; diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index df88205c..93e1a22e 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -153,7 +153,7 @@ void CodedInputStream::PopLimit(Limit limit) { std::pair CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) { - return make_pair(PushLimit(byte_limit), --recursion_budget_); + return std::make_pair(PushLimit(byte_limit), --recursion_budget_); } bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) { @@ -613,8 +613,15 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) } CodedOutputStream::~CodedOutputStream() { + Trim(); +} + +void CodedOutputStream::Trim() { if (buffer_size_ > 0) { output_->BackUp(buffer_size_); + total_bytes_ -= buffer_size_; + buffer_size_ = 0; + buffer_ = NULL; } } @@ -662,12 +669,7 @@ void CodedOutputStream::WriteAliasedRaw(const void* data, int size) { ) { WriteRaw(data, size); } else { - if (buffer_size_ > 0) { - output_->BackUp(buffer_size_); - total_bytes_ -= buffer_size_; - buffer_ = NULL; - buffer_size_ = 0; - } + Trim(); total_bytes_ += size; had_error_ |= !output_->WriteAliasedRaw(data, size); @@ -704,61 +706,12 @@ void CodedOutputStream::WriteLittleEndian64(uint64 value) { } } -inline uint8* CodedOutputStream::WriteVarint32FallbackToArrayInline( - uint32 value, uint8* target) { - target[0] = static_cast(value | 0x80); - if (value >= (1 << 7)) { - target[1] = static_cast((value >> 7) | 0x80); - if (value >= (1 << 14)) { - target[2] = static_cast((value >> 14) | 0x80); - if (value >= (1 << 21)) { - target[3] = static_cast((value >> 21) | 0x80); - if (value >= (1 << 28)) { - target[4] = static_cast(value >> 28); - return target + 5; - } else { - target[3] &= 0x7F; - return target + 4; - } - } else { - target[2] &= 0x7F; - return target + 3; - } - } else { - target[1] &= 0x7F; - return target + 2; - } - } else { - target[0] &= 0x7F; - return target + 1; - } -} - -void CodedOutputStream::WriteVarint32(uint32 value) { - if (buffer_size_ >= kMaxVarint32Bytes) { - // Fast path: We have enough bytes left in the buffer to guarantee that - // this write won't cross the end, so we can skip the checks. - uint8* target = buffer_; - uint8* end = WriteVarint32FallbackToArrayInline(value, target); - int size = end - target; - Advance(size); - } else { - // Slow path: This write might cross the end of the buffer, so we - // compose the bytes first then use WriteRaw(). - uint8 bytes[kMaxVarint32Bytes]; - int size = 0; - while (value > 0x7F) { - bytes[size++] = (static_cast(value) & 0x7F) | 0x80; - value >>= 7; - } - bytes[size++] = static_cast(value) & 0x7F; - WriteRaw(bytes, size); - } -} - -uint8* CodedOutputStream::WriteVarint32FallbackToArray( - uint32 value, uint8* target) { - return WriteVarint32FallbackToArrayInline(value, target); +void CodedOutputStream::WriteVarint32SlowPath(uint32 value) { + uint8 bytes[kMaxVarint32Bytes]; + uint8* target = &bytes[0]; + uint8* end = WriteVarint32ToArray(value, target); + int size = end - target; + WriteRaw(bytes, size); } inline uint8* CodedOutputStream::WriteVarint64ToArrayInline( diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 978cc19d..dea4b650 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -647,6 +647,13 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // ZeroCopyOutputStream immediately after the last byte written. ~CodedOutputStream(); + // Trims any unused space in the underlying buffer so that its size matches + // the number of bytes written by this stream. The underlying buffer will + // automatically be trimmed when this stream is destroyed; this call is only + // necessary if the underlying buffer is accessed *before* the stream is + // destroyed. + void Trim(); + // Skips a number of bytes, leaving the bytes unmodified in the underlying // buffer. Returns false if an underlying write error occurs. This is // mainly useful with GetDirectBufferPointer(). @@ -789,7 +796,9 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // ZeroCopyOutputStream supports it. void WriteAliasedRaw(const void* buffer, int size); - static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target); + // If this write might cross the end of the buffer, we compose the bytes first + // then use WriteRaw(). + void WriteVarint32SlowPath(uint32 value); // Always-inlined versions of WriteVarint* functions so that code can be // reused, while still controlling size. For instance, WriteVarint32ToArray() @@ -798,8 +807,6 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // WriteVarint32FallbackToArray. Meanwhile, WriteVarint32() is already // out-of-line, so it should just invoke this directly to avoid any extra // function call overhead. - static uint8* WriteVarint32FallbackToArrayInline( - uint32 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; static uint8* WriteVarint64ToArrayInline( uint64 value, uint8* target) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; @@ -919,7 +926,7 @@ inline std::pair CodedInputStream::ReadTagWithCutoff( const uint32 kMax1ByteVarint = 0x7f; uint32 tag = last_tag_ = buffer_[0]; Advance(1); - return make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff); + return std::make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff); } // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available, // and tag is two bytes. The latter is tested by bitwise-and-not of the @@ -937,12 +944,12 @@ inline std::pair CodedInputStream::ReadTagWithCutoff( // so we don't have to check for tag == 0. We may need to check whether // it exceeds cutoff. bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff; - return make_pair(tag, at_or_below_cutoff); + return std::make_pair(tag, at_or_below_cutoff); } } // Slow path last_tag_ = ReadTagFallback(); - return make_pair(last_tag_, static_cast(last_tag_ - 1) < cutoff); + return std::make_pair(last_tag_, static_cast(last_tag_ - 1) < cutoff); } inline bool CodedInputStream::LastTagWas(uint32 expected) { @@ -1027,13 +1034,14 @@ inline uint8* CodedOutputStream::GetDirectBufferForNBytesAndAdvance(int size) { } inline uint8* CodedOutputStream::WriteVarint32ToArray(uint32 value, - uint8* target) { - if (value < 0x80) { - *target = value; - return target + 1; - } else { - return WriteVarint32FallbackToArray(value, target); + uint8* target) { + while (value >= 0x80) { + *target = static_cast(value | 0x80); + value >>= 7; + ++target; } + *target = static_cast(value); + return target + 1; } inline void CodedOutputStream::WriteVarint32SignExtended(int32 value) { @@ -1086,22 +1094,26 @@ inline uint8* CodedOutputStream::WriteLittleEndian64ToArray(uint64 value, return target + sizeof(value); } +inline void CodedOutputStream::WriteVarint32(uint32 value) { + if (buffer_size_ >= 5) { + // Fast path: We have enough bytes left in the buffer to guarantee that + // this write won't cross the end, so we can skip the checks. + uint8* target = buffer_; + uint8* end = WriteVarint32ToArray(value, target); + int size = end - target; + Advance(size); + } else { + WriteVarint32SlowPath(value); + } +} + inline void CodedOutputStream::WriteTag(uint32 value) { WriteVarint32(value); } inline uint8* CodedOutputStream::WriteTagToArray( uint32 value, uint8* target) { - if (value < (1 << 7)) { - target[0] = value; - return target + 1; - } else if (value < (1 << 14)) { - target[0] = static_cast(value | 0x80); - target[1] = static_cast(value >> 7); - return target + 2; - } else { - return WriteVarint32FallbackToArray(value, target); - } + return WriteVarint32ToArray(value, target); } inline int CodedOutputStream::VarintSize32(uint32 value) { diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index bbe5e399..02d5bad3 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -502,11 +502,11 @@ struct Fixed64Case { }; inline std::ostream& operator<<(std::ostream& os, const Fixed32Case& c) { - return os << "0x" << hex << c.value << dec; + return os << "0x" << std::hex << c.value << std::dec; } inline std::ostream& operator<<(std::ostream& os, const Fixed64Case& c) { - return os << "0x" << hex << c.value << dec; + return os << "0x" << std::hex << c.value << std::dec; } Fixed32Case kFixed32Cases[] = { diff --git a/src/google/protobuf/io/gzip_stream.cc b/src/google/protobuf/io/gzip_stream.cc index e6037863..c9f4ca7f 100644 --- a/src/google/protobuf/io/gzip_stream.cc +++ b/src/google/protobuf/io/gzip_stream.cc @@ -49,6 +49,7 @@ static const int kDefaultBufferSize = 65536; GzipInputStream::GzipInputStream( ZeroCopyInputStream* sub_stream, Format format, int buffer_size) : format_(format), sub_stream_(sub_stream), zerror_(Z_OK), byte_count_(0) { + zcontext_.state = Z_NULL; zcontext_.zalloc = Z_NULL; zcontext_.zfree = Z_NULL; zcontext_.opaque = Z_NULL; diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h index 3e25edfa..4360b18f 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -368,7 +368,7 @@ inline char* mutable_string_data(string* s) { inline std::pair as_string_data(string* s) { char *p = mutable_string_data(s); #ifdef LANG_CXX11 - return make_pair(p, true); + return std::make_pair(p, true); #else return make_pair(p, p != NULL); #endif diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index a3705269..4ea21007 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -345,6 +345,6 @@ int main(int argc, char* argv[]) { GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size()); } - cout << "PASS" << endl; + std::cout << "PASS" << std::endl; return 0; } diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 6d8a9d03..e56af3fc 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -34,6 +34,8 @@ #include #include +#include +#include #include namespace google { @@ -45,10 +47,12 @@ class Map; template struct is_proto_enum; namespace internal { -template -class MapField; -} // namespace internal +template +class MapFieldLite; +} // This is the class for google::protobuf::Map's internal value_type. Instead of using // std::pair as value_type, we use this class which provides us more control of @@ -61,23 +65,24 @@ class MapPair { MapPair(const Key& other_first, const T& other_second) : first(other_first), second(other_second) {} - explicit MapPair(const Key& other_first) : first(other_first), second() {} - MapPair(const MapPair& other) : first(other.first), second(other.second) {} ~MapPair() {} - // Implicitly convertible to std::pair. - operator std::pair() const { - return std::pair(first, second); + // Implicitly convertible to std::pair of compatible types. + template + operator std::pair() const { + return std::pair(first, second); } const Key first; T second; private: + typedef void DestructorSkippable_; + friend class ::google::protobuf::Arena; friend class Map; }; @@ -86,6 +91,7 @@ class MapPair { // interface directly to visit or change map fields. template class Map { + typedef internal::MapCppTypeHandler KeyTypeHandler; typedef internal::MapCppTypeHandler ValueTypeHandler; public: @@ -100,20 +106,104 @@ class Map { typedef size_t size_type; typedef hash hasher; - - Map() : default_enum_value_(0) {} - - Map(const Map& other) { + typedef equal_to key_equal; + + Map() + : arena_(NULL), + allocator_(arena_), + elements_(0, hasher(), key_equal(), allocator_), + default_enum_value_(0) {} + explicit Map(Arena* arena) + : arena_(arena), + allocator_(arena_), + elements_(0, hasher(), key_equal(), allocator_), + default_enum_value_(0) {} + + Map(const Map& other) + : arena_(NULL), + allocator_(arena_), + elements_(0, hasher(), key_equal(), allocator_), + default_enum_value_(other.default_enum_value_) { insert(other.begin(), other.end()); } ~Map() { clear(); } + private: + // re-implement std::allocator to use arena allocator for memory allocation. + // Used for google::protobuf::Map implementation. Users should not use this class + // directly. + template + class MapAllocator { + public: + typedef U value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + + MapAllocator() : arena_(NULL) {} + explicit MapAllocator(Arena* arena) : arena_(arena) {} + template + MapAllocator(const MapAllocator& allocator) + : arena_(allocator.arena_) {} + + pointer allocate(size_type n, const_pointer hint = 0) { + // If arena is not given, malloc needs to be called which doesn't + // construct element object. + if (arena_ == NULL) { + return reinterpret_cast(malloc(n * sizeof(value_type))); + } else { + return reinterpret_cast( + Arena::CreateArray(arena_, n * sizeof(value_type))); + } + } + + void deallocate(pointer p, size_type n) { + if (arena_ == NULL) { + free(p); + } + } + + void construct(pointer p, const_reference t) { new (p) value_type(t); } + + void destroy(pointer p) { + if (arena_ == NULL) p->~value_type(); + } + + template + struct rebind { + typedef MapAllocator other; + }; + + template + bool operator==(const MapAllocator& other) const { + return arena_ == other.arena_; + } + + template + bool operator!=(const MapAllocator& other) const { + return arena_ != other.arena_; + } + + private: + Arena* arena_; + + template + friend class MapAllocator; + }; + + public: + typedef MapAllocator*> > Allocator; + // Iterators - class const_iterator + class LIBPROTOBUF_EXPORT const_iterator : public std::iterator { - typedef typename hash_map::const_iterator InnerIt; + typedef typename hash_map, equal_to, + Allocator>::const_iterator InnerIt; public: const_iterator() {} @@ -139,8 +229,9 @@ class Map { InnerIt it_; }; - class iterator : public std::iterator { - typedef typename hash_map::iterator InnerIt; + class LIBPROTOBUF_EXPORT iterator : public std::iterator { + typedef typename hash_map, + Allocator>::iterator InnerIt; public: iterator() {} @@ -185,7 +276,7 @@ class Map { T& operator[](const key_type& key) { value_type** value = &elements_[key]; if (*value == NULL) { - *value = new value_type(key); + *value = CreateValueTypeInternal(key); internal::MapValueInitializer::value, T>::Initialize((*value)->second, default_enum_value_); @@ -241,7 +332,7 @@ class Map { } else { return std::pair( iterator(elements_.insert(std::pair( - value.first, new value_type(value))).first), true); + value.first, CreateValueTypeInternal(value))).first), true); } } template @@ -256,28 +347,29 @@ class Map { // Erase size_type erase(const key_type& key) { - typename hash_map::iterator it = elements_.find(key); + typename hash_map, equal_to, + Allocator>::iterator it = elements_.find(key); if (it == elements_.end()) { return 0; } else { - delete it->second; + if (arena_ == NULL) delete it->second; elements_.erase(it); return 1; } } void erase(iterator pos) { - delete pos.it_->second; + if (arena_ == NULL) delete pos.it_->second; elements_.erase(pos.it_); } void erase(iterator first, iterator last) { for (iterator it = first; it != last;) { - delete it.it_->second; + if (arena_ == NULL) delete it.it_->second; elements_.erase((it++).it_); } } void clear() { for (iterator it = begin(); it != end(); ++it) { - delete it.it_->second; + if (arena_ == NULL) delete it.it_->second; } elements_.clear(); } @@ -297,12 +389,45 @@ class Map { default_enum_value_ = default_enum_value; } - hash_map elements_; + value_type* CreateValueTypeInternal(const Key& key) { + if (arena_ == NULL) { + return new value_type(key); + } else { + value_type* value = reinterpret_cast( + Arena::CreateArray(arena_, sizeof(value_type))); + Arena::CreateInArenaStorage(const_cast(&value->first), arena_); + Arena::CreateInArenaStorage(&value->second, arena_); + const_cast(value->first) = key; + return value; + } + } + + value_type* CreateValueTypeInternal(const value_type& value) { + if (arena_ == NULL) { + return new value_type(value); + } else { + value_type* p = reinterpret_cast( + Arena::CreateArray(arena_, sizeof(value_type))); + Arena::CreateInArenaStorage(const_cast(&p->first), arena_); + Arena::CreateInArenaStorage(&p->second, arena_); + const_cast(p->first) = value.first; + p->second = value.second; + return p; + } + } + + Arena* arena_; + Allocator allocator_; + hash_map, equal_to, Allocator> elements_; int default_enum_value_; - template - friend class internal::MapField; + friend class ::google::protobuf::Arena; + typedef void DestructorSkippable_; + template + friend class LIBPROTOBUF_EXPORT internal::MapFieldLite; }; } // namespace protobuf diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index 30302a09..f78a4f40 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -31,13 +31,23 @@ #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__ #define GOOGLE_PROTOBUF_MAP_ENTRY_H__ -#include +#include +#include #include +#include +#include #include namespace google { namespace protobuf { class Arena; +namespace internal { +template +class MapField; +} } namespace protobuf { @@ -83,179 +93,103 @@ class LIBPROTOBUF_EXPORT MapEntryBase : public Message { // while we need to explicitly tell cpp type if proto type is TYPE_MESSAGE to // get internal layout. // Moreover, default_enum_value is used to initialize enum field in proto2. -template -class MapEntry : public MapEntryBase { - // Handlers for key/value's proto field type. Used to infer internal layout - // and provide parsing/serialization support. - typedef MapProtoTypeHandler KeyProtoHandler; - typedef MapProtoTypeHandler ValueProtoHandler; +template +class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase { + // Handlers for key/value wire type. Provide utilities to parse/serialize + // key/value. + typedef MapWireFieldTypeHandler KeyWireHandler; + typedef MapWireFieldTypeHandler ValueWireHandler; // Define key/value's internal stored type. Message is the only one whose // internal stored type cannot be inferred from its proto type. - typedef typename KeyProtoHandler::CppType KeyProtoHandlerCppType; - typedef typename ValueProtoHandler::CppType ValueProtoHandlerCppType; - static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage; - static const bool kIsValueMessage = ValueProtoHandler::kIsMessage; - typedef typename MapIf::type + static const bool kIsKeyMessage = KeyWireHandler::kIsMessage; + static const bool kIsValueMessage = ValueWireHandler::kIsMessage; + typedef typename KeyWireHandler::CppType KeyInternalType; + typedef typename ValueWireHandler::CppType ValueInternalType; + typedef typename MapIf::type KeyCppType; - typedef typename MapIf::type + typedef typename MapIf::type ValCppType; - // Handlers for key/value's internal stored type. Provide utilities to - // manipulate internal stored type. We need it because some types are stored - // as values and others are stored as pointers (Message and string), but we - // need to keep the code in MapEntry unified instead of providing different - // codes for each type. - typedef MapCppTypeHandler KeyCppHandler; - typedef MapCppTypeHandler ValueCppHandler; - - // Define internal memory layout. Strings and messages are stored as - // pointers, while other types are stored as values. - static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage; - static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage; - typedef typename MapIf::type - KeyBase; - typedef typename MapIf::type - ValueBase; - // Abbreviation for MapEntry typedef typename google::protobuf::internal::MapEntry< - Key, Value, KeyProtoType, ValueProtoType, default_enum_value> EntryType; - - // Constants for field number. - static const int kKeyFieldNumber = 1; - static const int kValueFieldNumber = 2; + Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> EntryType; - // Constants for field tag. - static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( - kKeyFieldNumber, KeyProtoHandler::kWireType); - static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( - kValueFieldNumber, ValueProtoHandler::kWireType); - static const int kTagSize = 1; + // Abbreviation for MapEntryLite + typedef typename google::protobuf::internal::MapEntryLite< + Key, Value, kKeyFieldType, kValueFieldType, default_enum_value> + EntryLiteType; public: ~MapEntry() { if (this == default_instance_) { delete reflection_; - } else { - KeyCppHandler::Delete(key_); - ValueCppHandler::Delete(value_); } } // accessors ====================================================== - inline void set_key(const KeyCppType& key) { - KeyCppHandler::EnsureMutable(&key_); - KeyCppHandler::Merge(key, &key_); - set_has_key(); - } virtual inline const KeyCppType& key() const { - return KeyCppHandler::Reference(key_); + return entry_lite_.key(); } inline KeyCppType* mutable_key() { - set_has_key(); - KeyCppHandler::EnsureMutable(&key_); - return KeyCppHandler::Pointer(key_); - } - inline void set_value(const ValCppType& value) { - ValueCppHandler::EnsureMutable(&value_); - ValueCppHandler::Merge(value, &value_); - set_has_value(); + return entry_lite_.mutable_key(); } virtual inline const ValCppType& value() const { - GOOGLE_CHECK(default_instance_ != NULL); - return ValueCppHandler::DefaultIfNotInitialized(value_, - default_instance_->value_); + return entry_lite_.value(); } inline ValCppType* mutable_value() { - set_has_value(); - ValueCppHandler::EnsureMutable(&value_); - return ValueCppHandler::Pointer(value_); + return entry_lite_.mutable_value(); } // implements Message ============================================= bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) { - uint32 tag; - - for (;;) { - // 1) corrupted data: return false; - // 2) unknown field: skip without putting into unknown field set; - // 3) unknown enum value: keep it in parsing. In proto2, caller should - // check the value and put this entry into containing message's unknown - // field set if the value is an unknown enum. In proto3, caller doesn't - // need to care whether the value is unknown enum; - // 4) missing key/value: missed key/value will have default value. caller - // should take this entry as if key/value is set to default value. - tag = input->ReadTag(); - switch (tag) { - case kKeyTag: - if (!KeyProtoHandler::Read(input, mutable_key())) return false; - set_has_key(); - if (!input->ExpectTag(kValueTag)) break; - GOOGLE_FALLTHROUGH_INTENDED; - - case kValueTag: - if (!ValueProtoHandler::Read(input, mutable_value())) return false; - set_has_value(); - if (input->ExpectAtEnd()) return true; - break; - - default: - if (tag == 0 || - WireFormatLite::GetTagWireType(tag) == - WireFormatLite::WIRETYPE_END_GROUP) { - return true; - } - if (!WireFormatLite::SkipField(input, tag)) return false; - break; - } - } + return entry_lite_.MergePartialFromCodedStream(input); } int ByteSize() const { - int size = 0; - size += has_key() ? kTagSize + KeyProtoHandler::ByteSize(key()) : 0; - size += has_value() ? kTagSize + ValueProtoHandler::ByteSize(value()) : 0; - return size; + return entry_lite_.ByteSize(); } void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const { - KeyProtoHandler::Write(kKeyFieldNumber, key(), output); - ValueProtoHandler::Write(kValueFieldNumber, value(), output); + entry_lite_.SerializeWithCachedSizes(output); } ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { - output = KeyProtoHandler::WriteToArray(kKeyFieldNumber, key(), output); - output = - ValueProtoHandler::WriteToArray(kValueFieldNumber, value(), output); - return output; + return entry_lite_.SerializeWithCachedSizesToArray(output); } int GetCachedSize() const { - int size = 0; - size += has_key() ? kTagSize + KeyProtoHandler::GetCachedSize(key()) : 0; - size += - has_value() ? kTagSize + ValueProtoHandler::GetCachedSize(value()) : 0; - return size; + return entry_lite_.GetCachedSize(); } - bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); } + bool IsInitialized() const { + return entry_lite_.IsInitialized(); + } Message* New() const { MapEntry* entry = new MapEntry; entry->descriptor_ = descriptor_; entry->reflection_ = reflection_; - entry->default_instance_ = default_instance_; + entry->set_default_instance(default_instance_); + return entry; + } + + Message* New(Arena* arena) const { + MapEntry* entry = Arena::CreateMessage(arena); + entry->descriptor_ = descriptor_; + entry->reflection_ = reflection_; + entry->set_default_instance(default_instance_); return entry; } int SpaceUsed() const { int size = sizeof(MapEntry); - size += KeyCppHandler::SpaceUsedInMapEntry(key_); - size += ValueCppHandler::SpaceUsedInMapEntry(value_); + size += entry_lite_.SpaceUsed(); return size; } @@ -280,30 +214,19 @@ class MapEntry : public MapEntryBase { } void MergeFrom(const MapEntry& from) { - if (from._has_bits_[0]) { - if (from.has_key()) { - KeyCppHandler::EnsureMutable(&key_); - KeyCppHandler::Merge(from.key(), &key_); - set_has_key(); - } - if (from.has_value()) { - ValueCppHandler::EnsureMutable(&value_); - ValueCppHandler::Merge(from.value(), &value_); - set_has_value(); - } - } + entry_lite_.MergeFrom(from.entry_lite_); } void Clear() { - KeyCppHandler::Clear(&key_); - ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value); - clear_has_key(); - clear_has_value(); + entry_lite_.Clear(); } void InitAsDefaultInstance() { - KeyCppHandler::AssignDefaultValue(&key_); - ValueCppHandler::AssignDefaultValue(&value_); + entry_lite_.InitAsDefaultInstance(); + } + + Arena* GetArena() const { + return entry_lite_.GetArena(); } // Create default MapEntry instance for given descriptor. Descriptor has to be @@ -311,141 +234,58 @@ class MapEntry : public MapEntryBase { // may have the same type and MapEntry class. The given descriptor is needed // to distinguish instances of the same MapEntry class. static MapEntry* CreateDefaultInstance(const Descriptor* descriptor) { - MapEntry* entry = new MapEntry(); + MapEntry* entry = new MapEntry; const Reflection* reflection = new GeneratedMessageReflection( descriptor, entry, offsets_, - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _has_bits_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_._has_bits_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, _unknown_fields_), -1, DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(MapEntry), -1); entry->descriptor_ = descriptor; entry->reflection_ = reflection; - entry->default_instance_ = entry; + entry->set_default_instance(entry); entry->InitAsDefaultInstance(); RegisterMapEntryDefaultInstance(entry); return entry; } - // Create a MapEntry for given key and value from google::protobuf::Map in - // serialization. This function is only called when value is enum. Enum is - // treated differently because its type in MapEntry is int and its type in - // google::protobuf::Map is enum. We cannot create a reference to int from an enum. - static MapEntry* EnumWrap(const Key& key, const Value value) { - return new MapEnumEntryWrapper(key, value); - } + private: + MapEntry() : default_instance_(NULL), entry_lite_() {} - // Like above, but for all the other types. This avoids value copy to create - // MapEntry from google::protobuf::Map in serialization. - static MapEntry* Wrap(const Key& key, const Value& value) { - return new MapEntryWrapper(key, value); - } + explicit MapEntry(Arena* arena) + : default_instance_(NULL), entry_lite_(arena) {} - protected: - void set_has_key() { _has_bits_[0] |= 0x00000001u; } - bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void clear_has_key() { _has_bits_[0] &= ~0x00000001u; } - void set_has_value() { _has_bits_[0] |= 0x00000002u; } - bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void clear_has_value() { _has_bits_[0] &= ~0x00000002u; } + inline Arena* GetArenaNoVirtual() const { + return entry_lite_.GetArenaNoVirtual(); + } - private: - // Serializing a generated message containing map field involves serializing - // key-value pairs from google::protobuf::Map. The wire format of each key-value pair - // after serialization should be the same as that of a MapEntry message - // containing the same key and value inside it. However, google::protobuf::Map doesn't - // store key and value as MapEntry message, which disables us to use existing - // code to serialize message. In order to use existing code to serialize - // message, we need to construct a MapEntry from key-value pair. But it - // involves copy of key and value to construct a MapEntry. In order to avoid - // this copy in constructing a MapEntry, we need the following class which - // only takes references of given key and value. - template - class MapEntryWrapper - : public MapEntry { - typedef MapEntry Base; - typedef typename Base::KeyCppType KeyCppType; - typedef typename Base::ValCppType ValCppType; - - public: - MapEntryWrapper(const KeyNested& key, const ValueNested& value) - : key_(key), value_(value) { - Base::set_has_key(); - Base::set_has_value(); - } - inline const KeyCppType& key() const { return key_; } - inline const ValCppType& value() const { return value_; } - - private: - const Key& key_; - const Value& value_; - }; - - // Like above, but for enum value only, which stores value instead of - // reference of value field inside. This is needed because the type of value - // field in constructor is an enum, while we need to store it as an int. If we - // initialize a reference to int with a reference to enum, compiler will - // generate a temporary int from enum and initialize the reference to int with - // the temporary. - template - class MapEnumEntryWrapper - : public MapEntry { - typedef MapEntry Base; - typedef typename Base::KeyCppType KeyCppType; - typedef typename Base::ValCppType ValCppType; - - public: - MapEnumEntryWrapper(const KeyNested& key, const ValueNested& value) - : key_(key), value_(value) { - Base::set_has_key(); - Base::set_has_value(); - } - inline const KeyCppType& key() const { return key_; } - inline const ValCppType& value() const { return value_; } - - private: - const KeyCppType& key_; - const ValCppType value_; - }; - - MapEntry() : default_instance_(NULL) { - KeyCppHandler::Initialize(&key_); - ValueCppHandler::InitializeMaybeByDefaultEnum(&value_, default_enum_value); - _has_bits_[0] = 0; + void set_default_instance(MapEntry* default_instance) { + default_instance_ = default_instance; + entry_lite_.set_default_instance(&default_instance->entry_lite_); } - KeyBase key_; - ValueBase value_; static int offsets_[2]; UnknownFieldSet _unknown_fields_; - uint32 _has_bits_[1]; MapEntry* default_instance_; + EntryLiteType entry_lite_; friend class ::google::protobuf::Arena; - template - friend class internal::MapField; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + template + friend class LIBPROTOBUF_EXPORT internal::MapField; friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry); }; -template -int MapEntry +int MapEntry::offsets_[2] = { - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, key_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.key_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MapEntry, entry_lite_.value_), }; } // namespace internal diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h new file mode 100644 index 00000000..0602d847 --- /dev/null +++ b/src/google/protobuf/map_entry_lite.h @@ -0,0 +1,409 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ +#define GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ + +#include +#include + +namespace google { +namespace protobuf { +class Arena; +namespace internal { +template +class MapEntry; +template +class MapFieldLite; +} // namespace internal +} // namespace protobuf + +namespace protobuf { +namespace internal { + +// MapEntryLite is used to implement parsing and serialization of map for lite +// runtime. +template +class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { + // Handlers for key/value wire type. Provide utilities to parse/serialize + // key/value. + typedef MapWireFieldTypeHandler KeyWireHandler; + typedef MapWireFieldTypeHandler ValueWireHandler; + + // Define key/value's internal stored type. Message is the only one whose + // internal stored type cannot be inferred from its proto type + static const bool kIsKeyMessage = KeyWireHandler::kIsMessage; + static const bool kIsValueMessage = ValueWireHandler::kIsMessage; + typedef typename KeyWireHandler::CppType KeyInternalType; + typedef typename ValueWireHandler::CppType ValueInternalType; + typedef typename MapIf::type + KeyCppType; + typedef typename MapIf::type + ValCppType; + + // Handlers for key/value's internal stored type. Provide utilities to + // manipulate internal stored type. We need it because some types are stored + // as values and others are stored as pointers (Message and string), but we + // need to keep the code in MapEntry unified instead of providing different + // codes for each type. + typedef MapCppTypeHandler KeyCppHandler; + typedef MapCppTypeHandler ValueCppHandler; + + // Define internal memory layout. Strings and messages are stored as + // pointers, while other types are stored as values. + static const bool kKeyIsStringOrMessage = KeyCppHandler::kIsStringOrMessage; + static const bool kValIsStringOrMessage = ValueCppHandler::kIsStringOrMessage; + typedef typename MapIf::type + KeyBase; + typedef typename MapIf::type + ValueBase; + + // Constants for field number. + static const int kKeyFieldNumber = 1; + static const int kValueFieldNumber = 2; + + // Constants for field tag. + static const uint8 kKeyTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kKeyFieldNumber, KeyWireHandler::kWireType); + static const uint8 kValueTag = GOOGLE_PROTOBUF_WIRE_FORMAT_MAKE_TAG( + kValueFieldNumber, ValueWireHandler::kWireType); + static const int kTagSize = 1; + + public: + ~MapEntryLite() { + if (this != default_instance_) { + KeyCppHandler::Delete(key_); + ValueCppHandler::Delete(value_); + } + } + + // accessors ====================================================== + + virtual inline const KeyCppType& key() const { + return KeyCppHandler::Reference(key_); + } + inline KeyCppType* mutable_key() { + set_has_key(); + KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual()); + return KeyCppHandler::Pointer(key_); + } + virtual inline const ValCppType& value() const { + GOOGLE_CHECK(default_instance_ != NULL); + return ValueCppHandler::DefaultIfNotInitialized(value_, + default_instance_->value_); + } + inline ValCppType* mutable_value() { + set_has_value(); + ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual()); + return ValueCppHandler::Pointer(value_); + } + + // implements MessageLite ========================================= + + // MapEntryLite is for implementation only and this function isn't called + // anywhere. Just provide a fake implementation here for MessageLite. + string GetTypeName() const { return ""; } + + void CheckTypeAndMergeFrom(const MessageLite& other) { + MergeFrom(*::google::protobuf::down_cast(&other)); + } + + bool MergePartialFromCodedStream(::google::protobuf::io::CodedInputStream* input) { + uint32 tag; + + for (;;) { + // 1) corrupted data: return false; + // 2) unknown field: skip without putting into unknown field set; + // 3) unknown enum value: keep it in parsing. In proto2, caller should + // check the value and put this entry into containing message's unknown + // field set if the value is an unknown enum. In proto3, caller doesn't + // need to care whether the value is unknown enum; + // 4) missing key/value: missed key/value will have default value. caller + // should take this entry as if key/value is set to default value. + tag = input->ReadTag(); + switch (tag) { + case kKeyTag: + if (!KeyWireHandler::Read(input, mutable_key())) return false; + set_has_key(); + if (!input->ExpectTag(kValueTag)) break; + GOOGLE_FALLTHROUGH_INTENDED; + + case kValueTag: + if (!ValueWireHandler::Read(input, mutable_value())) return false; + set_has_value(); + if (input->ExpectAtEnd()) return true; + break; + + default: + if (tag == 0 || + WireFormatLite::GetTagWireType(tag) == + WireFormatLite::WIRETYPE_END_GROUP) { + return true; + } + if (!WireFormatLite::SkipField(input, tag)) return false; + break; + } + } + } + + int ByteSize() const { + int size = 0; + size += has_key() ? kTagSize + KeyWireHandler::ByteSize(key()) : 0; + size += has_value() ? kTagSize + ValueWireHandler::ByteSize(value()) : 0; + return size; + } + + void SerializeWithCachedSizes(::google::protobuf::io::CodedOutputStream* output) const { + KeyWireHandler::Write(kKeyFieldNumber, key(), output); + ValueWireHandler::Write(kValueFieldNumber, value(), output); + } + + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const { + output = KeyWireHandler::WriteToArray(kKeyFieldNumber, key(), output); + output = + ValueWireHandler::WriteToArray(kValueFieldNumber, value(), output); + return output; + } + + int GetCachedSize() const { + int size = 0; + size += has_key() ? kTagSize + KeyWireHandler::GetCachedSize(key()) : 0; + size += + has_value() ? kTagSize + ValueWireHandler::GetCachedSize(value()) : 0; + return size; + } + + bool IsInitialized() const { return ValueCppHandler::IsInitialized(value_); } + + MessageLite* New() const { + MapEntryLite* entry = new MapEntryLite; + entry->default_instance_ = default_instance_; + return entry; + } + + MessageLite* New(Arena* arena) const { + MapEntryLite* entry = Arena::CreateMessage(arena); + entry->default_instance_ = default_instance_; + return entry; + } + + int SpaceUsed() const { + int size = sizeof(MapEntryLite); + size += KeyCppHandler::SpaceUsedInMapEntry(key_); + size += ValueCppHandler::SpaceUsedInMapEntry(value_); + return size; + } + + void MergeFrom(const MapEntryLite& from) { + if (from._has_bits_[0]) { + if (from.has_key()) { + KeyCppHandler::EnsureMutable(&key_, GetArenaNoVirtual()); + KeyCppHandler::Merge(from.key(), &key_); + set_has_key(); + } + if (from.has_value()) { + ValueCppHandler::EnsureMutable(&value_, GetArenaNoVirtual()); + ValueCppHandler::Merge(from.value(), &value_); + set_has_value(); + } + } + } + + void Clear() { + KeyCppHandler::Clear(&key_); + ValueCppHandler::ClearMaybeByDefaultEnum(&value_, default_enum_value); + clear_has_key(); + clear_has_value(); + } + + void InitAsDefaultInstance() { + KeyCppHandler::AssignDefaultValue(&key_); + ValueCppHandler::AssignDefaultValue(&value_); + } + + Arena* GetArena() const { + return GetArenaNoVirtual(); + } + + // Create a MapEntryLite for given key and value from google::protobuf::Map in + // serialization. This function is only called when value is enum. Enum is + // treated differently because its type in MapEntry is int and its type in + // google::protobuf::Map is enum. We cannot create a reference to int from an enum. + static MapEntryLite* EnumWrap(const Key& key, const Value value, + Arena* arena) { + return Arena::Create >( + arena, key, value, arena); + } + + // Like above, but for all the other types. This avoids value copy to create + // MapEntryLite from google::protobuf::Map in serialization. + static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) { + return Arena::Create >( + arena, key, value, arena); + } + + protected: + void set_has_key() { _has_bits_[0] |= 0x00000001u; } + bool has_key() const { return (_has_bits_[0] & 0x00000001u) != 0; } + void clear_has_key() { _has_bits_[0] &= ~0x00000001u; } + void set_has_value() { _has_bits_[0] |= 0x00000002u; } + bool has_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } + void clear_has_value() { _has_bits_[0] &= ~0x00000002u; } + + private: + // Serializing a generated message containing map field involves serializing + // key-value pairs from google::protobuf::Map. The wire format of each key-value pair + // after serialization should be the same as that of a MapEntry message + // containing the same key and value inside it. However, google::protobuf::Map doesn't + // store key and value as MapEntry message, which disables us to use existing + // code to serialize message. In order to use existing code to serialize + // message, we need to construct a MapEntry from key-value pair. But it + // involves copy of key and value to construct a MapEntry. In order to avoid + // this copy in constructing a MapEntry, we need the following class which + // only takes references of given key and value. + template + class LIBPROTOBUF_EXPORT MapEntryWrapper + : public MapEntryLite { + typedef MapEntryLite Base; + typedef typename Base::KeyCppType KeyCppType; + typedef typename Base::ValCppType ValCppType; + + public: + MapEntryWrapper(const K& key, const V& value, Arena* arena) + : MapEntryLite(arena), + key_(key), + value_(value) { + Base::set_has_key(); + Base::set_has_value(); + } + inline const KeyCppType& key() const { return key_; } + inline const ValCppType& value() const { return value_; } + + private: + const Key& key_; + const Value& value_; + + friend class ::google::protobuf::Arena; + typedef void DestructorSkippable_; + }; + + // Like above, but for enum value only, which stores value instead of + // reference of value field inside. This is needed because the type of value + // field in constructor is an enum, while we need to store it as an int. If we + // initialize a reference to int with a reference to enum, compiler will + // generate a temporary int from enum and initialize the reference to int with + // the temporary. + template + class LIBPROTOBUF_EXPORT MapEnumEntryWrapper + : public MapEntryLite { + typedef MapEntryLite Base; + typedef typename Base::KeyCppType KeyCppType; + typedef typename Base::ValCppType ValCppType; + + public: + MapEnumEntryWrapper(const K& key, const V& value, Arena* arena) + : MapEntryLite(arena), + key_(key), + value_(value) { + Base::set_has_key(); + Base::set_has_value(); + } + inline const KeyCppType& key() const { return key_; } + inline const ValCppType& value() const { return value_; } + + private: + const KeyCppType& key_; + const ValCppType value_; + + friend class ::google::protobuf::Arena; + typedef void DestructorSkippable_; + }; + + MapEntryLite() : arena_(NULL) { + KeyCppHandler::Initialize(&key_, NULL); + ValueCppHandler::InitializeMaybeByDefaultEnum( + &value_, default_enum_value, NULL); + _has_bits_[0] = 0; + } + + explicit MapEntryLite(Arena* arena) + : arena_(arena) { + KeyCppHandler::Initialize(&key_, arena); + ValueCppHandler::InitializeMaybeByDefaultEnum( + &value_, default_enum_value, arena); + _has_bits_[0] = 0; + } + + inline Arena* GetArenaNoVirtual() const { + return arena_; + } + + void set_default_instance(MapEntryLite* default_instance) { + default_instance_ = default_instance; + } + + MapEntryLite* default_instance_ = NULL; + + KeyBase key_; + ValueBase value_; + Arena* arena_; + uint32 _has_bits_[1]; + + friend class ::google::protobuf::Arena; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + template + friend class LIBPROTOBUF_EXPORT internal::MapEntry; + template + friend class LIBPROTOBUF_EXPORT internal::MapFieldLite; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite); +}; + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__ diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc index b535ec28..fd40c0d8 100644 --- a/src/google/protobuf/map_field.cc +++ b/src/google/protobuf/map_field.cc @@ -55,14 +55,14 @@ void InitMapEntryDefaultInstances() { } void RegisterMapEntryDefaultInstance(MessageLite* default_instance) { - GoogleOnceInit(&map_entry_default_instances_once_, + ::google::protobuf::GoogleOnceInit(&map_entry_default_instances_once_, &InitMapEntryDefaultInstances); MutexLock lock(map_entry_default_instances_mutex_); map_entry_default_instances_->push_back(default_instance); } MapFieldBase::~MapFieldBase() { - if (repeated_field_ != NULL) delete repeated_field_; + if (repeated_field_ != NULL && arena_ == NULL) delete repeated_field_; } const RepeatedPtrFieldBase& MapFieldBase::GetRepeatedField() const { @@ -118,7 +118,9 @@ void MapFieldBase::SyncRepeatedFieldWithMap() const { } void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const { - if (repeated_field_ == NULL) repeated_field_ = new RepeatedPtrField; + if (repeated_field_ == NULL) { + repeated_field_ = Arena::Create >(arena_, arena_); + } } void MapFieldBase::SyncMapWithRepeatedField() const { diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 8516d74e..6d8b6ec8 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -34,8 +34,10 @@ #include #include #include -#include +#include #include +#include +#include #include #include #include @@ -56,7 +58,13 @@ class MapFieldAccessor; class LIBPROTOBUF_EXPORT MapFieldBase { public: MapFieldBase() - : base_map_(NULL), + : arena_(NULL), + repeated_field_(NULL), + entry_descriptor_(NULL), + assign_descriptor_callback_(NULL), + state_(STATE_MODIFIED_MAP) {} + explicit MapFieldBase(Arena* arena) + : arena_(arena), repeated_field_(NULL), entry_descriptor_(NULL), assign_descriptor_callback_(NULL), @@ -109,7 +117,7 @@ class LIBPROTOBUF_EXPORT MapFieldBase { CLEAN = 2, // data in map and repeated field are same }; - mutable void* base_map_; + Arena* arena_; mutable RepeatedPtrField* repeated_field_; // MapEntry can only be created from MapField. To create MapEntry, MapField // needs to know its descriptor, because MapEntry is not generated class which @@ -134,41 +142,55 @@ class LIBPROTOBUF_EXPORT MapFieldBase { // This class provides accesss to map field using generated api. It is used for // internal generated message implentation only. Users should never use this // directly. -template -class MapField : public MapFieldBase { - // Handlers for key/value's proto field type. - typedef MapProtoTypeHandler KeyProtoHandler; - typedef MapProtoTypeHandler ValueProtoHandler; +template +class LIBPROTOBUF_EXPORT MapField : public MapFieldBase, + public MapFieldLite { + // Handlers for key/value wire type. Provide utilities to parse/serialize + // key/value. + typedef MapWireFieldTypeHandler KeyWireHandler; + typedef MapWireFieldTypeHandler ValueWireHandler; // Define key/value's internal stored type. - typedef typename KeyProtoHandler::CppType KeyHandlerCpp; - typedef typename ValueProtoHandler::CppType ValHandlerCpp; - static const bool kIsKeyMessage = KeyProtoHandler::kIsMessage; - static const bool kIsValMessage = ValueProtoHandler::kIsMessage; - typedef typename MapIf::type KeyCpp; - typedef typename MapIf::type ValCpp; + static const bool kIsKeyMessage = KeyWireHandler::kIsMessage; + static const bool kIsValMessage = ValueWireHandler::kIsMessage; + typedef typename KeyWireHandler::CppType KeyInternalType; + typedef typename ValueWireHandler::CppType ValueInternalType; + typedef typename MapIf::type KeyCpp; + typedef typename MapIf::type ValCpp; // Handlers for key/value's internal stored type. typedef MapCppTypeHandler KeyHandler; typedef MapCppTypeHandler ValHandler; // Define message type for internal repeated field. - typedef MapEntry EntryType; + typedef MapEntry + EntryType; + typedef MapEntryLite EntryLiteType; + + // Define abbreviation for parent MapFieldLite + typedef MapFieldLite MapFieldLiteType; // Enum needs to be handled differently from other types because it has // different exposed type in google::protobuf::Map's api and repeated field's api. For // details see the comment in the implementation of // SyncMapWithRepeatedFieldNoLocki. - static const bool kIsValueEnum = ValueProtoHandler::kIsEnum; + static const bool kIsValueEnum = ValueWireHandler::kIsEnum; typedef typename MapIf::type CastValueType; public: MapField(); + explicit MapField(Arena* arena); // MapField doesn't own the default_entry, which means default_entry must // outlive the lifetime of MapField. MapField(const Message* default_entry); + // For tests only. + MapField(Arena* arena, const Message* default_entry); ~MapField(); // Accessors @@ -178,29 +200,22 @@ class MapField : public MapFieldBase { // Convenient methods for generated message implementation. int size() const; void Clear(); - void MergeFrom(const MapField& other); - void Swap(MapField* other); + void MergeFrom(const MapFieldLiteType& other); + void Swap(MapFieldLiteType* other); // Allocates metadata only if this MapField is part of a generated message. void SetEntryDescriptor(const Descriptor** descriptor); void SetAssignDescriptorCallback(void (*callback)()); - // Set default enum value only for proto2 map field whose value is enum type. - void SetDefaultEnumValue(); - - // Used in the implementation of parsing. Caller should take the ownership. - EntryType* NewEntry() const; - // Used in the implementation of serializing enum value type. Caller should - // take the ownership. - EntryType* NewEnumEntryWrapper(const Key& key, const T t) const; - // Used in the implementation of serializing other value types. Caller should - // take the ownership. - EntryType* NewEntryWrapper(const Key& key, const T& t) const; - private: + typedef void DestructorSkippable_; + // MapField needs MapEntry's default instance to create new MapEntry. void InitDefaultEntryOnce() const; + // Manually set default entry instance. For test only. + void SetDefaultEntryOnce(const EntryType* default_entry) const; + // Convenient methods to get internal google::protobuf::Map const Map& GetInternalMap() const; Map* MutableInternalMap(); @@ -211,14 +226,9 @@ class MapField : public MapFieldBase { int SpaceUsedExcludingSelfNoLock() const; mutable const EntryType* default_entry_; -}; -// True if IsInitialized() is true for value field in all elements of t. T is -// expected to be message. It's useful to have this helper here to keep the -// protobuf compiler from ever having to emit loops in IsInitialized() methods. -// We want the C++ compiler to inline this or not as it sees fit. -template -bool AllAreInitialized(const Map& t); + friend class ::google::protobuf::Arena; +}; } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h index 79302e48..ae63c721 100644 --- a/src/google/protobuf/map_field_inl.h +++ b/src/google/protobuf/map_field_inl.h @@ -43,160 +43,183 @@ namespace google { namespace protobuf { namespace internal { -template -MapField::MapField() - : default_entry_(NULL) { - MapFieldBase::base_map_ = new Map; - SetDefaultEnumValue(); -} +template +MapField::MapField() + : default_entry_(NULL) {} + +template +MapField::MapField( + Arena* arena) + : MapFieldBase(arena), + MapFieldLite( + arena), + default_entry_(NULL) {} -template -MapField::MapField( +template +MapField::MapField( const Message* default_entry) - : default_entry_(down_cast(default_entry)) { - MapFieldBase::base_map_ = new Map; - SetDefaultEnumValue(); -} + : default_entry_(down_cast(default_entry)) {} -template -MapField::~MapField() { - delete reinterpret_cast*>(MapFieldBase::base_map_); -} +template +MapField::MapField( + Arena* arena, const Message* default_entry) + : MapFieldBase(arena), + MapFieldLite( + arena), + default_entry_(down_cast(default_entry)) {} -template -int MapField::size() const { +template +MapField::~MapField() {} + +template +int +MapField::size() const { SyncMapWithRepeatedField(); - return GetInternalMap().size(); + return MapFieldLiteType::GetInternalMap().size(); } -template -void MapField::Clear() { +template +void +MapField::Clear() { SyncMapWithRepeatedField(); - MutableInternalMap()->clear(); + MapFieldLiteType::MutableInternalMap()->clear(); SetMapDirty(); } -template +template const Map& -MapField::GetMap() const { +MapField::GetMap() const { SyncMapWithRepeatedField(); - return GetInternalMap(); + return MapFieldLiteType::GetInternalMap(); } -template +template Map* -MapField::MutableMap() { +MapField::MutableMap() { SyncMapWithRepeatedField(); - Map* result = MutableInternalMap(); + Map* result = MapFieldLiteType::MutableInternalMap(); SetMapDirty(); return result; } -template -void MapField::MergeFrom( - const MapField& other) { +template +void +MapField::MergeFrom( + const MapFieldLiteType& other) { + const MapField& down_other = down_cast(other); SyncMapWithRepeatedField(); - other.SyncMapWithRepeatedField(); - - Map* map = MutableInternalMap(); - const Map& other_map = other.GetInternalMap(); - for (typename Map::const_iterator it = other_map.begin(); - it != other_map.end(); ++it) { - (*map)[it->first] = it->second; - } + down_other.SyncMapWithRepeatedField(); + MapFieldLiteType::MergeFrom(other); SetMapDirty(); } -template -void MapField::Swap( - MapField* other) { - std::swap(repeated_field_, other->repeated_field_); - std::swap(base_map_, other->base_map_); - std::swap(state_, other->state_); +template +void +MapField::Swap( + MapFieldLiteType* other) { + MapField* down_other = down_cast(other); + std::swap(repeated_field_, down_other->repeated_field_); + MapFieldLiteType::Swap(other); + std::swap(state_, down_other->state_); } -template +template void -MapField::SetEntryDescriptor( +MapField::SetEntryDescriptor( const Descriptor** descriptor) { entry_descriptor_ = descriptor; } -template +template void -MapField::SetAssignDescriptorCallback(void (*callback)()) { assign_descriptor_callback_ = callback; } -template -void MapField::SetDefaultEnumValue() { - MutableInternalMap()->SetDefaultEnumValue(default_enum_value); -} - -template -MapEntry* -MapField::NewEntry() const { - // The MapEntry instance created here is only used in generated code for - // parsing. It doesn't have default instance, descriptor or reflection, - // because these are not needed in parsing and will prevent us from using it - // for parsing MessageLite. - return new EntryType(); -} - -template -MapEntry* -MapField::NewEntryWrapper( - const Key& key, const T& t) const { - return EntryType::Wrap(key, t); -} - -template -MapEntry* -MapField::NewEnumEntryWrapper( - const Key& key, const T t) const { - return EntryType::EnumWrap(key, t); -} - -template -const Map& MapField::GetInternalMap() const { - return *reinterpret_cast*>(MapFieldBase::base_map_); +template +const Map& +MapField::GetInternalMap() const { + return MapFieldLiteType::GetInternalMap(); } -template -Map* MapField::MutableInternalMap() { - return reinterpret_cast*>(MapFieldBase::base_map_); +template +Map* +MapField::MutableInternalMap() { + return MapFieldLiteType::MutableInternalMap(); } -template -void MapField::SyncRepeatedFieldWithMapNoLock() const { +template +void +MapField::SyncRepeatedFieldWithMapNoLock() const { if (repeated_field_ == NULL) { - repeated_field_ = new RepeatedPtrField(); + if (arena_ == NULL) { + repeated_field_ = new RepeatedPtrField(); + } else { + repeated_field_ = + Arena::Create >(arena_, arena_); + } } - const Map& map = - *static_cast*>(MapFieldBase::base_map_); + const Map& map = GetInternalMap(); RepeatedPtrField* repeated_field = reinterpret_cast*>(repeated_field_); @@ -206,18 +229,21 @@ void MapField(default_entry_->New()); + EntryType* new_entry = down_cast(default_entry_->New(arena_)); repeated_field->AddAllocated(new_entry); - new_entry->set_key(it->first); - new_entry->set_value(it->second); + (*new_entry->mutable_key()) = it->first; + (*new_entry->mutable_value()) = it->second; } } -template -void MapField::SyncMapWithRepeatedFieldNoLock() const { - Map* map = reinterpret_cast*>(MapFieldBase::base_map_); +template +void +MapField::SyncMapWithRepeatedFieldNoLock() const { + Map* map = const_cast(this)->MutableInternalMap(); RepeatedPtrField* repeated_field = reinterpret_cast*>(repeated_field_); map->clear(); @@ -232,15 +258,18 @@ void MapField -int MapField::SpaceUsedExcludingSelfNoLock() const { +template +int +MapField::SpaceUsedExcludingSelfNoLock() const { int size = 0; if (repeated_field_ != NULL) { size += repeated_field_->SpaceUsedExcludingSelf(); } - Map* map = reinterpret_cast*>(MapFieldBase::base_map_); + Map* map = const_cast(this)->MutableInternalMap(); size += sizeof(*map); for (typename Map::iterator it = map->begin(); it != map->end(); ++it) { @@ -250,10 +279,14 @@ int MapField -void MapField::InitDefaultEntryOnce() const { +template +void +MapField::InitDefaultEntryOnce() + const { if (default_entry_ == NULL) { InitMetadataOnce(); GOOGLE_CHECK(*entry_descriptor_ != NULL); @@ -262,15 +295,6 @@ void MapField -bool AllAreInitialized(const Map& t) { - for (typename Map::const_iterator it = t.begin(); it != t.end(); - ++it) { - if (!it->second.IsInitialized()) return false; - } - return true; -} - } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h new file mode 100644 index 00000000..549ecc08 --- /dev/null +++ b/src/google/protobuf/map_field_lite.h @@ -0,0 +1,278 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +// This class provides accesss to map field using generated api. It is used for +// internal generated message implentation only. Users should never use this +// directly. +template +class LIBPROTOBUF_EXPORT MapFieldLite { + // Define message type for internal repeated field. + typedef MapEntryLite EntryType; + + public: + MapFieldLite(); + explicit MapFieldLite(Arena* arena); + virtual ~MapFieldLite(); + + // Accessors + virtual const Map& GetMap() const; + virtual Map* MutableMap(); + + // Convenient methods for generated message implementation. + virtual int size() const; + virtual void Clear(); + virtual void MergeFrom(const MapFieldLite& other); + virtual void Swap(MapFieldLite* other); + + // Set default enum value only for proto2 map field whose value is enum type. + void SetDefaultEnumValue(); + + // Used in the implementation of parsing. Caller should take the ownership. + EntryType* NewEntry() const; + // Used in the implementation of serializing enum value type. Caller should + // take the ownership. + EntryType* NewEnumEntryWrapper(const Key& key, const T t) const; + // Used in the implementation of serializing other value types. Caller should + // take the ownership. + EntryType* NewEntryWrapper(const Key& key, const T& t) const; + + protected: + // Convenient methods to get internal google::protobuf::Map + virtual const Map& GetInternalMap() const; + virtual Map* MutableInternalMap(); + + private: + typedef void DestructorSkippable_; + + Arena* arena_; + Map* map_; + + friend class ::google::protobuf::Arena; +}; + +template +MapFieldLite::MapFieldLite() + : arena_(NULL) { + map_ = new Map; + SetDefaultEnumValue(); +} + +template +MapFieldLite::MapFieldLite(Arena* arena) + : arena_(arena) { + map_ = Arena::Create >(arena, arena); + SetDefaultEnumValue(); +} + +template +MapFieldLite::~MapFieldLite() { + delete map_; +} + +template +const Map& +MapFieldLite::GetMap() const { + return *map_; +} + +template +Map* +MapFieldLite::MutableMap() { + return map_; +} + +template +int +MapFieldLite::size() const { + return map_->size(); +} + +template +void +MapFieldLite::Clear() { + map_->clear(); +} + +template +void +MapFieldLite::MergeFrom( + const MapFieldLite& other) { + for (typename Map::const_iterator it = other.map_->begin(); + it != other.map_->end(); ++it) { + (*map_)[it->first] = it->second; + } +} + +template +void +MapFieldLite::Swap( + MapFieldLite* other) { + std::swap(map_, other->map_); +} + +template +void +MapFieldLite::SetDefaultEnumValue() { + MutableInternalMap()->SetDefaultEnumValue(default_enum_value); +} + +template +const Map& +MapFieldLite::GetInternalMap() const { + return *map_; +} + +template +Map* +MapFieldLite::MutableInternalMap() { + return map_; +} + +#define EntryType \ + MapEntryLite + +template +EntryType* +MapFieldLite::NewEntry() const { + if (arena_ == NULL) { + return new EntryType(); + } else { + return Arena::CreateMessage(arena_); + } +} + +template +EntryType* +MapFieldLite::NewEnumEntryWrapper(const Key& key, + const T t) const { + return EntryType::EnumWrap(key, t, arena_); +} + +template +EntryType* +MapFieldLite::NewEntryWrapper(const Key& key, + const T& t) const { + return EntryType::Wrap(key, t, arena_); +} + +#undef EntryType + +// True if IsInitialized() is true for value field in all elements of t. T is +// expected to be message. It's useful to have this helper here to keep the +// protobuf compiler from ever having to emit loops in IsInitialized() methods. +// We want the C++ compiler to inline this or not as it sees fit. +template +bool AllAreInitialized(const Map& t) { + for (typename Map::const_iterator it = t.begin(); it != t.end(); + ++it) { + if (!it->second.IsInitialized()) return false; + } + return true; +} + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__ diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 045f8f2c..61344cbb 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -35,13 +35,16 @@ #endif #include +#include #include +#include #include #include #include #include #include #include +#include #include namespace google { @@ -53,6 +56,9 @@ using unittest::TestAllTypes; class MapFieldBaseStub : public MapFieldBase { public: + typedef void DestructorSkippable_; + MapFieldBaseStub() {} + explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {} void SyncRepeatedFieldWithMap() const { MapFieldBase::SyncRepeatedFieldWithMap(); } @@ -63,16 +69,6 @@ class MapFieldBaseStub : public MapFieldBase { RepeatedPtrField* InternalRepeatedField() { return repeated_field_; } - // Get underlined map without synchronizing repeated field. - template - const MapType& GetMap() { - return *reinterpret_cast(base_map_); - } - // Get underlined map without synchronizing repeated field. - template - MapType* MutableMap() { - return reinterpret_cast(base_map_); - } bool IsMapClean() { return state_ != 0; } bool IsRepeatedClean() { return state_ != 1; } void SetMapDirty() { state_ = 0; } @@ -81,8 +77,8 @@ class MapFieldBaseStub : public MapFieldBase { class MapFieldBasePrimitiveTest : public ::testing::Test { protected: - typedef MapField MapFieldType; + typedef MapField MapFieldType; MapFieldBasePrimitiveTest() { // Get descriptors @@ -144,6 +140,38 @@ TEST_F(MapFieldBasePrimitiveTest, MutableRepeatedField) { } } +TEST_F(MapFieldBasePrimitiveTest, Arena) { + // Allocate a large initial block to avoid mallocs during hooked test. + std::vector arena_block(128 * 1024); + ArenaOptions options; + options.initial_block = arena_block.data(); + options.initial_block_size = arena_block.size(); + Arena arena(options); + + { + NoHeapChecker no_heap; + + MapFieldType* map_field = + Arena::Create(&arena, &arena, default_entry_); + + // Set content in map + (*map_field->MutableMap())[100] = 101; + + // Trigger conversion to repeated field. + map_field->GetRepeatedField(); + } + + { + NoHeapChecker no_heap; + + MapFieldBaseStub* map_field = + Arena::Create(&arena, &arena); + + // Trigger conversion to repeated field. + EXPECT_TRUE(map_field->MutableRepeatedField() != NULL); + } +} + namespace { enum State { CLEAN, MAP_DIRTY, REPEATED_DIRTY }; } // anonymous namespace @@ -152,8 +180,10 @@ class MapFieldStateTest : public testing::TestWithParam { public: protected: - typedef MapField MapFieldType; + typedef MapField MapFieldType; + typedef MapFieldLite MapFieldLiteType; MapFieldStateTest() : state_(GetParam()) { // Build map field const Descriptor* map_descriptor = @@ -199,9 +229,8 @@ class MapFieldStateTest MakeMapDirty(map_field); MapFieldBase* map_field_base = map_field; map_field_base->MutableRepeatedField(); - MapFieldBaseStub* stub = - reinterpret_cast(map_field_base); - Map* map = stub->MutableMap >(); + Map* map = implicit_cast(map_field) + ->MapFieldLiteType::MutableMap(); map->clear(); Expect(map_field, REPEATED_DIRTY, 0, 1, false); @@ -213,7 +242,8 @@ class MapFieldStateTest MapFieldBaseStub* stub = reinterpret_cast(map_field_base); - Map* map = stub->MutableMap >(); + Map* map = implicit_cast(map_field) + ->MapFieldLiteType::MutableMap(); RepeatedPtrField* repeated_field = stub->InternalRepeatedField(); switch (state) { @@ -430,6 +460,7 @@ TEST_P(MapFieldStateTest, MutableMapField) { } } + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/map_lite_test_util.cc b/src/google/protobuf/map_lite_test_util.cc new file mode 100644 index 00000000..b65b4d63 --- /dev/null +++ b/src/google/protobuf/map_lite_test_util.cc @@ -0,0 +1,93 @@ +// 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 +#include +#include + +namespace google { +namespace protobuf { + +void MapLiteTestUtil::SetMapFields(unittest::TestMapLite* message) { + MapTestUtilImpl::SetMapFields(message); +} + +void MapLiteTestUtil::SetArenaMapFields(unittest::TestArenaMapLite* message) { + MapTestUtilImpl::SetArenaMapFields(message); +} + +void MapLiteTestUtil::SetMapFieldsInitialized(unittest::TestMapLite* message) { + MapTestUtilImpl::SetMapFieldsInitialized(message); +} + +void MapLiteTestUtil::ModifyMapFields(unittest::TestMapLite* message) { + MapTestUtilImpl::ModifyMapFields(message); +} + +void MapLiteTestUtil::ExpectClear(const unittest::TestMapLite& message) { + MapTestUtilImpl::ExpectClear(message); +} + +void MapLiteTestUtil::ExpectMapFieldsSet(const unittest::TestMapLite& message) { + MapTestUtilImpl::ExpectMapFieldsSet(message); +} + +void MapLiteTestUtil::ExpectArenaMapFieldsSet( + const unittest::TestArenaMapLite& message) { + MapTestUtilImpl::ExpectArenaMapFieldsSet( + message); +} + +void MapLiteTestUtil::ExpectMapFieldsSetInitialized( + const unittest::TestMapLite& message) { + MapTestUtilImpl::ExpectMapFieldsSetInitialized( + message); +} + +void MapLiteTestUtil::ExpectMapFieldsModified( + const unittest::TestMapLite& message) { + MapTestUtilImpl::ExpectMapFieldsModified( + message); +} + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/map_lite_test_util.h b/src/google/protobuf/map_lite_test_util.h new file mode 100644 index 00000000..77b5336f --- /dev/null +++ b/src/google/protobuf/map_lite_test_util.h @@ -0,0 +1,80 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__ +#define GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__ + +#include + +namespace google { +namespace protobuf { + +class MapLiteTestUtil { + public: + // Set every field in the TestMapLite message to a unique value. + static void SetMapFields(protobuf_unittest::TestMapLite* message); + + // Set every field in the TestArenaMapLite message to a unique value. + static void SetArenaMapFields(protobuf_unittest::TestArenaMapLite* message); + + // Set every field in the message to a default value. + static void SetMapFieldsInitialized(protobuf_unittest::TestMapLite* message); + + // Modify all the map fields of the messsage (which should already have been + // initialized with SetMapFields()). + static void ModifyMapFields(protobuf_unittest::TestMapLite* message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called. + static void ExpectMapFieldsSet(const protobuf_unittest::TestMapLite& message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called for TestArenaMapLite. + static void ExpectArenaMapFieldsSet( + const protobuf_unittest::TestArenaMapLite& message); + + // Check that all fields have the values that they should have after + // SetMapFieldsInitialized() is called. + static void ExpectMapFieldsSetInitialized( + const protobuf_unittest::TestMapLite& message); + + // Expect that the message is modified as would be expected from + // ModifyMapFields(). + static void ExpectMapFieldsModified( + const protobuf_unittest::TestMapLite& message); + + // Check that all fields are empty. + static void ExpectClear(const protobuf_unittest::TestMapLite& message); +}; + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__ diff --git a/src/google/protobuf/map_lite_unittest.proto b/src/google/protobuf/map_lite_unittest.proto index cc71555d..c69e8d94 100644 --- a/src/google/protobuf/map_lite_unittest.proto +++ b/src/google/protobuf/map_lite_unittest.proto @@ -30,10 +30,104 @@ syntax = "proto2"; +option cc_enable_arenas = true; option optimize_for = LITE_RUNTIME; +import "google/protobuf/unittest_lite.proto"; + package protobuf_unittest; -message MapLite { - map map_field = 1; +message TestMapLite { + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; + map map_sfixed32_sfixed32 = 9; + map map_sfixed64_sfixed64 = 10; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_string_string = 14; + map map_int32_bytes = 15; + map map_int32_enum = 16; + map map_int32_foreign_message = 17; + map teboring = 18; +} + +message TestArenaMapLite { + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; + map map_sfixed32_sfixed32 = 9; + map map_sfixed64_sfixed64 = 10; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_int32_enum = 14; + map map_int32_foreign_message = 15; +} + +// Test embeded message with required fields +message TestRequiredMessageMapLite { + map map_field = 1; +} + +message TestEnumStartWithNonZeroMapLite { + map map_field = 101; +} + +message TestEnumMapLite { + map known_map_field = 101; + map unknown_map_field = 102; +} + +message TestEnumMapPlusExtraLite { + map known_map_field = 101; + map unknown_map_field = 102; +} + +message TestMessageMapLite { + map map_int32_message = 1; +} + +enum Proto2MapEnumLite { + PROTO2_MAP_ENUM_FOO_LITE = 0; + PROTO2_MAP_ENUM_BAR_LITE = 1; + PROTO2_MAP_ENUM_BAZ_LITE = 2; +} + +enum Proto2MapEnumPlusExtraLite { + E_PROTO2_MAP_ENUM_FOO_LITE = 0; + E_PROTO2_MAP_ENUM_BAR_LITE = 1; + E_PROTO2_MAP_ENUM_BAZ_LITE = 2; + E_PROTO2_MAP_ENUM_EXTRA_LITE = 3; +} + +enum Proto2MapEnumStartWithNonZeroLite { + PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE = 1; +} + +enum MapEnumLite { + MAP_ENUM_FOO_LITE = 0; + MAP_ENUM_BAR_LITE = 1; + MAP_ENUM_BAZ_LITE = 2; +} + +message TestRequiredLite { + required int32 a = 1; + required int32 b = 2; + required int32 c = 3; +} + +message ForeignMessageArenaLite { + optional int32 c = 1; } diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index 9db67523..88cba1f2 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -39,7 +39,7 @@ #include #include #include -#include +#include #include #include #include @@ -191,6 +191,7 @@ TEST_F(MapImplTest, MutableAt) { } #ifdef PROTOBUF_HAS_DEATH_TEST + TEST_F(MapImplTest, MutableAtNonExistDeathTest) { EXPECT_DEATH(map_.at(0), ""); } @@ -198,6 +199,7 @@ TEST_F(MapImplTest, MutableAtNonExistDeathTest) { TEST_F(MapImplTest, ImmutableAtNonExistDeathTest) { EXPECT_DEATH(const_map_.at(0), ""); } + #endif // PROTOBUF_HAS_DEATH_TEST TEST_F(MapImplTest, CountNonExist) { @@ -553,6 +555,14 @@ TEST_F(MapImplTest, ConvertToStdMap) { EXPECT_EQ(101, std_map[100]); } +TEST_F(MapImplTest, ConvertToStdVectorOfPairs) { + map_[100] = 101; + std::vector > std_vec(map_.begin(), map_.end()); + EXPECT_EQ(1, std_vec.size()); + EXPECT_EQ(100, std_vec[0].first); + EXPECT_EQ(101, std_vec[0].second); +} + // Map Field Reflection Test ======================================== static int Func(int i, int j) { @@ -1717,6 +1727,20 @@ TEST(GeneratedMapFieldTest, MissedValueWireFormat) { EXPECT_EQ(0, message.map_int32_int32().at(1)); } +TEST(GeneratedMapFieldTest, MissedValueTextFormat) { + unittest::TestMap message; + + // No value field in text format + string text = + "map_int32_foreign_message {\n" + " key: 1234567890\n" + "}"; + + EXPECT_TRUE(google::protobuf::TextFormat::ParseFromString(text, &message)); + EXPECT_EQ(1, message.map_int32_foreign_message().size()); + EXPECT_EQ(11, message.ByteSize()); +} + TEST(GeneratedMapFieldTest, UnknownFieldWireFormat) { unittest::TestMap message; @@ -1737,18 +1761,6 @@ TEST(GeneratedMapFieldTest, CorruptedWireFormat) { EXPECT_FALSE(message.ParseFromString(data)); } -TEST(GeneratedMapFieldTest, MessageLiteMap) { - unittest::MapLite from, to; - (*from.mutable_map_field())[1] = 1; - - string data; - from.SerializeToString(&data); - to.ParseFromString(data); - - EXPECT_EQ(1, to.map_field().size()); - EXPECT_EQ(1, to.map_field().at(1)); -} - TEST(GeneratedMapFieldTest, IsInitialized) { unittest::TestRequiredMessageMap map_message; @@ -2247,6 +2259,52 @@ TEST(TextFormatMapTest, SerializeAndParse) { } +// arena support ================================================= +TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) { + // Allocate a large initial block to avoid mallocs during hooked test. + std::vector arena_block(128 * 1024); + ArenaOptions options; + options.initial_block = arena_block.data(); + options.initial_block_size = arena_block.size(); + Arena arena(options); + string data; + data.reserve(128 * 1024); + + { + NoHeapChecker no_heap; + + unittest::TestArenaMap* from = + Arena::CreateMessage(&arena); + MapTestUtil::SetArenaMapFields(from); + from->SerializeToString(&data); + + unittest::TestArenaMap* to = + Arena::CreateMessage(&arena); + to->ParseFromString(data); + MapTestUtil::ExpectArenaMapFieldsSet(*to); + } +} + +// Use text format parsing and serializing to test reflection api. +TEST(ArenaTest, RelfectionInTextFormat) { + Arena arena; + string data; + + TextFormat::Printer printer; + TextFormat::Parser parser; + + unittest::TestArenaMap* from = + Arena::CreateMessage(&arena); + unittest::TestArenaMap* to = + Arena::CreateMessage(&arena); + + MapTestUtil::SetArenaMapFields(from); + printer.PrintToString(*from, &data); + + EXPECT_TRUE(parser.ParseFromString(data, to)); + MapTestUtil::ExpectArenaMapFieldsSet(*to); +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/map_test_util.cc b/src/google/protobuf/map_test_util.cc index eb7ea511..1713e373 100644 --- a/src/google/protobuf/map_test_util.cc +++ b/src/google/protobuf/map_test_util.cc @@ -29,275 +29,60 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include +#include #include #include -#include -#include -#include - namespace google { namespace protobuf { void MapTestUtil::SetMapFields(unittest::TestMap* message) { - // Add first element. - (*message->mutable_map_int32_int32())[0] = 0; - (*message->mutable_map_int64_int64())[0] = 0; - (*message->mutable_map_uint32_uint32())[0] = 0; - (*message->mutable_map_uint64_uint64())[0] = 0; - (*message->mutable_map_sint32_sint32())[0] = 0; - (*message->mutable_map_sint64_sint64())[0] = 0; - (*message->mutable_map_fixed32_fixed32())[0] = 0; - (*message->mutable_map_fixed64_fixed64())[0] = 0; - (*message->mutable_map_sfixed32_sfixed32())[0] = 0; - (*message->mutable_map_sfixed64_sfixed64())[0] = 0; - (*message->mutable_map_int32_float())[0] = 0.0; - (*message->mutable_map_int32_double())[0] = 0.0; - (*message->mutable_map_bool_bool())[0] = false; - (*message->mutable_map_string_string())["0"] = "0"; - (*message->mutable_map_int32_bytes())[0] = "0"; - (*message->mutable_map_int32_enum())[0] = - unittest::MAP_ENUM_BAR; - (*message->mutable_map_int32_foreign_message())[0].set_c(0); + MapTestUtilImpl::SetMapFields(message); +} - // Add second element - (*message->mutable_map_int32_int32())[1] = 1; - (*message->mutable_map_int64_int64())[1] = 1; - (*message->mutable_map_uint32_uint32())[1] = 1; - (*message->mutable_map_uint64_uint64())[1] = 1; - (*message->mutable_map_sint32_sint32())[1] = 1; - (*message->mutable_map_sint64_sint64())[1] = 1; - (*message->mutable_map_fixed32_fixed32())[1] = 1; - (*message->mutable_map_fixed64_fixed64())[1] = 1; - (*message->mutable_map_sfixed32_sfixed32())[1] = 1; - (*message->mutable_map_sfixed64_sfixed64())[1] = 1; - (*message->mutable_map_int32_float())[1] = 1.0; - (*message->mutable_map_int32_double())[1] = 1.0; - (*message->mutable_map_bool_bool())[1] = true; - (*message->mutable_map_string_string())["1"] = "1"; - (*message->mutable_map_int32_bytes())[1] = "1"; - (*message->mutable_map_int32_enum())[1] = - unittest::MAP_ENUM_BAZ; - (*message->mutable_map_int32_foreign_message())[1].set_c(1); +void MapTestUtil::SetArenaMapFields(unittest::TestArenaMap* message) { + MapTestUtilImpl::SetArenaMapFields(message); } void MapTestUtil::SetMapFieldsInitialized(unittest::TestMap* message) { - // Add first element using bracket operator, which should assign default - // value automatically. - (*message->mutable_map_int32_int32())[0]; - (*message->mutable_map_int64_int64())[0]; - (*message->mutable_map_uint32_uint32())[0]; - (*message->mutable_map_uint64_uint64())[0]; - (*message->mutable_map_sint32_sint32())[0]; - (*message->mutable_map_sint64_sint64())[0]; - (*message->mutable_map_fixed32_fixed32())[0]; - (*message->mutable_map_fixed64_fixed64())[0]; - (*message->mutable_map_sfixed32_sfixed32())[0]; - (*message->mutable_map_sfixed64_sfixed64())[0]; - (*message->mutable_map_int32_float())[0]; - (*message->mutable_map_int32_double())[0]; - (*message->mutable_map_bool_bool())[0]; - (*message->mutable_map_string_string())["0"]; - (*message->mutable_map_int32_bytes())[0]; - (*message->mutable_map_int32_enum())[0]; - (*message->mutable_map_int32_foreign_message())[0]; + MapTestUtilImpl::SetMapFieldsInitialized(message); } void MapTestUtil::ModifyMapFields(unittest::TestMap* message) { - (*message->mutable_map_int32_int32())[1] = 2; - (*message->mutable_map_int64_int64())[1] = 2; - (*message->mutable_map_uint32_uint32())[1] = 2; - (*message->mutable_map_uint64_uint64())[1] = 2; - (*message->mutable_map_sint32_sint32())[1] = 2; - (*message->mutable_map_sint64_sint64())[1] = 2; - (*message->mutable_map_fixed32_fixed32())[1] = 2; - (*message->mutable_map_fixed64_fixed64())[1] = 2; - (*message->mutable_map_sfixed32_sfixed32())[1] = 2; - (*message->mutable_map_sfixed64_sfixed64())[1] = 2; - (*message->mutable_map_int32_float())[1] = 2.0; - (*message->mutable_map_int32_double())[1] = 2.0; - (*message->mutable_map_bool_bool())[1] = false; - (*message->mutable_map_string_string())["1"] = "2"; - (*message->mutable_map_int32_bytes())[1] = "2"; - (*message->mutable_map_int32_enum())[1] = - unittest::MAP_ENUM_FOO; - (*message->mutable_map_int32_foreign_message())[1].set_c(2); + MapTestUtilImpl::ModifyMapFields( + message); } void MapTestUtil::ExpectClear(const unittest::TestMap& message) { - EXPECT_EQ(0, message.map_int32_int32().size()); - EXPECT_EQ(0, message.map_int64_int64().size()); - EXPECT_EQ(0, message.map_uint32_uint32().size()); - EXPECT_EQ(0, message.map_uint64_uint64().size()); - EXPECT_EQ(0, message.map_sint32_sint32().size()); - EXPECT_EQ(0, message.map_sint64_sint64().size()); - EXPECT_EQ(0, message.map_fixed32_fixed32().size()); - EXPECT_EQ(0, message.map_fixed64_fixed64().size()); - EXPECT_EQ(0, message.map_sfixed32_sfixed32().size()); - EXPECT_EQ(0, message.map_sfixed64_sfixed64().size()); - EXPECT_EQ(0, message.map_int32_float().size()); - EXPECT_EQ(0, message.map_int32_double().size()); - EXPECT_EQ(0, message.map_bool_bool().size()); - EXPECT_EQ(0, message.map_string_string().size()); - EXPECT_EQ(0, message.map_int32_bytes().size()); - EXPECT_EQ(0, message.map_int32_enum().size()); - EXPECT_EQ(0, message.map_int32_foreign_message().size()); + MapTestUtilImpl::ExpectClear(message); } void MapTestUtil::ExpectMapFieldsSet(const unittest::TestMap& message) { - EXPECT_EQ(2, message.map_int32_int32().size()); - EXPECT_EQ(2, message.map_int64_int64().size()); - EXPECT_EQ(2, message.map_uint32_uint32().size()); - EXPECT_EQ(2, message.map_uint64_uint64().size()); - EXPECT_EQ(2, message.map_sint32_sint32().size()); - EXPECT_EQ(2, message.map_sint64_sint64().size()); - EXPECT_EQ(2, message.map_fixed32_fixed32().size()); - EXPECT_EQ(2, message.map_fixed64_fixed64().size()); - EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); - EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); - EXPECT_EQ(2, message.map_int32_float().size()); - EXPECT_EQ(2, message.map_int32_double().size()); - EXPECT_EQ(2, message.map_bool_bool().size()); - EXPECT_EQ(2, message.map_string_string().size()); - EXPECT_EQ(2, message.map_int32_bytes().size()); - EXPECT_EQ(2, message.map_int32_enum().size()); - EXPECT_EQ(2, message.map_int32_foreign_message().size()); - - EXPECT_EQ(0, message.map_int32_int32().at(0)); - EXPECT_EQ(0, message.map_int64_int64().at(0)); - EXPECT_EQ(0, message.map_uint32_uint32().at(0)); - EXPECT_EQ(0, message.map_uint64_uint64().at(0)); - EXPECT_EQ(0, message.map_sint32_sint32().at(0)); - EXPECT_EQ(0, message.map_sint64_sint64().at(0)); - EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); - EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); - EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); - EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); - EXPECT_EQ(0, message.map_int32_float().at(0)); - EXPECT_EQ(0, message.map_int32_double().at(0)); - EXPECT_EQ(false, message.map_bool_bool().at(0)); - EXPECT_EQ("0", message.map_string_string().at("0")); - EXPECT_EQ("0", message.map_int32_bytes().at(0)); - EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0)); - EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); - - EXPECT_EQ(1, message.map_int32_int32().at(1)); - EXPECT_EQ(1, message.map_int64_int64().at(1)); - EXPECT_EQ(1, message.map_uint32_uint32().at(1)); - EXPECT_EQ(1, message.map_uint64_uint64().at(1)); - EXPECT_EQ(1, message.map_sint32_sint32().at(1)); - EXPECT_EQ(1, message.map_sint64_sint64().at(1)); - EXPECT_EQ(1, message.map_fixed32_fixed32().at(1)); - EXPECT_EQ(1, message.map_fixed64_fixed64().at(1)); - EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1)); - EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1)); - EXPECT_EQ(1, message.map_int32_float().at(1)); - EXPECT_EQ(1, message.map_int32_double().at(1)); - EXPECT_EQ(true, message.map_bool_bool().at(1)); - EXPECT_EQ("1", message.map_string_string().at("1")); - EXPECT_EQ("1", message.map_int32_bytes().at(1)); - EXPECT_EQ(unittest::MAP_ENUM_BAZ, message.map_int32_enum().at(1)); - EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c()); + MapTestUtilImpl::ExpectMapFieldsSet(message); +} + +void MapTestUtil::ExpectArenaMapFieldsSet( + const unittest::TestArenaMap& message) { + MapTestUtilImpl::ExpectArenaMapFieldsSet< + unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_BAZ>( + message); } void MapTestUtil::ExpectMapFieldsSetInitialized( const unittest::TestMap& message) { - EXPECT_EQ(1, message.map_int32_int32().size()); - EXPECT_EQ(1, message.map_int64_int64().size()); - EXPECT_EQ(1, message.map_uint32_uint32().size()); - EXPECT_EQ(1, message.map_uint64_uint64().size()); - EXPECT_EQ(1, message.map_sint32_sint32().size()); - EXPECT_EQ(1, message.map_sint64_sint64().size()); - EXPECT_EQ(1, message.map_fixed32_fixed32().size()); - EXPECT_EQ(1, message.map_fixed64_fixed64().size()); - EXPECT_EQ(1, message.map_sfixed32_sfixed32().size()); - EXPECT_EQ(1, message.map_sfixed64_sfixed64().size()); - EXPECT_EQ(1, message.map_int32_float().size()); - EXPECT_EQ(1, message.map_int32_double().size()); - EXPECT_EQ(1, message.map_bool_bool().size()); - EXPECT_EQ(1, message.map_string_string().size()); - EXPECT_EQ(1, message.map_int32_bytes().size()); - EXPECT_EQ(1, message.map_int32_enum().size()); - EXPECT_EQ(1, message.map_int32_foreign_message().size()); - - EXPECT_EQ(0, message.map_int32_int32().at(0)); - EXPECT_EQ(0, message.map_int64_int64().at(0)); - EXPECT_EQ(0, message.map_uint32_uint32().at(0)); - EXPECT_EQ(0, message.map_uint64_uint64().at(0)); - EXPECT_EQ(0, message.map_sint32_sint32().at(0)); - EXPECT_EQ(0, message.map_sint64_sint64().at(0)); - EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); - EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); - EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); - EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); - EXPECT_EQ(0, message.map_int32_float().at(0)); - EXPECT_EQ(0, message.map_int32_double().at(0)); - EXPECT_EQ(false, message.map_bool_bool().at(0)); - EXPECT_EQ("", message.map_string_string().at("0")); - EXPECT_EQ("", message.map_int32_bytes().at(0)); - EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(0)); - EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize()); + MapTestUtilImpl::ExpectMapFieldsSetInitialized( + message); } void MapTestUtil::ExpectMapFieldsModified( const unittest::TestMap& message) { - // ModifyMapFields only sets the second element of each field. In addition to - // verifying this, we also verify that the first element and size were *not* - // modified. - EXPECT_EQ(2, message.map_int32_int32().size()); - EXPECT_EQ(2, message.map_int64_int64().size()); - EXPECT_EQ(2, message.map_uint32_uint32().size()); - EXPECT_EQ(2, message.map_uint64_uint64().size()); - EXPECT_EQ(2, message.map_sint32_sint32().size()); - EXPECT_EQ(2, message.map_sint64_sint64().size()); - EXPECT_EQ(2, message.map_fixed32_fixed32().size()); - EXPECT_EQ(2, message.map_fixed64_fixed64().size()); - EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); - EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); - EXPECT_EQ(2, message.map_int32_float().size()); - EXPECT_EQ(2, message.map_int32_double().size()); - EXPECT_EQ(2, message.map_bool_bool().size()); - EXPECT_EQ(2, message.map_string_string().size()); - EXPECT_EQ(2, message.map_int32_bytes().size()); - EXPECT_EQ(2, message.map_int32_enum().size()); - EXPECT_EQ(2, message.map_int32_foreign_message().size()); - - EXPECT_EQ(0, message.map_int32_int32().at(0)); - EXPECT_EQ(0, message.map_int64_int64().at(0)); - EXPECT_EQ(0, message.map_uint32_uint32().at(0)); - EXPECT_EQ(0, message.map_uint64_uint64().at(0)); - EXPECT_EQ(0, message.map_sint32_sint32().at(0)); - EXPECT_EQ(0, message.map_sint64_sint64().at(0)); - EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); - EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); - EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); - EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); - EXPECT_EQ(0, message.map_int32_float().at(0)); - EXPECT_EQ(0, message.map_int32_double().at(0)); - EXPECT_EQ(false, message.map_bool_bool().at(0)); - EXPECT_EQ("0", message.map_string_string().at("0")); - EXPECT_EQ("0", message.map_int32_bytes().at(0)); - EXPECT_EQ(unittest::MAP_ENUM_BAR, message.map_int32_enum().at(0)); - EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); - - // Actually verify the second (modified) elements now. - EXPECT_EQ(2, message.map_int32_int32().at(1)); - EXPECT_EQ(2, message.map_int64_int64().at(1)); - EXPECT_EQ(2, message.map_uint32_uint32().at(1)); - EXPECT_EQ(2, message.map_uint64_uint64().at(1)); - EXPECT_EQ(2, message.map_sint32_sint32().at(1)); - EXPECT_EQ(2, message.map_sint64_sint64().at(1)); - EXPECT_EQ(2, message.map_fixed32_fixed32().at(1)); - EXPECT_EQ(2, message.map_fixed64_fixed64().at(1)); - EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1)); - EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1)); - EXPECT_EQ(2, message.map_int32_float().at(1)); - EXPECT_EQ(2, message.map_int32_double().at(1)); - EXPECT_EQ(false, message.map_bool_bool().at(1)); - EXPECT_EQ("2", message.map_string_string().at("1")); - EXPECT_EQ("2", message.map_int32_bytes().at(1)); - EXPECT_EQ(unittest::MAP_ENUM_FOO, message.map_int32_enum().at(1)); - EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c()); + MapTestUtilImpl::ExpectMapFieldsModified< + unittest::MapEnum, unittest::MAP_ENUM_BAR, unittest::MAP_ENUM_FOO>( + message); } void MapTestUtil::ExpectMapsSize( @@ -1468,8 +1253,9 @@ void MapTestUtil::MapReflectionTester::ExpectMapEntryClearViaReflection( sub_message = reflection->AddMessage(message, F("map_int32_enum")); EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, key_descriptor)); - EXPECT_EQ(0, sub_message->GetReflection()->GetEnum(*sub_message, - value_descriptor)); + EXPECT_EQ(0, sub_message->GetReflection() + ->GetEnum(*sub_message, value_descriptor) + ->number()); } // Map using message as value has been tested in other place. Thus, we don't // test it here. diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h index 653cf107..f437e33e 100644 --- a/src/google/protobuf/map_test_util.h +++ b/src/google/protobuf/map_test_util.h @@ -40,9 +40,12 @@ namespace unittest = ::protobuf_unittest; class MapTestUtil { public: - // Set every field in the message to a unique value. + // Set every field in the TestMap message to a unique value. static void SetMapFields(unittest::TestMap* message); + // Set every field in the TestArenaMap message to a unique value. + static void SetArenaMapFields(unittest::TestArenaMap* message); + // Set every field in the message to a default value. static void SetMapFieldsInitialized(unittest::TestMap* message); @@ -54,6 +57,10 @@ class MapTestUtil { // SetMapFields() is called. static void ExpectMapFieldsSet(const unittest::TestMap& message); + // Check that all fields have the values that they should have after + // SetMapFields() is called for TestArenaMap. + static void ExpectArenaMapFieldsSet(const unittest::TestArenaMap& message); + // Check that all fields have the values that they should have after // SetMapFieldsInitialized() is called. static void ExpectMapFieldsSetInitialized( diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h new file mode 100644 index 00000000..5e7882a1 --- /dev/null +++ b/src/google/protobuf/map_test_util_impl.h @@ -0,0 +1,474 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ +#define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ + +#include + + +#define EXPECT_TRUE GOOGLE_CHECK +#define ASSERT_TRUE GOOGLE_CHECK +#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND)) +#define EXPECT_EQ GOOGLE_CHECK_EQ +#define ASSERT_EQ GOOGLE_CHECK_EQ + +namespace google { +namespace protobuf_unittest {} // forward declaration + +namespace protobuf { + +namespace unittest = ::protobuf_unittest; + +class MapTestUtilImpl { + public: + // Set every field in the TestMap message to a unique value. + template + static void SetMapFields(MapMessage* message); + + // Set every field in the TestArenaMap message to a unique value. + template + static void SetArenaMapFields(MapMessage* message); + + // Set every field in the message to a default value. + template + static void SetMapFieldsInitialized(MapMessage* message); + + // Modify all the map fields of the messsage (which should already have been + // initialized with SetMapFields()). + template + static void ModifyMapFields(MapMessage* message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called. + template + static void ExpectMapFieldsSet(const MapMessage& message); + + // Check that all fields have the values that they should have after + // SetMapFields() is called for TestArenaMap. + template + static void ExpectArenaMapFieldsSet(const MapMessage& message); + + // Check that all fields have the values that they should have after + // SetMapFieldsInitialized() is called. + template + static void ExpectMapFieldsSetInitialized(const MapMessage& message); + + // Expect that the message is modified as would be expected from + // ModifyMapFields(). + template + static void ExpectMapFieldsModified(const MapMessage& message); + + // Check that all fields are empty. + template + static void ExpectClear(const MapMessage& message); + + // // Check that all map fields have the given size. + // template + // static void ExpectMapsSize(const MapMessage& message, int size); + + // // Get pointers of map entries at given index. + // static std::vector GetMapEntries( + // const MapMessage& message, int index); + + // // Get pointers of map entries from release. + // static std::vector GetMapEntriesFromRelease( + // MapMessage* message); +}; + +template +void MapTestUtilImpl::SetMapFields(MapMessage* message) { + // Add first element. + (*message->mutable_map_int32_int32())[0] = 0; + (*message->mutable_map_int64_int64())[0] = 0; + (*message->mutable_map_uint32_uint32())[0] = 0; + (*message->mutable_map_uint64_uint64())[0] = 0; + (*message->mutable_map_sint32_sint32())[0] = 0; + (*message->mutable_map_sint64_sint64())[0] = 0; + (*message->mutable_map_fixed32_fixed32())[0] = 0; + (*message->mutable_map_fixed64_fixed64())[0] = 0; + (*message->mutable_map_sfixed32_sfixed32())[0] = 0; + (*message->mutable_map_sfixed64_sfixed64())[0] = 0; + (*message->mutable_map_int32_float())[0] = 0.0; + (*message->mutable_map_int32_double())[0] = 0.0; + (*message->mutable_map_bool_bool())[0] = false; + (*message->mutable_map_string_string())["0"] = "0"; + (*message->mutable_map_int32_bytes())[0] = "0"; + (*message->mutable_map_int32_enum())[0] = enum_value0; + (*message->mutable_map_int32_foreign_message())[0].set_c(0); + + // Add second element + (*message->mutable_map_int32_int32())[1] = 1; + (*message->mutable_map_int64_int64())[1] = 1; + (*message->mutable_map_uint32_uint32())[1] = 1; + (*message->mutable_map_uint64_uint64())[1] = 1; + (*message->mutable_map_sint32_sint32())[1] = 1; + (*message->mutable_map_sint64_sint64())[1] = 1; + (*message->mutable_map_fixed32_fixed32())[1] = 1; + (*message->mutable_map_fixed64_fixed64())[1] = 1; + (*message->mutable_map_sfixed32_sfixed32())[1] = 1; + (*message->mutable_map_sfixed64_sfixed64())[1] = 1; + (*message->mutable_map_int32_float())[1] = 1.0; + (*message->mutable_map_int32_double())[1] = 1.0; + (*message->mutable_map_bool_bool())[1] = true; + (*message->mutable_map_string_string())["1"] = "1"; + (*message->mutable_map_int32_bytes())[1] = "1"; + (*message->mutable_map_int32_enum())[1] = enum_value1; + (*message->mutable_map_int32_foreign_message())[1].set_c(1); +} + +template +void MapTestUtilImpl::SetArenaMapFields(MapMessage* message) { + // Add first element. + (*message->mutable_map_int32_int32())[0] = 0; + (*message->mutable_map_int64_int64())[0] = 0; + (*message->mutable_map_uint32_uint32())[0] = 0; + (*message->mutable_map_uint64_uint64())[0] = 0; + (*message->mutable_map_sint32_sint32())[0] = 0; + (*message->mutable_map_sint64_sint64())[0] = 0; + (*message->mutable_map_fixed32_fixed32())[0] = 0; + (*message->mutable_map_fixed64_fixed64())[0] = 0; + (*message->mutable_map_sfixed32_sfixed32())[0] = 0; + (*message->mutable_map_sfixed64_sfixed64())[0] = 0; + (*message->mutable_map_int32_float())[0] = 0.0; + (*message->mutable_map_int32_double())[0] = 0.0; + (*message->mutable_map_bool_bool())[0] = false; + (*message->mutable_map_int32_enum())[0] = enum_value0; + (*message->mutable_map_int32_foreign_message())[0].set_c(0); + + // Add second element + (*message->mutable_map_int32_int32())[1] = 1; + (*message->mutable_map_int64_int64())[1] = 1; + (*message->mutable_map_uint32_uint32())[1] = 1; + (*message->mutable_map_uint64_uint64())[1] = 1; + (*message->mutable_map_sint32_sint32())[1] = 1; + (*message->mutable_map_sint64_sint64())[1] = 1; + (*message->mutable_map_fixed32_fixed32())[1] = 1; + (*message->mutable_map_fixed64_fixed64())[1] = 1; + (*message->mutable_map_sfixed32_sfixed32())[1] = 1; + (*message->mutable_map_sfixed64_sfixed64())[1] = 1; + (*message->mutable_map_int32_float())[1] = 1.0; + (*message->mutable_map_int32_double())[1] = 1.0; + (*message->mutable_map_bool_bool())[1] = true; + (*message->mutable_map_int32_enum())[1] = enum_value1; + (*message->mutable_map_int32_foreign_message())[1].set_c(1); +} + +template +void MapTestUtilImpl::SetMapFieldsInitialized(MapMessage* message) { + // Add first element using bracket operator, which should assign default + // value automatically. + (*message->mutable_map_int32_int32())[0]; + (*message->mutable_map_int64_int64())[0]; + (*message->mutable_map_uint32_uint32())[0]; + (*message->mutable_map_uint64_uint64())[0]; + (*message->mutable_map_sint32_sint32())[0]; + (*message->mutable_map_sint64_sint64())[0]; + (*message->mutable_map_fixed32_fixed32())[0]; + (*message->mutable_map_fixed64_fixed64())[0]; + (*message->mutable_map_sfixed32_sfixed32())[0]; + (*message->mutable_map_sfixed64_sfixed64())[0]; + (*message->mutable_map_int32_float())[0]; + (*message->mutable_map_int32_double())[0]; + (*message->mutable_map_bool_bool())[0]; + (*message->mutable_map_string_string())["0"]; + (*message->mutable_map_int32_bytes())[0]; + (*message->mutable_map_int32_enum())[0]; + (*message->mutable_map_int32_foreign_message())[0]; +} + +template +void MapTestUtilImpl::ModifyMapFields(MapMessage* message) { + (*message->mutable_map_int32_int32())[1] = 2; + (*message->mutable_map_int64_int64())[1] = 2; + (*message->mutable_map_uint32_uint32())[1] = 2; + (*message->mutable_map_uint64_uint64())[1] = 2; + (*message->mutable_map_sint32_sint32())[1] = 2; + (*message->mutable_map_sint64_sint64())[1] = 2; + (*message->mutable_map_fixed32_fixed32())[1] = 2; + (*message->mutable_map_fixed64_fixed64())[1] = 2; + (*message->mutable_map_sfixed32_sfixed32())[1] = 2; + (*message->mutable_map_sfixed64_sfixed64())[1] = 2; + (*message->mutable_map_int32_float())[1] = 2.0; + (*message->mutable_map_int32_double())[1] = 2.0; + (*message->mutable_map_bool_bool())[1] = false; + (*message->mutable_map_string_string())["1"] = "2"; + (*message->mutable_map_int32_bytes())[1] = "2"; + (*message->mutable_map_int32_enum())[1] = enum_value; + (*message->mutable_map_int32_foreign_message())[1].set_c(2); +} + +template +void MapTestUtilImpl::ExpectClear(const MapMessage& message) { + EXPECT_EQ(0, message.map_int32_int32().size()); + EXPECT_EQ(0, message.map_int64_int64().size()); + EXPECT_EQ(0, message.map_uint32_uint32().size()); + EXPECT_EQ(0, message.map_uint64_uint64().size()); + EXPECT_EQ(0, message.map_sint32_sint32().size()); + EXPECT_EQ(0, message.map_sint64_sint64().size()); + EXPECT_EQ(0, message.map_fixed32_fixed32().size()); + EXPECT_EQ(0, message.map_fixed64_fixed64().size()); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(0, message.map_int32_float().size()); + EXPECT_EQ(0, message.map_int32_double().size()); + EXPECT_EQ(0, message.map_bool_bool().size()); + EXPECT_EQ(0, message.map_string_string().size()); + EXPECT_EQ(0, message.map_int32_bytes().size()); + EXPECT_EQ(0, message.map_int32_enum().size()); + EXPECT_EQ(0, message.map_int32_foreign_message().size()); +} + + + +template +void MapTestUtilImpl::ExpectMapFieldsSet(const MapMessage& message) { + EXPECT_EQ(2, message.map_int32_int32().size()); + EXPECT_EQ(2, message.map_int64_int64().size()); + EXPECT_EQ(2, message.map_uint32_uint32().size()); + EXPECT_EQ(2, message.map_uint64_uint64().size()); + EXPECT_EQ(2, message.map_sint32_sint32().size()); + EXPECT_EQ(2, message.map_sint64_sint64().size()); + EXPECT_EQ(2, message.map_fixed32_fixed32().size()); + EXPECT_EQ(2, message.map_fixed64_fixed64().size()); + EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(2, message.map_int32_float().size()); + EXPECT_EQ(2, message.map_int32_double().size()); + EXPECT_EQ(2, message.map_bool_bool().size()); + EXPECT_EQ(2, message.map_string_string().size()); + EXPECT_EQ(2, message.map_int32_bytes().size()); + EXPECT_EQ(2, message.map_int32_enum().size()); + EXPECT_EQ(2, message.map_int32_foreign_message().size()); + + EXPECT_EQ(0, message.map_int32_int32().at(0)); + EXPECT_EQ(0, message.map_int64_int64().at(0)); + EXPECT_EQ(0, message.map_uint32_uint32().at(0)); + EXPECT_EQ(0, message.map_uint64_uint64().at(0)); + EXPECT_EQ(0, message.map_sint32_sint32().at(0)); + EXPECT_EQ(0, message.map_sint64_sint64().at(0)); + EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); + EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); + EXPECT_EQ(0, message.map_int32_float().at(0)); + EXPECT_EQ(0, message.map_int32_double().at(0)); + EXPECT_EQ(false, message.map_bool_bool().at(0)); + EXPECT_EQ("0", message.map_string_string().at("0")); + EXPECT_EQ("0", message.map_int32_bytes().at(0)); + EXPECT_EQ(enum_value0, message.map_int32_enum().at(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); + + EXPECT_EQ(1, message.map_int32_int32().at(1)); + EXPECT_EQ(1, message.map_int64_int64().at(1)); + EXPECT_EQ(1, message.map_uint32_uint32().at(1)); + EXPECT_EQ(1, message.map_uint64_uint64().at(1)); + EXPECT_EQ(1, message.map_sint32_sint32().at(1)); + EXPECT_EQ(1, message.map_sint64_sint64().at(1)); + EXPECT_EQ(1, message.map_fixed32_fixed32().at(1)); + EXPECT_EQ(1, message.map_fixed64_fixed64().at(1)); + EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1)); + EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1)); + EXPECT_EQ(1, message.map_int32_float().at(1)); + EXPECT_EQ(1, message.map_int32_double().at(1)); + EXPECT_EQ(true, message.map_bool_bool().at(1)); + EXPECT_EQ("1", message.map_string_string().at("1")); + EXPECT_EQ("1", message.map_int32_bytes().at(1)); + EXPECT_EQ(enum_value1, message.map_int32_enum().at(1)); + EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c()); +} + +template +void MapTestUtilImpl::ExpectArenaMapFieldsSet(const MapMessage& message) { + EXPECT_EQ(2, message.map_int32_int32().size()); + EXPECT_EQ(2, message.map_int64_int64().size()); + EXPECT_EQ(2, message.map_uint32_uint32().size()); + EXPECT_EQ(2, message.map_uint64_uint64().size()); + EXPECT_EQ(2, message.map_sint32_sint32().size()); + EXPECT_EQ(2, message.map_sint64_sint64().size()); + EXPECT_EQ(2, message.map_fixed32_fixed32().size()); + EXPECT_EQ(2, message.map_fixed64_fixed64().size()); + EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(2, message.map_int32_float().size()); + EXPECT_EQ(2, message.map_int32_double().size()); + EXPECT_EQ(2, message.map_bool_bool().size()); + EXPECT_EQ(2, message.map_int32_enum().size()); + EXPECT_EQ(2, message.map_int32_foreign_message().size()); + + EXPECT_EQ(0, message.map_int32_int32().at(0)); + EXPECT_EQ(0, message.map_int64_int64().at(0)); + EXPECT_EQ(0, message.map_uint32_uint32().at(0)); + EXPECT_EQ(0, message.map_uint64_uint64().at(0)); + EXPECT_EQ(0, message.map_sint32_sint32().at(0)); + EXPECT_EQ(0, message.map_sint64_sint64().at(0)); + EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); + EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); + EXPECT_EQ(0, message.map_int32_float().at(0)); + EXPECT_EQ(0, message.map_int32_double().at(0)); + EXPECT_EQ(false, message.map_bool_bool().at(0)); + EXPECT_EQ(enum_value0, message.map_int32_enum().at(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); + + EXPECT_EQ(1, message.map_int32_int32().at(1)); + EXPECT_EQ(1, message.map_int64_int64().at(1)); + EXPECT_EQ(1, message.map_uint32_uint32().at(1)); + EXPECT_EQ(1, message.map_uint64_uint64().at(1)); + EXPECT_EQ(1, message.map_sint32_sint32().at(1)); + EXPECT_EQ(1, message.map_sint64_sint64().at(1)); + EXPECT_EQ(1, message.map_fixed32_fixed32().at(1)); + EXPECT_EQ(1, message.map_fixed64_fixed64().at(1)); + EXPECT_EQ(1, message.map_sfixed32_sfixed32().at(1)); + EXPECT_EQ(1, message.map_sfixed64_sfixed64().at(1)); + EXPECT_EQ(1, message.map_int32_float().at(1)); + EXPECT_EQ(1, message.map_int32_double().at(1)); + EXPECT_EQ(true, message.map_bool_bool().at(1)); + EXPECT_EQ(enum_value1, message.map_int32_enum().at(1)); + EXPECT_EQ(1, message.map_int32_foreign_message().at(1).c()); +} + +template +void MapTestUtilImpl::ExpectMapFieldsSetInitialized( + const MapMessage& message) { + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(1, message.map_int64_int64().size()); + EXPECT_EQ(1, message.map_uint32_uint32().size()); + EXPECT_EQ(1, message.map_uint64_uint64().size()); + EXPECT_EQ(1, message.map_sint32_sint32().size()); + EXPECT_EQ(1, message.map_sint64_sint64().size()); + EXPECT_EQ(1, message.map_fixed32_fixed32().size()); + EXPECT_EQ(1, message.map_fixed64_fixed64().size()); + EXPECT_EQ(1, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(1, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(1, message.map_int32_float().size()); + EXPECT_EQ(1, message.map_int32_double().size()); + EXPECT_EQ(1, message.map_bool_bool().size()); + EXPECT_EQ(1, message.map_string_string().size()); + EXPECT_EQ(1, message.map_int32_bytes().size()); + EXPECT_EQ(1, message.map_int32_enum().size()); + EXPECT_EQ(1, message.map_int32_foreign_message().size()); + + EXPECT_EQ(0, message.map_int32_int32().at(0)); + EXPECT_EQ(0, message.map_int64_int64().at(0)); + EXPECT_EQ(0, message.map_uint32_uint32().at(0)); + EXPECT_EQ(0, message.map_uint64_uint64().at(0)); + EXPECT_EQ(0, message.map_sint32_sint32().at(0)); + EXPECT_EQ(0, message.map_sint64_sint64().at(0)); + EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); + EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); + EXPECT_EQ(0, message.map_int32_float().at(0)); + EXPECT_EQ(0, message.map_int32_double().at(0)); + EXPECT_EQ(false, message.map_bool_bool().at(0)); + EXPECT_EQ("", message.map_string_string().at("0")); + EXPECT_EQ("", message.map_int32_bytes().at(0)); + EXPECT_EQ(enum_value, message.map_int32_enum().at(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).ByteSize()); +} + +template +void MapTestUtilImpl::ExpectMapFieldsModified( + const MapMessage& message) { + // ModifyMapFields only sets the second element of each field. In addition to + // verifying this, we also verify that the first element and size were *not* + // modified. + EXPECT_EQ(2, message.map_int32_int32().size()); + EXPECT_EQ(2, message.map_int64_int64().size()); + EXPECT_EQ(2, message.map_uint32_uint32().size()); + EXPECT_EQ(2, message.map_uint64_uint64().size()); + EXPECT_EQ(2, message.map_sint32_sint32().size()); + EXPECT_EQ(2, message.map_sint64_sint64().size()); + EXPECT_EQ(2, message.map_fixed32_fixed32().size()); + EXPECT_EQ(2, message.map_fixed64_fixed64().size()); + EXPECT_EQ(2, message.map_sfixed32_sfixed32().size()); + EXPECT_EQ(2, message.map_sfixed64_sfixed64().size()); + EXPECT_EQ(2, message.map_int32_float().size()); + EXPECT_EQ(2, message.map_int32_double().size()); + EXPECT_EQ(2, message.map_bool_bool().size()); + EXPECT_EQ(2, message.map_string_string().size()); + EXPECT_EQ(2, message.map_int32_bytes().size()); + EXPECT_EQ(2, message.map_int32_enum().size()); + EXPECT_EQ(2, message.map_int32_foreign_message().size()); + + EXPECT_EQ(0, message.map_int32_int32().at(0)); + EXPECT_EQ(0, message.map_int64_int64().at(0)); + EXPECT_EQ(0, message.map_uint32_uint32().at(0)); + EXPECT_EQ(0, message.map_uint64_uint64().at(0)); + EXPECT_EQ(0, message.map_sint32_sint32().at(0)); + EXPECT_EQ(0, message.map_sint64_sint64().at(0)); + EXPECT_EQ(0, message.map_fixed32_fixed32().at(0)); + EXPECT_EQ(0, message.map_fixed64_fixed64().at(0)); + EXPECT_EQ(0, message.map_sfixed32_sfixed32().at(0)); + EXPECT_EQ(0, message.map_sfixed64_sfixed64().at(0)); + EXPECT_EQ(0, message.map_int32_float().at(0)); + EXPECT_EQ(0, message.map_int32_double().at(0)); + EXPECT_EQ(false, message.map_bool_bool().at(0)); + EXPECT_EQ("0", message.map_string_string().at("0")); + EXPECT_EQ("0", message.map_int32_bytes().at(0)); + EXPECT_EQ(enum_value0, message.map_int32_enum().at(0)); + EXPECT_EQ(0, message.map_int32_foreign_message().at(0).c()); + + // Actually verify the second (modified) elements now. + EXPECT_EQ(2, message.map_int32_int32().at(1)); + EXPECT_EQ(2, message.map_int64_int64().at(1)); + EXPECT_EQ(2, message.map_uint32_uint32().at(1)); + EXPECT_EQ(2, message.map_uint64_uint64().at(1)); + EXPECT_EQ(2, message.map_sint32_sint32().at(1)); + EXPECT_EQ(2, message.map_sint64_sint64().at(1)); + EXPECT_EQ(2, message.map_fixed32_fixed32().at(1)); + EXPECT_EQ(2, message.map_fixed64_fixed64().at(1)); + EXPECT_EQ(2, message.map_sfixed32_sfixed32().at(1)); + EXPECT_EQ(2, message.map_sfixed64_sfixed64().at(1)); + EXPECT_EQ(2, message.map_int32_float().at(1)); + EXPECT_EQ(2, message.map_int32_double().at(1)); + EXPECT_EQ(false, message.map_bool_bool().at(1)); + EXPECT_EQ("2", message.map_string_string().at("1")); + EXPECT_EQ("2", message.map_int32_bytes().at(1)); + EXPECT_EQ(enum_value1, message.map_int32_enum().at(1)); + EXPECT_EQ(2, message.map_int32_foreign_message().at(1).c()); +} + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__ diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index 88a6d7b8..278b78ae 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -31,8 +31,8 @@ #ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__ #define GOOGLE_PROTOBUF_TYPE_HANDLER_H__ +#include #include -#include #include namespace google { @@ -92,6 +92,28 @@ class MapValueInitializer { static inline void Initialize(Type& value, int default_enum_value) {} }; +template +class MapArenaMessageCreator { + public: + // Use arena to create message if Type is arena constructable. Otherwise, + // create the message on heap. + static inline Type* CreateMessage(Arena* arena); +}; +template +class MapArenaMessageCreator { + public: + static inline Type* CreateMessage(Arena* arena) { + return Arena::CreateMessage(arena); + } +}; +template +class MapArenaMessageCreator { + public: + static inline Type* CreateMessage(Arena* arena) { + return new Type; + } +}; + // Handlers for key/value stored type in MapField. ================== // Handler for message @@ -124,20 +146,24 @@ class MapCppTypeHandler : public MapCommonTypeHandler { *value = const_cast(&Type::default_instance()); } // Initialize value when constructing MapEntry - static inline void Initialize(Type** x) { *x = NULL; } + static inline void Initialize(Type** x, Arena* arena) { *x = NULL; } // Same as above, but use default_enum_value to initialize enum type value. static inline void InitializeMaybeByDefaultEnum( - Type** x, int default_enum_value) { + Type** x, int default_enum_value, Arena* arena) { *x = NULL; } // Initialize value for the first time mutable accessor is called. - static inline void EnsureMutable(Type** value) { - if (*value == NULL) *value = new Type; + static inline void EnsureMutable(Type** value, Arena* arena) { + if (*value == NULL) { + *value = + MapArenaMessageCreator:: + type::value>::CreateMessage(arena); + } } // Return default instance if value is not initialized when calling const // reference accessor. - static inline const Type& DefaultIfNotInitialized(Type* value, - Type* default_value) { + static inline const Type& DefaultIfNotInitialized(const Type* value, + const Type* default_value) { return value != NULL ? *value : *default_value; } // Check if all required fields have values set. @@ -166,18 +192,23 @@ class MapCppTypeHandler : public MapCommonTypeHandler { if (ptr != &::google::protobuf::internal::GetEmptyString()) delete ptr; } static inline void AssignDefaultValue(string** value) {} - static inline void Initialize(string** value) { + static inline void Initialize(string** value, Arena* arena) { *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + if (arena != NULL) arena->Own(*value); } static inline void InitializeMaybeByDefaultEnum( - string** value, int default_enum_value) { + string** value, int default_enum_value, Arena* arena) { *value = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + if (arena != NULL) arena->Own(*value); } - static inline void EnsureMutable(string** value) { - if (*value == &::google::protobuf::internal::GetEmptyString()) *value = new string; + static inline void EnsureMutable(string** value, Arena* arena) { + if (*value == &::google::protobuf::internal::GetEmptyString()) { + *value = Arena::Create(arena); + } } - static inline const string& DefaultIfNotInitialized(string* value, - string* default_value) { + static inline const string& DefaultIfNotInitialized( + const string* value, + const string* default_value) { return value != default_value ? *value : *default_value; } static inline bool IsInitialized(string* value) { return true; } @@ -210,12 +241,13 @@ class MapPrimitiveTypeHandler : public MapCommonTypeHandler { int default_enum_value) { \ *value = static_cast(default_enum_value); \ } \ - static inline void Initialize(CType* value) { *value = 0; } \ + static inline void Initialize(CType* value, Arena* arena) { *value = 0; } \ static inline void InitializeMaybeByDefaultEnum(CType* value, \ - int default_enum_value) { \ + int default_enum_value, \ + Arena* arena) { \ *value = static_cast(default_enum_value); \ } \ - static inline void EnsureMutable(CType* value) {} \ + static inline void EnsureMutable(CType* value, Arena* arena) {} \ }; PRIMITIVE_HANDLER(int32 ) @@ -228,13 +260,13 @@ PRIMITIVE_HANDLER(bool ) #undef PRIMITIVE_HANDLER -// Define constants for given proto field type -template -class MapFieldTypeTraits {}; +// Define constants for given wire field type +template +class MapWireFieldTypeTraits {}; #define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum) \ template <> \ - class MapFieldTypeTraits { \ + class MapWireFieldTypeTraits { \ public: \ typedef CType CppType; \ static const bool kIsMessage = IsMessage; \ @@ -243,7 +275,7 @@ class MapFieldTypeTraits {}; WireFormatLite::WIRETYPE_##WireFormatType; \ }; -TYPE_TRAITS(MESSAGE , Message, LENGTH_DELIMITED, true, false) +TYPE_TRAITS(MESSAGE , MessageLite, LENGTH_DELIMITED, true, false) TYPE_TRAITS(STRING , string , LENGTH_DELIMITED, false, false) TYPE_TRAITS(BYTES , string , LENGTH_DELIMITED, false, false) TYPE_TRAITS(INT64 , int64 , VARINT , false, false) @@ -263,51 +295,46 @@ TYPE_TRAITS(BOOL , bool , VARINT , false, false) #undef TYPE_TRAITS -// Handler for proto field type. Define types and constants used in compile -// time. Also define functions used in parsing and serializing. -template -class MapProtoTypeHandler { +template +class MapWireFieldTypeHandler { public: - // Internal stored type in MapEntry for given proto field type. - typedef typename MapFieldTypeTraits::CppType CppType; - - // Whether given type is a message. - static const bool kIsMessage = MapFieldTypeTraits::kIsMessage; - - // Whether given type is an enum. - static const bool kIsEnum = MapFieldTypeTraits::kIsEnum; - - // The wire type of given proto field type. + // Internal stored type in MapEntryLite for given wire field type. + typedef typename MapWireFieldTypeTraits::CppType CppType; + // Corresponding wire type for field type. static const WireFormatLite::WireType kWireType = - MapFieldTypeTraits::kWireType; + MapWireFieldTypeTraits::kWireType; + // Whether wire type is for message. + static const bool kIsMessage = MapWireFieldTypeTraits::kIsMessage; + // Whether wire type is for enum. + static const bool kIsEnum = MapWireFieldTypeTraits::kIsEnum; // Functions used in parsing and serialization. =================== - template static inline int ByteSize(const ValueType& value); template static inline int GetCachedSize(const ValueType& value); + template + static inline bool Read(io::CodedInputStream* input, ValueType* value); static inline void Write(int field, const CppType& value, io::CodedOutputStream* output); static inline uint8* WriteToArray(int field, const CppType& value, uint8* output); - template - static inline bool Read(io::CodedInputStream* input, ValueType* value); }; template <> template -inline int MapProtoTypeHandler::ByteSize( +inline int MapWireFieldTypeHandler::ByteSize( const ValueType& value) { return WireFormatLite::MessageSizeNoVirtual(value); } -#define BYTE_SIZE(FieldType, DeclaredType) \ - template <> \ - template \ - inline int MapProtoTypeHandler::ByteSize( \ - const ValueType& value) { \ - return WireFormatLite::DeclaredType##Size(value); \ +#define BYTE_SIZE(FieldType, DeclaredType) \ + template <> \ + template \ + inline int \ + MapWireFieldTypeHandler::ByteSize( \ + const ValueType& value) { \ + return WireFormatLite::DeclaredType##Size(value); \ } BYTE_SIZE(STRING, String) @@ -322,12 +349,13 @@ BYTE_SIZE(ENUM , Enum) #undef BYTE_SIZE -#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \ - template <> \ - template \ - inline int MapProtoTypeHandler::ByteSize( \ - const ValueType& value) { \ - return WireFormatLite::k##DeclaredType##Size; \ +#define FIXED_BYTE_SIZE(FieldType, DeclaredType) \ + template <> \ + template \ + inline int \ + MapWireFieldTypeHandler::ByteSize( \ + const ValueType& value) { \ + return WireFormatLite::k##DeclaredType##Size; \ } FIXED_BYTE_SIZE(DOUBLE , Double) @@ -342,18 +370,18 @@ FIXED_BYTE_SIZE(BOOL , Bool) template <> template -inline int MapProtoTypeHandler::GetCachedSize( - const ValueType& value) { +inline int MapWireFieldTypeHandler< + WireFormatLite::TYPE_MESSAGE>::GetCachedSize(const ValueType& value) { return WireFormatLite::LengthDelimitedSize(value.GetCachedSize()); } -#define GET_CACHED_SIZE(FieldType, DeclaredType) \ - template <> \ - template \ - inline int \ - MapProtoTypeHandler::GetCachedSize( \ - const ValueType& value) { \ - return WireFormatLite::DeclaredType##Size(value); \ +#define GET_CACHED_SIZE(FieldType, DeclaredType) \ + template <> \ + template \ + inline int \ + MapWireFieldTypeHandler::GetCachedSize( \ + const ValueType& value) { \ + return WireFormatLite::DeclaredType##Size(value); \ } GET_CACHED_SIZE(STRING, String) @@ -368,13 +396,13 @@ GET_CACHED_SIZE(ENUM , Enum) #undef GET_CACHED_SIZE -#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \ - template <> \ - template \ - inline int \ - MapProtoTypeHandler::GetCachedSize( \ - const ValueType& value) { \ - return WireFormatLite::k##DeclaredType##Size; \ +#define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType) \ + template <> \ + template \ + inline int \ + MapWireFieldTypeHandler::GetCachedSize( \ + const ValueType& value) { \ + return WireFormatLite::k##DeclaredType##Size; \ } GET_FIXED_CACHED_SIZE(DOUBLE , Double) @@ -388,26 +416,28 @@ GET_FIXED_CACHED_SIZE(BOOL , Bool) #undef GET_FIXED_CACHED_SIZE template <> -inline void MapProtoTypeHandler::Write( - int field, const Message& value, io::CodedOutputStream* output) { +inline void MapWireFieldTypeHandler::Write( + int field, const MessageLite& value, io::CodedOutputStream* output) { WireFormatLite::WriteMessageMaybeToArray(field, value, output); } template <> -inline uint8* MapProtoTypeHandler::WriteToArray( - int field, const Message& value, uint8* output) { +inline uint8* +MapWireFieldTypeHandler::WriteToArray( + int field, const MessageLite& value, uint8* output) { return WireFormatLite::WriteMessageToArray(field, value, output); } #define WRITE_METHOD(FieldType, DeclaredType) \ template <> \ - inline void MapProtoTypeHandler::Write( \ + inline void \ + MapWireFieldTypeHandler::Write( \ int field, const CppType& value, io::CodedOutputStream* output) { \ return WireFormatLite::Write##DeclaredType(field, value, output); \ } \ template <> \ inline uint8* \ - MapProtoTypeHandler::WriteToArray( \ + MapWireFieldTypeHandler::WriteToArray( \ int field, const CppType& value, uint8* output) { \ return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \ } @@ -433,33 +463,33 @@ WRITE_METHOD(BOOL , Bool) template <> template -inline bool MapProtoTypeHandler::Read( +inline bool MapWireFieldTypeHandler::Read( io::CodedInputStream* input, ValueType* value) { return WireFormatLite::ReadMessageNoVirtual(input, value); } template <> template -inline bool MapProtoTypeHandler::Read( +inline bool MapWireFieldTypeHandler::Read( io::CodedInputStream* input, ValueType* value) { return WireFormatLite::ReadString(input, value); } template <> template -inline bool MapProtoTypeHandler::Read( +inline bool MapWireFieldTypeHandler::Read( io::CodedInputStream* input, ValueType* value) { return WireFormatLite::ReadBytes(input, value); } -#define READ_METHOD(FieldType) \ - template <> \ - template \ - inline bool MapProtoTypeHandler::Read( \ - io::CodedInputStream* input, ValueType* value) { \ - return WireFormatLite::ReadPrimitive( \ - input, value); \ +#define READ_METHOD(FieldType) \ + template <> \ + template \ + inline bool MapWireFieldTypeHandler::Read( \ + io::CodedInputStream* input, ValueType* value) { \ + return WireFormatLite::ReadPrimitive( \ + input, value); \ } READ_METHOD(INT64) diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto index 9232d58f..830f672b 100644 --- a/src/google/protobuf/map_unittest.proto +++ b/src/google/protobuf/map_unittest.proto @@ -30,6 +30,7 @@ syntax = "proto3"; +option cc_enable_arenas = true; import "google/protobuf/unittest.proto"; @@ -59,6 +60,10 @@ message TestMap { map map_int32_foreign_message = 17; } +message TestMapSubmessage { + optional TestMap test_map = 1; +} + message TestMessageMap { map map_int32_message = 1; } @@ -80,3 +85,21 @@ enum MapEnum { message TestRequiredMessageMap { map map_field = 1; } + +message TestArenaMap { + map map_int32_int32 = 1; + map map_int64_int64 = 2; + map map_uint32_uint32 = 3; + map map_uint64_uint64 = 4; + map map_sint32_sint32 = 5; + map map_sint64_sint64 = 6; + map map_fixed32_fixed32 = 7; + map map_fixed64_fixed64 = 8; + map map_sfixed32_sfixed32 = 9; + map map_sfixed64_sfixed64 = 10; + map map_int32_float = 11; + map map_int32_double = 12; + map map_bool_bool = 13; + map map_int32_enum = 14; + map map_int32_foreign_message = 15; +} diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 28955b35..f58be848 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -443,17 +443,17 @@ const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor( namespace internal { namespace { void ShutdownRepeatedFieldAccessor() { - Singleton >::ShutDown(); - Singleton >::ShutDown(); - Singleton >::ShutDown(); - Singleton >::ShutDown(); - Singleton >::ShutDown(); - Singleton >::ShutDown(); - Singleton >::ShutDown(); - Singleton::ShutDown(); - Singleton::ShutDown(); - Singleton::ShutDown(); -}; + internal::Singleton >::ShutDown(); + internal::Singleton >::ShutDown(); + internal::Singleton >::ShutDown(); + internal::Singleton >::ShutDown(); + internal::Singleton >::ShutDown(); + internal::Singleton >::ShutDown(); + internal::Singleton >::ShutDown(); + internal::Singleton::ShutDown(); + internal::Singleton::ShutDown(); + internal::Singleton::ShutDown(); +} struct ShutdownRepeatedFieldRegister { ShutdownRepeatedFieldRegister() { @@ -461,7 +461,7 @@ struct ShutdownRepeatedFieldRegister { } } shutdown_; -} // namesapce +} // namespace } // namespace internal namespace internal { diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index a200bc92..6e1929e5 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -208,7 +208,7 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // This is much, much slower than IsInitialized() as it is implemented // purely via reflection. Generally, you should not call this unless you // have already determined that an error exists by calling IsInitialized(). - void FindInitializationErrors(vector* errors) const; + void FindInitializationErrors(std::vector* errors) const; // Like FindInitializationErrors, but joins all the strings, delimited by // commas, and returns them. @@ -456,7 +456,7 @@ class LIBPROTOBUF_EXPORT Reflection { // Swap fields listed in fields vector of two messages. virtual void SwapFields(Message* message1, Message* message2, - const vector& fields) + const std::vector& fields) const = 0; // Swap two elements of a repeated field. @@ -470,8 +470,9 @@ class LIBPROTOBUF_EXPORT Reflection { // return true and repeated fields will only be listed if FieldSize(field) // would return non-zero. Fields (both normal fields and extension fields) // will be listed ordered by field number. - virtual void ListFields(const Message& message, - vector* output) const = 0; + virtual void ListFields( + const Message& message, + std::vector* output) const = 0; // Singular field getters ------------------------------------------ // These get the value of a non-repeated field. They return the default @@ -523,7 +524,7 @@ class LIBPROTOBUF_EXPORT Reflection { // regardless of the field's underlying representation. When initializing // a newly-constructed string, though, it's just as fast and more readable // to use code like: - // string str = reflection->GetString(field); + // string str = reflection->GetString(message, field); virtual const string& GetStringReference(const Message& message, const FieldDescriptor* field, string* scratch) const = 0; @@ -842,6 +843,19 @@ class LIBPROTOBUF_EXPORT Reflection { // } virtual bool SupportsUnknownEnumValues() const { return false; } + // Returns the MessageFactory associated with this message. This can be + // useful for determining if a message is a generated message or not, for + // example: + // + // if (message->GetReflection()->GetMessageFactory() == + // google::protobuf::MessageFactory::generated_factory()) { + // // This is a generated message. + // } + // + // It can also be used to create more messages of this type, though + // Message::New() is an easier way to accomplish this. + virtual MessageFactory* GetMessageFactory() const; + // --------------------------------------------------------------------------- protected: @@ -854,8 +868,6 @@ class LIBPROTOBUF_EXPORT Reflection { Message* message, const FieldDescriptor* field, FieldDescriptor::CppType, int ctype, const Descriptor* message_type) const = 0; - virtual MessageFactory* GetMessageFactory() const; - // The following methods are used to implement (Mutable)RepeatedFieldRef. // A Ref object will store a raw pointer to the repeated field data (obtained // from RepeatedFieldData()) and a pointer to a Accessor (obtained from diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index 106982cc..eab61c14 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -41,6 +41,7 @@ #include + namespace google { namespace protobuf { class Arena; @@ -133,9 +134,10 @@ class LIBPROTOBUF_EXPORT MessageLite { // just simple wrappers around MergeFromCodedStream(). Clear() will be called // before merging the input. - // Fill the message with a protocol buffer parsed from the given input - // stream. Returns false on a read error or if the input is in the - // wrong format. + // Fill the message with a protocol buffer parsed from the given input stream. + // Returns false on a read error or if the input is in the wrong format. A + // successful return does not indicate the entire input is consumed, ensure + // you call ConsumedEntireMessage() to check that if applicable. bool ParseFromCodedStream(io::CodedInputStream* input); // Like ParseFromCodedStream(), but accepts messages that are missing // required fields. @@ -154,7 +156,11 @@ class LIBPROTOBUF_EXPORT MessageLite { // missing required fields. bool ParsePartialFromBoundedZeroCopyStream(io::ZeroCopyInputStream* input, int size); - // Parse a protocol buffer contained in a string. + // Parses a protocol buffer contained in a string. Returns true on success. + // This function takes a string in the (non-human-readable) binary wire + // format, matching the encoding output by MessageLite::SerializeToString(). + // If you'd like to convert a human-readable string into a protocol buffer + // object, see google::protobuf::TextFormat::ParseFromString(). bool ParseFromString(const string& data); // Like ParseFromString(), but accepts messages that are missing // required fields. diff --git a/src/google/protobuf/new_delete_capture.cc b/src/google/protobuf/new_delete_capture.cc deleted file mode 100644 index baf42ffe..00000000 --- a/src/google/protobuf/new_delete_capture.cc +++ /dev/null @@ -1,121 +0,0 @@ -// 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. - -// This file exists for testing allocation behavior when using arenas by hooking -// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.cc. - -#include - -#include - -#include -#include -#include - -namespace google { -namespace { - -pthread_t gthread; -protobuf_unittest::NewDeleteCapture *ghooked_instance = NULL; -SpinLock gspinlock(base::LINKER_INITIALIZED); - -} // namespace - -namespace protobuf_unittest { - -NewDeleteCapture::NewDeleteCapture() - : alloc_count_(0), - alloc_size_(0), - alloc_ptr_(NULL), - free_count_(0), - free_ptr_(NULL) {} - -NewDeleteCapture::~NewDeleteCapture() { Unhook(); } - -void NewDeleteCapture::Reset() { - alloc_count_ = 0; - alloc_size_ = 0; - free_count_ = 0; - alloc_ptr_ = NULL; - free_ptr_ = NULL; -} - -bool NewDeleteCapture::Hook(bool reset) { - SpinLockHolder spinlock(&gspinlock); - if (ghooked_instance != this) { - GOOGLE_CHECK(ghooked_instance == NULL) - << " NewDeleteCapture can have only 1 active instance"; - GOOGLE_CHECK(MallocHook::AddNewHook(NewHook)); - GOOGLE_CHECK(MallocHook::AddDeleteHook(DeleteHook)); - gthread = pthread_self(); - ghooked_instance = this; - if (reset) { - Reset(); - } - return true; - } - return false; -} - -bool NewDeleteCapture::Unhook() { - SpinLockHolder spinlock(&gspinlock); - if (ghooked_instance == this) { - gthread = pthread_t(); - ghooked_instance = NULL; - GOOGLE_CHECK(MallocHook::RemoveDeleteHook(DeleteHook)); - GOOGLE_CHECK(MallocHook::RemoveNewHook(NewHook)); - return true; - } - return false; -} - -void NewDeleteCapture::NewHook(const void *ptr, size_t size) { - SpinLockHolder spinlock(&gspinlock); - if (gthread == pthread_self()) { - auto &rthis = *ghooked_instance; - if (++rthis.alloc_count_ == 1) { - rthis.alloc_size_ = size; - rthis.alloc_ptr_ = ptr; - } - } -} - -void NewDeleteCapture::DeleteHook(const void *ptr) { - SpinLockHolder spinlock(&gspinlock); - if (gthread == pthread_self()) { - auto &rthis = *ghooked_instance; - if (++rthis.free_count_ == 1) { - rthis.free_ptr_ = ptr; - } - } -} - -} // namespace protobuf_unittest -} // namespace google diff --git a/src/google/protobuf/new_delete_capture.h b/src/google/protobuf/new_delete_capture.h deleted file mode 100644 index 4ab550cd..00000000 --- a/src/google/protobuf/new_delete_capture.h +++ /dev/null @@ -1,175 +0,0 @@ -// 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. - -// This file exists for testing allocation behavior when using arenas by hooking -// new/delete. It is a copy of //experimental/mvels/util/new_delete_capture.h. -// -// Copyright 2014 Google Inc. -// -// Author: Martijn Vels -// -// A simple class that captures memory allocations and deletes. -// -// This class is private to //strings and only intended to be used inside -// unit tests. It uses the MallocHook functionality to capture memory -// allocation and delete operations performed by the thread that activated -// a hook on a specific instance. -// -// The class captures the following information: -// - Total allocation count (new, malloc(), etc). -// - Total delete count (delete, free(), etc). -// - The size and returned pointer for the first memory allocation. -// - The pointer for the first delete operation. -// -// The latter 2 infos (size and pointer of first new/delete) are usefull in -// cases where you can closely scope a Hook() / Unhook sequence around a -// specific piece of code where you expect no more than 1 pair of new / delete -// operations. -// -// Sample usage where we expect a single unique alloc / free: -// -// NewDeleteCapture capture_alloc; -// const void *ptr; -// { -// capture_alloc.Hook(); -// MyAllocationClass my_instance(size); -// capture_alloc.Unhook(); -// -// ptr = my_instance.ptr(); -// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count()); -// GOOGLE_CHECK_EQ(0, capture_alloc.free_count()); -// GOOGLE_CHECK_EQ(size, capture_alloc.alloc_size()); -// GOOGLE_CHECK_EQ(ptr, capture_alloc.alloc_ptr()); -// -// capture_alloc.Hook(); -// } -// capture_alloc.Unhook(); -// GOOGLE_CHECK_EQ(1, capture_alloc.alloc_count()); -// GOOGLE_CHECK_EQ(1, capture_alloc.free_count()); -// GOOGLE_CHECK_EQ(ptr, capture_alloc.free_ptr()); -// -// You can only have one NewDeleteCapture instance active at the time. It is -// total valid to have many instances in different threads, but only one -// instance can have a hook active. -// -// Legal: -// -// NewDeleteCapture capture_alloc1; -// NewDeleteCapture capture_alloc2; -// const void *ptr; -// { -// capture_alloc1.Hook(); -// MyAllocationClass my_instance(size); -// capture_alloc1.Unhook(); -// -// capture_alloc2.Hook(); -// my_instance.reset(size); -// capture_alloc2.Unhook(); -// } -// -// Illegal: -// -// NewDeleteCapture capture_alloc1; -// NewDeleteCapture capture_alloc2; -// const void *ptr; -// { -// capture_alloc1.Hook(); -// MyAllocationClass my_instance(size); -// -// capture_alloc2.Hook(); -// my_instance.reset(size); -// -// capture_alloc1.Unhook(); -// capture_alloc2.Unhook(); -// } -// -#ifndef GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__ -#define GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__ - -#include - -namespace google { -namespace protobuf_unittest { - -class NewDeleteCapture { - public: - // Creates a new inactive capture instance - NewDeleteCapture(); - - // Destroys this capture instance. Active hooks are automatically removed. - ~NewDeleteCapture(); - - // Activates a hook on this instance. If reset is true (the default), all - // internal counters will be reset to 0. - // Returns true if the hook was activated, false if this instance already - // owned the hook. - // Requires no other instance owning the hook (check fails) - bool Hook(bool reset = true); - - // De-activate the hook on this instance. - // Returns true if the hook was removed, false if this instance did not own - // the hook. - bool Unhook(); - - // Resets all counters to 0 - void Reset(); - - // Returns the total number of allocations (new, malloc(), etc) - size_t alloc_count() const { return alloc_count_; } - - // Returns the total number of deletes (delete, free(), etc) - size_t free_count() const { return free_count_; } - - // Returns the size of the first observed allocation - size_t alloc_size() const { return alloc_size_; } - - // Returns the allocated ptr of the first observed allocation - const void *alloc_ptr() const { return alloc_ptr_; } - - // Returns the ptr of the first observed delete - const void* free_ptr() const { return free_ptr_; } - - private: - static void NewHook(const void *ptr, size_t size); - static void DeleteHook(const void *ptr); - - private: - size_t alloc_count_; - size_t alloc_size_; - const void *alloc_ptr_; - - size_t free_count_; - const void *free_ptr_; -}; - -} // namespace protobuf_unittest - -} // namespace google -#endif // GOOGLE_PROTOBUF_NEW_DELETE_CAPTURE_H__ diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc index 816e52ca..9f8703ae 100644 --- a/src/google/protobuf/preserve_unknown_enum_test.cc +++ b/src/google/protobuf/preserve_unknown_enum_test.cc @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -39,46 +40,55 @@ namespace protobuf { namespace { void FillMessage( - proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) { message->set_e( - proto2_preserve_unknown_enum_unittest::E_EXTRA); + proto3_preserve_unknown_enum_unittest::E_EXTRA); message->add_repeated_e( - proto2_preserve_unknown_enum_unittest::E_EXTRA); + proto3_preserve_unknown_enum_unittest::E_EXTRA); message->add_repeated_packed_e( - proto2_preserve_unknown_enum_unittest::E_EXTRA); + proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->add_repeated_packed_unexpected_e( + proto3_preserve_unknown_enum_unittest::E_EXTRA); message->set_oneof_e_1( - proto2_preserve_unknown_enum_unittest::E_EXTRA); + proto3_preserve_unknown_enum_unittest::E_EXTRA); } void CheckMessage( - const proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) { - EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA, + const proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) { + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.e()); EXPECT_EQ(1, message.repeated_e_size()); - EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA, + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.repeated_e(0)); EXPECT_EQ(1, message.repeated_packed_e_size()); - EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA, + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.repeated_packed_e(0)); - EXPECT_EQ(proto2_preserve_unknown_enum_unittest::E_EXTRA, + EXPECT_EQ(1, message.repeated_packed_unexpected_e_size()); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, + message.repeated_packed_unexpected_e(0)); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, message.oneof_e_1()); } void CheckMessage( - const proto2_preserve_unknown_enum_unittest::MyMessage& message) { + const proto3_preserve_unknown_enum_unittest::MyMessage& message) { EXPECT_EQ(static_cast( - proto2_preserve_unknown_enum_unittest::E_EXTRA), + proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.e())); EXPECT_EQ(1, message.repeated_e_size()); EXPECT_EQ(static_cast( - proto2_preserve_unknown_enum_unittest::E_EXTRA), + proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.repeated_e(0))); EXPECT_EQ(1, message.repeated_packed_e_size()); EXPECT_EQ(static_cast( - proto2_preserve_unknown_enum_unittest::E_EXTRA), + proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.repeated_packed_e(0))); + EXPECT_EQ(1, message.repeated_packed_unexpected_e_size()); EXPECT_EQ(static_cast( - proto2_preserve_unknown_enum_unittest::E_EXTRA), + proto3_preserve_unknown_enum_unittest::E_EXTRA), + static_cast(message.repeated_packed_unexpected_e(0))); + EXPECT_EQ(static_cast( + proto3_preserve_unknown_enum_unittest::E_EXTRA), static_cast(message.oneof_e_1())); } @@ -87,12 +97,12 @@ void CheckMessage( // Test that parsing preserves an unknown value in the enum field and does not // punt it to the UnknownFieldSet. TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) { - proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); string serialized; orig_message.SerializeToString(&serialized); - proto2_preserve_unknown_enum_unittest::MyMessage message; + proto3_preserve_unknown_enum_unittest::MyMessage message; EXPECT_EQ(true, message.ParseFromString(serialized)); CheckMessage(message); @@ -105,13 +115,13 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) { // Test that reflection based implementation also keeps unknown enum values and // doesn't put them into UnknownFieldSet. TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) { - proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); string serialized = orig_message.SerializeAsString(); google::protobuf::DynamicMessageFactory factory; google::protobuf::scoped_ptr message(factory.GetPrototype( - proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); + proto3_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); EXPECT_EQ(true, message->ParseFromString(serialized)); message->DiscardUnknownFields(); @@ -120,14 +130,61 @@ TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) { CheckMessage(orig_message); } +// Test that for proto2 messages, unknown values are in unknown fields. +TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + + string serialized; + orig_message.SerializeToString(&serialized); + + proto2_preserve_unknown_enum_unittest::MyMessage message; + EXPECT_EQ(true, message.ParseFromString(serialized)); + // The intermediate message has everything in its "unknown fields". + proto2_preserve_unknown_enum_unittest::MyMessage message2 = message; + message2.DiscardUnknownFields(); + EXPECT_EQ(0, message2.ByteSize()); + + // But when we pass it to the correct structure, all values are there. + serialized.clear(); + message.SerializeToString(&serialized); + EXPECT_EQ(true, orig_message.ParseFromString(serialized)); + CheckMessage(orig_message); +} + +// Same as before, for a dynamic message. +TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + + string serialized; + orig_message.SerializeToString(&serialized); + + google::protobuf::DynamicMessageFactory factory; + google::protobuf::scoped_ptr message(factory.GetPrototype( + proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); + EXPECT_EQ(true, message->ParseFromString(serialized)); + // The intermediate message has everything in its "unknown fields". + proto2_preserve_unknown_enum_unittest::MyMessage message2; + message2.CopyFrom(*message); + message2.DiscardUnknownFields(); + EXPECT_EQ(0, message2.ByteSize()); + + // But when we pass it to the correct structure, all values are there. + serialized.clear(); + message->SerializeToString(&serialized); + EXPECT_EQ(true, orig_message.ParseFromString(serialized)); + CheckMessage(orig_message); +} + // Test that reflection provides EnumValueDescriptors for unknown values. TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { - proto2_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; FillMessage(&orig_message); string serialized; orig_message.SerializeToString(&serialized); - proto2_preserve_unknown_enum_unittest::MyMessage message; + proto3_preserve_unknown_enum_unittest::MyMessage message; EXPECT_EQ(true, message.ParseFromString(serialized)); CheckMessage(message); @@ -138,7 +195,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { // This should dynamically create an EnumValueDescriptor. const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field); EXPECT_EQ(enum_value->number(), - static_cast(proto2_preserve_unknown_enum_unittest::E_EXTRA)); + static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA)); // Fetching value for a second time should return the same pointer. const google::protobuf::EnumValueDescriptor* enum_value_second = @@ -150,7 +207,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { d->FindFieldByName("repeated_e"); enum_value = r->GetRepeatedEnum(message, repeated_field, 0); EXPECT_EQ(enum_value->number(), - static_cast(proto2_preserve_unknown_enum_unittest::E_EXTRA)); + static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA)); // Should reuse the same EnumValueDescriptor, even for a different field. EXPECT_EQ(enum_value, enum_value_second); @@ -164,7 +221,7 @@ TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { // Test that the new integer-based enum reflection API works. TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) { - proto2_preserve_unknown_enum_unittest::MyMessage message; + proto3_preserve_unknown_enum_unittest::MyMessage message; const google::protobuf::Reflection* r = message.GetReflection(); const google::protobuf::Descriptor* d = message.GetDescriptor(); @@ -220,7 +277,7 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) { TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) { protobuf_unittest::TestAllTypes proto2_message; - proto2_preserve_unknown_enum_unittest::MyMessage new_message; + proto3_preserve_unknown_enum_unittest::MyMessage new_message; const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection(); const google::protobuf::Reflection* new_reflection = new_message.GetReflection(); diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h index 17d89a18..8f8b1ab6 100644 --- a/src/google/protobuf/reflection.h +++ b/src/google/protobuf/reflection.h @@ -33,6 +33,11 @@ #ifndef GOOGLE_PROTOBUF_REFLECTION_H__ #define GOOGLE_PROTOBUF_REFLECTION_H__ +#include +#ifndef _SHARED_PTR_H +#include +#endif + #include namespace google { @@ -223,7 +228,7 @@ class RepeatedFieldRef< const Message* default_instance_; }; -// MutableRepeatedFieldRef definition for non-message types. +// MutableRepeatedFieldRef definition for message types. template class MutableRepeatedFieldRef< T, typename internal::enable_if::value>::type> { @@ -297,10 +302,298 @@ class MutableRepeatedFieldRef< const AccessorType* accessor_; const Message* default_instance_; }; + +namespace internal { +// Interfaces used to implement reflection RepeatedFieldRef API. +// Reflection::GetRepeatedAccessor() should return a pointer to an singleton +// object that implements the below interface. +// +// This interface passes/returns values using void pointers. The actual type +// of the value depends on the field's cpp_type. Following is a mapping from +// cpp_type to the type that should be used in this interface: +// +// field->cpp_type() T Actual type of void* +// CPPTYPE_INT32 int32 int32 +// CPPTYPE_UINT32 uint32 uint32 +// CPPTYPE_INT64 int64 int64 +// CPPTYPE_UINT64 uint64 uint64 +// CPPTYPE_DOUBLE double double +// CPPTYPE_FLOAT float float +// CPPTYPE_BOOL bool bool +// CPPTYPE_ENUM generated enum type int32 +// CPPTYPE_STRING string string +// CPPTYPE_MESSAGE generated message type google::protobuf::Message +// or google::protobuf::Message +// +// Note that for enums we use int32 in the interface. +// +// You can map from T to the actual type using RefTypeTraits: +// typedef RefTypeTraits::AccessorValueType ActualType; +class LIBPROTOBUF_EXPORT RepeatedFieldAccessor { + public: + // Typedefs for clarity. + typedef void Field; + typedef void Value; + typedef void Iterator; + + virtual ~RepeatedFieldAccessor(); + virtual bool IsEmpty(const Field* data) const = 0; + virtual int Size(const Field* data) const = 0; + // Depends on the underlying representation of the repeated field, this + // method can return a pointer to the underlying object if such an object + // exists, or fill the data into scratch_space and return scratch_space. + // Callers of this method must ensure scratch_space is a valid pointer + // to a mutable object of the correct type. + virtual const Value* Get( + const Field* data, int index, Value* scratch_space) const = 0; + + virtual void Clear(Field* data) const = 0; + virtual void Set(Field* data, int index, const Value* value) const = 0; + virtual void Add(Field* data, const Value* value) const = 0; + virtual void RemoveLast(Field* data) const = 0; + virtual void SwapElements(Field* data, int index1, int index2) const = 0; + virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator, + Field* other_data) const = 0; + + // Create an iterator that points at the begining of the repeated field. + virtual Iterator* BeginIterator(const Field* data) const = 0; + // Create an iterator that points at the end of the repeated field. + virtual Iterator* EndIterator(const Field* data) const = 0; + // Make a copy of an iterator and return the new copy. + virtual Iterator* CopyIterator(const Field* data, + const Iterator* iterator) const = 0; + // Move an iterator to point to the next element. + virtual Iterator* AdvanceIterator(const Field* data, + Iterator* iterator) const = 0; + // Compare whether two iterators point to the same element. + virtual bool EqualsIterator(const Field* data, const Iterator* a, + const Iterator* b) const = 0; + // Delete an iterator created by BeginIterator(), EndIterator() and + // CopyIterator(). + virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0; + // Like Get() but for iterators. + virtual const Value* GetIteratorValue(const Field* data, + const Iterator* iterator, + Value* scratch_space) const = 0; + + // Templated methods that make using this interface easier for non-message + // types. + template + T Get(const Field* data, int index) const { + typedef typename RefTypeTraits::AccessorValueType ActualType; + ActualType scratch_space; + return static_cast( + *reinterpret_cast( + Get(data, index, static_cast(&scratch_space)))); + } + + template + void Set(Field* data, int index, const ValueType& value) const { + typedef typename RefTypeTraits::AccessorValueType ActualType; + // In this RepeatedFieldAccessor interface we pass/return data using + // raw pointers. Type of the data these raw pointers point to should + // be ActualType. Here we have a ValueType object and want a ActualType + // pointer. We can't cast a ValueType pointer to an ActualType pointer + // directly because their type might be different (for enums ValueType + // may be a generated enum type while ActualType is int32). To be safe + // we make a copy to get a temporary ActualType object and use it. + ActualType tmp = static_cast(value); + Set(data, index, static_cast(&tmp)); + } + + template + void Add(Field* data, const ValueType& value) const { + typedef typename RefTypeTraits::AccessorValueType ActualType; + // In this RepeatedFieldAccessor interface we pass/return data using + // raw pointers. Type of the data these raw pointers point to should + // be ActualType. Here we have a ValueType object and want a ActualType + // pointer. We can't cast a ValueType pointer to an ActualType pointer + // directly because their type might be different (for enums ValueType + // may be a generated enum type while ActualType is int32). To be safe + // we make a copy to get a temporary ActualType object and use it. + ActualType tmp = static_cast(value); + Add(data, static_cast(&tmp)); + } +}; + +// Implement (Mutable)RepeatedFieldRef::iterator +template +class RepeatedFieldRefIterator + : public std::iterator { + typedef typename RefTypeTraits::AccessorValueType AccessorValueType; + typedef typename RefTypeTraits::IteratorValueType IteratorValueType; + typedef typename RefTypeTraits::IteratorPointerType IteratorPointerType; + + public: + // Constructor for non-message fields. + RepeatedFieldRefIterator(const void* data, + const RepeatedFieldAccessor* accessor, + bool begin) + : data_(data), accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) : + accessor->EndIterator(data)), + scratch_space_(new AccessorValueType) { + } + // Constructor for message fields. + RepeatedFieldRefIterator(const void* data, + const RepeatedFieldAccessor* accessor, + bool begin, + AccessorValueType* scratch_space) + : data_(data), accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) : + accessor->EndIterator(data)), + scratch_space_(scratch_space) { + } + ~RepeatedFieldRefIterator() { + accessor_->DeleteIterator(data_, iterator_); + } + RepeatedFieldRefIterator operator++(int) { + RepeatedFieldRefIterator tmp(*this); + iterator_ = accessor_->AdvanceIterator(data_, iterator_); + return tmp; + } + RepeatedFieldRefIterator& operator++() { + iterator_ = accessor_->AdvanceIterator(data_, iterator_); + return *this; + } + IteratorValueType operator*() const { + return static_cast( + *static_cast( + accessor_->GetIteratorValue( + data_, iterator_, scratch_space_.get()))); + } + IteratorPointerType operator->() const { + return static_cast( + accessor_->GetIteratorValue( + data_, iterator_, scratch_space_.get())); + } + bool operator!=(const RepeatedFieldRefIterator& other) const { + assert(data_ == other.data_); + assert(accessor_ == other.accessor_); + return !accessor_->EqualsIterator(data_, iterator_, other.iterator_); + } + bool operator==(const RepeatedFieldRefIterator& other) const { + return !this->operator!=(other); + } + + RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other) + : data_(other.data_), accessor_(other.accessor_), + iterator_(accessor_->CopyIterator(data_, other.iterator_)) { + } + RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) { + if (this != &other) { + accessor_->DeleteIterator(data_, iterator_); + data_ = other.data_; + accessor_ = other.accessor_; + iterator_ = accessor_->CopyIterator(data_, other.iterator_); + } + return *this; + } + + protected: + const void* data_; + const RepeatedFieldAccessor* accessor_; + void* iterator_; + google::protobuf::scoped_ptr scratch_space_; +}; + +// TypeTraits that maps the type parameter T of RepeatedFieldRef or +// MutableRepeatedFieldRef to corresponding iterator type, +// RepeatedFieldAccessor type, etc. +template +struct PrimitiveTraits { + static const bool is_primitive = false; +}; +#define DEFINE_PRIMITIVE(TYPE, type) \ + template<> struct PrimitiveTraits { \ + static const bool is_primitive = true; \ + static const FieldDescriptor::CppType cpp_type = \ + FieldDescriptor::CPPTYPE_ ## TYPE; \ + }; +DEFINE_PRIMITIVE(INT32, int32) +DEFINE_PRIMITIVE(UINT32, uint32) +DEFINE_PRIMITIVE(INT64, int64) +DEFINE_PRIMITIVE(UINT64, uint64) +DEFINE_PRIMITIVE(FLOAT, float) +DEFINE_PRIMITIVE(DOUBLE, double) +DEFINE_PRIMITIVE(BOOL, bool) +#undef DEFINE_PRIMITIVE + +template +struct RefTypeTraits< + T, typename internal::enable_if::is_primitive>::type> { + typedef RepeatedFieldRefIterator iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef T AccessorValueType; + typedef T IteratorValueType; + typedef T* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + PrimitiveTraits::cpp_type; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template +struct RefTypeTraits< + T, typename internal::enable_if::value>::type> { + typedef RepeatedFieldRefIterator iterator; + typedef RepeatedFieldAccessor AccessorType; + // We use int32 for repeated enums in RepeatedFieldAccessor. + typedef int32 AccessorValueType; + typedef T IteratorValueType; + typedef int32* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_ENUM; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template +struct RefTypeTraits< + T, typename internal::enable_if::value>::type> { + typedef RepeatedFieldRefIterator iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef string AccessorValueType; + typedef string IteratorValueType; + typedef string* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_STRING; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template +struct MessageDescriptorGetter { + static const Descriptor* get() { + return T::default_instance().GetDescriptor(); + } +}; +template<> +struct MessageDescriptorGetter { + static const Descriptor* get() { + return NULL; + } +}; + +template +struct RefTypeTraits< + T, typename internal::enable_if::value>::type> { + typedef RepeatedFieldRefIterator iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef Message AccessorValueType; + typedef const T& IteratorValueType; + typedef const T* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_MESSAGE; + static const Descriptor* GetMessageFieldDescriptor() { + return MessageDescriptorGetter::get(); + } +}; +} // namespace internal } // namespace protobuf } // namespace google -// Implementation details for (Mutable)RepeatedFieldRef. -#include - #endif // GOOGLE_PROTOBUF_REFLECTION_H__ diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 4798eeda..f5f5d3f4 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -2264,7 +2264,7 @@ RepeatedPtrField::pointer_end() const { // Iterators and helper functions that follow the spirit of the STL // std::back_insert_iterator and std::back_inserter but are tailor-made -// for RepeatedField and RepatedPtrField. Typical usage would be: +// for RepeatedField and RepeatedPtrField. Typical usage would be: // // std::copy(some_sequence.begin(), some_sequence.end(), // google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence())); diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc index 8b821806..fcebe5ce 100644 --- a/src/google/protobuf/repeated_field_reflection_unittest.cc +++ b/src/google/protobuf/repeated_field_reflection_unittest.cc @@ -410,6 +410,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { EXPECT_TRUE(mrf_message.empty()); #ifdef PROTOBUF_HAS_DEATH_TEST + // Make sure types are checked correctly at runtime. const FieldDescriptor* fd_optional_int32 = desc->FindFieldByName("optional_int32"); @@ -419,6 +420,7 @@ TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { message, fd_repeated_int32), ""); EXPECT_DEATH(refl->GetRepeatedFieldRef( message, fd_repeated_foreign_message), ""); + #endif // PROTOBUF_HAS_DEATH_TEST } diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 15c0c93e..66e74523 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -1131,7 +1131,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) { string v = "f"; RepeatedPtrField::const_iterator it = - lower_bound(proto_array_.begin(), proto_array_.end(), v); + std::lower_bound(proto_array_.begin(), proto_array_.end(), v); EXPECT_EQ(*it, "n"); EXPECT_TRUE(it == proto_array_.begin() + 3); @@ -1292,8 +1292,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { { string v = "f"; RepeatedPtrField::pointer_iterator it = - lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(), - &v, StringLessThan()); + std::lower_bound(proto_array_.pointer_begin(), + proto_array_.pointer_end(), &v, StringLessThan()); GOOGLE_CHECK(*it != NULL); @@ -1302,10 +1302,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { } { string v = "f"; - RepeatedPtrField::const_pointer_iterator it = - lower_bound(const_proto_array_->pointer_begin(), - const_proto_array_->pointer_end(), - &v, StringLessThan()); + RepeatedPtrField::const_pointer_iterator it = std::lower_bound( + const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(), + &v, StringLessThan()); GOOGLE_CHECK(*it != NULL); @@ -1343,9 +1342,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) { EXPECT_EQ("foo", proto_array_.Get(0)); EXPECT_EQ("n", proto_array_.Get(5)); EXPECT_EQ("x", proto_array_.Get(9)); - sort(proto_array_.pointer_begin(), - proto_array_.pointer_end(), - StringLessThan()); + std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(), + StringLessThan()); EXPECT_EQ("a", proto_array_.Get(0)); EXPECT_EQ("baz", proto_array_.Get(2)); EXPECT_EQ("y", proto_array_.Get(9)); @@ -1478,9 +1476,9 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, new_data->set_bb(i); } TestAllTypes testproto; - copy(data.begin(), data.end(), - AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_nested_message())); + std::copy(data.begin(), data.end(), + AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_nested_message())); EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } @@ -1497,9 +1495,8 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, *new_data = "name-" + SimpleItoa(i); } TestAllTypes testproto; - copy(data.begin(), data.end(), - AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_string())); + std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_string())); EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h index badcb6a5..33b7b91a 100644 --- a/src/google/protobuf/stubs/hash.h +++ b/src/google/protobuf/stubs/hash.h @@ -168,12 +168,14 @@ struct hash { }; template , - typename EqualKey = std::equal_to > + typename EqualKey = std::equal_to, + typename Alloc = std::allocator< std::pair > > class hash_map : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< - Key, Data, HashFcn, EqualKey> { + Key, Data, HashFcn, EqualKey, Alloc> { public: - hash_map(int = 0) {} + hash_map(int = 0, const HashFcn& = HashFcn(), const EqualKey& = EqualKey(), + const Alloc& = Alloc()) {} }; template , diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 86d45685..7955d261 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -1303,6 +1303,211 @@ string ToHex(uint64 num) { return string(bufptr, buf + 16 - bufptr); } +namespace strings { + +AlphaNum::AlphaNum(strings::Hex hex) { + char *const end = &digits[kFastToBufferSize]; + char *writer = end; + uint64 value = hex.value; + uint64 width = hex.spec; + // We accomplish minimum width by OR'ing in 0x10000 to the user's value, + // where 0x10000 is the smallest hex number that is as wide as the user + // asked for. + uint64 mask = ((static_cast(1) << (width - 1) * 4)) | value; + static const char hexdigits[] = "0123456789abcdef"; + do { + *--writer = hexdigits[value & 0xF]; + value >>= 4; + mask >>= 4; + } while (mask != 0); + piece_data_ = writer; + piece_size_ = end - writer; +} + +} // namespace strings + +// ---------------------------------------------------------------------- +// StrCat() +// This merges the given strings or integers, with no delimiter. This +// is designed to be the fastest possible way to construct a string out +// of a mix of raw C strings, C++ strings, and integer values. +// ---------------------------------------------------------------------- + +// Append is merely a version of memcpy that returns the address of the byte +// after the area just overwritten. It comes in multiple flavors to minimize +// call overhead. +static char *Append1(char *out, const AlphaNum &x) { + memcpy(out, x.data(), x.size()); + return out + x.size(); +} + +static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + + memcpy(out, x2.data(), x2.size()); + return out + x2.size(); +} + +static char *Append4(char *out, + const AlphaNum &x1, const AlphaNum &x2, + const AlphaNum &x3, const AlphaNum &x4) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + + memcpy(out, x2.data(), x2.size()); + out += x2.size(); + + memcpy(out, x3.data(), x3.size()); + out += x3.size(); + + memcpy(out, x4.data(), x4.size()); + return out + x4.size(); +} + +string StrCat(const AlphaNum &a, const AlphaNum &b) { + string result; + result.resize(a.size() + b.size()); + char *const begin = &*result.begin(); + char *out = Append2(begin, a, b); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + string result; + result.resize(a.size() + b.size() + c.size()); + char *const begin = &*result.begin(); + char *out = Append2(begin, a, b); + out = Append1(out, c); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append1(out, e); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append2(out, e, f); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append2(out, e, f); + out = Append1(out, g); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size() + h.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append4(out, e, f, g, h); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size() + h.size() + i.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append4(out, e, f, g, h); + out = Append1(out, i); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +// It's possible to call StrAppend with a char * pointer that is partway into +// the string we're appending to. However the results of this are random. +// Therefore, check for this in debug mode. Use unsigned math so we only have +// to do one comparison. +#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \ + GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \ + uintptr_t((dest).size())) + +void StrAppend(string *result, const AlphaNum &a) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + result->append(a.data(), a.size()); +} + +void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size()); + char *const begin = &*result->begin(); + char *out = Append2(begin + old_size, a, b); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +void StrAppend(string *result, + const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + GOOGLE_DCHECK_NO_OVERLAP(*result, c); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size() + c.size()); + char *const begin = &*result->begin(); + char *out = Append2(begin + old_size, a, b); + out = Append1(out, c); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +void StrAppend(string *result, + const AlphaNum &a, const AlphaNum &b, + const AlphaNum &c, const AlphaNum &d) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + GOOGLE_DCHECK_NO_OVERLAP(*result, c); + GOOGLE_DCHECK_NO_OVERLAP(*result, d); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size() + c.size() + d.size()); + char *const begin = &*result->begin(); + char *out = Append4(begin + old_size, a, b, c, d); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + int GlobalReplaceSubstring(const string& substring, const string& replacement, string* s) { diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index f2e1a944..920701eb 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -495,57 +495,168 @@ LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer); static const int kDoubleToBufferSize = 32; static const int kFloatToBufferSize = 24; -// ---------------------------------------------------------------------- -// ToString() are internal help methods used in StrCat() and Join() -// ---------------------------------------------------------------------- -namespace internal { -inline string ToString(int i) { - return SimpleItoa(i); -} +namespace strings { -inline string ToString(string a) { - return a; -} -} // namespace internal +struct Hex { + uint64 value; + enum PadSpec { + NONE = 1, + ZERO_PAD_2, + ZERO_PAD_3, + ZERO_PAD_4, + ZERO_PAD_5, + ZERO_PAD_6, + ZERO_PAD_7, + ZERO_PAD_8, + ZERO_PAD_9, + ZERO_PAD_10, + ZERO_PAD_11, + ZERO_PAD_12, + ZERO_PAD_13, + ZERO_PAD_14, + ZERO_PAD_15, + ZERO_PAD_16, + } spec; + template + explicit Hex(Int v, PadSpec s = NONE) + : spec(s) { + // Prevent sign-extension by casting integers to + // their unsigned counterparts. +#ifdef LANG_CXX11 + static_assert( + sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8, + "Unknown integer type"); +#endif + value = sizeof(v) == 1 ? static_cast(v) + : sizeof(v) == 2 ? static_cast(v) + : sizeof(v) == 4 ? static_cast(v) + : static_cast(v); + } +}; -// ---------------------------------------------------------------------- -// StrCat() -// These methods join some strings together. -// ---------------------------------------------------------------------- -template -string StrCat( - const T1& a, const T2& b, const T3& c, const T4& d, const T5& e, - const T6& f, const T7& g) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c) + internal::ToString(d) + internal::ToString(e) + - internal::ToString(f) + internal::ToString(g); -} +struct AlphaNum { + const char *piece_data_; // move these to string_ref eventually + size_t piece_size_; // move these to string_ref eventually -template -string StrCat( - const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c) + internal::ToString(d) + internal::ToString(e); -} + char digits[kFastToBufferSize]; -template -string StrCat( - const T1& a, const T2& b, const T3& c, const T4& d) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c) + internal::ToString(d); -} + // No bool ctor -- bools convert to an integral type. + // A bool ctor would also convert incoming pointers (bletch). -template -string StrCat(const T1& a, const T2& b, const T3& c) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c); -} + AlphaNum(int32 i32) + : piece_data_(digits), + piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {} + AlphaNum(uint32 u32) + : piece_data_(digits), + piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {} + AlphaNum(int64 i64) + : piece_data_(digits), + piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {} + AlphaNum(uint64 u64) + : piece_data_(digits), + piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {} -template -string StrCat(const T1& a, const T2& b) { - return internal::ToString(a) + internal::ToString(b); -} + AlphaNum(float f) + : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {} + AlphaNum(double f) + : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {} + + AlphaNum(Hex hex); + + AlphaNum(const char* c_str) + : piece_data_(c_str), piece_size_(strlen(c_str)) {} + // TODO: Add a string_ref constructor, eventually + // AlphaNum(const StringPiece &pc) : piece(pc) {} + + AlphaNum(const string& str) + : piece_data_(str.data()), piece_size_(str.size()) {} + + size_t size() const { return piece_size_; } + const char *data() const { return piece_data_; } + + private: + // Use ":" not ':' + AlphaNum(char c); // NOLINT(runtime/explicit) + + // Disallow copy and assign. + AlphaNum(const AlphaNum&); + void operator=(const AlphaNum&); +}; + +} // namespace strings + +using strings::AlphaNum; + +// ---------------------------------------------------------------------- +// StrCat() +// This merges the given strings or numbers, with no delimiter. This +// is designed to be the fastest possible way to construct a string out +// of a mix of raw C strings, strings, bool values, +// and numeric values. +// +// Don't use this for user-visible strings. The localization process +// works poorly on strings built up out of fragments. +// +// For clarity and performance, don't use StrCat when appending to a +// string. In particular, avoid using any of these (anti-)patterns: +// str.append(StrCat(...) +// str += StrCat(...) +// str = StrCat(str, ...) +// where the last is the worse, with the potential to change a loop +// from a linear time operation with O(1) dynamic allocations into a +// quadratic time operation with O(n) dynamic allocations. StrAppend +// is a better choice than any of the above, subject to the restriction +// of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may +// be a reference into str. +// ---------------------------------------------------------------------- + +string StrCat(const AlphaNum &a, const AlphaNum &b); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h); +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h, const AlphaNum &i); + +inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } + +// ---------------------------------------------------------------------- +// StrAppend() +// Same as above, but adds the output to the given string. +// WARNING: For speed, StrAppend does not try to check each of its input +// arguments to be sure that they are not a subset of the string being +// appended to. That is, while this will work: +// +// string s = "foo"; +// s += s; +// +// This will not (necessarily) work: +// +// string s = "foo"; +// StrAppend(&s, s); +// +// Note: while StrCat supports appending up to 9 arguments, StrAppend +// is currently limited to 4. That's rarely an issue except when +// automatically transforming StrCat to StrAppend, and can easily be +// worked around as consecutive calls to StrAppend are quite efficient. +// ---------------------------------------------------------------------- + +void StrAppend(string* dest, const AlphaNum& a); +void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b); +void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c); +void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d); // ---------------------------------------------------------------------- // Join() @@ -559,7 +670,7 @@ void Join(Iterator start, Iterator end, if (it != start) { result->append(delim); } - result->append(internal::ToString(*it)); + StrAppend(result, *it); } } diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 8e867c09..ec070c51 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -1360,9 +1360,8 @@ void TextFormat::Printer::SetDefaultFieldValuePrinter( bool TextFormat::Printer::RegisterFieldValuePrinter( const FieldDescriptor* field, const FieldValuePrinter* printer) { - return field != NULL - && printer != NULL - && custom_printers_.insert(make_pair(field, printer)).second; + return field != NULL && printer != NULL && + custom_printers_.insert(std::make_pair(field, printer)).second; } bool TextFormat::Printer::PrintToString(const Message& message, @@ -1422,7 +1421,7 @@ void TextFormat::Printer::Print(const Message& message, vector fields; reflection->ListFields(message, &fields); if (print_message_fields_in_index_order_) { - sort(fields.begin(), fields.end(), FieldIndexSorter()); + std::sort(fields.begin(), fields.end(), FieldIndexSorter()); } for (int i = 0; i < fields.size(); i++) { PrintField(message, reflection, fields[i], generator); diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index 44d68cab..9e2cb070 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -278,8 +278,20 @@ class LIBPROTOBUF_EXPORT TextFormat { }; // Parses a text-format protocol message from the given input stream to - // the given message object. This function parses the format written - // by Print(). + // the given message object. This function parses the human-readable format + // written by Print(). Returns true on success. The message is cleared first, + // even if the function fails -- See Merge() to avoid this behavior. + // + // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}" + // + // One use for this function is parsing handwritten strings in test code. + // Another use is to parse the output from google::protobuf::Message::DebugString() + // (or ShortDebugString()), because these functions output using + // google::protobuf::TextFormat::Print(). + // + // If you would like to read a protocol buffer serialized in the + // (non-human-readable) binary wire format, see + // google::protobuf::MessageLite::ParseFromString(). static bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like Parse(), but reads directly from a string. static bool ParseFromString(const string& input, Message* output); diff --git a/src/google/protobuf/unittest_no_arena.proto b/src/google/protobuf/unittest_no_arena.proto index 1a420838..36fb8656 100644 --- a/src/google/protobuf/unittest_no_arena.proto +++ b/src/google/protobuf/unittest_no_arena.proto @@ -113,7 +113,7 @@ message TestAllTypes { optional protobuf_unittest_import.PublicImportMessage optional_public_import_message = 26; - optional NestedMessage optional_lazy_message = 27 [lazy=true]; + optional NestedMessage optional_message = 27 [lazy=true]; // Repeated repeated int32 repeated_int32 = 31; @@ -180,6 +180,7 @@ message TestAllTypes { NestedMessage oneof_nested_message = 112; string oneof_string = 113; bytes oneof_bytes = 114; + NestedMessage lazy_oneof_nested_message = 115 [lazy=true]; } } diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto index ba050d70..67e57499 100644 --- a/src/google/protobuf/unittest_preserve_unknown_enum.proto +++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto @@ -30,7 +30,7 @@ syntax = "proto3"; -package proto2_preserve_unknown_enum_unittest; +package proto3_preserve_unknown_enum_unittest; enum MyEnum { FOO = 0; @@ -49,9 +49,10 @@ message MyMessage { optional MyEnum e = 1; repeated MyEnum repeated_e = 2; repeated MyEnum repeated_packed_e = 3 [packed=true]; + repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4; // not packed oneof o { - MyEnum oneof_e_1 = 4; - MyEnum oneof_e_2 = 5; + MyEnum oneof_e_1 = 5; + MyEnum oneof_e_2 = 6; } } @@ -59,8 +60,9 @@ message MyMessagePlusExtra { optional MyEnumPlusExtra e = 1; repeated MyEnumPlusExtra repeated_e = 2; repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true]; + repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true]; oneof o { - MyEnumPlusExtra oneof_e_1 = 4; - MyEnumPlusExtra oneof_e_2 = 5; + MyEnumPlusExtra oneof_e_1 = 5; + MyEnumPlusExtra oneof_e_2 = 6; } } diff --git a/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto new file mode 100644 index 00000000..adf42968 --- /dev/null +++ b/src/google/protobuf/unittest_preserve_unknown_enum2.proto @@ -0,0 +1,50 @@ +// 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. + +syntax = "proto2"; + +package proto2_preserve_unknown_enum_unittest; + +enum MyEnum { + FOO = 0; + BAR = 1; + BAZ = 2; +} + +message MyMessage { + optional MyEnum e = 1; + repeated MyEnum repeated_e = 2; + repeated MyEnum repeated_packed_e = 3 [packed=true]; + repeated MyEnum repeated_packed_unexpected_e = 4; // not packed + oneof o { + MyEnum oneof_e_1 = 5; + MyEnum oneof_e_2 = 6; + } +} diff --git a/src/google/protobuf/unknown_enum_impl.h b/src/google/protobuf/unknown_enum_impl.h index fb5380aa..39c10cbc 100644 --- a/src/google/protobuf/unknown_enum_impl.h +++ b/src/google/protobuf/unknown_enum_impl.h @@ -98,6 +98,29 @@ bool GetRepeatedEnumUnknowns_Template( } } +// NOTE: You should not call these functions directly. Instead use +// CLEAR_UNKNOWN_ENUM(), defined in the public header. The macro-versions +// operate in a type-safe manner and behave appropriately for the proto +// version of the message, whereas these versions assume a specific proto +// version and allow the caller to pass in any arbitrary integer value as a +// field number. +// +// Clears the unknown entries of the given field of the message. +void ClearUnknownEnum(Message* message, int32 field_number); +// In proto1, clears the field if the value is out of range. +// TODO(karner): Delete this or make it proto2-only once the migration +// to proto2 is complete. +void ClearUnknownEnumProto1(Message* message, int32 field_number); +template +void ClearUnknownEnum_Template(T* message, int32 field_number) { + if (internal::is_base_of::value || + !internal::is_base_of::value) { + ClearUnknownEnum(message, field_number); + } else { + ClearUnknownEnumProto1(message, field_number); + } +} + // NOTE: You should not call these functions directly. Instead use // SET_UNKNOWN_ENUM(), defined in the public header. The macro-versions // operate in a type-safe manner and behave appropriately for the proto diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h index e8c0a13c..987b1979 100644 --- a/src/google/protobuf/unknown_field_set.h +++ b/src/google/protobuf/unknown_field_set.h @@ -222,13 +222,12 @@ class LIBPROTOBUF_EXPORT UnknownField { // UnknownField is being created. inline void SetType(Type type); - uint32 number_; - uint32 type_; - union LengthDelimited { string* string_value_; }; + uint32 number_; + uint32 type_; union { uint64 varint_; uint32 fixed32_; diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index f4f02157..c5bbbf2e 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -141,7 +141,7 @@ bool WireFormat::SkipField(io::CodedInputStream* input, uint32 tag, bool WireFormat::SkipMessage(io::CodedInputStream* input, UnknownFieldSet* unknown_fields) { - while(true) { + while (true) { uint32 tag = input->ReadTag(); if (tag == 0) { // End of input. This is a valid place to end, so return true. @@ -159,6 +159,31 @@ bool WireFormat::SkipMessage(io::CodedInputStream* input, } } +bool WireFormat::ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input, + uint32 field_number, + bool (*is_valid)(int), + UnknownFieldSet* unknown_fields, + RepeatedField* values) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + int value; + if (!google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, WireFormatLite::TYPE_ENUM>(input, &value)) { + return false; + } + if (is_valid == NULL || is_valid(value)) { + values->Add(value); + } else { + unknown_fields->AddVarint(field_number, value); + } + } + input->PopLimit(limit); + return true; +} + + void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields, io::CodedOutputStream* output) { for (int i = 0; i < unknown_fields.field_count(); i++) { @@ -520,6 +545,14 @@ bool WireFormat::ParseAndMergeField( field->enum_type()->FindValueByNumber(value); if (enum_value != NULL) { message_reflection->AddEnum(message, field, enum_value); + } else { + // The enum value is not one of the known values. Add it to the + // UnknownFieldSet. + int64 sign_extended_value = static_cast(value); + message_reflection->MutableUnknownFields(message) + ->AddVarint( + WireFormatLite::GetTagFieldNumber(tag), + sign_extended_value); } } } diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index 9f26eb29..8de491a6 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h @@ -138,6 +138,14 @@ class LIBPROTOBUF_EXPORT WireFormat { static bool SkipMessage(io::CodedInputStream* input, UnknownFieldSet* unknown_fields); + // Read a packed enum field. If the is_valid function is not NULL, values for + // which is_valid(value) returns false are appended to unknown_fields_stream. + static bool ReadPackedEnumPreserveUnknowns(io::CodedInputStream* input, + uint32 field_number, + bool (*is_valid)(int), + UnknownFieldSet* unknown_fields, + RepeatedField* values); + // Write the contents of an UnknownFieldSet to the output. static void SerializeUnknownFields(const UnknownFieldSet& unknown_fields, io::CodedOutputStream* output); diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc index 50616551..2ce4920c 100644 --- a/src/google/protobuf/wire_format_lite.cc +++ b/src/google/protobuf/wire_format_lite.cc @@ -304,6 +304,34 @@ bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input, return true; } +bool WireFormatLite::ReadPackedEnumPreserveUnknowns( + io::CodedInputStream* input, + int field_number, + bool (*is_valid)(int), + io::CodedOutputStream* unknown_fields_stream, + RepeatedField* values) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + io::CodedInputStream::Limit limit = input->PushLimit(length); + while (input->BytesUntilLimit() > 0) { + int value; + if (!google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, WireFormatLite::TYPE_ENUM>(input, &value)) { + return false; + } + if (is_valid == NULL || is_valid(value)) { + values->Add(value); + } else { + uint32 tag = WireFormatLite::MakeTag(field_number, + WireFormatLite::WIRETYPE_VARINT); + unknown_fields_stream->WriteVarint32(tag); + unknown_fields_stream->WriteVarint32(value); + } + } + input->PopLimit(limit); + return true; +} + void WireFormatLite::WriteInt32(int field_number, int32 value, io::CodedOutputStream* output) { WriteTag(field_number, WIRETYPE_VARINT, output); diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h index acf88ead..76bc75a1 100644 --- a/src/google/protobuf/wire_format_lite.h +++ b/src/google/protobuf/wire_format_lite.h @@ -291,11 +291,20 @@ class LIBPROTOBUF_EXPORT WireFormatLite { template static bool ReadPackedPrimitiveNoInline(input, RepeatedField* value); - // Read a packed enum field. Values for which is_valid() returns false are - // dropped. If is_valid == NULL, no values are dropped. + // Read a packed enum field. If the is_valid function is not NULL, values for + // which is_valid(value) returns false are silently dropped. static bool ReadPackedEnumNoInline(input, bool (*is_valid)(int), - RepeatedField* value); + RepeatedField* values); + + // Read a packed enum field. If the is_valid function is not NULL, values for + // which is_valid(value) returns false are appended to unknown_fields_stream. + static bool ReadPackedEnumPreserveUnknowns( + input, + field_number, + bool (*is_valid)(int), + io::CodedOutputStream* unknown_fields_stream, + RepeatedField* values); // Read a string. ReadString(..., string* value) requires an existing string. static inline bool ReadString(input, string* value); @@ -647,7 +656,7 @@ inline double WireFormatLite::DecodeDouble(uint64 value) { inline uint32 WireFormatLite::ZigZagEncode32(int32 n) { // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 31); + return (static_cast(n) << 1) ^ (n >> 31); } inline int32 WireFormatLite::ZigZagDecode32(uint32 n) { @@ -656,7 +665,7 @@ inline int32 WireFormatLite::ZigZagDecode32(uint32 n) { inline uint64 WireFormatLite::ZigZagEncode64(int64 n) { // Note: the right-shift must be arithmetic - return (n << 1) ^ (n >> 63); + return (static_cast(n) << 1) ^ (n >> 63); } inline int64 WireFormatLite::ZigZagDecode64(uint64 n) { -- cgit v1.2.3 From 9d31c227a3ab0260c3e6ebc7e1a555f47582dab4 Mon Sep 17 00:00:00 2001 From: Feng Xiao Date: Fri, 13 Mar 2015 17:06:10 -0700 Subject: Add a missing proto file. Change-Id: Ic98584616bd6ee49680273f0cdbe6d9c038ec0e9 --- src/Makefile.am | 5 ++- .../compiler/cpp/test_large_enum_value.proto | 43 ++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/google/protobuf/compiler/cpp/test_large_enum_value.proto (limited to 'src/google/protobuf/compiler') diff --git a/src/Makefile.am b/src/Makefile.am index 63a14518..eb75b51e 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -322,7 +322,8 @@ protoc_inputs = \ google/protobuf/unittest_preserve_unknown_enum.proto \ google/protobuf/unittest_preserve_unknown_enum2.proto \ google/protobuf/unittest_proto3_arena.proto \ - google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \ + google/protobuf/compiler/cpp/test_large_enum_value.proto EXTRA_DIST = \ $(protoc_inputs) \ @@ -398,6 +399,8 @@ protoc_outputs = \ google/protobuf/unittest_preserve_unknown_enum2.pb.h \ google/protobuf/unittest_proto3_arena.pb.cc \ google/protobuf/unittest_proto3_arena.pb.h \ + google/protobuf/compiler/cpp/test_large_enum_value.pb.cc \ + google/protobuf/compiler/cpp/test_large_enum_value.pb.h \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h diff --git a/src/google/protobuf/compiler/cpp/test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto new file mode 100644 index 00000000..cb6ca1b1 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto @@ -0,0 +1,43 @@ +// 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. + +// Test that proto2 compiler can generate valid code when the enum value +// is INT_MAX. Note that this is a compile-only test and this proto is not +// referenced in any C++ code. +syntax = "proto2"; + +package protobuf_unittest; + +message TestLargeEnumValue { + enum EnumWithLargeValue { + VALUE_1 = 1; + VALUE_MAX = 0x7fffffff; + } +} -- cgit v1.2.3 From 0d77c824e7015190a9174052fc5290c23f2b85d0 Mon Sep 17 00:00:00 2001 From: Chris Conroy Date: Fri, 25 Oct 2013 16:43:29 -0400 Subject: Sanitize Enum names from collisions with reserved words. --- src/google/protobuf/compiler/cpp/cpp_enum.cc | 11 ++++++----- src/google/protobuf/compiler/cpp/cpp_helpers.cc | 8 ++++++++ src/google/protobuf/compiler/cpp/cpp_helpers.h | 3 +++ .../compiler/cpp/cpp_test_bad_identifiers.proto | 18 ++++++++++++++++++ src/google/protobuf/compiler/cpp/cpp_unittest.cc | 15 +++++++++++++++ 5 files changed, 50 insertions(+), 5 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 0404b739..3eb20ab1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -82,7 +82,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { const EnumValueDescriptor* max_value = descriptor_->value(0); for (int i = 0; i < descriptor_->value_count(); i++) { - vars["name"] = descriptor_->value(i)->name(); + vars["name"] = EnumValueName(descriptor_->value(i)); // In C++, an value of -2147483648 gets interpreted as the negative of // 2147483648, and since 2147483648 can't fit in an integer, this produces a // compiler warning. This works around that issue. @@ -90,6 +90,7 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { vars["prefix"] = (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; + if (i > 0) printer->Print(",\n"); printer->Print(vars, "$prefix$$name$ = $number$"); @@ -113,8 +114,8 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { printer->Outdent(); printer->Print("\n};\n"); - vars["min_name"] = min_value->name(); - vars["max_name"] = max_value->name(); + vars["min_name"] = EnumValueName(min_value); + vars["max_name"] = EnumValueName(max_value); if (options_.dllexport_decl.empty()) { vars["dllexport"] = ""; @@ -174,7 +175,7 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { printer->Print(vars, "typedef $classname$ $nested_name$;\n"); for (int j = 0; j < descriptor_->value_count(); j++) { - vars["tag"] = descriptor_->value(j)->name(); + vars["tag"] = EnumValueName(descriptor_->value(j)); printer->Print(vars, "static const $nested_name$ $tag$ = $classname$_$tag$;\n"); } @@ -278,7 +279,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { vars["parent"] = ClassName(descriptor_->containing_type(), false); vars["nested_name"] = descriptor_->name(); for (int i = 0; i < descriptor_->value_count(); i++) { - vars["value"] = descriptor_->value(i)->name(); + vars["value"] = EnumValueName(descriptor_->value(i)); printer->Print(vars, "const $classname$ $parent$::$value$;\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 237278db..4e7155c3 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -176,6 +176,14 @@ string FieldName(const FieldDescriptor* field) { return result; } +string EnumValueName(const EnumValueDescriptor* enum_value) { + string result = enum_value->name(); + if (kKeywords.count(result) > 0) { + result.append("_"); + } + return result; +} + string FieldConstantName(const FieldDescriptor *field) { string field_name = UnderscoresToCamelCase(field->name(), true); string result = "k" + field_name + "FieldNumber"; diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index c7bb8f98..284fa2c1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -74,6 +74,9 @@ string SuperClassName(const Descriptor* descriptor); // anyway, so normally this just returns field->name(). string FieldName(const FieldDescriptor* field); +// Get the sanitized name that should be used for the given enum in C++ code. +string EnumValueName(const EnumValueDescriptor* enum_value); + // Get the unqualified name that should be used for a field's field // number constant. string FieldConstantName(const FieldDescriptor *field); diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto index 4fa3c144..9f63155b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -131,6 +131,24 @@ message TestConflictingSymbolNamesExtension { // NO_PROTO3 } // NO_PROTO3 } // NO_PROTO3 +message TestConflictingEnumNames { + enum NestedConflictingEnum { + and = 1; + class = 2; + int = 3; + typedef = 4; + XOR = 5; + } + + optional NestedConflictingEnum conflicting_enum = 1; +} + +enum ConflictingEnum { + NOT_EQ = 1; + volatile = 2; + return = 3; +} + message DummyMessage {} service TestConflictingMethodNames { diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 2a04b293..cc758cf5 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -794,6 +794,21 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) { message.GetExtension(ExtensionMessage::repeated_int32_ext, 0)); } +TEST(GeneratedMessageTest, TestConflictingEnumNames) { + protobuf_unittest::TestConflictingEnumNames message; + message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_and_); + EXPECT_EQ(1, message.conflicting_enum()); + message.set_conflicting_enum(protobuf_unittest::TestConflictingEnumNames_NestedConflictingEnum_XOR); + EXPECT_EQ(5, message.conflicting_enum()); + + + protobuf_unittest::ConflictingEnum conflicting_enum; + conflicting_enum = protobuf_unittest::NOT_EQ; + EXPECT_EQ(1, conflicting_enum); + conflicting_enum = protobuf_unittest::return_; + EXPECT_EQ(3, conflicting_enum); +} + #ifndef PROTOBUF_TEST_NO_DESCRIPTORS TEST(GeneratedMessageTest, TestOptimizedForSize) { -- cgit v1.2.3 From ed715048c60177a669dfcb2851f67e4951d97a5b Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Wed, 18 Mar 2015 00:43:34 -0700 Subject: Add OS X to travis; fix tests to pass on OS X --- .travis.yml | 3 +++ src/google/protobuf/compiler/command_line_interface_unittest.cc | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/.travis.yml b/.travis.yml index 93013b8b..b2e73943 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: cpp +os: + - linux + - osx script: ./autogen.sh && ./configure && make distcheck notifications: email: false diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 2b26f3be..a2cbbdc6 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -991,7 +991,7 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { " optional Foo foo = 1;\n" "}\n"); - string current_working_directory = get_current_dir_name(); + string current_working_directory = getcwd(NULL, 0); SwitchToTempDirectory(); Run("protocol_compiler --dependency_out=manifest --test_out=. " -- cgit v1.2.3 From 685ae36ca2dbb455b440997f75cca3e88085a23f Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 16 Mar 2015 19:07:16 -0700 Subject: Rewrote C# protogen to C++ (initial version) --- src/Makefile.am | 21 +- src/google/protobuf/compiler/csharp/csharp_enum.cc | 79 ++ src/google/protobuf/compiler/csharp/csharp_enum.h | 65 ++ .../protobuf/compiler/csharp/csharp_enum_field.cc | 160 +++ .../protobuf/compiler/csharp/csharp_enum_field.h | 73 ++ .../protobuf/compiler/csharp/csharp_extension.cc | 170 +++ .../protobuf/compiler/csharp/csharp_extension.h | 80 ++ .../protobuf/compiler/csharp/csharp_field_base.cc | 394 +++++++ .../protobuf/compiler/csharp/csharp_field_base.h | 100 ++ .../protobuf/compiler/csharp/csharp_generator.cc | 82 ++ .../protobuf/compiler/csharp/csharp_generator.h | 58 + .../compiler/csharp/csharp_generator_unittest.cc | 54 + .../protobuf/compiler/csharp/csharp_helpers.cc | 383 +++++++ .../protobuf/compiler/csharp/csharp_helpers.h | 108 ++ .../protobuf/compiler/csharp/csharp_message.cc | 900 ++++++++++++++++ .../protobuf/compiler/csharp/csharp_message.h | 98 ++ .../compiler/csharp/csharp_message_field.cc | 183 ++++ .../compiler/csharp/csharp_message_field.h | 73 ++ .../compiler/csharp/csharp_primitive_field.cc | 148 +++ .../compiler/csharp/csharp_primitive_field.h | 73 ++ .../compiler/csharp/csharp_repeated_enum_field.cc | 226 ++++ .../compiler/csharp/csharp_repeated_enum_field.h | 73 ++ .../csharp/csharp_repeated_message_field.cc | 201 ++++ .../csharp/csharp_repeated_message_field.h | 73 ++ .../csharp/csharp_repeated_primitive_field.cc | 219 ++++ .../csharp/csharp_repeated_primitive_field.h | 73 ++ .../csharp/csharp_source_generator_base.cc | 82 ++ .../compiler/csharp/csharp_source_generator_base.h | 83 ++ .../compiler/csharp/csharp_umbrella_class.cc | 297 ++++++ .../compiler/csharp/csharp_umbrella_class.h | 76 ++ .../protobuf/compiler/csharp/csharp_writer.cc | 136 +++ .../protobuf/compiler/csharp/csharp_writer.h | 93 ++ src/google/protobuf/compiler/main.cc | 6 + src/google/protobuf/descriptor.pb.cc | 1116 +++++++++++++++++++- src/google/protobuf/descriptor.pb.h | 581 +++++++++- src/google/protobuf/descriptor.proto | 52 + 36 files changed, 6640 insertions(+), 49 deletions(-) create mode 100644 src/google/protobuf/compiler/csharp/csharp_enum.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_enum.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_enum_field.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_enum_field.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_extension.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_extension.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_field_base.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_field_base.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_generator.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_generator.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_helpers.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_helpers.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_message.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_message.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_message_field.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_message_field.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_primitive_field.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_primitive_field.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_source_generator_base.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_umbrella_class.h create mode 100644 src/google/protobuf/compiler/csharp/csharp_writer.cc create mode 100644 src/google/protobuf/compiler/csharp/csharp_writer.h (limited to 'src/google/protobuf/compiler') diff --git a/src/Makefile.am b/src/Makefile.am index 8a27b823..59f7eaa2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -126,7 +126,8 @@ nobase_include_HEADERS = \ google/protobuf/compiler/java/java_names.h \ google/protobuf/compiler/javanano/javanano_generator.h \ google/protobuf/compiler/python/python_generator.h \ - google/protobuf/compiler/ruby/ruby_generator.h + google/protobuf/compiler/ruby/ruby_generator.h \ + google/protobuf/compiler/csharp/csharp_generator.h nobase_nodist_include_HEADERS = \ $(public_config) @@ -288,7 +289,22 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/javanano/javanano_primitive_field.cc \ google/protobuf/compiler/javanano/javanano_primitive_field.h \ google/protobuf/compiler/python/python_generator.cc \ - google/protobuf/compiler/ruby/ruby_generator.cc + google/protobuf/compiler/ruby/ruby_generator.cc \ + google/protobuf/compiler/csharp/csharp_enum.cc \ + google/protobuf/compiler/csharp/csharp_enum_field.cc \ + google/protobuf/compiler/csharp/csharp_extension.cc \ + google/protobuf/compiler/csharp/csharp_field_base.cc \ + google/protobuf/compiler/csharp/csharp_generator.cc \ + google/protobuf/compiler/csharp/csharp_helpers.cc \ + google/protobuf/compiler/csharp/csharp_message.cc \ + google/protobuf/compiler/csharp/csharp_message_field.cc \ + google/protobuf/compiler/csharp/csharp_primitive_field.cc \ + google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc \ + google/protobuf/compiler/csharp/csharp_repeated_message_field.cc \ + google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc \ + google/protobuf/compiler/csharp/csharp_source_generator_base.cc \ + google/protobuf/compiler/csharp/csharp_umbrella_class.cc \ + google/protobuf/compiler/csharp/csharp_writer.cc bin_PROGRAMS = protoc protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la @@ -493,6 +509,7 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/java/java_doc_comment_unittest.cc \ google/protobuf/compiler/python/python_plugin_unittest.cc \ google/protobuf/compiler/ruby/ruby_generator_unittest.cc \ + google/protobuf/compiler/csharp/csharp_generator_unittest.cc \ $(COMMON_TEST_SOURCES) nodist_protobuf_test_SOURCES = $(protoc_outputs) diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc new file mode 100644 index 00000000..27643e61 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -0,0 +1,79 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using google::protobuf::internal::scoped_ptr; + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) : + SourceGeneratorBase(descriptor->file()), + descriptor_(descriptor) { +} + +EnumGenerator::~EnumGenerator() { +} + +void EnumGenerator::Generate(Writer* writer) { + WriteGeneratedCodeAttributes(writer); + writer->WriteLine("$0$ enum $1$ {", + class_access_level(), + descriptor_->name()); + writer->Indent(); + for (int i = 0; i < descriptor_->value_count(); i++) { + writer->WriteLine("$0$ = $1$,", + descriptor_->value(i)->name(), + SimpleItoa(descriptor_->value(i)->number())); + } + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h new file mode 100644 index 00000000..eaa7a9c5 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_enum.h @@ -0,0 +1,65 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class EnumGenerator : public SourceGeneratorBase { + public: + EnumGenerator(const EnumDescriptor* descriptor); + ~EnumGenerator(); + + void Generate(Writer* writer); + + private: + const EnumDescriptor* descriptor_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc new file mode 100644 index 00000000..d5b1b477 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -0,0 +1,160 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { +} + +EnumFieldGenerator::~EnumFieldGenerator() { + +} + +void EnumFieldGenerator::GenerateMembers(Writer* writer) { + writer->WriteLine("private bool has$0$;", property_name()); + writer->WriteLine("private $0$ $1$_ = $2$;", type_name(), name(), + default_value()); + AddDeprecatedFlag(writer); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return has$0$; }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return $0$_; }", name()); + writer->WriteLine("}"); +} + +void EnumFieldGenerator::GenerateBuilderMembers(Writer* writer) { + AddDeprecatedFlag(writer); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return result.has$0$; }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return result.$0$; }", property_name()); + writer->WriteLine(" set { Set$0$(value); }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), + type_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.has$0$ = true;", property_name()); + writer->WriteLine(" result.$0$_ = value;", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.has$0$ = false;", property_name()); + writer->WriteLine(" result.$0$_ = $1$;", name(), default_value()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void EnumFieldGenerator::GenerateMergingCode(Writer* writer) { + writer->WriteLine("if (other.Has$0$) {", property_name()); + writer->WriteLine(" $0$ = other.$0$;", property_name()); + writer->WriteLine("}"); +} + +void EnumFieldGenerator::GenerateBuildingCode(Writer* writer) { + // Nothing to do here for enum types +} + +void EnumFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine("object unknown;"); + writer->WriteLine("if(input.ReadEnum(ref result.$0$_, out unknown)) {", + name()); + writer->WriteLine(" result.has$0$ = true;", property_name()); + writer->WriteLine("} else if(unknown is int) {"); + if (!use_lite_runtime()) { + writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now + writer->WriteLine( + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); + writer->WriteLine(" }"); + writer->WriteLine( + " unknownFields.MergeVarintField($0$, (ulong)(int)unknown);", + number()); + } + writer->WriteLine("}"); +} + +void EnumFieldGenerator::GenerateSerializationCode(Writer* writer) { + writer->WriteLine("if (has$0$) {", property_name()); + writer->WriteLine( + " output.WriteEnum($0$, field_names[$2$], (int) $1$, $1$);", number(), + property_name(), field_ordinal()); + writer->WriteLine("}"); +} + +void EnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { + writer->WriteLine("if (has$0$) {", property_name()); + writer->WriteLine( + " size += pb::CodedOutputStream.ComputeEnumSize($0$, (int) $1$);", + number(), property_name()); + writer->WriteLine("}"); +} + +void EnumFieldGenerator::WriteHash(Writer* writer) { + writer->WriteLine("if (has$0$) hash ^= $1$_.GetHashCode();", property_name(), + name()); +} +void EnumFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine( + "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", + property_name(), name()); +} +void EnumFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", has$1$, $2$_, writer);", + descriptor_->name(), property_name(), name()); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h new file mode 100644 index 00000000..b21fa9dc --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -0,0 +1,73 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class EnumFieldGenerator : public FieldGeneratorBase { + public: + EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~EnumFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void GenerateMergingCode(Writer* writer); + virtual void GenerateBuildingCode(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateSerializationCode(Writer* writer); + virtual void GenerateSerializedSizeCode(Writer* writer); + + virtual void WriteHash(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc new file mode 100644 index 00000000..f929f49f --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_extension.cc @@ -0,0 +1,170 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using google::protobuf::internal::scoped_ptr; + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) + : FieldGeneratorBase(descriptor, 0) { + if (descriptor_->extension_scope()) { + scope_ = GetClassName(descriptor_->extension_scope()); + } else { + scope_ = GetFullUmbrellaClassName(descriptor_->file()); + } + extends_ = GetClassName(descriptor_->containing_type()); +} + +ExtensionGenerator::~ExtensionGenerator() { +} + +void ExtensionGenerator::Generate(Writer* writer) { + if (descriptor_->file()->options().csharp_cls_compliance() + && (GetFieldConstantName(descriptor_).substr(0, 1) == "_")) { + writer->WriteLine("[global::System.CLSCompliant(false)]"); + } + + writer->WriteLine("public const int $0$ = $1$;", + GetFieldConstantName(descriptor_), + SimpleItoa(descriptor_->number())); + + if (use_lite_runtime()) { + // TODO(jtattermusch): check the argument... + //if (Descriptor.MappedType == MappedType.Message && Descriptor.MessageType.Options.MessageSetWireFormat) + //{ + // throw new ArgumentException( + // "option message_set_wire_format = true; is not supported in Lite runtime extensions."); + //} + + AddClsComplianceCheck(writer); + writer->Write("$0$ ", class_access_level()); + writer->WriteLine( + "static pb::$3$<$0$, $1$> $2$;", + extends_, + type_name(), + property_name(), + descriptor_->is_repeated() ? + "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"); + } else if (descriptor_->is_repeated()) { + AddClsComplianceCheck(writer); + writer->WriteLine( + "$0$ static pb::GeneratedExtensionBase> $2$;", + class_access_level(), type_name(), property_name()); + } else { + AddClsComplianceCheck(writer); + writer->WriteLine("$0$ static pb::GeneratedExtensionBase<$1$> $2$;", + class_access_level(), type_name(), property_name()); + } +} + +void ExtensionGenerator::GenerateStaticVariableInitializers(Writer* writer) { + if (use_lite_runtime()) { + writer->WriteLine("$0$.$1$ = ", scope_, property_name()); + writer->Indent(); + writer->WriteLine( + "new pb::$0$<$1$, $2$>(", + descriptor_->is_repeated() ? + "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite", + extends_, type_name()); + writer->Indent(); + writer->WriteLine("\"$0$\",", descriptor_->full_name()); + writer->WriteLine("$0$.DefaultInstance,", extends_); + if (!descriptor_->is_repeated()) { + std::string default_val; + if (descriptor_->has_default_value()) { + default_val = default_value(); + } else { + default_val = is_nullable_type() ? "null" : ("default(" + type_name() + ")"); + } + writer->WriteLine("$0$,", default_val); + } + // TODO(jtattermusch): + //writer.WriteLine("{0},", + // (Descriptor.MappedType == MappedType.Message) ? type + ".DefaultInstance" : "null"); + //writer.WriteLine("{0},", + // (Descriptor.MappedType == MappedType.Enum) ? "new EnumLiteMap<" + type + ">()" : "null"); + //writer.WriteLine("{0}.{1}FieldNumber,", scope, name); + //writer.Write("pbd::FieldType.{0}", Descriptor.FieldType); + if (descriptor_->is_repeated()) { + writer->WriteLine(","); + writer->Write(descriptor_->is_packed() ? "true" : "false"); + } + writer->Outdent(); + writer->WriteLine(");"); + writer->Outdent(); + } + else if (descriptor_->is_repeated()) + { + writer->WriteLine( + "$0$.$1$ = pb::GeneratedRepeatExtension<$2$>.CreateInstance($0$.Descriptor.Extensions[$3$]);", + scope_, property_name(), type_name(), SimpleItoa(descriptor_->index())); + } + else + { + writer->WriteLine( + "$0$.$1$ = pb::GeneratedSingleExtension<$2$>.CreateInstance($0$.Descriptor.Extensions[$3$]);", + scope_, property_name(), type_name(), SimpleItoa(descriptor_->index())); + } +} + +void ExtensionGenerator::GenerateExtensionRegistrationCode(Writer* writer) { + writer->WriteLine("registry.Add($0$.$1$);", scope_, property_name()); +} + +void ExtensionGenerator::WriteHash(Writer* writer) { +} + +void ExtensionGenerator::WriteEquals(Writer* writer) { +} + +void ExtensionGenerator::WriteToString(Writer* writer) { +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.h b/src/google/protobuf/compiler/csharp/csharp_extension.h new file mode 100644 index 00000000..203f6e5e --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_extension.h @@ -0,0 +1,80 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class ExtensionGenerator : public FieldGeneratorBase { + public: + ExtensionGenerator(const FieldDescriptor* descriptor); + ~ExtensionGenerator(); + + void GenerateStaticVariableInitializers(Writer* writer); + void GenerateExtensionRegistrationCode(Writer* writer); + void Generate(Writer* writer); + + virtual void WriteHash(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + + virtual void GenerateMembers(Writer* writer) {}; + virtual void GenerateBuilderMembers(Writer* writer) {}; + virtual void GenerateMergingCode(Writer* writer) {}; + virtual void GenerateBuildingCode(Writer* writer) {}; + virtual void GenerateParsingCode(Writer* writer) {}; + virtual void GenerateSerializationCode(Writer* writer) {}; + virtual void GenerateSerializedSizeCode(Writer* writer) {}; + + private: + std::string scope_; + std::string extends_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc new file mode 100644 index 00000000..48af999c --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -0,0 +1,394 @@ +// 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using google::protobuf::internal::scoped_ptr; + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, + int fieldOrdinal) + : SourceGeneratorBase(descriptor->file()), + descriptor_(descriptor), + fieldOrdinal_(fieldOrdinal) { +} + +FieldGeneratorBase::~FieldGeneratorBase() { +} + +void FieldGeneratorBase::AddDeprecatedFlag(Writer* writer) { + // TODO(jtattermusch): + //if (IsObsolete) + //{ + // writer.WriteLine("[global::System.ObsoleteAttribute()]"); + //} +} + +void FieldGeneratorBase::AddNullCheck(Writer* writer) { + AddNullCheck(writer, "value"); +} + +void FieldGeneratorBase::AddNullCheck(Writer* writer, const std::string& name) { + if (is_nullable_type()) { + writer->WriteLine(" pb::ThrowHelper.ThrowIfNull($0$, \"$0$\");", name); + } +} + +void FieldGeneratorBase::AddPublicMemberAttributes(Writer* writer) { + AddDeprecatedFlag(writer); + AddClsComplianceCheck(writer); +} + +void FieldGeneratorBase::AddClsComplianceCheck(Writer* writer) { + if (!is_cls_compliant() && descriptor_->file()->options().csharp_cls_compliance()) { + writer->WriteLine("[global::System.CLSCompliant(false)]"); + } +} + +std::string FieldGeneratorBase::property_name() { + return GetPropertyName(descriptor_); +} + +std::string FieldGeneratorBase::name() { + return UnderscoresToCamelCase(GetFieldName(descriptor_), false); +} + +std::string FieldGeneratorBase::type_name() { + switch (descriptor_->type()) { + case FieldDescriptor::TYPE_ENUM: + return GetClassName(descriptor_->enum_type()); + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_GROUP: + return GetClassName(descriptor_->message_type()); + case FieldDescriptor::TYPE_DOUBLE: + return "double"; + case FieldDescriptor::TYPE_FLOAT: + return "float"; + case FieldDescriptor::TYPE_INT64: + return "long"; + case FieldDescriptor::TYPE_UINT64: + return "ulong"; + case FieldDescriptor::TYPE_INT32: + return "int"; + case FieldDescriptor::TYPE_FIXED64: + return "ulong"; + case FieldDescriptor::TYPE_FIXED32: + return "uint"; + case FieldDescriptor::TYPE_BOOL: + return "bool"; + case FieldDescriptor::TYPE_STRING: + return "string"; + case FieldDescriptor::TYPE_BYTES: + return "pb::ByteString"; + case FieldDescriptor::TYPE_UINT32: + return "uint"; + case FieldDescriptor::TYPE_SFIXED32: + return "int"; + case FieldDescriptor::TYPE_SFIXED64: + return "long"; + case FieldDescriptor::TYPE_SINT32: + return "int"; + case FieldDescriptor::TYPE_SINT64: + return "long"; + default: + GOOGLE_LOG(FATAL)<< "Unknown field type."; + return ""; + } +} + +bool FieldGeneratorBase::has_default_value() { + switch (descriptor_->type()) { + case FieldDescriptor::TYPE_ENUM: + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_GROUP: + return true; + case FieldDescriptor::TYPE_DOUBLE: + return descriptor_->default_value_double() != 0.0; + case FieldDescriptor::TYPE_FLOAT: + return descriptor_->default_value_float() != 0.0; + case FieldDescriptor::TYPE_INT64: + return descriptor_->default_value_int64() != 0L; + case FieldDescriptor::TYPE_UINT64: + return descriptor_->default_value_uint64() != 0L; + case FieldDescriptor::TYPE_INT32: + return descriptor_->default_value_int32() != 0; + case FieldDescriptor::TYPE_FIXED64: + return descriptor_->default_value_uint64() != 0L; + case FieldDescriptor::TYPE_FIXED32: + return descriptor_->default_value_uint32() != 0; + case FieldDescriptor::TYPE_BOOL: + return descriptor_->default_value_bool(); + case FieldDescriptor::TYPE_STRING: + return true; + case FieldDescriptor::TYPE_BYTES: + return true; + case FieldDescriptor::TYPE_UINT32: + return descriptor_->default_value_uint32() != 0; + case FieldDescriptor::TYPE_SFIXED32: + return descriptor_->default_value_int32() != 0; + case FieldDescriptor::TYPE_SFIXED64: + return descriptor_->default_value_int64() != 0L; + case FieldDescriptor::TYPE_SINT32: + return descriptor_->default_value_int32() != 0; + case FieldDescriptor::TYPE_SINT64: + return descriptor_->default_value_int64() != 0L; + default: + GOOGLE_LOG(FATAL)<< "Unknown field type."; + return true; + } +} + +bool FieldGeneratorBase::is_nullable_type() { + switch (descriptor_->type()) { + case FieldDescriptor::TYPE_ENUM: + case FieldDescriptor::TYPE_DOUBLE: + case FieldDescriptor::TYPE_FLOAT: + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_UINT64: + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_BOOL: + case FieldDescriptor::TYPE_UINT32: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_SFIXED64: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SINT64: + return false; + + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_STRING: + case FieldDescriptor::TYPE_BYTES: + return true; + + default: + GOOGLE_LOG(FATAL)<< "Unknown field type."; + return true; + } +} + +bool FieldGeneratorBase::is_cls_compliant() { + CSharpType type = GetCSharpType(descriptor_->type()); + return (type != CSHARPTYPE_UINT32) && (type != CSHARPTYPE_UINT64) + && (UnderscoresToPascalCase(name()).substr(0, 1) != "_"); +} + +inline bool IsNaN(double value) { + // NaN is never equal to anything, even itself. + return value != value; +} + +bool AllPrintableAscii(const std::string& text) { + for(int i = 0; i < text.size(); i++) { + if (text[i] < 0x20 || text[i] > 0x7e) { + return false; + } + } + return true; +} + +std::string FieldGeneratorBase::GetStringDefaultValueInternal() { + if (!descriptor_->has_default_value()) { + return "\"\""; + } + if (AllPrintableAscii(descriptor_->default_value_string())) { + // All chars are ASCII and printable. In this case we only + // need to escape quotes and backslashes. + std::string temp = descriptor_->default_value_string(); + temp = StringReplace(temp, "\\", "\\\\", true); + temp = StringReplace(temp, "'", "\\'", true); + temp = StringReplace(temp, "\"", "\\\"", true); + return "\"" + temp + "\""; + } + if (use_lite_runtime()) { + return "pb::ByteString.FromBase64(\"" + + StringToBase64(descriptor_->default_value_string()) + + "\").ToStringUtf8()"; + } + return "(string) " + GetClassName(descriptor_->containing_type()) + + ".Descriptor.Fields[" + SimpleItoa(descriptor_->index()) + + "].DefaultValue"; +} + +std::string FieldGeneratorBase::GetBytesDefaultValueInternal() { + if (!descriptor_->has_default_value()) { + return "pb::ByteString.Empty"; + } + if (use_lite_runtime()) { + return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor_->default_value_string()) + "\")"; + } + return "(pb::ByteString) "+ GetClassName(descriptor_->containing_type()) + + ".Descriptor.Fields[" + SimpleItoa(descriptor_->index()) + "].DefaultValue"; +} + +std::string FieldGeneratorBase::default_value() { + switch (descriptor_->type()) { + case FieldDescriptor::TYPE_ENUM: + return type_name() + "." + descriptor_->default_value_enum()->name(); + case FieldDescriptor::TYPE_MESSAGE: + case FieldDescriptor::TYPE_GROUP: + return type_name() + ".DefaultInstance"; + case FieldDescriptor::TYPE_DOUBLE: { + double value = descriptor_->default_value_double(); + if (value == numeric_limits::infinity()) { + return "double.PositiveInfinity"; + } else if (value == -numeric_limits::infinity()) { + return "double.NegativeInfinity"; + } else if (IsNaN(value)) { + return "double.NaN"; + } + return SimpleDtoa(value) + "D"; + } + case FieldDescriptor::TYPE_FLOAT: { + float value = descriptor_->default_value_float(); + if (value == numeric_limits::infinity()) { + return "float.PositiveInfinity"; + } else if (value == -numeric_limits::infinity()) { + return "float.NegativeInfinity"; + } else if (IsNaN(value)) { + return "float.NaN"; + } + return SimpleFtoa(value) + "F"; + } + case FieldDescriptor::TYPE_INT64: + return SimpleItoa(descriptor_->default_value_int64()) + "L"; + case FieldDescriptor::TYPE_UINT64: + return SimpleItoa(descriptor_->default_value_uint64()) + "UL"; + case FieldDescriptor::TYPE_INT32: + return SimpleItoa(descriptor_->default_value_int32()); + case FieldDescriptor::TYPE_FIXED64: + return SimpleItoa(descriptor_->default_value_uint64()) + "UL"; + case FieldDescriptor::TYPE_FIXED32: + return SimpleItoa(descriptor_->default_value_uint32()); + case FieldDescriptor::TYPE_BOOL: + if (descriptor_->default_value_bool()) { + return "true"; + } else { + return "false"; + } + case FieldDescriptor::TYPE_STRING: + return GetStringDefaultValueInternal(); + case FieldDescriptor::TYPE_BYTES: + return GetBytesDefaultValueInternal(); + case FieldDescriptor::TYPE_UINT32: + return SimpleItoa(descriptor_->default_value_uint32()); + case FieldDescriptor::TYPE_SFIXED32: + return SimpleItoa(descriptor_->default_value_int32()); + case FieldDescriptor::TYPE_SFIXED64: + return SimpleItoa(descriptor_->default_value_int64()) + "L"; + case FieldDescriptor::TYPE_SINT32: + return SimpleItoa(descriptor_->default_value_int32()); + case FieldDescriptor::TYPE_SINT64: + return SimpleItoa(descriptor_->default_value_int64()) + "L"; + default: + GOOGLE_LOG(FATAL)<< "Unknown field type."; + return ""; + } +} + +std::string FieldGeneratorBase::number() { + return SimpleItoa(descriptor_->number()); +} + +std::string FieldGeneratorBase::message_or_group() { + return + (descriptor_->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; +} + +std::string FieldGeneratorBase::capitalized_type_name() { + switch (descriptor_->type()) { + case FieldDescriptor::TYPE_ENUM: + return "Enum"; + case FieldDescriptor::TYPE_MESSAGE: + return "Message"; + case FieldDescriptor::TYPE_GROUP: + return "Group"; + case FieldDescriptor::TYPE_DOUBLE: + return "Double"; + case FieldDescriptor::TYPE_FLOAT: + return "Float"; + case FieldDescriptor::TYPE_INT64: + return "Int64"; + case FieldDescriptor::TYPE_UINT64: + return "UInt64"; + case FieldDescriptor::TYPE_INT32: + return "Int32"; + case FieldDescriptor::TYPE_FIXED64: + return "Fixed64"; + case FieldDescriptor::TYPE_FIXED32: + return "Fixed32"; + case FieldDescriptor::TYPE_BOOL: + return "Bool"; + case FieldDescriptor::TYPE_STRING: + return "String"; + case FieldDescriptor::TYPE_BYTES: + return "Bytes"; + case FieldDescriptor::TYPE_UINT32: + return "UInt32"; + case FieldDescriptor::TYPE_SFIXED32: + return "SFixed32"; + case FieldDescriptor::TYPE_SFIXED64: + return "SFixed64"; + case FieldDescriptor::TYPE_SINT32: + return "SInt32"; + case FieldDescriptor::TYPE_SINT64: + return "SInt64"; + default: + GOOGLE_LOG(FATAL)<< "Unknown field type."; + return ""; + } +} + +std::string FieldGeneratorBase::field_ordinal() { + return SimpleItoa(fieldOrdinal_); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h new file mode 100644 index 00000000..4f3a7658 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -0,0 +1,100 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__ + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class FieldGeneratorBase : public SourceGeneratorBase { + public: + FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal); + ~FieldGeneratorBase(); + + virtual void GenerateMembers(Writer* writer) = 0; + virtual void GenerateBuilderMembers(Writer* writer) = 0; + virtual void GenerateMergingCode(Writer* writer) = 0; + virtual void GenerateBuildingCode(Writer* writer) = 0; + virtual void GenerateParsingCode(Writer* writer) = 0; + virtual void GenerateSerializationCode(Writer* writer) = 0; + virtual void GenerateSerializedSizeCode(Writer* writer) = 0; + + virtual void WriteHash(Writer* writer) = 0; + virtual void WriteEquals(Writer* writer) = 0; + virtual void WriteToString(Writer* writer) = 0; + + protected: + const FieldDescriptor* descriptor_; + const int fieldOrdinal_; + + void AddDeprecatedFlag(Writer* writer); + void AddNullCheck(Writer* writer); + void AddNullCheck(Writer* writer, const std::string& name); + + void AddPublicMemberAttributes(Writer* writer); + void AddClsComplianceCheck(Writer* writer); + + std::string property_name(); + std::string name(); + std::string type_name(); + bool has_default_value(); + bool is_nullable_type(); + bool is_cls_compliant(); + std::string default_value(); + std::string number(); + std::string message_or_group(); + std::string capitalized_type_name(); + std::string field_ordinal(); + + private: + std::string GetStringDefaultValueInternal(); + std::string GetBytesDefaultValueInternal(); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorBase); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc new file mode 100644 index 00000000..0cac22df --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -0,0 +1,82 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using google::protobuf::internal::scoped_ptr; + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +void GenerateFile(const google::protobuf::FileDescriptor* file, + Writer* writer) { + UmbrellaClassGenerator umbrellaGenerator(file); + umbrellaGenerator.Generate(writer); +} + +bool Generator::Generate( + const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const { + + // TODO: parse generator parameters... + + // TODO: file output file naming logic + std::string filename = + StripDotProto(file->name()) + ".cs"; + scoped_ptr output( + generator_context->Open(filename)); + io::Printer printer(output.get(), '$'); + Writer writer(&printer); + + GenerateFile(file, &writer); + + return true; +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h new file mode 100644 index 00000000..9b54e914 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_generator.h @@ -0,0 +1,58 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__ + +#include + +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class LIBPROTOC_EXPORT Generator + : public google::protobuf::compiler::CodeGenerator { + virtual bool Generate( + const FileDescriptor* file, + const string& parameter, + GeneratorContext* generator_context, + string* error) const; +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc new file mode 100644 index 00000000..7ef7df42 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc @@ -0,0 +1,54 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 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 + +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { +namespace { + +// TODO(jtattermusch): add some tests. + +} // namespace +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc new file mode 100644 index 00000000..49ae2c94 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -0,0 +1,383 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +CSharpType GetCSharpType(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32: + return CSHARPTYPE_INT32; + case FieldDescriptor::TYPE_INT64: + return CSHARPTYPE_INT64; + case FieldDescriptor::TYPE_UINT32: + return CSHARPTYPE_UINT32; + case FieldDescriptor::TYPE_UINT64: + return CSHARPTYPE_UINT32; + case FieldDescriptor::TYPE_SINT32: + return CSHARPTYPE_INT32; + case FieldDescriptor::TYPE_SINT64: + return CSHARPTYPE_INT64; + case FieldDescriptor::TYPE_FIXED32: + return CSHARPTYPE_UINT32; + case FieldDescriptor::TYPE_FIXED64: + return CSHARPTYPE_UINT64; + case FieldDescriptor::TYPE_SFIXED32: + return CSHARPTYPE_INT32; + case FieldDescriptor::TYPE_SFIXED64: + return CSHARPTYPE_INT64; + case FieldDescriptor::TYPE_FLOAT: + return CSHARPTYPE_FLOAT; + case FieldDescriptor::TYPE_DOUBLE: + return CSHARPTYPE_DOUBLE; + case FieldDescriptor::TYPE_BOOL: + return CSHARPTYPE_BOOL; + case FieldDescriptor::TYPE_ENUM: + return CSHARPTYPE_ENUM; + case FieldDescriptor::TYPE_STRING: + return CSHARPTYPE_STRING; + case FieldDescriptor::TYPE_BYTES: + return CSHARPTYPE_BYTESTRING; + case FieldDescriptor::TYPE_GROUP: + return CSHARPTYPE_MESSAGE; + case FieldDescriptor::TYPE_MESSAGE: + return CSHARPTYPE_MESSAGE; + + // No default because we want the compiler to complain if any new + // types are added. + } + GOOGLE_LOG(FATAL)<< "Can't get here."; + return (CSharpType) -1; +} + +std::string StripDotProto(const std::string& proto_file) { + int lastindex = proto_file.find_last_of("."); + return proto_file.substr(0, lastindex); +} + +std::string GetFileNamespace(const FileDescriptor* descriptor) { + if (descriptor->options().has_csharp_namespace()) { + return descriptor->options().csharp_namespace(); + } + return descriptor->package(); +} + +std::string GetUmbrellaClassNameInternal(const std::string& proto_file) { + int lastslash = proto_file.find_last_of("/"); + std::string base = proto_file.substr(lastslash + 1); + return UnderscoresToPascalCase(StripDotProto(base)); +} + +std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor) { + if (descriptor->options().has_csharp_umbrella_classname()) { + return descriptor->options().csharp_umbrella_namespace(); + } else { + return GetUmbrellaClassNameInternal(descriptor->name()); + } +} + +std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) { + if (!descriptor->options().csharp_nest_classes() + && !descriptor->options().has_csharp_umbrella_namespace()) { + bool collision = false; + // TODO(jtattermusch): detect collisions! +// foreach (IDescriptor d in MessageTypes) +// { +// collision |= d.Name == builder.UmbrellaClassname; +// } +// foreach (IDescriptor d in Services) +// { +// collision |= d.Name == builder.UmbrellaClassname; +// } +// foreach (IDescriptor d in EnumTypes) +// { +// collision |= d.Name == builder.UmbrellaClassname; +// } + if (collision) { + return "Proto"; + } + } + return ""; +} + +// TODO(jtattermusch): can we reuse a utility function? +std::string UnderscoresToCamelCase(const std::string& input, + bool cap_next_letter) { + string result; + // Note: I distrust ctype.h due to locales. + for (int i = 0; i < input.size(); i++) { + if ('a' <= input[i] && input[i] <= 'z') { + if (cap_next_letter) { + result += input[i] + ('A' - 'a'); + } else { + result += input[i]; + } + cap_next_letter = false; + } else if ('A' <= input[i] && input[i] <= 'Z') { + if (i == 0 && !cap_next_letter) { + // Force first letter to lower-case unless explicitly told to + // capitalize it. + result += input[i] + ('a' - 'A'); + } else { + // Capital letters after the first are left as-is. + result += input[i]; + } + cap_next_letter = false; + } else if ('0' <= input[i] && input[i] <= '9') { + result += input[i]; + cap_next_letter = true; + } else { + cap_next_letter = true; + } + } + // Add a trailing "_" if the name should be altered. + if (input[input.size() - 1] == '#') { + result += '_'; + } + return result; +} + +std::string UnderscoresToPascalCase(const std::string& input) { + return UnderscoresToCamelCase(input, true); +} + +std::string ToCSharpName(const std::string& name, const FileDescriptor* file) { + std::string result = GetFileNamespace(file); + if (file->options().csharp_nest_classes()) { + if (result != "") { + result += "."; + } + result += GetFileUmbrellaClassname(file); + } + if (result != "") { + result += '.'; + } + string classname; + if (file->package().empty()) { + classname = name; + } else { + // Strip the proto package from full_name since we've replaced it with + // the C# namespace. + classname = name.substr(file->package().size() + 1); + } + result += StringReplace(classname, ".", ".Types.", false); + return "global::" + result; +} + + + +std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor) { + std::string result = GetFileNamespace(descriptor); + if (!result.empty()) { + result += '.'; + } + result += GetQualifiedUmbrellaClassName(descriptor); + return "global::" + result; +} + +std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor) { + std::string umbrellaNamespace = GetFileUmbrellaNamespace(descriptor); + std::string umbrellaClassname = GetFileUmbrellaClassname(descriptor); + + std::string fullName = umbrellaClassname; + if (!descriptor->options().csharp_nest_classes() + && !umbrellaNamespace.empty()) { + fullName = umbrellaNamespace + "." + umbrellaClassname; + } + return fullName; +} + +std::string GetClassName(const Descriptor* descriptor) { + return ToCSharpName(descriptor->full_name(), descriptor->file()); +} + +std::string GetClassName(const EnumDescriptor* descriptor) { + return ToCSharpName(descriptor->full_name(), descriptor->file()); +} + +// Groups are hacky: The name of the field is just the lower-cased name +// of the group type. In C#, though, we would like to retain the original +// capitalization of the type name. +std::string GetFieldName(const FieldDescriptor* descriptor) { + if (descriptor->type() == FieldDescriptor::TYPE_GROUP) { + return descriptor->message_type()->name(); + } else { + return descriptor->name(); + } +} + +std::string GetFieldConstantName(const FieldDescriptor* field) { + return GetPropertyName(field) + "FieldNumber"; +} + +std::string GetPropertyName(const FieldDescriptor* descriptor) { + // TODO: fix this. + std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor)); + if (property_name == descriptor->containing_type()->name()) { + property_name += "_"; + } + return property_name; +} + +// TODO: c&p from Java protoc plugin +// For encodings with fixed sizes, returns that size in bytes. Otherwise +// returns -1. +int GetFixedSize(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32 : return -1; + case FieldDescriptor::TYPE_INT64 : return -1; + case FieldDescriptor::TYPE_UINT32 : return -1; + case FieldDescriptor::TYPE_UINT64 : return -1; + case FieldDescriptor::TYPE_SINT32 : return -1; + case FieldDescriptor::TYPE_SINT64 : return -1; + case FieldDescriptor::TYPE_FIXED32 : return internal::WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return internal::WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return internal::WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return internal::WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return internal::WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return internal::WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return internal::WireFormatLite::kBoolSize; + case FieldDescriptor::TYPE_ENUM : return -1; + + case FieldDescriptor::TYPE_STRING : return -1; + case FieldDescriptor::TYPE_BYTES : return -1; + case FieldDescriptor::TYPE_GROUP : return -1; + case FieldDescriptor::TYPE_MESSAGE : return -1; + + // No default because we want the compiler to complain if any new + // types are added. + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; +} + +static const char base64_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +std::string StringToBase64(const std::string& input) { + std::string result; + size_t remaining = input.size(); + const unsigned char *src = (const unsigned char*) input.c_str(); + while (remaining > 2) { + result += base64_chars[src[0] >> 2]; + result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)]; + result += base64_chars[((src[1] & 0xf) << 2) | (src[2] >> 6)]; + result += base64_chars[src[2] & 0x3f]; + remaining -= 3; + src += 3; + } + switch (remaining) { + case 2: + result += base64_chars[src[0] >> 2]; + result += base64_chars[((src[0] & 0x3) << 4) | (src[1] >> 4)]; + result += base64_chars[(src[1] & 0xf) << 2]; + result += '='; + src += 2; + break; + case 1: + result += base64_chars[src[0] >> 2]; + result += base64_chars[((src[0] & 0x3) << 4)]; + result += '='; + result += '='; + src += 1; + break; + } + return result; +} + +std::string FileDescriptorToBase64(const FileDescriptor* descriptor) { + std::string fdp_bytes; + FileDescriptorProto fdp; + descriptor->CopyTo(&fdp); + fdp.SerializeToString(&fdp_bytes); + return StringToBase64(fdp_bytes); +} + +FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) { + switch (descriptor->type()) { + case FieldDescriptor::TYPE_GROUP: + case FieldDescriptor::TYPE_MESSAGE: + if (descriptor->is_repeated()) { + return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal); + } else { + return new MessageFieldGenerator(descriptor, fieldOrdinal); + } + case FieldDescriptor::TYPE_ENUM: + if (descriptor->is_repeated()) { + return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal); + } else { + return new EnumFieldGenerator(descriptor, fieldOrdinal); + } + default: + if (descriptor->is_repeated()) { + return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal); + } else { + return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); + } + } +} + +bool HasRequiredFields(const Descriptor* descriptor) { + // TODO(jtattermusch): implement this. + return true; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h new file mode 100644 index 00000000..8fdd214e --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -0,0 +1,108 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class FieldGeneratorBase; + +// TODO: start using this enum. +enum CSharpType { + CSHARPTYPE_INT32 = 1, + CSHARPTYPE_INT64 = 2, + CSHARPTYPE_UINT32 = 3, + CSHARPTYPE_UINT64 = 4, + CSHARPTYPE_FLOAT = 5, + CSHARPTYPE_DOUBLE = 6, + CSHARPTYPE_BOOL = 7, + CSHARPTYPE_STRING = 8, + CSHARPTYPE_BYTESTRING = 9, + CSHARPTYPE_MESSAGE = 10, + CSHARPTYPE_ENUM = 11, + MAX_CSHARPTYPE = 11 +}; + +// Converts field type to corresponding C# type. +CSharpType GetCSharpType(FieldDescriptor::Type type); + +std::string StripDotProto(const std::string& proto_file); + +std::string GetFileNamespace(const FileDescriptor* descriptor); +std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor); +std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor); + +std::string GetFullUmbrellaClassName(const FileDescriptor* descriptor); + +std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor); + +std::string GetClassName(const Descriptor* descriptor); +std::string GetClassName(const EnumDescriptor* descriptor); + +std::string GetFieldName(const FieldDescriptor* descriptor); + +std::string GetFieldConstantName(const FieldDescriptor* field); + +std::string GetPropertyName(const FieldDescriptor* descriptor); + +int GetFixedSize(FieldDescriptor::Type type); + +std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter); + +std::string UnderscoresToPascalCase(const std::string& input); + +// TODO(jtattermusch): perhaps we could move this to strutil +std::string StringToBase64(const std::string& input); + +std::string FileDescriptorToBase64(const FileDescriptor* descriptor); + +FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + +bool HasRequiredFields(const Descriptor* descriptor); + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__ diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc new file mode 100644 index 00000000..2df3bd2d --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -0,0 +1,900 @@ +// 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using google::protobuf::internal::scoped_ptr; + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +bool CompareFieldNumbers(const FieldDescriptor* d1, const FieldDescriptor* d2) { + return d1->number() < d2->number(); +} + +MessageGenerator::MessageGenerator(const Descriptor* descriptor) + : SourceGeneratorBase(descriptor->file()), + descriptor_(descriptor) { + + // sorted field names + for (int i = 0; i < descriptor_->field_count(); i++) { + field_names_.push_back(descriptor_->field(i)->name()); + } + std::sort(field_names_.begin(), field_names_.end()); + + // fields by number + for (int i = 0; i < descriptor_->field_count(); i++) { + fields_by_number_.push_back(descriptor_->field(i)); + } + std::sort(fields_by_number_.begin(), fields_by_number_.end(), + CompareFieldNumbers); +} + +MessageGenerator::~MessageGenerator() { +} + +std::string MessageGenerator::class_name() { + // TODO: check correctness. + return descriptor_->name(); +} + +std::string MessageGenerator::full_class_name() { + return GetClassName(descriptor_); +} + +const std::vector& MessageGenerator::field_names() { + return field_names_; +} + +const std::vector& MessageGenerator::fields_by_number() { + return fields_by_number_; +} + +/// Get an identifier that uniquely identifies this type within the file. +/// This is used to declare static variables related to this type at the +/// outermost file scope. +std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) { + std::string result = descriptor->full_name(); + std::replace(result.begin(), result.end(), '.', '_'); + return "static_" + result; +} + +void MessageGenerator::GenerateStaticVariables(Writer* writer) { + // Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is + // used in the construction of descriptors, we have a tricky bootstrapping + // problem. To help control static initialization order, we make sure all + // descriptors and other static data that depends on them are members of + // the proto-descriptor class. This way, they will be initialized in + // a deterministic order. + + std::string identifier = GetUniqueFileScopeIdentifier(descriptor_); + + if (!use_lite_runtime()) { + // The descriptor for this type. + std::string access = + descriptor_->file()->options().csharp_nest_classes() ? + "private" : "internal"; + writer->WriteLine( + "$0$ static pbd::MessageDescriptor internal__$1$__Descriptor;", access, + identifier); + writer->WriteLine( + "$0$ static pb::FieldAccess.FieldAccessorTable<$1$, $1$.Builder> internal__$2$__FieldAccessorTable;", + access, full_class_name(), identifier); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.GenerateStaticVariables(writer); + } +} + +void MessageGenerator::GenerateStaticVariableInitializers(Writer* writer) { + std::string identifier = GetUniqueFileScopeIdentifier(descriptor_); + + if (!use_lite_runtime()) { + writer->Write("internal__$0$__Descriptor = ", identifier); + + if (!descriptor_->containing_type()) { + writer->WriteLine("Descriptor.MessageTypes[$0$];", + SimpleItoa(descriptor_->index())); + } else { + writer->WriteLine( + "internal__$0$__Descriptor.NestedTypes[$1$];", + GetUniqueFileScopeIdentifier(descriptor_->containing_type()), + SimpleItoa(descriptor_->index())); + } + + writer->WriteLine("internal__$0$__FieldAccessorTable = ", identifier); + writer->WriteLine( + " new pb::FieldAccess.FieldAccessorTable<$1$, $1$.Builder>(internal__$0$__Descriptor,", + identifier, full_class_name()); + writer->Write(" new string[] { "); + for (int i = 0; i < descriptor_->field_count(); i++) { + writer->Write("\"$0$\", ", GetPropertyName(descriptor_->field(i))); + } + writer->WriteLine("});"); + } + + // Generate static member initializers for all nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.GenerateStaticVariableInitializers(writer); + } + + for (int i = 0; i < descriptor_->extension_count(); i++) { + ExtensionGenerator extensionGenerator(descriptor_->extension(i)); + extensionGenerator.GenerateStaticVariableInitializers(writer); + } +} + +void MessageGenerator::Generate(Writer* writer) { + if (descriptor_->file()->options().csharp_add_serializable()) { + writer->WriteLine("[global::System.SerializableAttribute()]"); + } + writer->WriteLine( + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); + WriteGeneratedCodeAttributes(writer); + writer->WriteLine( + "$0$ sealed partial class $1$ : pb::$2$Message$3$<$1$, $1$.Builder> {", + class_access_level(), class_name(), + descriptor_->extension_range_count() > 0 ? "Extendable" : "Generated", + runtime_suffix()); + writer->Indent(); + if (descriptor_->file()->options().csharp_generate_private_ctor()) { + writer->WriteLine("private $0$() { }", class_name()); + } + // Must call MakeReadOnly() to make sure all lists are made read-only + writer->WriteLine( + "private static readonly $0$ defaultInstance = new $0$().MakeReadOnly();", + class_name()); + + if (optimize_speed()) { + writer->WriteLine( + "private static readonly string[] _$0$FieldNames = new string[] { $2$$1$$2$ };", + UnderscoresToCamelCase(class_name(), false), + JoinStrings(field_names(), "\", \""), + field_names().size() > 0 ? "\"" : ""); + std::vector tags; + for (int i = 0; i < field_names().size(); i++) { + uint32 tag = internal::WireFormat::MakeTag( + descriptor_->FindFieldByName(field_names()[i])); + tags.push_back(SimpleItoa(tag)); + } + writer->WriteLine( + "private static readonly uint[] _$0$FieldTags = new uint[] { $1$ };", + UnderscoresToCamelCase(class_name(), false), JoinStrings(tags, ", ")); + } + writer->WriteLine("public static $0$ DefaultInstance {", class_name()); + writer->WriteLine(" get { return defaultInstance; }"); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine("public override $0$ DefaultInstanceForType {", + class_name()); + writer->WriteLine(" get { return DefaultInstance; }"); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine("protected override $0$ ThisMessage {", class_name()); + writer->WriteLine(" get { return this; }"); + writer->WriteLine("}"); + writer->WriteLine(); + if (!use_lite_runtime()) { + writer->WriteLine("public static pbd::MessageDescriptor Descriptor {"); + writer->WriteLine(" get { return $0$.internal__$1$__Descriptor; }", + GetFullUmbrellaClassName(descriptor_->file()), + GetUniqueFileScopeIdentifier(descriptor_)); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine( + "protected override pb::FieldAccess.FieldAccessorTable<$0$, $0$.Builder> InternalFieldAccessors {", + class_name()); + writer->WriteLine(" get { return $0$.internal__$1$__FieldAccessorTable; }", + GetFullUmbrellaClassName(descriptor_->file()), + GetUniqueFileScopeIdentifier(descriptor_)); + writer->WriteLine("}"); + writer->WriteLine(); + } + + // Extensions don't need to go in an extra nested type + for (int i = 0; i < descriptor_->extension_count(); i++) { + ExtensionGenerator extensionGenerator(descriptor_->extension(i)); + extensionGenerator.Generate(writer); + } + + if (descriptor_->enum_type_count() + descriptor_->nested_type_count() > 0) { + writer->WriteLine("#region Nested types"); + writer->WriteLine( + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); + WriteGeneratedCodeAttributes(writer); + writer->WriteLine("public static partial class Types {"); + writer->Indent(); + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + EnumGenerator enumGenerator(descriptor_->enum_type(i)); + enumGenerator.Generate(writer); + } + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.Generate(writer); + } + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine("#endregion"); + writer->WriteLine(); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + // TODO(jtattermusch): same code for cls compliance is in csharp_extension + if (descriptor_->file()->options().csharp_cls_compliance() + && GetFieldConstantName(fieldDescriptor)[0] == '_') { + writer->WriteLine("[global::System.CLSCompliant(false)]"); + } + + // Rats: we lose the debug comment here :( + writer->WriteLine("public const int $0$ = $1$;", + GetFieldConstantName(fieldDescriptor), + SimpleItoa(fieldDescriptor->number())); + scoped_ptr generator( + CreateFieldGeneratorInternal(fieldDescriptor)); + generator->GenerateMembers(writer); + writer->WriteLine(); + } + + if (optimize_speed()) { + GenerateIsInitialized(writer); + GenerateMessageSerializationMethods(writer); + } + if (use_lite_runtime()) { + GenerateLiteRuntimeMethods(writer); + } + + GenerateParseFromMethods(writer); + GenerateBuilder(writer); + + // Force the static initialization code for the file to run, since it may + // initialize static variables declared in this class. + writer->WriteLine("static $0$() {", class_name()); + // We call object.ReferenceEquals() just to make it a valid statement on its own. + // Another option would be GetType(), but that causes problems in DescriptorProtoFile, + // where the bootstrapping is somewhat recursive - type initializers call + // each other, effectively. We temporarily see Descriptor as null. + writer->WriteLine(" object.ReferenceEquals($0$.Descriptor, null);", + GetFullUmbrellaClassName(descriptor_->file())); + writer->WriteLine("}"); + + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + +} + +void MessageGenerator::GenerateLiteRuntimeMethods(Writer* writer) { + bool callbase = descriptor_->extension_range_count() > 0; + writer->WriteLine("#region Lite runtime methods"); + writer->WriteLine("public override int GetHashCode() {"); + writer->Indent(); + writer->WriteLine("int hash = GetType().GetHashCode();"); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteHash(writer); + } + if (callbase) { + writer->WriteLine("hash ^= base.GetHashCode();"); + } + writer->WriteLine("return hash;"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + + writer->WriteLine("public override bool Equals(object obj) {"); + writer->Indent(); + writer->WriteLine("$0$ other = obj as $0$;", class_name()); + writer->WriteLine("if (other == null) return false;"); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteEquals(writer); + } + if (callbase) { + writer->WriteLine("if (!base.Equals(other)) return false;"); + } + writer->WriteLine("return true;"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + + writer->WriteLine( + "public override void PrintTo(global::System.IO.TextWriter writer) {"); + writer->Indent(); + + for (int i = 0; i < fields_by_number().size(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(fields_by_number()[i])); + generator->WriteToString(writer); + } + + if (callbase) { + writer->WriteLine("base.PrintTo(writer);"); + } + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine("#endregion"); + writer->WriteLine(); +} + +bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1, + const Descriptor::ExtensionRange* r2) { + return r1->start < r2->start; +} + +void MessageGenerator::GenerateMessageSerializationMethods(Writer* writer) { + std::vector extension_ranges_sorted; + for (int i = 0; i < descriptor_->extension_range_count(); i++) { + extension_ranges_sorted.push_back(descriptor_->extension_range(i)); + } + std::sort(extension_ranges_sorted.begin(), extension_ranges_sorted.end(), + CompareExtensionRangesStart); + + writer->WriteLine( + "public override void WriteTo(pb::ICodedOutputStream output) {"); + writer->Indent(); + // Make sure we've computed the serialized length, so that packed fields are generated correctly. + writer->WriteLine("int size = SerializedSize;"); + writer->WriteLine("string[] field_names = _$0$FieldNames;", + UnderscoresToCamelCase(class_name(), false)); + if (descriptor_->extension_range_count()) { + writer->WriteLine( + "pb::ExtendableMessage$1$<$0$, $0$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);", + class_name(), runtime_suffix()); + } + + // Merge the fields and the extension ranges, both sorted by field number. + for (int i = 0, j = 0; + i < fields_by_number().size() || j < extension_ranges_sorted.size();) { + if (i == fields_by_number().size()) { + GenerateSerializeOneExtensionRange(writer, extension_ranges_sorted[j++]); + } else if (j == extension_ranges_sorted.size()) { + GenerateSerializeOneField(writer, fields_by_number()[i++]); + } else if (fields_by_number()[i]->number() + < extension_ranges_sorted[j]->start) { + GenerateSerializeOneField(writer, fields_by_number()[i++]); + } else { + GenerateSerializeOneExtensionRange(writer, extension_ranges_sorted[j++]); + } + } + + if (!use_lite_runtime()) { + if (descriptor_->options().message_set_wire_format()) + { + writer->WriteLine("UnknownFields.WriteAsMessageSetTo(output);"); + } else { + writer->WriteLine("UnknownFields.WriteTo(output);"); + } + } + + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine("private int memoizedSerializedSize = -1;"); + writer->WriteLine("public override int SerializedSize {"); + writer->Indent(); + writer->WriteLine("get {"); + writer->Indent(); + writer->WriteLine("int size = memoizedSerializedSize;"); + writer->WriteLine("if (size != -1) return size;"); + writer->WriteLine(); + writer->WriteLine("size = 0;"); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateSerializedSizeCode(writer); + } + if (descriptor_->extension_range_count() > 0) { + writer->WriteLine("size += ExtensionsSerializedSize;"); + } + + if (!use_lite_runtime()) { + if (descriptor_->options().message_set_wire_format()) { + writer->WriteLine("size += UnknownFields.SerializedSizeAsMessageSet;"); + } else { + writer->WriteLine("size += UnknownFields.SerializedSize;"); + } + } + writer->WriteLine("memoizedSerializedSize = size;"); + writer->WriteLine("return size;"); + writer->Outdent(); + writer->WriteLine("}"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); +} + +void MessageGenerator::GenerateSerializeOneField( + Writer* writer, const FieldDescriptor* fieldDescriptor) { + scoped_ptr generator( + CreateFieldGeneratorInternal(fieldDescriptor)); + generator->GenerateSerializationCode(writer); +} + +void MessageGenerator::GenerateSerializeOneExtensionRange( + Writer* writer, const Descriptor::ExtensionRange* extensionRange) { + writer->WriteLine("extensionWriter.WriteUntil($0$, output);", + SimpleItoa(extensionRange->end)); +} + +void MessageGenerator::GenerateParseFromMethods(Writer* writer) { + // Note: These are separate from GenerateMessageSerializationMethods() + // because they need to be generated even for messages that are optimized + // for code size. + + writer->WriteLine("public static $0$ ParseFrom(pb::ByteString data) {", + class_name()); + writer->WriteLine( + " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine( + "public static $0$ ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {", + class_name()); + writer->WriteLine( + " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine("public static $0$ ParseFrom(byte[] data) {", class_name()); + writer->WriteLine( + " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine( + "public static $0$ ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {", + class_name()); + writer->WriteLine( + " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine( + "public static $0$ ParseFrom(global::System.IO.Stream input) {", + class_name()); + writer->WriteLine( + " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine( + "public static $0$ ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {", + class_name()); + writer->WriteLine( + " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine( + "public static $0$ ParseDelimitedFrom(global::System.IO.Stream input) {", + class_name()); + writer->WriteLine( + " return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine( + "public static $0$ ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {", + class_name()); + writer->WriteLine( + " return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine( + "public static $0$ ParseFrom(pb::ICodedInputStream input) {", + class_name()); + writer->WriteLine( + " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();"); + writer->WriteLine("}"); + writer->WriteLine( + "public static $0$ ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {", + class_name()); + writer->WriteLine( + " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();"); + writer->WriteLine("}"); +} + +void MessageGenerator::GenerateBuilder(Writer* writer) { + writer->WriteLine("private $0$ MakeReadOnly() {", class_name()); + writer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateBuildingCode(writer); + } + writer->WriteLine("return this;"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + + writer->WriteLine( + "public static Builder CreateBuilder() { return new Builder(); }"); + writer->WriteLine( + "public override Builder ToBuilder() { return CreateBuilder(this); }"); + writer->WriteLine( + "public override Builder CreateBuilderForType() { return new Builder(); }"); + writer->WriteLine("public static Builder CreateBuilder($0$ prototype) {", + class_name()); + writer->WriteLine(" return new Builder(prototype);"); + writer->WriteLine("}"); + writer->WriteLine(); + if (descriptor_->file()->options().csharp_add_serializable()) { + writer->WriteLine("[global::System.SerializableAttribute()]"); + } + writer->WriteLine( + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); + WriteGeneratedCodeAttributes(writer); + writer->WriteLine( + "$0$ sealed partial class Builder : pb::$2$Builder$3$<$1$, Builder> {", + class_access_level(), class_name(), + descriptor_->extension_range_count() > 0 ? "Extendable" : "Generated", + runtime_suffix()); + writer->Indent(); + writer->WriteLine("protected override Builder ThisBuilder {"); + writer->WriteLine(" get { return this; }"); + writer->WriteLine("}"); + GenerateCommonBuilderMethods(writer); + if (optimize_speed()) { + GenerateBuilderParsingMethods(writer); + } + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + writer->WriteLine(); + // No field comment :( + generator->GenerateBuilderMembers(writer); + } + writer->Outdent(); + writer->WriteLine("}"); +} + +void MessageGenerator::GenerateCommonBuilderMethods(Writer* writer) { + //default constructor + writer->WriteLine("public Builder() {"); + //Durring static initialization of message, DefaultInstance is expected to return null. + writer->WriteLine(" result = DefaultInstance;"); + writer->WriteLine(" resultIsReadOnly = true;"); + writer->WriteLine("}"); + //clone constructor + writer->WriteLine("internal Builder($0$ cloneFrom) {", class_name()); + writer->WriteLine(" result = cloneFrom;"); + writer->WriteLine(" resultIsReadOnly = true;"); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine("private bool resultIsReadOnly;"); + writer->WriteLine("private $0$ result;", class_name()); + writer->WriteLine(); + writer->WriteLine("private $0$ PrepareBuilder() {", class_name()); + writer->WriteLine(" if (resultIsReadOnly) {"); + writer->WriteLine(" $0$ original = result;", class_name()); + writer->WriteLine(" result = new $0$();", class_name()); + writer->WriteLine(" resultIsReadOnly = false;"); + writer->WriteLine(" MergeFrom(original);"); + writer->WriteLine(" }"); + writer->WriteLine(" return result;"); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine("public override bool IsInitialized {"); + writer->WriteLine(" get { return result.IsInitialized; }"); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine("protected override $0$ MessageBeingBuilt {", class_name()); + writer->WriteLine(" get { return PrepareBuilder(); }"); + writer->WriteLine("}"); + writer->WriteLine(); + //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break + writer->WriteLine("public override Builder Clear() {"); + writer->WriteLine(" result = DefaultInstance;"); + writer->WriteLine(" resultIsReadOnly = true;"); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine("public override Builder Clone() {"); + writer->WriteLine(" if (resultIsReadOnly) {"); + writer->WriteLine(" return new Builder(result);"); + writer->WriteLine(" } else {"); + writer->WriteLine(" return new Builder().MergeFrom(result);"); + writer->WriteLine(" }"); + writer->WriteLine("}"); + writer->WriteLine(); + if (!use_lite_runtime()) { + writer->WriteLine( + "public override pbd::MessageDescriptor DescriptorForType {"); + writer->WriteLine(" get { return $0$.Descriptor; }", full_class_name()); + writer->WriteLine("}"); + writer->WriteLine(); + } + writer->WriteLine("public override $0$ DefaultInstanceForType {", + class_name()); + writer->WriteLine(" get { return $0$.DefaultInstance; }", full_class_name()); + writer->WriteLine("}"); + writer->WriteLine(); + + writer->WriteLine("public override $0$ BuildPartial() {", class_name()); + writer->Indent(); + writer->WriteLine("if (resultIsReadOnly) {"); + writer->WriteLine(" return result;"); + writer->WriteLine("}"); + writer->WriteLine("resultIsReadOnly = true;"); + writer->WriteLine("return result.MakeReadOnly();"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + + if (optimize_speed()) { + writer->WriteLine( + "public override Builder MergeFrom(pb::IMessage$0$ other) {", + runtime_suffix()); + writer->WriteLine(" if (other is $0$) {", class_name()); + writer->WriteLine(" return MergeFrom(($0$) other);", class_name()); + writer->WriteLine(" } else {"); + writer->WriteLine(" base.MergeFrom(other);"); + writer->WriteLine(" return this;"); + writer->WriteLine(" }"); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine("public override Builder MergeFrom($0$ other) {", + class_name()); + // Optimization: If other is the default instance, we know none of its + // fields are set so we can skip the merge. + writer->Indent(); + writer->WriteLine("if (other == $0$.DefaultInstance) return this;", + full_class_name()); + writer->WriteLine("PrepareBuilder();"); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateMergingCode(writer); + } + // if message type has extensions + if (descriptor_->extension_range_count() > 0) { + writer->WriteLine(" this.MergeExtensionFields(other);"); + } + if (!use_lite_runtime()) { + writer->WriteLine("this.MergeUnknownFields(other.UnknownFields);"); + } + writer->WriteLine("return this;"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + } + +} + +void MessageGenerator::GenerateBuilderParsingMethods(Writer* writer) { + writer->WriteLine( + "public override Builder MergeFrom(pb::ICodedInputStream input) {"); + writer->WriteLine(" return MergeFrom(input, pb::ExtensionRegistry.Empty);"); + writer->WriteLine("}"); + writer->WriteLine(); + writer->WriteLine( + "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {"); + writer->Indent(); + writer->WriteLine("PrepareBuilder();"); + if (!use_lite_runtime()) { + writer->WriteLine("pb::UnknownFieldSet.Builder unknownFields = null;"); + } + writer->WriteLine("uint tag;"); + writer->WriteLine("string field_name;"); + writer->WriteLine("while (input.ReadTag(out tag, out field_name)) {"); + writer->Indent(); + writer->WriteLine("if(tag == 0 && field_name != null) {"); + writer->Indent(); + //if you change from StringComparer.Ordinal, the array sort in FieldNames { get; } must also change + writer->WriteLine( + "int field_ordinal = global::System.Array.BinarySearch(_$0$FieldNames, field_name, global::System.StringComparer.Ordinal);", + UnderscoresToCamelCase(class_name(), false)); + writer->WriteLine("if(field_ordinal >= 0)"); + writer->WriteLine(" tag = _$0$FieldTags[field_ordinal];", + UnderscoresToCamelCase(class_name(), false)); + writer->WriteLine("else {"); + if (!use_lite_runtime()) { + writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now + writer->WriteLine( + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); + writer->WriteLine(" }"); + } + writer->WriteLine( + " ParseUnknownField(input, $0$extensionRegistry, tag, field_name);", + use_lite_runtime() ? "" : "unknownFields, "); + writer->WriteLine(" continue;"); + writer->WriteLine("}"); + writer->Outdent(); + writer->WriteLine("}"); + + writer->WriteLine("switch (tag) {"); + writer->Indent(); + writer->WriteLine("case 0: {"); // 0 signals EOF / limit reached + writer->WriteLine(" throw pb::InvalidProtocolBufferException.InvalidTag();"); + writer->WriteLine("}"); + writer->WriteLine("default: {"); + writer->WriteLine(" if (pb::WireFormat.IsEndGroupTag(tag)) {"); + if (!use_lite_runtime()) { + writer->WriteLine(" if (unknownFields != null) {"); + writer->WriteLine(" this.UnknownFields = unknownFields.Build();"); + writer->WriteLine(" }"); + } + writer->WriteLine(" return this;"); // it's an endgroup tag + writer->WriteLine(" }"); + if (!use_lite_runtime()) { + writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now + writer->WriteLine( + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); + writer->WriteLine(" }"); + } + writer->WriteLine( + " ParseUnknownField(input, $0$extensionRegistry, tag, field_name);", + use_lite_runtime() ? "" : "unknownFields, "); + writer->WriteLine(" break;"); + writer->WriteLine("}"); + + for (int i = 0; i < fields_by_number().size(); i++) { + const FieldDescriptor* field = fields_by_number()[i]; + internal::WireFormatLite::WireType wt = + internal::WireFormat::WireTypeForFieldType(field->type()); + uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt); + if (field->is_repeated() + && (wt == internal::WireFormatLite::WIRETYPE_VARINT + || wt == internal::WireFormatLite::WIRETYPE_FIXED32 + || wt == internal::WireFormatLite::WIRETYPE_FIXED64)) { + writer->WriteLine( + "case $0$:", + SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); + } + + writer->WriteLine("case $0$: {", SimpleItoa(tag)); + writer->Indent(); + scoped_ptr generator( + CreateFieldGeneratorInternal(field)); + generator->GenerateParsingCode(writer); + writer->WriteLine("break;"); + writer->Outdent(); + writer->WriteLine("}"); + } + + writer->Outdent(); + writer->WriteLine("}"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + if (!use_lite_runtime()) { + writer->WriteLine("if (unknownFields != null) {"); + writer->WriteLine(" this.UnknownFields = unknownFields.Build();"); + writer->WriteLine("}"); + } + writer->WriteLine("return this;"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); +} + +void MessageGenerator::GenerateIsInitialized(Writer* writer) { + writer->WriteLine("public override bool IsInitialized {"); + writer->Indent(); + writer->WriteLine("get {"); + writer->Indent(); + + // Check that all required fields in this message are set. + // TODO(kenton): We can optimize this when we switch to putting all the + // "has" fields into a single bitfield. + for (int i = 0; i < descriptor_->field_count(); i++) { + if (descriptor_->field(i)->is_required()) { + writer->WriteLine("if (!has$0$) return false;", + GetPropertyName(descriptor_->field(i))); + } + } + + // Now check that all embedded messages are initialized. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + if (field->type() != FieldDescriptor::TYPE_MESSAGE || + !HasRequiredFields(field->message_type())) + { + continue; + } + // TODO(jtattermusch): shouldn't we use GetPropertyName here? + string propertyName = UnderscoresToPascalCase(GetFieldName(field)); + if (field->is_repeated()) + { + writer->WriteLine("foreach ($0$ element in $1$List) {", + GetClassName(field->message_type()), + propertyName); + writer->WriteLine(" if (!element.IsInitialized) return false;"); + writer->WriteLine("}"); + } + else if (field->is_optional()) + { + writer->WriteLine("if (Has$0$) {", propertyName); + writer->WriteLine(" if (!$0$.IsInitialized) return false;", propertyName); + writer->WriteLine("}"); + } + else + { + writer->WriteLine("if (!$0$.IsInitialized) return false;", propertyName); + } + } + + if (descriptor_->extension_range_count() > 0) { + writer->WriteLine("if (!ExtensionsAreInitialized) return false;"); + } + writer->WriteLine("return true;"); + writer->Outdent(); + writer->WriteLine("}"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); +} + +void MessageGenerator::GenerateExtensionRegistrationCode(Writer* writer) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + ExtensionGenerator extensionGenerator(descriptor_->extension(i)); + extensionGenerator.GenerateExtensionRegistrationCode(writer); + } + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.GenerateExtensionRegistrationCode(writer); + } +} + +int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) { + for (int i = 0; i < field_names().size(); i++) { + if (field_names()[i] == descriptor->name()) { + return i; + } + } + GOOGLE_LOG(DFATAL)<< "Could not find ordinal for field " << descriptor->name(); + return -1; +} + +FieldGeneratorBase* MessageGenerator::CreateFieldGeneratorInternal( + const FieldDescriptor* descriptor) { + return CreateFieldGenerator(descriptor, GetFieldOrdinal(descriptor)); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h new file mode 100644 index 00000000..b8d15df0 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -0,0 +1,98 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__ + +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; +class FieldGeneratorBase; + +class MessageGenerator : public SourceGeneratorBase { + public: + MessageGenerator(const Descriptor* descriptor); + ~MessageGenerator(); + + void GenerateStaticVariables(Writer* printer); + void GenerateStaticVariableInitializers(Writer* printer); + void GenerateExtensionRegistrationCode(Writer* printer); + void Generate(Writer* printer); + + private: + const Descriptor* descriptor_; + std::vector field_names_; + std::vector fields_by_number_; + + void GenerateLiteRuntimeMethods(Writer* writer); + void GenerateMessageSerializationMethods(Writer* writer); + void GenerateSerializeOneField(Writer* writer, + const FieldDescriptor* fieldDescriptor); + void GenerateSerializeOneExtensionRange( + Writer* writer, const Descriptor::ExtensionRange* extendsionRange); + void GenerateParseFromMethods(Writer* writer); + void GenerateBuilder(Writer* writer); + void GenerateCommonBuilderMethods(Writer* writer); + void GenerateBuilderParsingMethods(Writer* writer); + void GenerateIsInitialized(Writer* writer); + + int GetFieldOrdinal(const FieldDescriptor* descriptor); + FieldGeneratorBase* CreateFieldGeneratorInternal( + const FieldDescriptor* descriptor); + + std::string class_name(); + std::string full_class_name(); + + // field names sorted alphabetically + const std::vector& field_names(); + + // field descriptors sorted by number + const std::vector& fields_by_number(); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc new file mode 100644 index 00000000..10464c4b --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -0,0 +1,183 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { +} + +MessageFieldGenerator::~MessageFieldGenerator() { + +} + +void MessageFieldGenerator::GenerateMembers(Writer* writer) { + writer->WriteLine("private bool has$0$;", property_name()); + writer->WriteLine("private $0$ $1$_;", type_name(), name()); + AddDeprecatedFlag(writer); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return has$0$; }", property_name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return $0$_ ?? $1$; }", name(), default_value()); + writer->WriteLine("}"); +} + +void MessageFieldGenerator::GenerateBuilderMembers(Writer* writer) { + AddDeprecatedFlag(writer); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return result.has$0$; }", property_name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return result.$0$; }", property_name()); + writer->WriteLine(" set { Set$0$(value); }", property_name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), + type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.has$0$ = true;", property_name()); + writer->WriteLine(" result.$0$_ = value;", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Set$0$($1$.Builder builderForValue) {", + property_name(), type_name()); + AddNullCheck(writer, "builderForValue"); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.has$0$ = true;", property_name()); + writer->WriteLine(" result.$0$_ = builderForValue.Build();", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Merge$0$($1$ value) {", property_name(), + type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" if (result.has$0$ &&", property_name()); + writer->WriteLine(" result.$0$_ != $1$) {", name(), default_value()); + writer->WriteLine( + " result.$0$_ = $1$.CreateBuilder(result.$0$_).MergeFrom(value).BuildPartial();", + name(), type_name()); + writer->WriteLine(" } else {"); + writer->WriteLine(" result.$0$_ = value;", name()); + writer->WriteLine(" }"); + writer->WriteLine(" result.has$0$ = true;", property_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.has$0$ = false;", property_name()); + writer->WriteLine(" result.$0$_ = null;", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void MessageFieldGenerator::GenerateMergingCode(Writer* writer) { + writer->WriteLine("if (other.Has$0$) {", property_name()); + writer->WriteLine(" Merge$0$(other.$0$);", property_name()); + writer->WriteLine("}"); +} + +void MessageFieldGenerator::GenerateBuildingCode(Writer* writer) { + // Nothing to do for singular fields +} + +void MessageFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine("$0$.Builder subBuilder = $0$.CreateBuilder();", + type_name()); + writer->WriteLine("if (result.has$0$) {", property_name()); + writer->WriteLine(" subBuilder.MergeFrom($0$);", property_name()); + writer->WriteLine("}"); + + if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { + writer->WriteLine("input.ReadGroup($0$, subBuilder, extensionRegistry);", + number()); + } else { + writer->WriteLine("input.ReadMessage(subBuilder, extensionRegistry);"); + } + writer->WriteLine("$0$ = subBuilder.BuildPartial();", property_name()); +} + +void MessageFieldGenerator::GenerateSerializationCode(Writer* writer) { + writer->WriteLine("if (has$0$) {", property_name()); + writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", + message_or_group(), number(), property_name(), + field_ordinal()); + writer->WriteLine("}"); +} + +void MessageFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { + writer->WriteLine("if (has$0$) {", property_name()); + writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", + message_or_group(), number(), property_name()); + writer->WriteLine("}"); +} + +void MessageFieldGenerator::WriteHash(Writer* writer) { + writer->WriteLine("if (has$0$) hash ^= $1$_.GetHashCode();", property_name(), + name()); +} +void MessageFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine( + "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", + property_name(), name()); +} +void MessageFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$2$\", has$0$, $1$_, writer);", + property_name(), name(), GetFieldName(descriptor_)); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h new file mode 100644 index 00000000..48bf8be5 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -0,0 +1,73 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class MessageFieldGenerator : public FieldGeneratorBase { + public: + MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~MessageFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void GenerateMergingCode(Writer* writer); + virtual void GenerateBuildingCode(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateSerializationCode(Writer* writer); + virtual void GenerateSerializedSizeCode(Writer* writer); + + virtual void WriteHash(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc new file mode 100644 index 00000000..54287b41 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -0,0 +1,148 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +PrimitiveFieldGenerator::PrimitiveFieldGenerator( + const FieldDescriptor* descriptor, int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { +} + +PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { + +} + +void PrimitiveFieldGenerator::GenerateMembers(Writer* writer) { + writer->WriteLine("private bool has$0$;", property_name()); + writer->WriteLine("private $0$ $1$_$2$;", type_name(), name(), + has_default_value() ? " = " + default_value() : ""); + AddDeprecatedFlag(writer); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return has$0$; }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return $0$_; }", name()); + writer->WriteLine("}"); +} + +void PrimitiveFieldGenerator::GenerateBuilderMembers(Writer* writer) { + AddDeprecatedFlag(writer); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return result.has$0$; }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return result.$0$; }", property_name()); + writer->WriteLine(" set { Set$0$(value); }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), + type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.has$0$ = true;", property_name()); + writer->WriteLine(" result.$0$_ = value;", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.has$0$ = false;", property_name()); + writer->WriteLine(" result.$0$_ = $1$;", name(), default_value()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void PrimitiveFieldGenerator::GenerateMergingCode(Writer* writer) { + writer->WriteLine("if (other.Has$0$) {", property_name()); + writer->WriteLine(" $0$ = other.$0$;", property_name()); + writer->WriteLine("}"); +} + +void PrimitiveFieldGenerator::GenerateBuildingCode(Writer* writer) { + // Nothing to do here for primitive types +} + +void PrimitiveFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine("result.has$0$ = input.Read$1$(ref result.$2$_);", + property_name(), capitalized_type_name(), name()); +} + +void PrimitiveFieldGenerator::GenerateSerializationCode(Writer* writer) { + writer->WriteLine("if (has$0$) {", property_name()); + writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", + capitalized_type_name(), number(), property_name(), + field_ordinal()); + writer->WriteLine("}"); +} + +void PrimitiveFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { + writer->WriteLine("if (has$0$) {", property_name()); + writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", + capitalized_type_name(), number(), property_name()); + writer->WriteLine("}"); +} + +void PrimitiveFieldGenerator::WriteHash(Writer* writer) { + writer->WriteLine("if (has$0$) hash ^= $1$_.GetHashCode();", property_name(), + name()); +} +void PrimitiveFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine( + "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", + property_name(), name()); +} +void PrimitiveFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", has$1$, $2$_, writer);", + descriptor_->name(), property_name(), name()); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h new file mode 100644 index 00000000..fb27ab43 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -0,0 +1,73 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class PrimitiveFieldGenerator : public FieldGeneratorBase { + public: + PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~PrimitiveFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void GenerateMergingCode(Writer* writer); + virtual void GenerateBuildingCode(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateSerializationCode(Writer* writer); + virtual void GenerateSerializedSizeCode(Writer* writer); + + virtual void WriteHash(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc new file mode 100644 index 00000000..cc8745ae --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -0,0 +1,226 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( + const FieldDescriptor* descriptor, int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { +} + +RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { + +} + +void RepeatedEnumFieldGenerator::GenerateMembers(Writer* writer) { + if (descriptor_->is_packed() && optimize_speed()) { + writer->WriteLine("private int $0$MemoizedSerializedSize;", name()); + } + writer->WriteLine( + "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", + type_name(), name()); + AddDeprecatedFlag(writer); + writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), + property_name()); + writer->WriteLine(" get { return pbc::Lists.AsReadOnly($0$_); }", name()); + writer->WriteLine("}"); + + // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. + AddDeprecatedFlag(writer); + writer->WriteLine("public int $0$Count {", property_name()); + writer->WriteLine(" get { return $0$_.Count; }", name()); + writer->WriteLine("}"); + + AddDeprecatedFlag(writer); + writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), + property_name()); + writer->WriteLine(" return $0$_[index];", name()); + writer->WriteLine("}"); +} + +void RepeatedEnumFieldGenerator::GenerateBuilderMembers(Writer* writer) { + // Note: We can return the original list here, because we make it unmodifiable when we build + // We return it via IPopsicleList so that collection initializers work more pleasantly. + AddDeprecatedFlag(writer); + writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), + property_name()); + writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public int $0$Count {", property_name()); + writer->WriteLine(" get { return result.$0$Count; }", property_name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), + property_name()); + writer->WriteLine(" return result.Get$0$(index);", property_name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", + property_name(), type_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_[index] = value;", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), + type_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine( + "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", + property_name(), type_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Add(values);", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Clear();", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void RepeatedEnumFieldGenerator::GenerateMergingCode(Writer* writer) { + writer->WriteLine("if (other.$0$_.Count != 0) {", name()); + writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); + writer->WriteLine("}"); +} + +void RepeatedEnumFieldGenerator::GenerateBuildingCode(Writer* writer) { + writer->WriteLine("$0$_.MakeReadOnly();", name()); +} + +void RepeatedEnumFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine("scg::ICollection unknownItems;"); + writer->WriteLine( + "input.ReadEnumArray<$0$>(tag, field_name, result.$1$_, out unknownItems);", + type_name(), name()); + if (!use_lite_runtime()) { + writer->WriteLine("if (unknownItems != null) {"); + writer->WriteLine(" if (unknownFields == null) {"); + writer->WriteLine( + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); + writer->WriteLine(" }"); + writer->WriteLine(" foreach (object rawValue in unknownItems)"); + writer->WriteLine(" if (rawValue is int)"); + writer->WriteLine( + " unknownFields.MergeVarintField($0$, (ulong)(int)rawValue);", + number()); + writer->WriteLine("}"); + } +} + +void RepeatedEnumFieldGenerator::GenerateSerializationCode(Writer* writer) { + writer->WriteLine("if ($0$_.Count > 0) {", name()); + writer->Indent(); + if (descriptor_->is_packed()) { + writer->WriteLine( + "output.WritePackedEnumArray($0$, field_names[$2$], $1$MemoizedSerializedSize, $1$_);", + number(), name(), field_ordinal()); + } else { + writer->WriteLine("output.WriteEnumArray($0$, field_names[$2$], $1$_);", + number(), name(), field_ordinal()); + } + writer->Outdent(); + writer->WriteLine("}"); +} + +void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { + writer->WriteLine("{"); + writer->Indent(); + writer->WriteLine("int dataSize = 0;"); + writer->WriteLine("if ($0$_.Count > 0) {", name()); + writer->Indent(); + writer->WriteLine("foreach ($0$ element in $1$_) {", type_name(), name()); + writer->WriteLine( + " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);"); + writer->WriteLine("}"); + writer->WriteLine("size += dataSize;"); + int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + if (descriptor_->is_packed()) { + writer->WriteLine("size += $0$;", SimpleItoa(tagSize)); + writer->WriteLine( + "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);"); + } else { + writer->WriteLine("size += $0$ * $1$_.Count;", SimpleItoa(tagSize), name()); + } + writer->Outdent(); + writer->WriteLine("}"); + // cache the data size for packed fields. + if (descriptor_->is_packed()) { + writer->WriteLine("$0$MemoizedSerializedSize = dataSize;", name()); + } + writer->Outdent(); + writer->WriteLine("}"); +} + +void RepeatedEnumFieldGenerator::WriteHash(Writer* writer) { + writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); + writer->WriteLine(" hash ^= i.GetHashCode();"); +} + +void RepeatedEnumFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); + writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); + writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", + name()); +} + +void RepeatedEnumFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", descriptor_->name(), + name()); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h new file mode 100644 index 00000000..c872131c --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -0,0 +1,73 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class RepeatedEnumFieldGenerator : public FieldGeneratorBase { + public: + RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~RepeatedEnumFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void GenerateMergingCode(Writer* writer); + virtual void GenerateBuildingCode(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateSerializationCode(Writer* writer); + virtual void GenerateSerializedSizeCode(Writer* writer); + + virtual void WriteHash(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc new file mode 100644 index 00000000..2dfcd402 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -0,0 +1,201 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( + const FieldDescriptor* descriptor, int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { +} + +RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { + +} + +void RepeatedMessageFieldGenerator::GenerateMembers(Writer* writer) { + writer->WriteLine( + "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", + type_name(), name()); + AddDeprecatedFlag(writer); + writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), + property_name()); + writer->WriteLine(" get { return $0$_; }", name()); + writer->WriteLine("}"); + + // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. + AddDeprecatedFlag(writer); + writer->WriteLine("public int $0$Count {", property_name()); + writer->WriteLine(" get { return $0$_.Count; }", name()); + writer->WriteLine("}"); + + AddDeprecatedFlag(writer); + writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), + property_name()); + writer->WriteLine(" return $0$_[index];", name()); + writer->WriteLine("}"); +} + +void RepeatedMessageFieldGenerator::GenerateBuilderMembers(Writer* writer) { + // Note: We can return the original list here, because we make it unmodifiable when we build + // We return it via IPopsicleList so that collection initializers work more pleasantly. + AddDeprecatedFlag(writer); + writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), + property_name()); + writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public int $0$Count {", property_name()); + writer->WriteLine(" get { return result.$0$Count; }", property_name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), + property_name()); + writer->WriteLine(" return result.Get$0$(index);", property_name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", + property_name(), type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_[index] = value;", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + // Extra overload for builder (just on messages) + AddDeprecatedFlag(writer); + writer->WriteLine( + "public Builder Set$0$(int index, $1$.Builder builderForValue) {", + property_name(), type_name()); + AddNullCheck(writer, "builderForValue"); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_[index] = builderForValue.Build();", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), + type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + // Extra overload for builder (just on messages) + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Add$0$($1$.Builder builderForValue) {", + property_name(), type_name()); + AddNullCheck(writer, "builderForValue"); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Add(builderForValue.Build());", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine( + "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", + property_name(), type_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Add(values);", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Clear();", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void RepeatedMessageFieldGenerator::GenerateMergingCode(Writer* writer) { + writer->WriteLine("if (other.$0$_.Count != 0) {", name()); + writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); + writer->WriteLine("}"); +} + +void RepeatedMessageFieldGenerator::GenerateBuildingCode(Writer* writer) { + writer->WriteLine("$0$_.MakeReadOnly();", name()); +} + +void RepeatedMessageFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine( + "input.Read$0$Array(tag, field_name, result.$1$_, $2$.DefaultInstance, extensionRegistry);", + message_or_group(), name(), type_name()); +} + +void RepeatedMessageFieldGenerator::GenerateSerializationCode(Writer* writer) { + writer->WriteLine("if ($0$_.Count > 0) {", name()); + writer->Indent(); + writer->WriteLine("output.Write$0$Array($1$, field_names[$3$], $2$_);", + message_or_group(), number(), name(), field_ordinal()); + writer->Outdent(); + writer->WriteLine("}"); +} + +void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { + writer->WriteLine("foreach ($0$ element in $1$List) {", type_name(), + property_name()); + writer->WriteLine( + " size += pb::CodedOutputStream.Compute$0$Size($1$, element);", + message_or_group(), number()); + writer->WriteLine("}"); +} + +void RepeatedMessageFieldGenerator::WriteHash(Writer* writer) { + writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); + writer->WriteLine(" hash ^= i.GetHashCode();"); +} +void RepeatedMessageFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); + writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); + writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", + name()); +} +void RepeatedMessageFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", + GetFieldName(descriptor_), name()); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h new file mode 100644 index 00000000..104274cb --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -0,0 +1,73 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class RepeatedMessageFieldGenerator : public FieldGeneratorBase { + public: + RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~RepeatedMessageFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void GenerateMergingCode(Writer* writer); + virtual void GenerateBuildingCode(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateSerializationCode(Writer* writer); + virtual void GenerateSerializedSizeCode(Writer* writer); + + virtual void WriteHash(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc new file mode 100644 index 00000000..8b285468 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -0,0 +1,219 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( + const FieldDescriptor* descriptor, int fieldOrdinal) + : FieldGeneratorBase(descriptor, fieldOrdinal) { +} + +RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { + +} + +void RepeatedPrimitiveFieldGenerator::GenerateMembers(Writer* writer) { + if (descriptor_->is_packed() && optimize_speed()) { + writer->WriteLine("private int $0$MemoizedSerializedSize;", name()); + } + writer->WriteLine( + "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", + type_name(), name()); + AddPublicMemberAttributes(writer); + writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), + property_name()); + writer->WriteLine(" get { return pbc::Lists.AsReadOnly($0$_); }", name()); + writer->WriteLine("}"); + + // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. + AddDeprecatedFlag(writer); + writer->WriteLine("public int $0$Count {", property_name()); + writer->WriteLine(" get { return $0$_.Count; }", name()); + writer->WriteLine("}"); + + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), + property_name()); + writer->WriteLine(" return $0$_[index];", name()); + writer->WriteLine("}"); +} + +void RepeatedPrimitiveFieldGenerator::GenerateBuilderMembers(Writer* writer) { + // Note: We can return the original list here, because we make it unmodifiable when we build + // We return it via IPopsicleList so that collection initializers work more pleasantly. + AddPublicMemberAttributes(writer); + writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), + property_name()); + writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public int $0$Count {", property_name()); + writer->WriteLine(" get { return result.$0$Count; }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), + property_name()); + writer->WriteLine(" return result.Get$0$(index);", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", + property_name(), type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_[index] = value;", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), + type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine( + "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", + property_name(), type_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Add(values);", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_.Clear();", name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(Writer* writer) { + writer->WriteLine("if (other.$0$_.Count != 0) {", name()); + writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); + writer->WriteLine("}"); +} + +void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(Writer* writer) { + writer->WriteLine("$0$_.MakeReadOnly();", name()); +} + +void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine("input.Read$0$Array(tag, field_name, result.$1$_);", + capitalized_type_name(), name()); +} + +void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( + Writer* writer) { + writer->WriteLine("if ($0$_.Count > 0) {", name()); + writer->Indent(); + if (descriptor_->is_packed()) { + writer->WriteLine( + "output.WritePacked$0$Array($1$, field_names[$3$], $2$MemoizedSerializedSize, $2$_);", + capitalized_type_name(), number(), name(), field_ordinal()); + } else { + writer->WriteLine("output.Write$0$Array($1$, field_names[$3$], $2$_);", + capitalized_type_name(), number(), name(), + field_ordinal()); + } + writer->Outdent(); + writer->WriteLine("}"); +} + +void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( + Writer* writer) { + writer->WriteLine("{"); + writer->Indent(); + writer->WriteLine("int dataSize = 0;"); + int fixedSize = GetFixedSize(descriptor_->type()); + if (fixedSize == -1) { + writer->WriteLine("foreach ($0$ element in $1$List) {", type_name(), + property_name()); + writer->WriteLine( + " dataSize += pb::CodedOutputStream.Compute$0$SizeNoTag(element);", + capitalized_type_name(), number()); + writer->WriteLine("}"); + } else { + writer->WriteLine("dataSize = $0$ * $1$_.Count;", SimpleItoa(fixedSize), name()); + } + writer->WriteLine("size += dataSize;"); + int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + if (descriptor_->is_packed()) { + writer->WriteLine("if ($0$_.Count != 0) {", name()); + writer->WriteLine( + " size += $0$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);", + SimpleItoa(tagSize)); + writer->WriteLine("}"); + } else { + writer->WriteLine("size += $0$ * $1$_.Count;", SimpleItoa(tagSize), name()); + } + // cache the data size for packed fields. + if (descriptor_->is_packed()) { + writer->WriteLine("$0$MemoizedSerializedSize = dataSize;", name()); + } + writer->Outdent(); + writer->WriteLine("}"); +} + +void RepeatedPrimitiveFieldGenerator::WriteHash(Writer* writer) { + writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); + writer->WriteLine(" hash ^= i.GetHashCode();"); +} +void RepeatedPrimitiveFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); + writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); + writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", + name()); +} +void RepeatedPrimitiveFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", descriptor_->name(), + name()); +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h new file mode 100644 index 00000000..07b12015 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -0,0 +1,73 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { + public: + RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~RepeatedPrimitiveFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void GenerateMergingCode(Writer* writer); + virtual void GenerateBuildingCode(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateSerializationCode(Writer* writer); + virtual void GenerateSerializedSizeCode(Writer* writer); + + virtual void WriteHash(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc new file mode 100644 index 00000000..35c28141 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -0,0 +1,82 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor) + : descriptor_(descriptor) { + optimizeSize_ = (descriptor->options().optimize_for() + == FileOptions::CODE_SIZE); + optimizeSpeed_ = (descriptor->options().optimize_for() == FileOptions::SPEED); + useLiteRuntime_ = (descriptor->options().optimize_for() + == FileOptions::LITE_RUNTIME); + + optimizeSpeed_ |= useLiteRuntime_; + runtimeSuffix_ = useLiteRuntime_ ? "Lite" : ""; +} + +SourceGeneratorBase::~SourceGeneratorBase() { +} + +void SourceGeneratorBase::WriteGeneratedCodeAttributes(Writer* writer) { + // TODO(jtattermusch): + //if (descriptor.File.CSharpOptions.GeneratedCodeAttributes) + // { + // writer.WriteLine("[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]"); + // writer.WriteLine("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{0}\", \"{1}\")]", + // GetType().Assembly.GetName().Name, GetType().Assembly.GetName().Version); + // } +} + +std::string SourceGeneratorBase::class_access_level() { + // TODO(jtattermusch): implement this + return "public"; +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h new file mode 100644 index 00000000..1955394e --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -0,0 +1,83 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__ + +#include + +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class SourceGeneratorBase { + protected: + SourceGeneratorBase(const FileDescriptor* descriptor); + virtual ~SourceGeneratorBase(); + + std::string class_access_level(); + + bool optimize_size() { + return optimizeSize_; + } + bool optimize_speed() { + return optimizeSpeed_; + } + bool use_lite_runtime() { + return useLiteRuntime_; + } + std::string runtime_suffix() { + return runtimeSuffix_; + } + + void WriteGeneratedCodeAttributes(Writer* writer); + + private: + const FileDescriptor* descriptor_; + bool optimizeSize_; + bool optimizeSpeed_; + bool useLiteRuntime_; + std::string runtimeSuffix_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_SOURCE_GENERATOR_BASE_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc new file mode 100644 index 00000000..ead6c1a9 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc @@ -0,0 +1,297 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +UmbrellaClassGenerator::UmbrellaClassGenerator(const FileDescriptor* file) + : SourceGeneratorBase(file), + file_(file) { + namespace_ = GetFileNamespace(file); + umbrellaClassname_ = GetFileUmbrellaClassname(file); + umbrellaNamespace_ = GetFileUmbrellaNamespace(file); +} + +UmbrellaClassGenerator::~UmbrellaClassGenerator() { +} + +void UmbrellaClassGenerator::Generate(Writer* writer) { + WriteIntroduction(writer); + WriteExtensionRegistration(writer); + + // write children: Extensions + if (file_->extension_count() > 0) { + writer->WriteLine("#region Extensions"); + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator extensionGenerator(file_->extension(i)); + extensionGenerator.Generate(writer); + } + writer->WriteLine("#endregion"); + writer->WriteLine(); + } + + writer->WriteLine("#region Static variables"); + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator messageGenerator(file_->message_type(i)); + messageGenerator.GenerateStaticVariables(writer); + } + writer->WriteLine("#endregion"); + if (!use_lite_runtime()) { + WriteDescriptor(writer); + } else { + WriteLiteExtensions(writer); + } + // The class declaration either gets closed before or after the children are written. + if (!file_->options().csharp_nest_classes()) { + writer->Outdent(); + writer->WriteLine("}"); + + // Close the namespace around the umbrella class if defined + if (!file_->options().csharp_nest_classes() + && !umbrellaNamespace_.empty()) { + writer->Outdent(); + writer->WriteLine("}"); + } + } + + // write children: Enums + if (file_->enum_type_count() > 0) { + writer->WriteLine("#region Enums"); + for (int i = 0; i < file_->enum_type_count(); i++) { + EnumGenerator enumGenerator(file_->enum_type(i)); + enumGenerator.Generate(writer); + } + writer->WriteLine("#endregion"); + writer->WriteLine(); + } + + // write children: Messages + if (file_->message_type_count() > 0) { + writer->WriteLine("#region Messages"); + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator messageGenerator(file_->message_type(i)); + messageGenerator.Generate(writer); + } + writer->WriteLine("#endregion"); + writer->WriteLine(); + } + + // TODO(jtattermusch): add support for generating services. + //WriteChildren(writer, "Services", Descriptor.Services); + if (file_->options().csharp_nest_classes()) { + writer->Outdent(); + writer->WriteLine("}"); + } + if (!namespace_.empty()) { + writer->Outdent(); + writer->WriteLine("}"); + } + writer->WriteLine(); + writer->WriteLine("#endregion Designer generated code"); +} + +void UmbrellaClassGenerator::WriteIntroduction(Writer* writer) { + writer->WriteLine( + "// Generated by the protocol buffer compiler. DO NOT EDIT!"); + writer->WriteLine("// source: $0$", file_->name()); + writer->WriteLine("#pragma warning disable 1591, 0612, 3021"); + writer->WriteLine("#region Designer generated code"); + + writer->WriteLine(); + writer->WriteLine("using pb = global::Google.ProtocolBuffers;"); + writer->WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;"); + writer->WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;"); + writer->WriteLine("using scg = global::System.Collections.Generic;"); + + if (!namespace_.empty()) { + writer->WriteLine("namespace $0$ {", namespace_); + writer->Indent(); + writer->WriteLine(); + } + + // Add the namespace around the umbrella class if defined + if (!file_->options().csharp_nest_classes() && !umbrellaNamespace_.empty()) { + writer->WriteLine("namespace $0$ {", umbrellaNamespace_); + writer->Indent(); + writer->WriteLine(); + } + + if (file_->options().csharp_code_contracts()) { + writer->WriteLine( + "[global::System.Diagnostics.Contracts.ContractVerificationAttribute(false)]"); + } + writer->WriteLine( + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); + WriteGeneratedCodeAttributes(writer); + writer->WriteLine("$0$ static partial class $1$ {", class_access_level(), + umbrellaClassname_); + writer->WriteLine(); + writer->Indent(); +} + +void UmbrellaClassGenerator::WriteExtensionRegistration(Writer* writer) { + writer->WriteLine("#region Extension registration"); + writer->WriteLine( + "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {"); + writer->Indent(); + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator extensionGenerator(file_->extension(i)); + extensionGenerator.GenerateExtensionRegistrationCode(writer); + } + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator messageGenerator(file_->message_type(i)); + messageGenerator.GenerateExtensionRegistrationCode(writer); + } + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine("#endregion"); +} + +void UmbrellaClassGenerator::WriteDescriptor(Writer* writer) { + writer->WriteLine("#region Descriptor"); + + writer->WriteLine("public static pbd::FileDescriptor Descriptor {"); + writer->WriteLine(" get { return descriptor; }"); + writer->WriteLine("}"); + writer->WriteLine("private static pbd::FileDescriptor descriptor;"); + writer->WriteLine(); + writer->WriteLine("static $0$() {", umbrellaClassname_); + writer->Indent(); + writer->WriteLine( + "byte[] descriptorData = global::System.Convert.FromBase64String("); + writer->Indent(); + writer->Indent(); + writer->WriteLine("string.Concat("); + writer->Indent(); + + // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64. + std::string base64 = FileDescriptorToBase64(file_); + while (base64.size() > 60) { + writer->WriteLine("\"$0$\", ", base64.substr(0, 60)); + base64 = base64.substr(60); + } + writer->Outdent(); + writer->WriteLine("\"$0$\"));", base64); + writer->Outdent(); + writer->Outdent(); + writer->WriteLine( + "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {"); + writer->Indent(); + writer->WriteLine("descriptor = root;"); + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator messageGenerator(file_->message_type(i)); + messageGenerator.GenerateStaticVariableInitializers(writer); + } + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator extensionGenerator(file_->extension(i)); + extensionGenerator.GenerateStaticVariableInitializers(writer); + } + + if (uses_extensions()) { + // Must construct an ExtensionRegistry containing all possible extensions + // and return it. + writer->WriteLine( + "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();"); + writer->WriteLine("RegisterAllExtensions(registry);"); + for (int i = 0; i < file_->dependency_count(); i++) { + writer->WriteLine("$0$.RegisterAllExtensions(registry);", + GetFullUmbrellaClassName(file_->dependency(i))); + } + writer->WriteLine("return registry;"); + } else { + writer->WriteLine("return null;"); + } + writer->Outdent(); + writer->WriteLine("};"); + + // ----------------------------------------------------------------- + // Invoke internalBuildGeneratedFileFrom() to build the file. + writer->WriteLine( + "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,"); + writer->WriteLine(" new pbd::FileDescriptor[] {"); + for (int i = 0; i < file_->dependency_count(); i++) { + writer->WriteLine(" $0$.Descriptor, ", + GetFullUmbrellaClassName(file_->dependency(i))); + } + writer->WriteLine(" }, assigner);"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine("#endregion"); + writer->WriteLine(); +} + +void UmbrellaClassGenerator::WriteLiteExtensions(Writer* writer) { + writer->WriteLine("#region Extensions"); + writer->WriteLine("internal static readonly object Descriptor;"); + writer->WriteLine("static $0$() {", umbrellaClassname_); + writer->Indent(); + writer->WriteLine("Descriptor = null;"); + for (int i = 0; i < file_->message_type_count(); i++) { + MessageGenerator messageGenerator(file_->message_type(i)); + messageGenerator.GenerateStaticVariableInitializers(writer); + } + for (int i = 0; i < file_->extension_count(); i++) { + ExtensionGenerator extensionGenerator(file_->extension(i)); + extensionGenerator.GenerateStaticVariableInitializers(writer); + } + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine("#endregion"); + writer->WriteLine(); +} + +bool UmbrellaClassGenerator::uses_extensions() { + // TODO(jtattermusch): implement recursive descent that looks for extensions. + // For now, we conservatively assume that extensions are used. + return true; +} + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h new file mode 100644 index 00000000..757f8f91 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h @@ -0,0 +1,76 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +class Writer; + +class UmbrellaClassGenerator : public SourceGeneratorBase { + public: + UmbrellaClassGenerator(const FileDescriptor* file); + ~UmbrellaClassGenerator(); + + void Generate(Writer* write); + + private: + const FileDescriptor* file_; + + std::string namespace_; + std::string umbrellaClassname_; + std::string umbrellaNamespace_; + + void WriteIntroduction(Writer* writer); + void WriteExtensionRegistration(Writer* writer); + void WriteDescriptor(Writer* writer); + void WriteLiteExtensions(Writer* write); + + bool uses_extensions(); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator); +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__ + diff --git a/src/google/protobuf/compiler/csharp/csharp_writer.cc b/src/google/protobuf/compiler/csharp/csharp_writer.cc new file mode 100644 index 00000000..2bcafde5 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_writer.cc @@ -0,0 +1,136 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +Writer::Writer(google::protobuf::io::Printer* printer) + : printer_(printer), + newline_("\n") { + // TODO(jtattermusch): make newline customizable. +} + +Writer::~Writer() { +} + +void Writer::Indent() { + printer_->Indent(); +} + +void Writer::Outdent() { + printer_->Outdent(); +} + +void Writer::Write(const char* text) { + printer_->Print(text); +} + +void Writer::Write(const char* text, const string& value0) { + printer_->Print(text, "0", value0); +} + +void Writer::Write(const char* text, const string& value0, + const string& value1) { + printer_->Print(text, "0", value0, "1", value1); +} + +void Writer::Write(const char* text, const string& value0, const string& value1, + const string& value2) { + printer_->Print(text, "0", value0, "1", value1, "2", value2); +} + +void Writer::Write(const char* text, const string& value0, const string& value1, + const string& value2, const string& value3) { + printer_->Print(text, "0", value0, "1", value1, "2", value2, "3", value3); +} + +void Writer::WriteLine() { + printer_->Print(newline_); +} + +void Writer::WriteLine(const char* text) { + Write(text); + WriteLine(); +} + +void Writer::WriteLine(const char* text, const string& value0) { + Write(text, value0); + WriteLine(); +} + +void Writer::WriteLine(const char* text, const string& value0, + const string& value1) { + Write(text, value0, value1); + WriteLine(); +} + +void Writer::WriteLine(const char* text, const string& value0, + const string& value1, const string& value2) { + Write(text, value0, value1, value2); + WriteLine(); +} + +void Writer::WriteLine(const char* text, const string& value0, + const string& value1, const string& value2, + const string& value3) { + Write(text, value0, value1, value2, value3); + WriteLine(); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_writer.h b/src/google/protobuf/compiler/csharp/csharp_writer.h new file mode 100644 index 00000000..26c59b31 --- /dev/null +++ b/src/google/protobuf/compiler/csharp/csharp_writer.h @@ -0,0 +1,93 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ +#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace csharp { + +// Simple wrapper around Printer that supports customizable line endings +// and number-based variables (e.g. $0$). +class Writer { + public: + Writer(io::Printer* printer); + ~Writer(); + + void Indent(); + void Outdent(); + + void Write(const char* text); + + void Write(const char* text, const string& value0); + + void Write(const char* text, const string& value0, const string& value1); + + void Write(const char* text, const string& value0, const string& value1, + const string& value2); + + void Write(const char* text, const string& value0, const string& value1, + const string& value2, const string& value3); + + void WriteLine(); + + void WriteLine(const char* text); + + void WriteLine(const char* text, const string& value0); + + void WriteLine(const char* text, const string& value0, const string& value1); + + void WriteLine(const char* text, const string& value0, const string& value1, + const string& value2); + + void WriteLine(const char* text, const string& value0, const string& value1, + const string& value2, const string& value3); + private: + io::Printer* printer_; + const char* newline_; +}; + +} // namespace csharp +} // namespace compiler +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc index 931b8fa3..bc2da38e 100644 --- a/src/google/protobuf/compiler/main.cc +++ b/src/google/protobuf/compiler/main.cc @@ -36,6 +36,7 @@ #include #include #include +#include int main(int argc, char* argv[]) { @@ -68,5 +69,10 @@ int main(int argc, char* argv[]) { cli.RegisterGenerator("--ruby_out", &rb_generator, "Generate Ruby source file."); + // CSharp + google::protobuf::compiler::csharp::Generator csharp_generator; + cli.RegisterGenerator("--csharp_out", &csharp_generator, + "Generate C# source file."); + return cli.Run(argc, argv); } diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 9556206c..3a67e5e0 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -289,7 +289,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_), -1); FileOptions_descriptor_ = file->message_type(9); - static const int FileOptions_offsets_[14] = { + static const int FileOptions_offsets_[27] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), @@ -303,6 +303,19 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_umbrella_classname_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_public_classes_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_multiple_files_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_nest_classes_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_code_contracts_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_expand_namespace_directories_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_cls_compliance_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_add_serializable_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_generate_private_ctor_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_file_extension_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_umbrella_namespace_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_generated_code_attributes_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), }; FileOptions_reflection_ = @@ -574,6 +587,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() { delete MethodDescriptorProto_reflection_; delete FileOptions::default_instance_; delete FileOptions_reflection_; + delete FileOptions::_default_csharp_file_extension_; delete MessageOptions::default_instance_; delete MessageOptions_reflection_; delete FieldOptions::default_instance_; @@ -663,7 +677,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "t_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.p" "rotobuf.MethodOptions\022\037\n\020client_streamin" "g\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010" - ":\005false\"\347\004\n\013FileOptions\022\024\n\014java_package\030" + ":\005false\"\302\010\n\013FileOptions\022\024\n\014java_package\030" "\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023j" "ava_multiple_files\030\n \001(\010:\005false\022,\n\035java_" "generate_equals_and_hash\030\024 \001(\010:\005false\022%\n" @@ -675,50 +689,62 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031" "\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_a" "renas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030" - "$ \001(\t\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g" - "oogle.protobuf.UninterpretedOption\":\n\014Op" - "timizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014" - "LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOpt" - "ions\022&\n\027message_set_wire_format\030\001 \001(\010:\005f" - "alse\022.\n\037no_standard_descriptor_accessor\030" - "\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" - "\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterpreted_opti" - "on\030\347\007 \003(\0132$.google.protobuf.Uninterprete" - "dOption*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005c" - "type\030\001 \001(\0162#.google.protobuf.FieldOption" - "s.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030" - "\005 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" - "\023\n\004weak\030\n \001(\010:\005false\022C\n\024uninterpreted_op" - "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" - "tedOption\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001" - "\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOp" - "tions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated" - "\030\003 \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007" + "$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022!\n\031cshar" + "p_umbrella_classname\030& \001(\t\022#\n\025csharp_pub" + "lic_classes\030\' \001(\010:\004true\022\035\n\025csharp_multip" + "le_files\030( \001(\010\022\033\n\023csharp_nest_classes\030) " + "\001(\010\022\035\n\025csharp_code_contracts\030* \001(\010\022+\n#cs" + "harp_expand_namespace_directories\030+ \001(\010\022" + "#\n\025csharp_cls_compliance\030, \001(\010:\004true\022&\n\027" + "csharp_add_serializable\030- \001(\010:\005false\022*\n\034" + "csharp_generate_private_ctor\030. \001(\010:\004true" + "\022\"\n\025csharp_file_extension\030/ \001(\t:\003.cs\022!\n\031" + "csharp_umbrella_namespace\0300 \001(\t\022/\n cshar" + "p_generated_code_attributes\0301 \001(\010:\005false" + "\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.google" + ".protobuf.UninterpretedOption\":\n\014Optimiz" + "eMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_" + "RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022" + "&\n\027message_set_wire_format\030\001 \001(\010:\005false\022" + ".\n\037no_standard_descriptor_accessor\030\002 \001(\010" + ":\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tma" + "p_entry\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007" " \003(\0132$.google.protobuf.UninterpretedOpti" - "on*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndep" - "recated\030\001 \001(\010:\005false\022C\n\024uninterpreted_op" + "on*\t\010\350\007\020\200\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005ctype\030" + "\001 \001(\0162#.google.protobuf.FieldOptions.CTy" + "pe:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010" + ":\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004we" + "ak\030\n \001(\010:\005false\022C\n\024uninterpreted_option\030" + "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" + "tion\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014S" + "TRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions" + "\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(" + "\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132" + "$.google.protobuf.UninterpretedOption*\t\010" + "\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022\031\n\ndeprecat" + "ed\030\001 \001(\010:\005false\022C\n\024uninterpreted_option\030" + "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" + "tion*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndep" + "recated\030! \001(\010:\005false\022C\n\024uninterpreted_op" "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre" - "tedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031" - "\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninterpret" - "ed_option\030\347\007 \003(\0132$.google.protobuf.Unint" - "erpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptio" - "ns\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninter" - "preted_option\030\347\007 \003(\0132$.google.protobuf.U" - "ninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninte" - "rpretedOption\022;\n\004name\030\002 \003(\0132-.google.pro" - "tobuf.UninterpretedOption.NamePart\022\030\n\020id" - "entifier_value\030\003 \001(\t\022\032\n\022positive_int_val" - "ue\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014" - "double_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014" - "\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n" - "\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325" - "\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003(\0132(.go" - "ogle.protobuf.SourceCodeInfo.Location\032\206\001" - "\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003" - "(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trai" - "ling_comments\030\004 \001(\t\022!\n\031leading_detached_" - "comments\030\006 \003(\tB)\n\023com.google.protobufB\020D" - "escriptorProtosH\001", 4617); + "tedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n" + "\ndeprecated\030! \001(\010:\005false\022C\n\024uninterprete" + "d_option\030\347\007 \003(\0132$.google.protobuf.Uninte" + "rpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninterpret" + "edOption\022;\n\004name\030\002 \003(\0132-.google.protobuf" + ".UninterpretedOption.NamePart\022\030\n\020identif" + "ier_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 " + "\001(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014doubl" + "e_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017a" + "ggregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname" + "_part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016So" + "urceCodeInfo\022:\n\010location\030\001 \003(\0132(.google." + "protobuf.SourceCodeInfo.Location\032\206\001\n\010Loc" + "ation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020" + "\001\022\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trailing_" + "comments\030\004 \001(\t\022!\n\031leading_detached_comme" + "nts\030\006 \003(\tB)\n\023com.google.protobufB\020Descri" + "ptorProtosH\001", 5092); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -731,6 +757,8 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { EnumValueDescriptorProto::default_instance_ = new EnumValueDescriptorProto(); ServiceDescriptorProto::default_instance_ = new ServiceDescriptorProto(); MethodDescriptorProto::default_instance_ = new MethodDescriptorProto(); + FileOptions::_default_csharp_file_extension_ = + new ::std::string(".cs", 3); FileOptions::default_instance_ = new FileOptions(); MessageOptions::default_instance_ = new MessageOptions(); FieldOptions::default_instance_ = new FieldOptions(); @@ -7002,6 +7030,7 @@ const FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN; const FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX; const int FileOptions::OptimizeMode_ARRAYSIZE; #endif // _MSC_VER +::std::string* FileOptions::_default_csharp_file_extension_ = NULL; #ifndef _MSC_VER const int FileOptions::kJavaPackageFieldNumber; const int FileOptions::kJavaOuterClassnameFieldNumber; @@ -7016,6 +7045,19 @@ const int FileOptions::kPyGenericServicesFieldNumber; const int FileOptions::kDeprecatedFieldNumber; const int FileOptions::kCcEnableArenasFieldNumber; const int FileOptions::kObjcClassPrefixFieldNumber; +const int FileOptions::kCsharpNamespaceFieldNumber; +const int FileOptions::kCsharpUmbrellaClassnameFieldNumber; +const int FileOptions::kCsharpPublicClassesFieldNumber; +const int FileOptions::kCsharpMultipleFilesFieldNumber; +const int FileOptions::kCsharpNestClassesFieldNumber; +const int FileOptions::kCsharpCodeContractsFieldNumber; +const int FileOptions::kCsharpExpandNamespaceDirectoriesFieldNumber; +const int FileOptions::kCsharpClsComplianceFieldNumber; +const int FileOptions::kCsharpAddSerializableFieldNumber; +const int FileOptions::kCsharpGeneratePrivateCtorFieldNumber; +const int FileOptions::kCsharpFileExtensionFieldNumber; +const int FileOptions::kCsharpUmbrellaNamespaceFieldNumber; +const int FileOptions::kCsharpGeneratedCodeAttributesFieldNumber; const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER @@ -7052,6 +7094,19 @@ void FileOptions::SharedCtor() { deprecated_ = false; cc_enable_arenas_ = false; objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + csharp_umbrella_classname_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + csharp_public_classes_ = true; + csharp_multiple_files_ = false; + csharp_nest_classes_ = false; + csharp_code_contracts_ = false; + csharp_expand_namespace_directories_ = false; + csharp_cls_compliance_ = true; + csharp_add_serializable_ = false; + csharp_generate_private_ctor_ = true; + csharp_file_extension_.UnsafeSetDefault(_default_csharp_file_extension_); + csharp_umbrella_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + csharp_generated_code_attributes_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -7065,6 +7120,10 @@ void FileOptions::SharedDtor() { java_outer_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + csharp_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + csharp_umbrella_classname_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + csharp_file_extension_.DestroyNoArena(_default_csharp_file_extension_); + csharp_umbrella_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (this != default_instance_) { } } @@ -7117,11 +7176,34 @@ void FileOptions::Clear() { go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } } - if (_has_bits_[8 / 32] & 7936) { + if (_has_bits_[8 / 32] & 65280) { ZR_(java_generic_services_, cc_enable_arenas_); if (has_objc_class_prefix()) { objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + if (has_csharp_namespace()) { + csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + if (has_csharp_umbrella_classname()) { + csharp_umbrella_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + csharp_public_classes_ = true; + } + if (_has_bits_[16 / 32] & 16711680) { + ZR_(csharp_multiple_files_, csharp_code_contracts_); + csharp_expand_namespace_directories_ = false; + csharp_cls_compliance_ = true; + csharp_add_serializable_ = false; + csharp_generate_private_ctor_ = true; + if (has_csharp_file_extension()) { + csharp_file_extension_.ClearToDefaultNoArena(_default_csharp_file_extension_); + } + } + if (_has_bits_[24 / 32] & 50331648) { + if (has_csharp_umbrella_namespace()) { + csharp_umbrella_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + csharp_generated_code_attributes_ = false; } #undef ZR_HELPER_ @@ -7347,6 +7429,209 @@ bool FileOptions::MergePartialFromCodedStream( } else { goto handle_unusual; } + if (input->ExpectTag(298)) goto parse_csharp_namespace; + break; + } + + // optional string csharp_namespace = 37; + case 37: { + if (tag == 298) { + parse_csharp_namespace: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_csharp_namespace())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_namespace().data(), this->csharp_namespace().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.FileOptions.csharp_namespace"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(306)) goto parse_csharp_umbrella_classname; + break; + } + + // optional string csharp_umbrella_classname = 38; + case 38: { + if (tag == 306) { + parse_csharp_umbrella_classname: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_csharp_umbrella_classname())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_umbrella_classname().data(), this->csharp_umbrella_classname().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.FileOptions.csharp_umbrella_classname"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(312)) goto parse_csharp_public_classes; + break; + } + + // optional bool csharp_public_classes = 39 [default = true]; + case 39: { + if (tag == 312) { + parse_csharp_public_classes: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_public_classes_))); + set_has_csharp_public_classes(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(320)) goto parse_csharp_multiple_files; + break; + } + + // optional bool csharp_multiple_files = 40; + case 40: { + if (tag == 320) { + parse_csharp_multiple_files: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_multiple_files_))); + set_has_csharp_multiple_files(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(328)) goto parse_csharp_nest_classes; + break; + } + + // optional bool csharp_nest_classes = 41; + case 41: { + if (tag == 328) { + parse_csharp_nest_classes: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_nest_classes_))); + set_has_csharp_nest_classes(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(336)) goto parse_csharp_code_contracts; + break; + } + + // optional bool csharp_code_contracts = 42; + case 42: { + if (tag == 336) { + parse_csharp_code_contracts: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_code_contracts_))); + set_has_csharp_code_contracts(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(344)) goto parse_csharp_expand_namespace_directories; + break; + } + + // optional bool csharp_expand_namespace_directories = 43; + case 43: { + if (tag == 344) { + parse_csharp_expand_namespace_directories: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_expand_namespace_directories_))); + set_has_csharp_expand_namespace_directories(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(352)) goto parse_csharp_cls_compliance; + break; + } + + // optional bool csharp_cls_compliance = 44 [default = true]; + case 44: { + if (tag == 352) { + parse_csharp_cls_compliance: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_cls_compliance_))); + set_has_csharp_cls_compliance(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(360)) goto parse_csharp_add_serializable; + break; + } + + // optional bool csharp_add_serializable = 45 [default = false]; + case 45: { + if (tag == 360) { + parse_csharp_add_serializable: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_add_serializable_))); + set_has_csharp_add_serializable(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(368)) goto parse_csharp_generate_private_ctor; + break; + } + + // optional bool csharp_generate_private_ctor = 46 [default = true]; + case 46: { + if (tag == 368) { + parse_csharp_generate_private_ctor: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_generate_private_ctor_))); + set_has_csharp_generate_private_ctor(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(378)) goto parse_csharp_file_extension; + break; + } + + // optional string csharp_file_extension = 47 [default = ".cs"]; + case 47: { + if (tag == 378) { + parse_csharp_file_extension: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_csharp_file_extension())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_file_extension().data(), this->csharp_file_extension().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.FileOptions.csharp_file_extension"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(386)) goto parse_csharp_umbrella_namespace; + break; + } + + // optional string csharp_umbrella_namespace = 48; + case 48: { + if (tag == 386) { + parse_csharp_umbrella_namespace: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_csharp_umbrella_namespace())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_umbrella_namespace().data(), this->csharp_umbrella_namespace().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.FileOptions.csharp_umbrella_namespace"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(392)) goto parse_csharp_generated_code_attributes; + break; + } + + // optional bool csharp_generated_code_attributes = 49 [default = false]; + case 49: { + if (tag == 392) { + parse_csharp_generated_code_attributes: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &csharp_generated_code_attributes_))); + set_has_csharp_generated_code_attributes(); + } else { + goto handle_unusual; + } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } @@ -7481,6 +7766,91 @@ void FileOptions::SerializeWithCachedSizes( 36, this->objc_class_prefix(), output); } + // optional string csharp_namespace = 37; + if (has_csharp_namespace()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_namespace().data(), this->csharp_namespace().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_namespace"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 37, this->csharp_namespace(), output); + } + + // optional string csharp_umbrella_classname = 38; + if (has_csharp_umbrella_classname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_umbrella_classname().data(), this->csharp_umbrella_classname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_umbrella_classname"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 38, this->csharp_umbrella_classname(), output); + } + + // optional bool csharp_public_classes = 39 [default = true]; + if (has_csharp_public_classes()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(39, this->csharp_public_classes(), output); + } + + // optional bool csharp_multiple_files = 40; + if (has_csharp_multiple_files()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(40, this->csharp_multiple_files(), output); + } + + // optional bool csharp_nest_classes = 41; + if (has_csharp_nest_classes()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(41, this->csharp_nest_classes(), output); + } + + // optional bool csharp_code_contracts = 42; + if (has_csharp_code_contracts()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(42, this->csharp_code_contracts(), output); + } + + // optional bool csharp_expand_namespace_directories = 43; + if (has_csharp_expand_namespace_directories()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(43, this->csharp_expand_namespace_directories(), output); + } + + // optional bool csharp_cls_compliance = 44 [default = true]; + if (has_csharp_cls_compliance()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(44, this->csharp_cls_compliance(), output); + } + + // optional bool csharp_add_serializable = 45 [default = false]; + if (has_csharp_add_serializable()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(45, this->csharp_add_serializable(), output); + } + + // optional bool csharp_generate_private_ctor = 46 [default = true]; + if (has_csharp_generate_private_ctor()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(46, this->csharp_generate_private_ctor(), output); + } + + // optional string csharp_file_extension = 47 [default = ".cs"]; + if (has_csharp_file_extension()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_file_extension().data(), this->csharp_file_extension().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_file_extension"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 47, this->csharp_file_extension(), output); + } + + // optional string csharp_umbrella_namespace = 48; + if (has_csharp_umbrella_namespace()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_umbrella_namespace().data(), this->csharp_umbrella_namespace().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_umbrella_namespace"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 48, this->csharp_umbrella_namespace(), output); + } + + // optional bool csharp_generated_code_attributes = 49 [default = false]; + if (has_csharp_generated_code_attributes()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(49, this->csharp_generated_code_attributes(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -7591,6 +7961,95 @@ void FileOptions::SerializeWithCachedSizes( 36, this->objc_class_prefix(), target); } + // optional string csharp_namespace = 37; + if (has_csharp_namespace()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_namespace().data(), this->csharp_namespace().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_namespace"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 37, this->csharp_namespace(), target); + } + + // optional string csharp_umbrella_classname = 38; + if (has_csharp_umbrella_classname()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_umbrella_classname().data(), this->csharp_umbrella_classname().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_umbrella_classname"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 38, this->csharp_umbrella_classname(), target); + } + + // optional bool csharp_public_classes = 39 [default = true]; + if (has_csharp_public_classes()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(39, this->csharp_public_classes(), target); + } + + // optional bool csharp_multiple_files = 40; + if (has_csharp_multiple_files()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(40, this->csharp_multiple_files(), target); + } + + // optional bool csharp_nest_classes = 41; + if (has_csharp_nest_classes()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(41, this->csharp_nest_classes(), target); + } + + // optional bool csharp_code_contracts = 42; + if (has_csharp_code_contracts()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(42, this->csharp_code_contracts(), target); + } + + // optional bool csharp_expand_namespace_directories = 43; + if (has_csharp_expand_namespace_directories()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(43, this->csharp_expand_namespace_directories(), target); + } + + // optional bool csharp_cls_compliance = 44 [default = true]; + if (has_csharp_cls_compliance()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(44, this->csharp_cls_compliance(), target); + } + + // optional bool csharp_add_serializable = 45 [default = false]; + if (has_csharp_add_serializable()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(45, this->csharp_add_serializable(), target); + } + + // optional bool csharp_generate_private_ctor = 46 [default = true]; + if (has_csharp_generate_private_ctor()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(46, this->csharp_generate_private_ctor(), target); + } + + // optional string csharp_file_extension = 47 [default = ".cs"]; + if (has_csharp_file_extension()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_file_extension().data(), this->csharp_file_extension().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_file_extension"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 47, this->csharp_file_extension(), target); + } + + // optional string csharp_umbrella_namespace = 48; + if (has_csharp_umbrella_namespace()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->csharp_umbrella_namespace().data(), this->csharp_umbrella_namespace().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.FileOptions.csharp_umbrella_namespace"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 48, this->csharp_umbrella_namespace(), target); + } + + // optional bool csharp_generated_code_attributes = 49 [default = false]; + if (has_csharp_generated_code_attributes()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(49, this->csharp_generated_code_attributes(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -7662,7 +8121,7 @@ int FileOptions::ByteSize() const { } } - if (_has_bits_[8 / 32] & 7936) { + if (_has_bits_[8 / 32] & 65280) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; @@ -7690,6 +8149,83 @@ int FileOptions::ByteSize() const { this->objc_class_prefix()); } + // optional string csharp_namespace = 37; + if (has_csharp_namespace()) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->csharp_namespace()); + } + + // optional string csharp_umbrella_classname = 38; + if (has_csharp_umbrella_classname()) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->csharp_umbrella_classname()); + } + + // optional bool csharp_public_classes = 39 [default = true]; + if (has_csharp_public_classes()) { + total_size += 2 + 1; + } + + } + if (_has_bits_[16 / 32] & 16711680) { + // optional bool csharp_multiple_files = 40; + if (has_csharp_multiple_files()) { + total_size += 2 + 1; + } + + // optional bool csharp_nest_classes = 41; + if (has_csharp_nest_classes()) { + total_size += 2 + 1; + } + + // optional bool csharp_code_contracts = 42; + if (has_csharp_code_contracts()) { + total_size += 2 + 1; + } + + // optional bool csharp_expand_namespace_directories = 43; + if (has_csharp_expand_namespace_directories()) { + total_size += 2 + 1; + } + + // optional bool csharp_cls_compliance = 44 [default = true]; + if (has_csharp_cls_compliance()) { + total_size += 2 + 1; + } + + // optional bool csharp_add_serializable = 45 [default = false]; + if (has_csharp_add_serializable()) { + total_size += 2 + 1; + } + + // optional bool csharp_generate_private_ctor = 46 [default = true]; + if (has_csharp_generate_private_ctor()) { + total_size += 2 + 1; + } + + // optional string csharp_file_extension = 47 [default = ".cs"]; + if (has_csharp_file_extension()) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->csharp_file_extension()); + } + + } + if (_has_bits_[24 / 32] & 50331648) { + // optional string csharp_umbrella_namespace = 48; + if (has_csharp_umbrella_namespace()) { + total_size += 2 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->csharp_umbrella_namespace()); + } + + // optional bool csharp_generated_code_attributes = 49 [default = false]; + if (has_csharp_generated_code_attributes()) { + total_size += 2 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -7773,6 +8309,53 @@ void FileOptions::MergeFrom(const FileOptions& from) { set_has_objc_class_prefix(); objc_class_prefix_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.objc_class_prefix_); } + if (from.has_csharp_namespace()) { + set_has_csharp_namespace(); + csharp_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_namespace_); + } + if (from.has_csharp_umbrella_classname()) { + set_has_csharp_umbrella_classname(); + csharp_umbrella_classname_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_umbrella_classname_); + } + if (from.has_csharp_public_classes()) { + set_csharp_public_classes(from.csharp_public_classes()); + } + } + if (from._has_bits_[16 / 32] & (0xffu << (16 % 32))) { + if (from.has_csharp_multiple_files()) { + set_csharp_multiple_files(from.csharp_multiple_files()); + } + if (from.has_csharp_nest_classes()) { + set_csharp_nest_classes(from.csharp_nest_classes()); + } + if (from.has_csharp_code_contracts()) { + set_csharp_code_contracts(from.csharp_code_contracts()); + } + if (from.has_csharp_expand_namespace_directories()) { + set_csharp_expand_namespace_directories(from.csharp_expand_namespace_directories()); + } + if (from.has_csharp_cls_compliance()) { + set_csharp_cls_compliance(from.csharp_cls_compliance()); + } + if (from.has_csharp_add_serializable()) { + set_csharp_add_serializable(from.csharp_add_serializable()); + } + if (from.has_csharp_generate_private_ctor()) { + set_csharp_generate_private_ctor(from.csharp_generate_private_ctor()); + } + if (from.has_csharp_file_extension()) { + set_has_csharp_file_extension(); + csharp_file_extension_.AssignWithDefault(_default_csharp_file_extension_, from.csharp_file_extension_); + } + } + if (from._has_bits_[24 / 32] & (0xffu << (24 % 32))) { + if (from.has_csharp_umbrella_namespace()) { + set_has_csharp_umbrella_namespace(); + csharp_umbrella_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_umbrella_namespace_); + } + if (from.has_csharp_generated_code_attributes()) { + set_csharp_generated_code_attributes(from.csharp_generated_code_attributes()); + } } _extensions_.MergeFrom(from._extensions_); if (from._internal_metadata_.have_unknown_fields()) { @@ -7817,6 +8400,19 @@ void FileOptions::InternalSwap(FileOptions* other) { std::swap(deprecated_, other->deprecated_); std::swap(cc_enable_arenas_, other->cc_enable_arenas_); objc_class_prefix_.Swap(&other->objc_class_prefix_); + csharp_namespace_.Swap(&other->csharp_namespace_); + csharp_umbrella_classname_.Swap(&other->csharp_umbrella_classname_); + std::swap(csharp_public_classes_, other->csharp_public_classes_); + std::swap(csharp_multiple_files_, other->csharp_multiple_files_); + std::swap(csharp_nest_classes_, other->csharp_nest_classes_); + std::swap(csharp_code_contracts_, other->csharp_code_contracts_); + std::swap(csharp_expand_namespace_directories_, other->csharp_expand_namespace_directories_); + std::swap(csharp_cls_compliance_, other->csharp_cls_compliance_); + std::swap(csharp_add_serializable_, other->csharp_add_serializable_); + std::swap(csharp_generate_private_ctor_, other->csharp_generate_private_ctor_); + csharp_file_extension_.Swap(&other->csharp_file_extension_); + csharp_umbrella_namespace_.Swap(&other->csharp_umbrella_namespace_); + std::swap(csharp_generated_code_attributes_, other->csharp_generated_code_attributes_); uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); @@ -8264,6 +8860,434 @@ void FileOptions::InternalSwap(FileOptions* other) { // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) } +// optional string csharp_namespace = 37; + bool FileOptions::has_csharp_namespace() const { + return (_has_bits_[0] & 0x00002000u) != 0; +} + void FileOptions::set_has_csharp_namespace() { + _has_bits_[0] |= 0x00002000u; +} + void FileOptions::clear_has_csharp_namespace() { + _has_bits_[0] &= ~0x00002000u; +} + void FileOptions::clear_csharp_namespace() { + csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_csharp_namespace(); +} + const ::std::string& FileOptions::csharp_namespace() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace) + return csharp_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_csharp_namespace(const ::std::string& value) { + set_has_csharp_namespace(); + csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace) +} + void FileOptions::set_csharp_namespace(const char* value) { + set_has_csharp_namespace(); + csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace) +} + void FileOptions::set_csharp_namespace(const char* value, size_t size) { + set_has_csharp_namespace(); + csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace) +} + ::std::string* FileOptions::mutable_csharp_namespace() { + set_has_csharp_namespace(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace) + return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_csharp_namespace() { + clear_has_csharp_namespace(); + return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_namespace) { + if (csharp_namespace != NULL) { + set_has_csharp_namespace(); + } else { + clear_has_csharp_namespace(); + } + csharp_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_namespace); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) +} + +// optional string csharp_umbrella_classname = 38; + bool FileOptions::has_csharp_umbrella_classname() const { + return (_has_bits_[0] & 0x00004000u) != 0; +} + void FileOptions::set_has_csharp_umbrella_classname() { + _has_bits_[0] |= 0x00004000u; +} + void FileOptions::clear_has_csharp_umbrella_classname() { + _has_bits_[0] &= ~0x00004000u; +} + void FileOptions::clear_csharp_umbrella_classname() { + csharp_umbrella_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_csharp_umbrella_classname(); +} + const ::std::string& FileOptions::csharp_umbrella_classname() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_umbrella_classname) + return csharp_umbrella_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_csharp_umbrella_classname(const ::std::string& value) { + set_has_csharp_umbrella_classname(); + csharp_umbrella_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_umbrella_classname) +} + void FileOptions::set_csharp_umbrella_classname(const char* value) { + set_has_csharp_umbrella_classname(); + csharp_umbrella_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_umbrella_classname) +} + void FileOptions::set_csharp_umbrella_classname(const char* value, size_t size) { + set_has_csharp_umbrella_classname(); + csharp_umbrella_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_umbrella_classname) +} + ::std::string* FileOptions::mutable_csharp_umbrella_classname() { + set_has_csharp_umbrella_classname(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_umbrella_classname) + return csharp_umbrella_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_csharp_umbrella_classname() { + clear_has_csharp_umbrella_classname(); + return csharp_umbrella_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_csharp_umbrella_classname(::std::string* csharp_umbrella_classname) { + if (csharp_umbrella_classname != NULL) { + set_has_csharp_umbrella_classname(); + } else { + clear_has_csharp_umbrella_classname(); + } + csharp_umbrella_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_umbrella_classname); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_umbrella_classname) +} + +// optional bool csharp_public_classes = 39 [default = true]; + bool FileOptions::has_csharp_public_classes() const { + return (_has_bits_[0] & 0x00008000u) != 0; +} + void FileOptions::set_has_csharp_public_classes() { + _has_bits_[0] |= 0x00008000u; +} + void FileOptions::clear_has_csharp_public_classes() { + _has_bits_[0] &= ~0x00008000u; +} + void FileOptions::clear_csharp_public_classes() { + csharp_public_classes_ = true; + clear_has_csharp_public_classes(); +} + bool FileOptions::csharp_public_classes() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_public_classes) + return csharp_public_classes_; +} + void FileOptions::set_csharp_public_classes(bool value) { + set_has_csharp_public_classes(); + csharp_public_classes_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_public_classes) +} + +// optional bool csharp_multiple_files = 40; + bool FileOptions::has_csharp_multiple_files() const { + return (_has_bits_[0] & 0x00010000u) != 0; +} + void FileOptions::set_has_csharp_multiple_files() { + _has_bits_[0] |= 0x00010000u; +} + void FileOptions::clear_has_csharp_multiple_files() { + _has_bits_[0] &= ~0x00010000u; +} + void FileOptions::clear_csharp_multiple_files() { + csharp_multiple_files_ = false; + clear_has_csharp_multiple_files(); +} + bool FileOptions::csharp_multiple_files() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_multiple_files) + return csharp_multiple_files_; +} + void FileOptions::set_csharp_multiple_files(bool value) { + set_has_csharp_multiple_files(); + csharp_multiple_files_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_multiple_files) +} + +// optional bool csharp_nest_classes = 41; + bool FileOptions::has_csharp_nest_classes() const { + return (_has_bits_[0] & 0x00020000u) != 0; +} + void FileOptions::set_has_csharp_nest_classes() { + _has_bits_[0] |= 0x00020000u; +} + void FileOptions::clear_has_csharp_nest_classes() { + _has_bits_[0] &= ~0x00020000u; +} + void FileOptions::clear_csharp_nest_classes() { + csharp_nest_classes_ = false; + clear_has_csharp_nest_classes(); +} + bool FileOptions::csharp_nest_classes() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_nest_classes) + return csharp_nest_classes_; +} + void FileOptions::set_csharp_nest_classes(bool value) { + set_has_csharp_nest_classes(); + csharp_nest_classes_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_nest_classes) +} + +// optional bool csharp_code_contracts = 42; + bool FileOptions::has_csharp_code_contracts() const { + return (_has_bits_[0] & 0x00040000u) != 0; +} + void FileOptions::set_has_csharp_code_contracts() { + _has_bits_[0] |= 0x00040000u; +} + void FileOptions::clear_has_csharp_code_contracts() { + _has_bits_[0] &= ~0x00040000u; +} + void FileOptions::clear_csharp_code_contracts() { + csharp_code_contracts_ = false; + clear_has_csharp_code_contracts(); +} + bool FileOptions::csharp_code_contracts() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_code_contracts) + return csharp_code_contracts_; +} + void FileOptions::set_csharp_code_contracts(bool value) { + set_has_csharp_code_contracts(); + csharp_code_contracts_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_code_contracts) +} + +// optional bool csharp_expand_namespace_directories = 43; + bool FileOptions::has_csharp_expand_namespace_directories() const { + return (_has_bits_[0] & 0x00080000u) != 0; +} + void FileOptions::set_has_csharp_expand_namespace_directories() { + _has_bits_[0] |= 0x00080000u; +} + void FileOptions::clear_has_csharp_expand_namespace_directories() { + _has_bits_[0] &= ~0x00080000u; +} + void FileOptions::clear_csharp_expand_namespace_directories() { + csharp_expand_namespace_directories_ = false; + clear_has_csharp_expand_namespace_directories(); +} + bool FileOptions::csharp_expand_namespace_directories() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_expand_namespace_directories) + return csharp_expand_namespace_directories_; +} + void FileOptions::set_csharp_expand_namespace_directories(bool value) { + set_has_csharp_expand_namespace_directories(); + csharp_expand_namespace_directories_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_expand_namespace_directories) +} + +// optional bool csharp_cls_compliance = 44 [default = true]; + bool FileOptions::has_csharp_cls_compliance() const { + return (_has_bits_[0] & 0x00100000u) != 0; +} + void FileOptions::set_has_csharp_cls_compliance() { + _has_bits_[0] |= 0x00100000u; +} + void FileOptions::clear_has_csharp_cls_compliance() { + _has_bits_[0] &= ~0x00100000u; +} + void FileOptions::clear_csharp_cls_compliance() { + csharp_cls_compliance_ = true; + clear_has_csharp_cls_compliance(); +} + bool FileOptions::csharp_cls_compliance() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_cls_compliance) + return csharp_cls_compliance_; +} + void FileOptions::set_csharp_cls_compliance(bool value) { + set_has_csharp_cls_compliance(); + csharp_cls_compliance_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_cls_compliance) +} + +// optional bool csharp_add_serializable = 45 [default = false]; + bool FileOptions::has_csharp_add_serializable() const { + return (_has_bits_[0] & 0x00200000u) != 0; +} + void FileOptions::set_has_csharp_add_serializable() { + _has_bits_[0] |= 0x00200000u; +} + void FileOptions::clear_has_csharp_add_serializable() { + _has_bits_[0] &= ~0x00200000u; +} + void FileOptions::clear_csharp_add_serializable() { + csharp_add_serializable_ = false; + clear_has_csharp_add_serializable(); +} + bool FileOptions::csharp_add_serializable() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_add_serializable) + return csharp_add_serializable_; +} + void FileOptions::set_csharp_add_serializable(bool value) { + set_has_csharp_add_serializable(); + csharp_add_serializable_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_add_serializable) +} + +// optional bool csharp_generate_private_ctor = 46 [default = true]; + bool FileOptions::has_csharp_generate_private_ctor() const { + return (_has_bits_[0] & 0x00400000u) != 0; +} + void FileOptions::set_has_csharp_generate_private_ctor() { + _has_bits_[0] |= 0x00400000u; +} + void FileOptions::clear_has_csharp_generate_private_ctor() { + _has_bits_[0] &= ~0x00400000u; +} + void FileOptions::clear_csharp_generate_private_ctor() { + csharp_generate_private_ctor_ = true; + clear_has_csharp_generate_private_ctor(); +} + bool FileOptions::csharp_generate_private_ctor() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_generate_private_ctor) + return csharp_generate_private_ctor_; +} + void FileOptions::set_csharp_generate_private_ctor(bool value) { + set_has_csharp_generate_private_ctor(); + csharp_generate_private_ctor_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_generate_private_ctor) +} + +// optional string csharp_file_extension = 47 [default = ".cs"]; + bool FileOptions::has_csharp_file_extension() const { + return (_has_bits_[0] & 0x00800000u) != 0; +} + void FileOptions::set_has_csharp_file_extension() { + _has_bits_[0] |= 0x00800000u; +} + void FileOptions::clear_has_csharp_file_extension() { + _has_bits_[0] &= ~0x00800000u; +} + void FileOptions::clear_csharp_file_extension() { + csharp_file_extension_.ClearToDefaultNoArena(_default_csharp_file_extension_); + clear_has_csharp_file_extension(); +} + const ::std::string& FileOptions::csharp_file_extension() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_file_extension) + return csharp_file_extension_.GetNoArena(_default_csharp_file_extension_); +} + void FileOptions::set_csharp_file_extension(const ::std::string& value) { + set_has_csharp_file_extension(); + csharp_file_extension_.SetNoArena(_default_csharp_file_extension_, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_file_extension) +} + void FileOptions::set_csharp_file_extension(const char* value) { + set_has_csharp_file_extension(); + csharp_file_extension_.SetNoArena(_default_csharp_file_extension_, ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_file_extension) +} + void FileOptions::set_csharp_file_extension(const char* value, size_t size) { + set_has_csharp_file_extension(); + csharp_file_extension_.SetNoArena(_default_csharp_file_extension_, + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_file_extension) +} + ::std::string* FileOptions::mutable_csharp_file_extension() { + set_has_csharp_file_extension(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_file_extension) + return csharp_file_extension_.MutableNoArena(_default_csharp_file_extension_); +} + ::std::string* FileOptions::release_csharp_file_extension() { + clear_has_csharp_file_extension(); + return csharp_file_extension_.ReleaseNoArena(_default_csharp_file_extension_); +} + void FileOptions::set_allocated_csharp_file_extension(::std::string* csharp_file_extension) { + if (csharp_file_extension != NULL) { + set_has_csharp_file_extension(); + } else { + clear_has_csharp_file_extension(); + } + csharp_file_extension_.SetAllocatedNoArena(_default_csharp_file_extension_, csharp_file_extension); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_file_extension) +} + +// optional string csharp_umbrella_namespace = 48; + bool FileOptions::has_csharp_umbrella_namespace() const { + return (_has_bits_[0] & 0x01000000u) != 0; +} + void FileOptions::set_has_csharp_umbrella_namespace() { + _has_bits_[0] |= 0x01000000u; +} + void FileOptions::clear_has_csharp_umbrella_namespace() { + _has_bits_[0] &= ~0x01000000u; +} + void FileOptions::clear_csharp_umbrella_namespace() { + csharp_umbrella_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_csharp_umbrella_namespace(); +} + const ::std::string& FileOptions::csharp_umbrella_namespace() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_umbrella_namespace) + return csharp_umbrella_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_csharp_umbrella_namespace(const ::std::string& value) { + set_has_csharp_umbrella_namespace(); + csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_umbrella_namespace) +} + void FileOptions::set_csharp_umbrella_namespace(const char* value) { + set_has_csharp_umbrella_namespace(); + csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_umbrella_namespace) +} + void FileOptions::set_csharp_umbrella_namespace(const char* value, size_t size) { + set_has_csharp_umbrella_namespace(); + csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_umbrella_namespace) +} + ::std::string* FileOptions::mutable_csharp_umbrella_namespace() { + set_has_csharp_umbrella_namespace(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_umbrella_namespace) + return csharp_umbrella_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + ::std::string* FileOptions::release_csharp_umbrella_namespace() { + clear_has_csharp_umbrella_namespace(); + return csharp_umbrella_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + void FileOptions::set_allocated_csharp_umbrella_namespace(::std::string* csharp_umbrella_namespace) { + if (csharp_umbrella_namespace != NULL) { + set_has_csharp_umbrella_namespace(); + } else { + clear_has_csharp_umbrella_namespace(); + } + csharp_umbrella_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_umbrella_namespace); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_umbrella_namespace) +} + +// optional bool csharp_generated_code_attributes = 49 [default = false]; + bool FileOptions::has_csharp_generated_code_attributes() const { + return (_has_bits_[0] & 0x02000000u) != 0; +} + void FileOptions::set_has_csharp_generated_code_attributes() { + _has_bits_[0] |= 0x02000000u; +} + void FileOptions::clear_has_csharp_generated_code_attributes() { + _has_bits_[0] &= ~0x02000000u; +} + void FileOptions::clear_csharp_generated_code_attributes() { + csharp_generated_code_attributes_ = false; + clear_has_csharp_generated_code_attributes(); +} + bool FileOptions::csharp_generated_code_attributes() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_generated_code_attributes) + return csharp_generated_code_attributes_; +} + void FileOptions::set_csharp_generated_code_attributes(bool value) { + set_has_csharp_generated_code_attributes(); + csharp_generated_code_attributes_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_generated_code_attributes) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index d8cba659..f51ab536 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -1837,6 +1837,117 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { ::std::string* release_objc_class_prefix(); void set_allocated_objc_class_prefix(::std::string* objc_class_prefix); + // optional string csharp_namespace = 37; + bool has_csharp_namespace() const; + void clear_csharp_namespace(); + static const int kCsharpNamespaceFieldNumber = 37; + const ::std::string& csharp_namespace() const; + void set_csharp_namespace(const ::std::string& value); + void set_csharp_namespace(const char* value); + void set_csharp_namespace(const char* value, size_t size); + ::std::string* mutable_csharp_namespace(); + ::std::string* release_csharp_namespace(); + void set_allocated_csharp_namespace(::std::string* csharp_namespace); + + // optional string csharp_umbrella_classname = 38; + bool has_csharp_umbrella_classname() const; + void clear_csharp_umbrella_classname(); + static const int kCsharpUmbrellaClassnameFieldNumber = 38; + const ::std::string& csharp_umbrella_classname() const; + void set_csharp_umbrella_classname(const ::std::string& value); + void set_csharp_umbrella_classname(const char* value); + void set_csharp_umbrella_classname(const char* value, size_t size); + ::std::string* mutable_csharp_umbrella_classname(); + ::std::string* release_csharp_umbrella_classname(); + void set_allocated_csharp_umbrella_classname(::std::string* csharp_umbrella_classname); + + // optional bool csharp_public_classes = 39 [default = true]; + bool has_csharp_public_classes() const; + void clear_csharp_public_classes(); + static const int kCsharpPublicClassesFieldNumber = 39; + bool csharp_public_classes() const; + void set_csharp_public_classes(bool value); + + // optional bool csharp_multiple_files = 40; + bool has_csharp_multiple_files() const; + void clear_csharp_multiple_files(); + static const int kCsharpMultipleFilesFieldNumber = 40; + bool csharp_multiple_files() const; + void set_csharp_multiple_files(bool value); + + // optional bool csharp_nest_classes = 41; + bool has_csharp_nest_classes() const; + void clear_csharp_nest_classes(); + static const int kCsharpNestClassesFieldNumber = 41; + bool csharp_nest_classes() const; + void set_csharp_nest_classes(bool value); + + // optional bool csharp_code_contracts = 42; + bool has_csharp_code_contracts() const; + void clear_csharp_code_contracts(); + static const int kCsharpCodeContractsFieldNumber = 42; + bool csharp_code_contracts() const; + void set_csharp_code_contracts(bool value); + + // optional bool csharp_expand_namespace_directories = 43; + bool has_csharp_expand_namespace_directories() const; + void clear_csharp_expand_namespace_directories(); + static const int kCsharpExpandNamespaceDirectoriesFieldNumber = 43; + bool csharp_expand_namespace_directories() const; + void set_csharp_expand_namespace_directories(bool value); + + // optional bool csharp_cls_compliance = 44 [default = true]; + bool has_csharp_cls_compliance() const; + void clear_csharp_cls_compliance(); + static const int kCsharpClsComplianceFieldNumber = 44; + bool csharp_cls_compliance() const; + void set_csharp_cls_compliance(bool value); + + // optional bool csharp_add_serializable = 45 [default = false]; + bool has_csharp_add_serializable() const; + void clear_csharp_add_serializable(); + static const int kCsharpAddSerializableFieldNumber = 45; + bool csharp_add_serializable() const; + void set_csharp_add_serializable(bool value); + + // optional bool csharp_generate_private_ctor = 46 [default = true]; + bool has_csharp_generate_private_ctor() const; + void clear_csharp_generate_private_ctor(); + static const int kCsharpGeneratePrivateCtorFieldNumber = 46; + bool csharp_generate_private_ctor() const; + void set_csharp_generate_private_ctor(bool value); + + // optional string csharp_file_extension = 47 [default = ".cs"]; + bool has_csharp_file_extension() const; + void clear_csharp_file_extension(); + static const int kCsharpFileExtensionFieldNumber = 47; + const ::std::string& csharp_file_extension() const; + void set_csharp_file_extension(const ::std::string& value); + void set_csharp_file_extension(const char* value); + void set_csharp_file_extension(const char* value, size_t size); + ::std::string* mutable_csharp_file_extension(); + ::std::string* release_csharp_file_extension(); + void set_allocated_csharp_file_extension(::std::string* csharp_file_extension); + + // optional string csharp_umbrella_namespace = 48; + bool has_csharp_umbrella_namespace() const; + void clear_csharp_umbrella_namespace(); + static const int kCsharpUmbrellaNamespaceFieldNumber = 48; + const ::std::string& csharp_umbrella_namespace() const; + void set_csharp_umbrella_namespace(const ::std::string& value); + void set_csharp_umbrella_namespace(const char* value); + void set_csharp_umbrella_namespace(const char* value, size_t size); + ::std::string* mutable_csharp_umbrella_namespace(); + ::std::string* release_csharp_umbrella_namespace(); + void set_allocated_csharp_umbrella_namespace(::std::string* csharp_umbrella_namespace); + + // optional bool csharp_generated_code_attributes = 49 [default = false]; + bool has_csharp_generated_code_attributes() const; + void clear_csharp_generated_code_attributes(); + static const int kCsharpGeneratedCodeAttributesFieldNumber = 49; + bool csharp_generated_code_attributes() const; + void set_csharp_generated_code_attributes(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; void clear_uninterpreted_option(); @@ -1878,6 +1989,32 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void clear_has_cc_enable_arenas(); inline void set_has_objc_class_prefix(); inline void clear_has_objc_class_prefix(); + inline void set_has_csharp_namespace(); + inline void clear_has_csharp_namespace(); + inline void set_has_csharp_umbrella_classname(); + inline void clear_has_csharp_umbrella_classname(); + inline void set_has_csharp_public_classes(); + inline void clear_has_csharp_public_classes(); + inline void set_has_csharp_multiple_files(); + inline void clear_has_csharp_multiple_files(); + inline void set_has_csharp_nest_classes(); + inline void clear_has_csharp_nest_classes(); + inline void set_has_csharp_code_contracts(); + inline void clear_has_csharp_code_contracts(); + inline void set_has_csharp_expand_namespace_directories(); + inline void clear_has_csharp_expand_namespace_directories(); + inline void set_has_csharp_cls_compliance(); + inline void clear_has_csharp_cls_compliance(); + inline void set_has_csharp_add_serializable(); + inline void clear_has_csharp_add_serializable(); + inline void set_has_csharp_generate_private_ctor(); + inline void clear_has_csharp_generate_private_ctor(); + inline void set_has_csharp_file_extension(); + inline void clear_has_csharp_file_extension(); + inline void set_has_csharp_umbrella_namespace(); + inline void clear_has_csharp_umbrella_namespace(); + inline void set_has_csharp_generated_code_attributes(); + inline void clear_has_csharp_generated_code_attributes(); ::google::protobuf::internal::ExtensionSet _extensions_; @@ -1893,11 +2030,25 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { int optimize_for_; ::google::protobuf::internal::ArenaStringPtr go_package_; ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + ::google::protobuf::internal::ArenaStringPtr csharp_namespace_; bool java_generic_services_; bool py_generic_services_; bool deprecated_; bool cc_enable_arenas_; + bool csharp_public_classes_; + bool csharp_multiple_files_; + bool csharp_nest_classes_; + bool csharp_code_contracts_; + ::google::protobuf::internal::ArenaStringPtr csharp_umbrella_classname_; + bool csharp_expand_namespace_directories_; + bool csharp_cls_compliance_; + bool csharp_add_serializable_; + bool csharp_generate_private_ctor_; + bool csharp_generated_code_attributes_; + static ::std::string* _default_csharp_file_extension_; + ::google::protobuf::internal::ArenaStringPtr csharp_file_extension_; + ::google::protobuf::internal::ArenaStringPtr csharp_umbrella_namespace_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -5502,6 +5653,434 @@ inline void FileOptions::set_allocated_objc_class_prefix(::std::string* objc_cla // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.objc_class_prefix) } +// optional string csharp_namespace = 37; +inline bool FileOptions::has_csharp_namespace() const { + return (_has_bits_[0] & 0x00002000u) != 0; +} +inline void FileOptions::set_has_csharp_namespace() { + _has_bits_[0] |= 0x00002000u; +} +inline void FileOptions::clear_has_csharp_namespace() { + _has_bits_[0] &= ~0x00002000u; +} +inline void FileOptions::clear_csharp_namespace() { + csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_csharp_namespace(); +} +inline const ::std::string& FileOptions::csharp_namespace() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_namespace) + return csharp_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_csharp_namespace(const ::std::string& value) { + set_has_csharp_namespace(); + csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_namespace) +} +inline void FileOptions::set_csharp_namespace(const char* value) { + set_has_csharp_namespace(); + csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_namespace) +} +inline void FileOptions::set_csharp_namespace(const char* value, size_t size) { + set_has_csharp_namespace(); + csharp_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_namespace) +} +inline ::std::string* FileOptions::mutable_csharp_namespace() { + set_has_csharp_namespace(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_namespace) + return csharp_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* FileOptions::release_csharp_namespace() { + clear_has_csharp_namespace(); + return csharp_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_namespace) { + if (csharp_namespace != NULL) { + set_has_csharp_namespace(); + } else { + clear_has_csharp_namespace(); + } + csharp_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_namespace); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) +} + +// optional string csharp_umbrella_classname = 38; +inline bool FileOptions::has_csharp_umbrella_classname() const { + return (_has_bits_[0] & 0x00004000u) != 0; +} +inline void FileOptions::set_has_csharp_umbrella_classname() { + _has_bits_[0] |= 0x00004000u; +} +inline void FileOptions::clear_has_csharp_umbrella_classname() { + _has_bits_[0] &= ~0x00004000u; +} +inline void FileOptions::clear_csharp_umbrella_classname() { + csharp_umbrella_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_csharp_umbrella_classname(); +} +inline const ::std::string& FileOptions::csharp_umbrella_classname() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_umbrella_classname) + return csharp_umbrella_classname_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_csharp_umbrella_classname(const ::std::string& value) { + set_has_csharp_umbrella_classname(); + csharp_umbrella_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_umbrella_classname) +} +inline void FileOptions::set_csharp_umbrella_classname(const char* value) { + set_has_csharp_umbrella_classname(); + csharp_umbrella_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_umbrella_classname) +} +inline void FileOptions::set_csharp_umbrella_classname(const char* value, size_t size) { + set_has_csharp_umbrella_classname(); + csharp_umbrella_classname_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_umbrella_classname) +} +inline ::std::string* FileOptions::mutable_csharp_umbrella_classname() { + set_has_csharp_umbrella_classname(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_umbrella_classname) + return csharp_umbrella_classname_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* FileOptions::release_csharp_umbrella_classname() { + clear_has_csharp_umbrella_classname(); + return csharp_umbrella_classname_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_allocated_csharp_umbrella_classname(::std::string* csharp_umbrella_classname) { + if (csharp_umbrella_classname != NULL) { + set_has_csharp_umbrella_classname(); + } else { + clear_has_csharp_umbrella_classname(); + } + csharp_umbrella_classname_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_umbrella_classname); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_umbrella_classname) +} + +// optional bool csharp_public_classes = 39 [default = true]; +inline bool FileOptions::has_csharp_public_classes() const { + return (_has_bits_[0] & 0x00008000u) != 0; +} +inline void FileOptions::set_has_csharp_public_classes() { + _has_bits_[0] |= 0x00008000u; +} +inline void FileOptions::clear_has_csharp_public_classes() { + _has_bits_[0] &= ~0x00008000u; +} +inline void FileOptions::clear_csharp_public_classes() { + csharp_public_classes_ = true; + clear_has_csharp_public_classes(); +} +inline bool FileOptions::csharp_public_classes() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_public_classes) + return csharp_public_classes_; +} +inline void FileOptions::set_csharp_public_classes(bool value) { + set_has_csharp_public_classes(); + csharp_public_classes_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_public_classes) +} + +// optional bool csharp_multiple_files = 40; +inline bool FileOptions::has_csharp_multiple_files() const { + return (_has_bits_[0] & 0x00010000u) != 0; +} +inline void FileOptions::set_has_csharp_multiple_files() { + _has_bits_[0] |= 0x00010000u; +} +inline void FileOptions::clear_has_csharp_multiple_files() { + _has_bits_[0] &= ~0x00010000u; +} +inline void FileOptions::clear_csharp_multiple_files() { + csharp_multiple_files_ = false; + clear_has_csharp_multiple_files(); +} +inline bool FileOptions::csharp_multiple_files() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_multiple_files) + return csharp_multiple_files_; +} +inline void FileOptions::set_csharp_multiple_files(bool value) { + set_has_csharp_multiple_files(); + csharp_multiple_files_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_multiple_files) +} + +// optional bool csharp_nest_classes = 41; +inline bool FileOptions::has_csharp_nest_classes() const { + return (_has_bits_[0] & 0x00020000u) != 0; +} +inline void FileOptions::set_has_csharp_nest_classes() { + _has_bits_[0] |= 0x00020000u; +} +inline void FileOptions::clear_has_csharp_nest_classes() { + _has_bits_[0] &= ~0x00020000u; +} +inline void FileOptions::clear_csharp_nest_classes() { + csharp_nest_classes_ = false; + clear_has_csharp_nest_classes(); +} +inline bool FileOptions::csharp_nest_classes() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_nest_classes) + return csharp_nest_classes_; +} +inline void FileOptions::set_csharp_nest_classes(bool value) { + set_has_csharp_nest_classes(); + csharp_nest_classes_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_nest_classes) +} + +// optional bool csharp_code_contracts = 42; +inline bool FileOptions::has_csharp_code_contracts() const { + return (_has_bits_[0] & 0x00040000u) != 0; +} +inline void FileOptions::set_has_csharp_code_contracts() { + _has_bits_[0] |= 0x00040000u; +} +inline void FileOptions::clear_has_csharp_code_contracts() { + _has_bits_[0] &= ~0x00040000u; +} +inline void FileOptions::clear_csharp_code_contracts() { + csharp_code_contracts_ = false; + clear_has_csharp_code_contracts(); +} +inline bool FileOptions::csharp_code_contracts() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_code_contracts) + return csharp_code_contracts_; +} +inline void FileOptions::set_csharp_code_contracts(bool value) { + set_has_csharp_code_contracts(); + csharp_code_contracts_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_code_contracts) +} + +// optional bool csharp_expand_namespace_directories = 43; +inline bool FileOptions::has_csharp_expand_namespace_directories() const { + return (_has_bits_[0] & 0x00080000u) != 0; +} +inline void FileOptions::set_has_csharp_expand_namespace_directories() { + _has_bits_[0] |= 0x00080000u; +} +inline void FileOptions::clear_has_csharp_expand_namespace_directories() { + _has_bits_[0] &= ~0x00080000u; +} +inline void FileOptions::clear_csharp_expand_namespace_directories() { + csharp_expand_namespace_directories_ = false; + clear_has_csharp_expand_namespace_directories(); +} +inline bool FileOptions::csharp_expand_namespace_directories() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_expand_namespace_directories) + return csharp_expand_namespace_directories_; +} +inline void FileOptions::set_csharp_expand_namespace_directories(bool value) { + set_has_csharp_expand_namespace_directories(); + csharp_expand_namespace_directories_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_expand_namespace_directories) +} + +// optional bool csharp_cls_compliance = 44 [default = true]; +inline bool FileOptions::has_csharp_cls_compliance() const { + return (_has_bits_[0] & 0x00100000u) != 0; +} +inline void FileOptions::set_has_csharp_cls_compliance() { + _has_bits_[0] |= 0x00100000u; +} +inline void FileOptions::clear_has_csharp_cls_compliance() { + _has_bits_[0] &= ~0x00100000u; +} +inline void FileOptions::clear_csharp_cls_compliance() { + csharp_cls_compliance_ = true; + clear_has_csharp_cls_compliance(); +} +inline bool FileOptions::csharp_cls_compliance() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_cls_compliance) + return csharp_cls_compliance_; +} +inline void FileOptions::set_csharp_cls_compliance(bool value) { + set_has_csharp_cls_compliance(); + csharp_cls_compliance_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_cls_compliance) +} + +// optional bool csharp_add_serializable = 45 [default = false]; +inline bool FileOptions::has_csharp_add_serializable() const { + return (_has_bits_[0] & 0x00200000u) != 0; +} +inline void FileOptions::set_has_csharp_add_serializable() { + _has_bits_[0] |= 0x00200000u; +} +inline void FileOptions::clear_has_csharp_add_serializable() { + _has_bits_[0] &= ~0x00200000u; +} +inline void FileOptions::clear_csharp_add_serializable() { + csharp_add_serializable_ = false; + clear_has_csharp_add_serializable(); +} +inline bool FileOptions::csharp_add_serializable() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_add_serializable) + return csharp_add_serializable_; +} +inline void FileOptions::set_csharp_add_serializable(bool value) { + set_has_csharp_add_serializable(); + csharp_add_serializable_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_add_serializable) +} + +// optional bool csharp_generate_private_ctor = 46 [default = true]; +inline bool FileOptions::has_csharp_generate_private_ctor() const { + return (_has_bits_[0] & 0x00400000u) != 0; +} +inline void FileOptions::set_has_csharp_generate_private_ctor() { + _has_bits_[0] |= 0x00400000u; +} +inline void FileOptions::clear_has_csharp_generate_private_ctor() { + _has_bits_[0] &= ~0x00400000u; +} +inline void FileOptions::clear_csharp_generate_private_ctor() { + csharp_generate_private_ctor_ = true; + clear_has_csharp_generate_private_ctor(); +} +inline bool FileOptions::csharp_generate_private_ctor() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_generate_private_ctor) + return csharp_generate_private_ctor_; +} +inline void FileOptions::set_csharp_generate_private_ctor(bool value) { + set_has_csharp_generate_private_ctor(); + csharp_generate_private_ctor_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_generate_private_ctor) +} + +// optional string csharp_file_extension = 47 [default = ".cs"]; +inline bool FileOptions::has_csharp_file_extension() const { + return (_has_bits_[0] & 0x00800000u) != 0; +} +inline void FileOptions::set_has_csharp_file_extension() { + _has_bits_[0] |= 0x00800000u; +} +inline void FileOptions::clear_has_csharp_file_extension() { + _has_bits_[0] &= ~0x00800000u; +} +inline void FileOptions::clear_csharp_file_extension() { + csharp_file_extension_.ClearToDefaultNoArena(_default_csharp_file_extension_); + clear_has_csharp_file_extension(); +} +inline const ::std::string& FileOptions::csharp_file_extension() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_file_extension) + return csharp_file_extension_.GetNoArena(_default_csharp_file_extension_); +} +inline void FileOptions::set_csharp_file_extension(const ::std::string& value) { + set_has_csharp_file_extension(); + csharp_file_extension_.SetNoArena(_default_csharp_file_extension_, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_file_extension) +} +inline void FileOptions::set_csharp_file_extension(const char* value) { + set_has_csharp_file_extension(); + csharp_file_extension_.SetNoArena(_default_csharp_file_extension_, ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_file_extension) +} +inline void FileOptions::set_csharp_file_extension(const char* value, size_t size) { + set_has_csharp_file_extension(); + csharp_file_extension_.SetNoArena(_default_csharp_file_extension_, + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_file_extension) +} +inline ::std::string* FileOptions::mutable_csharp_file_extension() { + set_has_csharp_file_extension(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_file_extension) + return csharp_file_extension_.MutableNoArena(_default_csharp_file_extension_); +} +inline ::std::string* FileOptions::release_csharp_file_extension() { + clear_has_csharp_file_extension(); + return csharp_file_extension_.ReleaseNoArena(_default_csharp_file_extension_); +} +inline void FileOptions::set_allocated_csharp_file_extension(::std::string* csharp_file_extension) { + if (csharp_file_extension != NULL) { + set_has_csharp_file_extension(); + } else { + clear_has_csharp_file_extension(); + } + csharp_file_extension_.SetAllocatedNoArena(_default_csharp_file_extension_, csharp_file_extension); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_file_extension) +} + +// optional string csharp_umbrella_namespace = 48; +inline bool FileOptions::has_csharp_umbrella_namespace() const { + return (_has_bits_[0] & 0x01000000u) != 0; +} +inline void FileOptions::set_has_csharp_umbrella_namespace() { + _has_bits_[0] |= 0x01000000u; +} +inline void FileOptions::clear_has_csharp_umbrella_namespace() { + _has_bits_[0] &= ~0x01000000u; +} +inline void FileOptions::clear_csharp_umbrella_namespace() { + csharp_umbrella_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + clear_has_csharp_umbrella_namespace(); +} +inline const ::std::string& FileOptions::csharp_umbrella_namespace() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_umbrella_namespace) + return csharp_umbrella_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_csharp_umbrella_namespace(const ::std::string& value) { + set_has_csharp_umbrella_namespace(); + csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_umbrella_namespace) +} +inline void FileOptions::set_csharp_umbrella_namespace(const char* value) { + set_has_csharp_umbrella_namespace(); + csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_umbrella_namespace) +} +inline void FileOptions::set_csharp_umbrella_namespace(const char* value, size_t size) { + set_has_csharp_umbrella_namespace(); + csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_umbrella_namespace) +} +inline ::std::string* FileOptions::mutable_csharp_umbrella_namespace() { + set_has_csharp_umbrella_namespace(); + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_umbrella_namespace) + return csharp_umbrella_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* FileOptions::release_csharp_umbrella_namespace() { + clear_has_csharp_umbrella_namespace(); + return csharp_umbrella_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void FileOptions::set_allocated_csharp_umbrella_namespace(::std::string* csharp_umbrella_namespace) { + if (csharp_umbrella_namespace != NULL) { + set_has_csharp_umbrella_namespace(); + } else { + clear_has_csharp_umbrella_namespace(); + } + csharp_umbrella_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_umbrella_namespace); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_umbrella_namespace) +} + +// optional bool csharp_generated_code_attributes = 49 [default = false]; +inline bool FileOptions::has_csharp_generated_code_attributes() const { + return (_has_bits_[0] & 0x02000000u) != 0; +} +inline void FileOptions::set_has_csharp_generated_code_attributes() { + _has_bits_[0] |= 0x02000000u; +} +inline void FileOptions::clear_has_csharp_generated_code_attributes() { + _has_bits_[0] &= ~0x02000000u; +} +inline void FileOptions::clear_csharp_generated_code_attributes() { + csharp_generated_code_attributes_ = false; + clear_has_csharp_generated_code_attributes(); +} +inline bool FileOptions::csharp_generated_code_attributes() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_generated_code_attributes) + return csharp_generated_code_attributes_; +} +inline void FileOptions::set_csharp_generated_code_attributes(bool value) { + set_has_csharp_generated_code_attributes(); + csharp_generated_code_attributes_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_generated_code_attributes) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 367b16e5..d3f7fae9 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -351,6 +351,58 @@ message FileOptions { // generated classes from this .proto. There is no default. optional string objc_class_prefix = 36; + // Namespace for generated classes; defaults to the package. + optional string csharp_namespace = 37; + + // Name of the "umbrella" class used for metadata about all + // the messages within this file. Default is based on the name + // of the file. + optional string csharp_umbrella_classname = 38; + + // Whether classes should be public (true) or internal (false) + optional bool csharp_public_classes = 39 [default = true]; + + // Whether to generate a single file for everything within the + // .proto file (false), or one file per message (true). + // This option is not currently honored; please log a feature + // request if you really want it. + optional bool csharp_multiple_files = 40; + + // Whether to nest messages within a single umbrella class (true) + // or create the umbrella class as a peer, with messages as + // top-level classes in the namespace (false) + optional bool csharp_nest_classes = 41; + + // Generate appropriate support for Code Contracts + // (Ongoing; support should improve over time) + optional bool csharp_code_contracts = 42; + + // Create subdirectories for namespaces, e.g. namespace "Foo.Bar" + // would generate files within [output directory]/Foo/Bar + optional bool csharp_expand_namespace_directories = 43; + + // Generate attributes indicating non-CLS-compliance + optional bool csharp_cls_compliance = 44 [default = true]; + + // Generate messages/builders with the [Serializable] attribute + optional bool csharp_add_serializable = 45 [default = false]; + + // Generates a private ctor for Message types + optional bool csharp_generate_private_ctor = 46 [default = true]; + + // The extension that should be appended to the umbrella_classname when creating files. + optional string csharp_file_extension = 47 [default = ".cs"]; + + // A nested namespace for the umbrella class. Helpful for name collisions caused by + // umbrella_classname conflicting with an existing type. This will be automatically + // set to 'Proto' if a collision is detected with types being generated. This value + // is ignored when nest_classes == true + optional string csharp_umbrella_namespace = 48; + + // Used to add the System.Runtime.CompilerServices.CompilerGeneratedAttribute and + // System.CodeDom.Compiler.GeneratedCodeAttribute attributes to generated code. + optional bool csharp_generated_code_attributes = 49 [default = false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; -- cgit v1.2.3 From 53bee665f8406c966443f67bd8ee4f433cec9497 Mon Sep 17 00:00:00 2001 From: Tamir Duberstein Date: Tue, 31 Mar 2015 10:19:05 -0700 Subject: Change fixture name to be consistent This fixes the problem where `make check` generates files not ignored by `.gitignore`. --- src/Makefile.am | 6 +-- .../compiler/cpp/cpp_test_large_enum_value.proto | 43 ++++++++++++++++++++++ .../compiler/cpp/test_large_enum_value.proto | 43 ---------------------- 3 files changed, 46 insertions(+), 46 deletions(-) create mode 100644 src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto delete mode 100644 src/google/protobuf/compiler/cpp/test_large_enum_value.proto (limited to 'src/google/protobuf/compiler') diff --git a/src/Makefile.am b/src/Makefile.am index 8a27b823..7811b0ae 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -322,7 +322,7 @@ protoc_inputs = \ google/protobuf/unittest_preserve_unknown_enum2.proto \ google/protobuf/unittest_proto3_arena.proto \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \ - google/protobuf/compiler/cpp/test_large_enum_value.proto + google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto EXTRA_DIST = \ $(protoc_inputs) \ @@ -398,8 +398,8 @@ protoc_outputs = \ google/protobuf/unittest_preserve_unknown_enum2.pb.h \ google/protobuf/unittest_proto3_arena.pb.cc \ google/protobuf/unittest_proto3_arena.pb.h \ - google/protobuf/compiler/cpp/test_large_enum_value.pb.cc \ - google/protobuf/compiler/cpp/test_large_enum_value.pb.h \ + google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.cc \ + google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.h \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h diff --git a/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto new file mode 100644 index 00000000..cb6ca1b1 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto @@ -0,0 +1,43 @@ +// 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. + +// Test that proto2 compiler can generate valid code when the enum value +// is INT_MAX. Note that this is a compile-only test and this proto is not +// referenced in any C++ code. +syntax = "proto2"; + +package protobuf_unittest; + +message TestLargeEnumValue { + enum EnumWithLargeValue { + VALUE_1 = 1; + VALUE_MAX = 0x7fffffff; + } +} diff --git a/src/google/protobuf/compiler/cpp/test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto deleted file mode 100644 index cb6ca1b1..00000000 --- a/src/google/protobuf/compiler/cpp/test_large_enum_value.proto +++ /dev/null @@ -1,43 +0,0 @@ -// 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. - -// Test that proto2 compiler can generate valid code when the enum value -// is INT_MAX. Note that this is a compile-only test and this proto is not -// referenced in any C++ code. -syntax = "proto2"; - -package protobuf_unittest; - -message TestLargeEnumValue { - enum EnumWithLargeValue { - VALUE_1 = 1; - VALUE_MAX = 0x7fffffff; - } -} -- cgit v1.2.3 From 153a226a2aa4c98cce932350ff74b8b3eb089e28 Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Wed, 8 Apr 2015 09:53:26 -0400 Subject: CR feedback: spacing, document return values --- src/google/protobuf/compiler/java/java_extension.h | 4 ++++ src/google/protobuf/compiler/java/java_file.cc | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h index fac5ba00..bdd42263 100644 --- a/src/google/protobuf/compiler/java/java_extension.h +++ b/src/google/protobuf/compiler/java/java_extension.h @@ -67,7 +67,11 @@ class ExtensionGenerator { virtual ~ExtensionGenerator() {} virtual void Generate(io::Printer* printer) = 0; + + // Returns an estimate of the number of bytes the printed code will compile to virtual int GenerateNonNestedInitializationCode(io::Printer* printer) = 0; + + // Returns an estimate of the number of bytes the printed code will compile to virtual int GenerateRegistrationCode(io::Printer* printer) = 0; protected: diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 9f285774..4a1f4529 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -65,7 +65,7 @@ namespace { struct FieldDescriptorCompare { bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) { - if(f1== NULL) { + if(f1 == NULL) { return false; } if(f2 == NULL) { -- cgit v1.2.3 From 0f1393d66ed0ceb81ea784e050b7b58524b53331 Mon Sep 17 00:00:00 2001 From: Daniel Martin Date: Thu, 9 Apr 2015 12:20:55 -0400 Subject: More 'int' return value documentation --- src/google/protobuf/compiler/java/java_message.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index 91e529cc..4c4c137a 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -67,7 +67,7 @@ class MessageGenerator { virtual void GenerateStaticVariables(io::Printer* printer) = 0; // Output code which initializes the static variables generated by - // GenerateStaticVariables(). + // GenerateStaticVariables(). Returns an estimate of bytecode size. virtual int GenerateStaticVariableInitializers(io::Printer* printer) = 0; // Generate the class itself. @@ -97,6 +97,8 @@ class ImmutableMessageGenerator : public MessageGenerator { virtual void GenerateInterface(io::Printer* printer); virtual void GenerateExtensionRegistrationCode(io::Printer* printer); virtual void GenerateStaticVariables(io::Printer* printer); + + // Returns an estimate of the number of bytes the printed code will compile to virtual int GenerateStaticVariableInitializers(io::Printer* printer); private: @@ -106,6 +108,8 @@ class ImmutableMessageGenerator : public MessageGenerator { }; void GenerateFieldAccessorTable(io::Printer* printer); + + // Returns an estimate of the number of bytes the printed code will compile to int GenerateFieldAccessorTableInitializer(io::Printer* printer); void GenerateMessageSerializationMethods(io::Printer* printer); -- cgit v1.2.3 From 44664bb705fc704ac3cc5a745d200145a4897ed2 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 12:40:48 -0700 Subject: updated C# codegen to use restricted set of csharp options from descriptor.proto --- .../protobuf/compiler/csharp/csharp_extension.cc | 2 +- .../protobuf/compiler/csharp/csharp_field_base.cc | 2 +- .../protobuf/compiler/csharp/csharp_generator.cc | 6 +++-- .../protobuf/compiler/csharp/csharp_helpers.cc | 19 +++----------- .../protobuf/compiler/csharp/csharp_message.cc | 15 ++--------- .../csharp/csharp_source_generator_base.cc | 5 ++++ .../compiler/csharp/csharp_source_generator_base.h | 1 + .../compiler/csharp/csharp_umbrella_class.cc | 29 +++++++--------------- 8 files changed, 27 insertions(+), 52 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc index f929f49f..b089aed1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ b/src/google/protobuf/compiler/csharp/csharp_extension.cc @@ -63,7 +63,7 @@ ExtensionGenerator::~ExtensionGenerator() { } void ExtensionGenerator::Generate(Writer* writer) { - if (descriptor_->file()->options().csharp_cls_compliance() + if (cls_compliance() && (GetFieldConstantName(descriptor_).substr(0, 1) == "_")) { writer->WriteLine("[global::System.CLSCompliant(false)]"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 48af999c..d7eb5d34 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -84,7 +84,7 @@ void FieldGeneratorBase::AddPublicMemberAttributes(Writer* writer) { } void FieldGeneratorBase::AddClsComplianceCheck(Writer* writer) { - if (!is_cls_compliant() && descriptor_->file()->options().csharp_cls_compliance()) { + if (cls_compliance() && !is_cls_compliant()) { writer->WriteLine("[global::System.CLSCompliant(false)]"); } } diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index 0cac22df..deb3d205 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -61,9 +61,11 @@ bool Generator::Generate( GeneratorContext* generator_context, string* error) const { - // TODO: parse generator parameters... + // TODO(jtattermusch): parse generator parameters: + // cls_compliance + // file_extension - // TODO: file output file naming logic + // TODO(jtattermusch): rework output file naming logic std::string filename = StripDotProto(file->name()) + ".cs"; scoped_ptr output( diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 49ae2c94..ac258f04 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -122,16 +122,12 @@ std::string GetUmbrellaClassNameInternal(const std::string& proto_file) { } std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor) { - if (descriptor->options().has_csharp_umbrella_classname()) { - return descriptor->options().csharp_umbrella_namespace(); - } else { - return GetUmbrellaClassNameInternal(descriptor->name()); - } + // umbrella_classname can no longer be set using message option. + return GetUmbrellaClassNameInternal(descriptor->name()); } std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) { - if (!descriptor->options().csharp_nest_classes() - && !descriptor->options().has_csharp_umbrella_namespace()) { + if (!descriptor->options().has_csharp_umbrella_namespace()) { bool collision = false; // TODO(jtattermusch): detect collisions! // foreach (IDescriptor d in MessageTypes) @@ -196,12 +192,6 @@ std::string UnderscoresToPascalCase(const std::string& input) { std::string ToCSharpName(const std::string& name, const FileDescriptor* file) { std::string result = GetFileNamespace(file); - if (file->options().csharp_nest_classes()) { - if (result != "") { - result += "."; - } - result += GetFileUmbrellaClassname(file); - } if (result != "") { result += '.'; } @@ -233,8 +223,7 @@ std::string GetQualifiedUmbrellaClassName(const FileDescriptor* descriptor) { std::string umbrellaClassname = GetFileUmbrellaClassname(descriptor); std::string fullName = umbrellaClassname; - if (!descriptor->options().csharp_nest_classes() - && !umbrellaNamespace.empty()) { + if (!umbrellaNamespace.empty()) { fullName = umbrellaNamespace + "." + umbrellaClassname; } return fullName; diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 2df3bd2d..126ed22d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -118,9 +118,7 @@ void MessageGenerator::GenerateStaticVariables(Writer* writer) { if (!use_lite_runtime()) { // The descriptor for this type. - std::string access = - descriptor_->file()->options().csharp_nest_classes() ? - "private" : "internal"; + std::string access = "internal"; writer->WriteLine( "$0$ static pbd::MessageDescriptor internal__$1$__Descriptor;", access, identifier); @@ -175,9 +173,6 @@ void MessageGenerator::GenerateStaticVariableInitializers(Writer* writer) { } void MessageGenerator::Generate(Writer* writer) { - if (descriptor_->file()->options().csharp_add_serializable()) { - writer->WriteLine("[global::System.SerializableAttribute()]"); - } writer->WriteLine( "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); WriteGeneratedCodeAttributes(writer); @@ -187,9 +182,6 @@ void MessageGenerator::Generate(Writer* writer) { descriptor_->extension_range_count() > 0 ? "Extendable" : "Generated", runtime_suffix()); writer->Indent(); - if (descriptor_->file()->options().csharp_generate_private_ctor()) { - writer->WriteLine("private $0$() { }", class_name()); - } // Must call MakeReadOnly() to make sure all lists are made read-only writer->WriteLine( "private static readonly $0$ defaultInstance = new $0$().MakeReadOnly();", @@ -271,7 +263,7 @@ void MessageGenerator::Generate(Writer* writer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); // TODO(jtattermusch): same code for cls compliance is in csharp_extension - if (descriptor_->file()->options().csharp_cls_compliance() + if (cls_compliance() && GetFieldConstantName(fieldDescriptor)[0] == '_') { writer->WriteLine("[global::System.CLSCompliant(false)]"); } @@ -557,9 +549,6 @@ void MessageGenerator::GenerateBuilder(Writer* writer) { writer->WriteLine(" return new Builder(prototype);"); writer->WriteLine("}"); writer->WriteLine(); - if (descriptor_->file()->options().csharp_add_serializable()) { - writer->WriteLine("[global::System.SerializableAttribute()]"); - } writer->WriteLine( "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); WriteGeneratedCodeAttributes(writer); diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index 35c28141..ed016b46 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -76,6 +76,11 @@ std::string SourceGeneratorBase::class_access_level() { return "public"; } +bool SourceGeneratorBase::cls_compliance() { + // TODO(jtattermusch): implement this based on "cls_compliance" cmdline param. + return true; +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index 1955394e..dbc65d04 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -48,6 +48,7 @@ class SourceGeneratorBase { virtual ~SourceGeneratorBase(); std::string class_access_level(); + bool cls_compliance(); bool optimize_size() { return optimizeSize_; diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc index ead6c1a9..358cfa4f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc @@ -86,17 +86,14 @@ void UmbrellaClassGenerator::Generate(Writer* writer) { } else { WriteLiteExtensions(writer); } - // The class declaration either gets closed before or after the children are written. - if (!file_->options().csharp_nest_classes()) { + // Close the class declaration. + writer->Outdent(); + writer->WriteLine("}"); + + // Close the namespace around the umbrella class if defined + if (!umbrellaNamespace_.empty()) { writer->Outdent(); writer->WriteLine("}"); - - // Close the namespace around the umbrella class if defined - if (!file_->options().csharp_nest_classes() - && !umbrellaNamespace_.empty()) { - writer->Outdent(); - writer->WriteLine("}"); - } } // write children: Enums @@ -121,12 +118,8 @@ void UmbrellaClassGenerator::Generate(Writer* writer) { writer->WriteLine(); } - // TODO(jtattermusch): add support for generating services. - //WriteChildren(writer, "Services", Descriptor.Services); - if (file_->options().csharp_nest_classes()) { - writer->Outdent(); - writer->WriteLine("}"); - } + // TODO(jtattermusch): add insertion point for services. + if (!namespace_.empty()) { writer->Outdent(); writer->WriteLine("}"); @@ -155,16 +148,12 @@ void UmbrellaClassGenerator::WriteIntroduction(Writer* writer) { } // Add the namespace around the umbrella class if defined - if (!file_->options().csharp_nest_classes() && !umbrellaNamespace_.empty()) { + if (!umbrellaNamespace_.empty()) { writer->WriteLine("namespace $0$ {", umbrellaNamespace_); writer->Indent(); writer->WriteLine(); } - if (file_->options().csharp_code_contracts()) { - writer->WriteLine( - "[global::System.Diagnostics.Contracts.ContractVerificationAttribute(false)]"); - } writer->WriteLine( "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); WriteGeneratedCodeAttributes(writer); -- cgit v1.2.3 From 16a3e2b91423c32680b3dc904c839853c9dc8cc8 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 13:03:23 -0700 Subject: enable overriding of property name using csharp_property_name --- src/google/protobuf/compiler/csharp/csharp_helpers.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index ac258f04..55ce3285 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -253,7 +253,9 @@ std::string GetFieldConstantName(const FieldDescriptor* field) { } std::string GetPropertyName(const FieldDescriptor* descriptor) { - // TODO: fix this. + if (descriptor->options().has_csharp_property_name()) { + return descriptor->options().csharp_property_name(); + } std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor)); if (property_name == descriptor->containing_type()->name()) { property_name += "_"; -- cgit v1.2.3 From 8cec65e761a90a6370e4f4439abd072f43834505 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 14:21:33 -0700 Subject: added support for deprecated fields, reworded some todos --- src/google/protobuf/compiler/csharp/csharp_extension.cc | 4 ++-- src/google/protobuf/compiler/csharp/csharp_field_base.cc | 9 ++++----- src/google/protobuf/compiler/csharp/csharp_message.cc | 1 - 3 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc index b089aed1..8a30144d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ b/src/google/protobuf/compiler/csharp/csharp_extension.cc @@ -73,7 +73,7 @@ void ExtensionGenerator::Generate(Writer* writer) { SimpleItoa(descriptor_->number())); if (use_lite_runtime()) { - // TODO(jtattermusch): check the argument... + // TODO(jtattermusch): include the following check //if (Descriptor.MappedType == MappedType.Message && Descriptor.MessageType.Options.MessageSetWireFormat) //{ // throw new ArgumentException( @@ -122,7 +122,7 @@ void ExtensionGenerator::GenerateStaticVariableInitializers(Writer* writer) { } writer->WriteLine("$0$,", default_val); } - // TODO(jtattermusch): + // TODO(jtattermusch): include following snippet //writer.WriteLine("{0},", // (Descriptor.MappedType == MappedType.Message) ? type + ".DefaultInstance" : "null"); //writer.WriteLine("{0},", diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index d7eb5d34..ed4d55c4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -61,11 +61,10 @@ FieldGeneratorBase::~FieldGeneratorBase() { } void FieldGeneratorBase::AddDeprecatedFlag(Writer* writer) { - // TODO(jtattermusch): - //if (IsObsolete) - //{ - // writer.WriteLine("[global::System.ObsoleteAttribute()]"); - //} + if (descriptor_->options().deprecated()) + { + writer->WriteLine("[global::System.ObsoleteAttribute()]"); + } } void FieldGeneratorBase::AddNullCheck(Writer* writer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 126ed22d..7156c9e5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -81,7 +81,6 @@ MessageGenerator::~MessageGenerator() { } std::string MessageGenerator::class_name() { - // TODO: check correctness. return descriptor_->name(); } -- cgit v1.2.3 From f61e1791c0df2a518103b5924ee76098d5b72fab Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 15:10:07 -0700 Subject: output file naming logic, configurable file extension, comment rewording --- .../protobuf/compiler/csharp/csharp_generator.cc | 27 +++++++++++++++++----- .../protobuf/compiler/csharp/csharp_helpers.cc | 2 +- .../csharp/csharp_source_generator_base.cc | 11 ++------- 3 files changed, 24 insertions(+), 16 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index deb3d205..61ed37ad 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -49,6 +49,11 @@ namespace protobuf { namespace compiler { namespace csharp { +std::string GetOutputFile(const google::protobuf::FileDescriptor* file, const std::string file_extension) +{ + return GetFileUmbrellaClassname(file) + file_extension; +} + void GenerateFile(const google::protobuf::FileDescriptor* file, Writer* writer) { UmbrellaClassGenerator umbrellaGenerator(file); @@ -61,13 +66,23 @@ bool Generator::Generate( GeneratorContext* generator_context, string* error) const { - // TODO(jtattermusch): parse generator parameters: - // cls_compliance - // file_extension + vector > options; + ParseGeneratorParameter(parameter, &options); + + std::string file_extension = ".cs"; + for (int i = 0; i < options.size(); i++) { + if (options[i].first == "no_cls_compliance") { + *error = "Turning off CLS compliance is not implemented yet."; + return false; + } else if (options[i].first == "file_extension") { + file_extension = options[i].second; + } else { + *error = "Unknown generator option: " + options[i].first; + return false; + } + } - // TODO(jtattermusch): rework output file naming logic - std::string filename = - StripDotProto(file->name()) + ".cs"; + std::string filename = GetOutputFile(file, file_extension); scoped_ptr output( generator_context->Open(filename)); io::Printer printer(output.get(), '$'); diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 55ce3285..5829c61e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -364,7 +364,7 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, } bool HasRequiredFields(const Descriptor* descriptor) { - // TODO(jtattermusch): implement this. + // TODO(jtattermusch): implement HasRequiredFields logic. return true; } diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index ed016b46..e39911ee 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -62,18 +62,11 @@ SourceGeneratorBase::~SourceGeneratorBase() { } void SourceGeneratorBase::WriteGeneratedCodeAttributes(Writer* writer) { - // TODO(jtattermusch): - //if (descriptor.File.CSharpOptions.GeneratedCodeAttributes) - // { - // writer.WriteLine("[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]"); - // writer.WriteLine("[global::System.CodeDom.Compiler.GeneratedCodeAttribute(\"{0}\", \"{1}\")]", - // GetType().Assembly.GetName().Name, GetType().Assembly.GetName().Version); - // } + // This hook can be used to reintroduce generated code attributes in the future. } std::string SourceGeneratorBase::class_access_level() { - // TODO(jtattermusch): implement this - return "public"; + return "public"; // public_classes is always on. } bool SourceGeneratorBase::cls_compliance() { -- cgit v1.2.3 From d92de1742d2bbc77058637709140717e00f011da Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 15:28:43 -0700 Subject: creating private ctor for builders is now the default (as it used to be for old codegen) --- src/google/protobuf/compiler/csharp/csharp_message.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 7156c9e5..66b8c2d5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -181,6 +181,7 @@ void MessageGenerator::Generate(Writer* writer) { descriptor_->extension_range_count() > 0 ? "Extendable" : "Generated", runtime_suffix()); writer->Indent(); + writer->WriteLine("private $0$() { }", class_name()); // Private ctor. // Must call MakeReadOnly() to make sure all lists are made read-only writer->WriteLine( "private static readonly $0$ defaultInstance = new $0$().MakeReadOnly();", -- cgit v1.2.3 From db9060dc61ce72f3747197644f31a57b9ddbf6a4 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 15:48:40 -0700 Subject: addressed TODO for lite runtime --- .../protobuf/compiler/csharp/csharp_extension.cc | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc index 8a30144d..5d38f52e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ b/src/google/protobuf/compiler/csharp/csharp_extension.cc @@ -122,13 +122,17 @@ void ExtensionGenerator::GenerateStaticVariableInitializers(Writer* writer) { } writer->WriteLine("$0$,", default_val); } - // TODO(jtattermusch): include following snippet - //writer.WriteLine("{0},", - // (Descriptor.MappedType == MappedType.Message) ? type + ".DefaultInstance" : "null"); - //writer.WriteLine("{0},", - // (Descriptor.MappedType == MappedType.Enum) ? "new EnumLiteMap<" + type + ">()" : "null"); - //writer.WriteLine("{0}.{1}FieldNumber,", scope, name); - //writer.Write("pbd::FieldType.{0}", Descriptor.FieldType); + writer->WriteLine( + "$0$,", + (GetCSharpType(descriptor_->type()) == CSHARPTYPE_MESSAGE) ? + type_name() + ".DefaultInstance" : "null"); + writer->WriteLine( + "$0$,", + (GetCSharpType(descriptor_->type()) == CSHARPTYPE_ENUM) ? + "new EnumLiteMap<" + type_name() + ">()" : "null"); + writer->WriteLine("$0$.$1$FieldNumber,", scope_, + GetPropertyName(descriptor_)); + writer->Write("pbd::FieldType.$0$", capitalized_type_name()); if (descriptor_->is_repeated()) { writer->WriteLine(","); writer->Write(descriptor_->is_packed() ? "true" : "false"); -- cgit v1.2.3 From 5ac8de5b46a7b2adb81f957dfb78c612137d9ffb Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 16:12:29 -0700 Subject: implemented HasRequiredFields logic --- .../protobuf/compiler/csharp/csharp_helpers.cc | 39 ++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 5829c61e..fd6e3722 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -363,9 +363,44 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, } } +bool HasRequiredFields(const Descriptor* descriptor, std::set* already_seen) { + if (already_seen->find(descriptor) != already_seen->end()) { + // The type is already in cache. This means that either: + // a. The type has no required fields. + // b. We are in the midst of checking if the type has required fields, + // somewhere up the stack. In this case, we know that if the type + // has any required fields, they'll be found when we return to it, + // and the whole call to HasRequiredFields() will return true. + // Therefore, we don't have to check if this type has required fields + // here. + return false; + } + already_seen->insert(descriptor); + + // If the type has extensions, an extension with message type could contain + // required fields, so we have to be conservative and assume such an + // extension exists. + if (descriptor->extension_count() > 0) { + return true; + } + + for (int i = 0; i < descriptor->field_count(); i++) { + const FieldDescriptor* field = descriptor->field(i); + if (field->is_required()) { + return true; + } + if (GetCSharpType(field->type()) == CSHARPTYPE_MESSAGE) { + if (HasRequiredFields(field->message_type(), already_seen)) { + return true; + } + } + } + return false; +} + bool HasRequiredFields(const Descriptor* descriptor) { - // TODO(jtattermusch): implement HasRequiredFields logic. - return true; + std::set already_seen; + return HasRequiredFields(descriptor, &already_seen); } } // namespace java -- cgit v1.2.3 From 7cc05ecb3a6fecf97604ab89803e7cbb34838268 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 16:32:54 -0700 Subject: fixing implementation of GetFileUmbrellaNamespace --- .../protobuf/compiler/csharp/csharp_helpers.cc | 40 ++++++++++++---------- 1 file changed, 22 insertions(+), 18 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index fd6e3722..c7e9e4cc 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -127,26 +127,30 @@ std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor) { } std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) { - if (!descriptor->options().has_csharp_umbrella_namespace()) { - bool collision = false; - // TODO(jtattermusch): detect collisions! -// foreach (IDescriptor d in MessageTypes) -// { -// collision |= d.Name == builder.UmbrellaClassname; -// } -// foreach (IDescriptor d in Services) -// { -// collision |= d.Name == builder.UmbrellaClassname; -// } -// foreach (IDescriptor d in EnumTypes) -// { -// collision |= d.Name == builder.UmbrellaClassname; -// } - if (collision) { - return "Proto"; + if (descriptor->options().has_csharp_umbrella_namespace()) { + return descriptor->options().csharp_umbrella_namespace(); + } + bool collision = false; + std::string umbrella_classname = GetFileUmbrellaClassname(descriptor); + for(int i = 0; i < descriptor->message_type_count(); i++) { + if (descriptor->message_type(i)->name() == umbrella_classname) { + collision = true; + break; + } + } + for (int i = 0; i < descriptor->service_count(); i++) { + if (descriptor->service(i)->name() == umbrella_classname) { + collision = true; + break; + } + } + for (int i = 0; i < descriptor->enum_type_count(); i++) { + if (descriptor->enum_type(i)->name() == umbrella_classname) { + collision = true; + break; } } - return ""; + return collision ? "Proto" : ""; } // TODO(jtattermusch): can we reuse a utility function? -- cgit v1.2.3 From 333d200a96b067dcc43f249d957cf1efd52bf592 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Mon, 13 Apr 2015 17:41:03 -0700 Subject: integrate CalcSerializedSize() fix from protobuf-csharp-port issue 84 --- src/google/protobuf/compiler/csharp/csharp_message.cc | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 66b8c2d5..f7c8ddfb 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -378,7 +378,7 @@ void MessageGenerator::GenerateMessageSerializationMethods(Writer* writer) { "public override void WriteTo(pb::ICodedOutputStream output) {"); writer->Indent(); // Make sure we've computed the serialized length, so that packed fields are generated correctly. - writer->WriteLine("int size = SerializedSize;"); + writer->WriteLine("CalcSerializedSize();"); writer->WriteLine("string[] field_names = _$0$FieldNames;", UnderscoresToCamelCase(class_name(), false)); if (descriptor_->extension_range_count()) { @@ -421,6 +421,17 @@ void MessageGenerator::GenerateMessageSerializationMethods(Writer* writer) { writer->Indent(); writer->WriteLine("int size = memoizedSerializedSize;"); writer->WriteLine("if (size != -1) return size;"); + writer->WriteLine("return CalcSerializedSize();"); + writer->Outdent(); + writer->WriteLine("}"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine(); + + writer->WriteLine("private int CalcSerializedSize() {"); + writer->Indent(); + writer->WriteLine("int size = memoizedSerializedSize;"); + writer->WriteLine("if (size != -1) return size;"); writer->WriteLine(); writer->WriteLine("size = 0;"); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -443,9 +454,6 @@ void MessageGenerator::GenerateMessageSerializationMethods(Writer* writer) { writer->WriteLine("return size;"); writer->Outdent(); writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); } void MessageGenerator::GenerateSerializeOneField( -- cgit v1.2.3 From 83a5991d12ecabc3388c99d121892a488ea8ee97 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 17 Apr 2015 10:53:06 -0700 Subject: removing csharp_property_name field option --- .../protobuf/compiler/csharp/csharp_helpers.cc | 4 +- src/google/protobuf/descriptor.pb.cc | 180 ++++----------------- src/google/protobuf/descriptor.pb.h | 68 -------- src/google/protobuf/descriptor.proto | 6 - 4 files changed, 35 insertions(+), 223 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index c7e9e4cc..cae12e2e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -257,9 +257,7 @@ std::string GetFieldConstantName(const FieldDescriptor* field) { } std::string GetPropertyName(const FieldDescriptor* descriptor) { - if (descriptor->options().has_csharp_property_name()) { - return descriptor->options().csharp_property_name(); - } + // TODO(jtattermusch): consider introducing csharp_property_name field option std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor)); if (property_name == descriptor->containing_type()->name()) { property_name += "_"; diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 2aac269b..aa5952c7 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -339,13 +339,12 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_), -1); FieldOptions_descriptor_ = file->message_type(11); - static const int FieldOptions_offsets_[7] = { + static const int FieldOptions_offsets_[6] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, csharp_property_name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, uninterpreted_option_), }; FieldOptions_reflection_ = @@ -689,41 +688,40 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "recated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022" "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google." "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"" - "\276\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.google" + "\240\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.google" ".protobuf.FieldOptions.CType:\006STRING\022\016\n\006" "packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndep" "recated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005fals" - "e\022\034\n\024csharp_property_name\030\013 \001(\t\022C\n\024unint" - "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption\"/\n\005CType\022\n\n\006STRING\020" - "\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007\020\200\200\200\200\002" - "\"\215\001\n\013EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n" - "\ndeprecated\030\003 \001(\010:\005false\022C\n\024uninterprete" - "d_option\030\347\007 \003(\0132$.google.protobuf.Uninte" - "rpretedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOpt" - "ions\022\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024unint" - "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016Servi" - "ceOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024" - "uninterpreted_option\030\347\007 \003(\0132$.google.pro" - "tobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\r" - "MethodOptions\022\031\n\ndeprecated\030! \001(\010:\005false" - "\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.google" - ".protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002" - "\"\236\002\n\023UninterpretedOption\022;\n\004name\030\002 \003(\0132-" - ".google.protobuf.UninterpretedOption.Nam" - "ePart\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022posit" - "ive_int_value\030\004 \001(\004\022\032\n\022negative_int_valu" - "e\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_" - "value\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010" - "NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extens" - "ion\030\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location" - "\030\001 \003(\0132(.google.protobuf.SourceCodeInfo." - "Location\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022" - "\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 " - "\001(\t\022\031\n\021trailing_comments\030\004 \001(\t\022!\n\031leadin" - "g_detached_comments\030\006 \003(\tB)\n\023com.google." - "protobufB\020DescriptorProtosH\001", 4708); + "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl" + "e.protobuf.UninterpretedOption\"/\n\005CType\022" + "\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*" + "\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow_alia" + "s\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024un" + "interpreted_option\030\347\007 \003(\0132$.google.proto" + "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020En" + "umValueOptions\022\031\n\ndeprecated\030\001 \001(\010:\005fals" + "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl" + "e.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200" + "\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030! \001(\010:" + "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." + "google.protobuf.UninterpretedOption*\t\010\350\007" + "\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprecated\030! " + "\001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(" + "\0132$.google.protobuf.UninterpretedOption*" + "\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022;\n\004na" + "me\030\002 \003(\0132-.google.protobuf.Uninterpreted" + "Option.NamePart\022\030\n\020identifier_value\030\003 \001(" + "\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022negativ" + "e_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022" + "\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_value" + "\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n" + "\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:" + "\n\010location\030\001 \003(\0132(.google.protobuf.Sourc" + "eCodeInfo.Location\032\206\001\n\010Location\022\020\n\004path\030" + "\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_c" + "omments\030\003 \001(\t\022\031\n\021trailing_comments\030\004 \001(\t" + "\022!\n\031leading_detached_comments\030\006 \003(\tB)\n\023c" + "om.google.protobufB\020DescriptorProtosH\001", 4678); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -9090,7 +9088,6 @@ const int FieldOptions::kPackedFieldNumber; const int FieldOptions::kLazyFieldNumber; const int FieldOptions::kDeprecatedFieldNumber; const int FieldOptions::kWeakFieldNumber; -const int FieldOptions::kCsharpPropertyNameFieldNumber; const int FieldOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER @@ -9112,14 +9109,12 @@ FieldOptions::FieldOptions(const FieldOptions& from) } void FieldOptions::SharedCtor() { - ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; ctype_ = 0; packed_ = false; lazy_ = false; deprecated_ = false; weak_ = false; - csharp_property_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -9129,7 +9124,6 @@ FieldOptions::~FieldOptions() { } void FieldOptions::SharedDtor() { - csharp_property_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (this != default_instance_) { } } @@ -9169,11 +9163,8 @@ void FieldOptions::Clear() { ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) - if (_has_bits_[0 / 32] & 63) { + if (_has_bits_[0 / 32] & 31) { ZR_(ctype_, weak_); - if (has_csharp_property_name()) { - csharp_property_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } } #undef ZR_HELPER_ @@ -9271,23 +9262,6 @@ bool FieldOptions::MergePartialFromCodedStream( } else { goto handle_unusual; } - if (input->ExpectTag(90)) goto parse_csharp_property_name; - break; - } - - // optional string csharp_property_name = 11; - case 11: { - if (tag == 90) { - parse_csharp_property_name: - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_csharp_property_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_property_name().data(), this->csharp_property_name().length(), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FieldOptions.csharp_property_name"); - } else { - goto handle_unusual; - } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } @@ -9362,16 +9336,6 @@ void FieldOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output); } - // optional string csharp_property_name = 11; - if (has_csharp_property_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_property_name().data(), this->csharp_property_name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldOptions.csharp_property_name"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 11, this->csharp_property_name(), output); - } - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -9418,17 +9382,6 @@ void FieldOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target); } - // optional string csharp_property_name = 11; - if (has_csharp_property_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_property_name().data(), this->csharp_property_name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FieldOptions.csharp_property_name"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 11, this->csharp_property_name(), target); - } - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -9451,7 +9404,7 @@ void FieldOptions::SerializeWithCachedSizes( int FieldOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 63) { + if (_has_bits_[0 / 32] & 31) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (has_ctype()) { total_size += 1 + @@ -9478,13 +9431,6 @@ int FieldOptions::ByteSize() const { total_size += 1 + 1; } - // optional string csharp_property_name = 11; - if (has_csharp_property_name()) { - total_size += 1 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->csharp_property_name()); - } - } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -9538,10 +9484,6 @@ void FieldOptions::MergeFrom(const FieldOptions& from) { if (from.has_weak()) { set_weak(from.weak()); } - if (from.has_csharp_property_name()) { - set_has_csharp_property_name(); - csharp_property_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_property_name_); - } } _extensions_.MergeFrom(from._extensions_); if (from._internal_metadata_.have_unknown_fields()) { @@ -9578,7 +9520,6 @@ void FieldOptions::InternalSwap(FieldOptions* other) { std::swap(lazy_, other->lazy_); std::swap(deprecated_, other->deprecated_); std::swap(weak_, other->weak_); - csharp_property_name_.Swap(&other->csharp_property_name_); uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); @@ -9718,59 +9659,6 @@ void FieldOptions::InternalSwap(FieldOptions* other) { // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) } -// optional string csharp_property_name = 11; - bool FieldOptions::has_csharp_property_name() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} - void FieldOptions::set_has_csharp_property_name() { - _has_bits_[0] |= 0x00000020u; -} - void FieldOptions::clear_has_csharp_property_name() { - _has_bits_[0] &= ~0x00000020u; -} - void FieldOptions::clear_csharp_property_name() { - csharp_property_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_csharp_property_name(); -} - const ::std::string& FieldOptions::csharp_property_name() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.csharp_property_name) - return csharp_property_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} - void FieldOptions::set_csharp_property_name(const ::std::string& value) { - set_has_csharp_property_name(); - csharp_property_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.csharp_property_name) -} - void FieldOptions::set_csharp_property_name(const char* value) { - set_has_csharp_property_name(); - csharp_property_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldOptions.csharp_property_name) -} - void FieldOptions::set_csharp_property_name(const char* value, size_t size) { - set_has_csharp_property_name(); - csharp_property_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldOptions.csharp_property_name) -} - ::std::string* FieldOptions::mutable_csharp_property_name() { - set_has_csharp_property_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.csharp_property_name) - return csharp_property_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} - ::std::string* FieldOptions::release_csharp_property_name() { - clear_has_csharp_property_name(); - return csharp_property_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} - void FieldOptions::set_allocated_csharp_property_name(::std::string* csharp_property_name) { - if (csharp_property_name != NULL) { - set_has_csharp_property_name(); - } else { - clear_has_csharp_property_name(); - } - csharp_property_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_property_name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldOptions.csharp_property_name) -} - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int FieldOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 106fc0b3..0c564abd 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -2196,18 +2196,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { bool weak() const; void set_weak(bool value); - // optional string csharp_property_name = 11; - bool has_csharp_property_name() const; - void clear_csharp_property_name(); - static const int kCsharpPropertyNameFieldNumber = 11; - const ::std::string& csharp_property_name() const; - void set_csharp_property_name(const ::std::string& value); - void set_csharp_property_name(const char* value); - void set_csharp_property_name(const char* value, size_t size); - ::std::string* mutable_csharp_property_name(); - ::std::string* release_csharp_property_name(); - void set_allocated_csharp_property_name(::std::string* csharp_property_name); - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; void clear_uninterpreted_option(); @@ -2233,8 +2221,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { inline void clear_has_deprecated(); inline void set_has_weak(); inline void clear_has_weak(); - inline void set_has_csharp_property_name(); - inline void clear_has_csharp_property_name(); ::google::protobuf::internal::ExtensionSet _extensions_; @@ -2246,7 +2232,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { bool lazy_; bool deprecated_; bool weak_; - ::google::protobuf::internal::ArenaStringPtr csharp_property_name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); @@ -5938,59 +5923,6 @@ inline void FieldOptions::set_weak(bool value) { // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) } -// optional string csharp_property_name = 11; -inline bool FieldOptions::has_csharp_property_name() const { - return (_has_bits_[0] & 0x00000020u) != 0; -} -inline void FieldOptions::set_has_csharp_property_name() { - _has_bits_[0] |= 0x00000020u; -} -inline void FieldOptions::clear_has_csharp_property_name() { - _has_bits_[0] &= ~0x00000020u; -} -inline void FieldOptions::clear_csharp_property_name() { - csharp_property_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_csharp_property_name(); -} -inline const ::std::string& FieldOptions::csharp_property_name() const { - // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.csharp_property_name) - return csharp_property_name_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -inline void FieldOptions::set_csharp_property_name(const ::std::string& value) { - set_has_csharp_property_name(); - csharp_property_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.csharp_property_name) -} -inline void FieldOptions::set_csharp_property_name(const char* value) { - set_has_csharp_property_name(); - csharp_property_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FieldOptions.csharp_property_name) -} -inline void FieldOptions::set_csharp_property_name(const char* value, size_t size) { - set_has_csharp_property_name(); - csharp_property_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldOptions.csharp_property_name) -} -inline ::std::string* FieldOptions::mutable_csharp_property_name() { - set_has_csharp_property_name(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.csharp_property_name) - return csharp_property_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -inline ::std::string* FieldOptions::release_csharp_property_name() { - clear_has_csharp_property_name(); - return csharp_property_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -inline void FieldOptions::set_allocated_csharp_property_name(::std::string* csharp_property_name) { - if (csharp_property_name != NULL) { - set_has_csharp_property_name(); - } else { - clear_has_csharp_property_name(); - } - csharp_property_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_property_name); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldOptions.csharp_property_name) -} - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int FieldOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 33e8a322..912e4301 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -491,12 +491,6 @@ message FieldOptions { // For Google-internal migration only. Do not use. optional bool weak = 10 [default=false]; - // Provides the ability to override the name of the property - // generated for this field. This is applied to all properties - // and methods to do with this field, including HasFoo, FooCount, - // FooList etc. - optional string csharp_property_name = 11; - // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; -- cgit v1.2.3 From 8e190d498c9e402c787e70cde4afc7124393bea6 Mon Sep 17 00:00:00 2001 From: Jan Tattermusch Date: Fri, 17 Apr 2015 11:07:02 -0700 Subject: temporarily removing csharp_umbrella_namespace file option --- .../protobuf/compiler/csharp/csharp_helpers.cc | 4 +- src/google/protobuf/descriptor.pb.cc | 200 +++++---------------- src/google/protobuf/descriptor.pb.h | 68 ------- src/google/protobuf/descriptor.proto | 7 - 4 files changed, 46 insertions(+), 233 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index cae12e2e..4580b7be 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -127,9 +127,7 @@ std::string GetFileUmbrellaClassname(const FileDescriptor* descriptor) { } std::string GetFileUmbrellaNamespace(const FileDescriptor* descriptor) { - if (descriptor->options().has_csharp_umbrella_namespace()) { - return descriptor->options().csharp_umbrella_namespace(); - } + // TODO(jtattermusch): reintroduce csharp_umbrella_namespace option bool collision = false; std::string umbrella_classname = GetFileUmbrellaClassname(descriptor); for(int i = 0; i < descriptor->message_type_count(); i++) { diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index aa5952c7..9e703d96 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -289,7 +289,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, _internal_metadata_), -1); FileOptions_descriptor_ = file->message_type(9); - static const int FileOptions_offsets_[16] = { + static const int FileOptions_offsets_[15] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), @@ -304,7 +304,6 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_enable_arenas_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, objc_class_prefix_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_namespace_), - GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, csharp_umbrella_namespace_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), }; FileOptions_reflection_ = @@ -665,7 +664,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "t_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.p" "rotobuf.MethodOptions\022\037\n\020client_streamin" "g\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010" - ":\005false\"\244\005\n\013FileOptions\022\024\n\014java_package\030" + ":\005false\"\201\005\n\013FileOptions\022\024\n\014java_package\030" "\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023j" "ava_multiple_files\030\n \001(\010:\005false\022,\n\035java_" "generate_equals_and_hash\030\024 \001(\010:\005false\022%\n" @@ -677,51 +676,51 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031" "\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_a" "renas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030" - "$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022!\n\031cshar" - "p_umbrella_namespace\030& \001(\t\022C\n\024uninterpre" - "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin" - "terpretedOption\":\n\014OptimizeMode\022\t\n\005SPEED" - "\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007" - "\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027message_set" - "_wire_format\030\001 \001(\010:\005false\022.\n\037no_standard" - "_descriptor_accessor\030\002 \001(\010:\005false\022\031\n\ndep" - "recated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007 \001(\010\022" + "$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022C\n\024unint" + "erpreted_option\030\347\007 \003(\0132$.google.protobuf" + ".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005" + "SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003" + "*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027messag" + "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta" + "ndard_descriptor_accessor\030\002 \001(\010:\005false\022\031" + "\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007" + " \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go" + "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200" + "\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.g" + "oogle.protobuf.FieldOptions.CType:\006STRIN" + "G\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031" + "\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:" + "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." + "google.protobuf.UninterpretedOption\"/\n\005C" + "Type\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIE" + "CE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow" + "_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google." "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"" - "\240\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.google" - ".protobuf.FieldOptions.CType:\006STRING\022\016\n\006" - "packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031\n\ndep" - "recated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005fals" - "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl" - "e.protobuf.UninterpretedOption\"/\n\005CType\022" - "\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*" - "\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow_alia" - "s\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022C\n\024un" - "interpreted_option\030\347\007 \003(\0132$.google.proto" - "buf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020En" - "umValueOptions\022\031\n\ndeprecated\030\001 \001(\010:\005fals" - "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl" - "e.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200" - "\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030! \001(\010:" + "}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:" "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." "google.protobuf.UninterpretedOption*\t\010\350\007" - "\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprecated\030! " - "\001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(" - "\0132$.google.protobuf.UninterpretedOption*" - "\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022;\n\004na" - "me\030\002 \003(\0132-.google.protobuf.Uninterpreted" - "Option.NamePart\022\030\n\020identifier_value\030\003 \001(" - "\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022negativ" - "e_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 \001(\001\022" - "\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_value" - "\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022\024\n" - "\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeInfo\022:" - "\n\010location\030\001 \003(\0132(.google.protobuf.Sourc" - "eCodeInfo.Location\032\206\001\n\010Location\022\020\n\004path\030" - "\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020leading_c" - "omments\030\003 \001(\t\022\031\n\021trailing_comments\030\004 \001(\t" - "\022!\n\031leading_detached_comments\030\006 \003(\tB)\n\023c" - "om.google.protobufB\020DescriptorProtosH\001", 4678); + "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!" + " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003" + "(\0132$.google.protobuf.UninterpretedOption" + "*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprecat" + "ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030" + "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" + "tion*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022" + ";\n\004name\030\002 \003(\0132-.google.protobuf.Uninterp" + "retedOption.NamePart\022\030\n\020identifier_value" + "\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022ne" + "gative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006" + " \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_" + "value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002" + "(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeI" + "nfo\022:\n\010location\030\001 \003(\0132(.google.protobuf." + "SourceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004" + "path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lead" + "ing_comments\030\003 \001(\t\022\031\n\021trailing_comments\030" + "\004 \001(\t\022!\n\031leading_detached_comments\030\006 \003(\t" + "B)\n\023com.google.protobufB\020DescriptorProto" + "sH\001", 4643); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -7020,7 +7019,6 @@ const int FileOptions::kDeprecatedFieldNumber; const int FileOptions::kCcEnableArenasFieldNumber; const int FileOptions::kObjcClassPrefixFieldNumber; const int FileOptions::kCsharpNamespaceFieldNumber; -const int FileOptions::kCsharpUmbrellaNamespaceFieldNumber; const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER @@ -7058,7 +7056,6 @@ void FileOptions::SharedCtor() { cc_enable_arenas_ = false; objc_class_prefix_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); csharp_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - csharp_umbrella_namespace_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } @@ -7073,7 +7070,6 @@ void FileOptions::SharedDtor() { go_package_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); objc_class_prefix_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); csharp_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - csharp_umbrella_namespace_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); if (this != default_instance_) { } } @@ -7126,7 +7122,7 @@ void FileOptions::Clear() { go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } } - if (_has_bits_[8 / 32] & 32512) { + if (_has_bits_[8 / 32] & 16128) { ZR_(java_generic_services_, cc_enable_arenas_); if (has_objc_class_prefix()) { objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); @@ -7134,9 +7130,6 @@ void FileOptions::Clear() { if (has_csharp_namespace()) { csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } - if (has_csharp_umbrella_namespace()) { - csharp_umbrella_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - } } #undef ZR_HELPER_ @@ -7379,23 +7372,6 @@ bool FileOptions::MergePartialFromCodedStream( } else { goto handle_unusual; } - if (input->ExpectTag(306)) goto parse_csharp_umbrella_namespace; - break; - } - - // optional string csharp_umbrella_namespace = 38; - case 38: { - if (tag == 306) { - parse_csharp_umbrella_namespace: - DO_(::google::protobuf::internal::WireFormatLite::ReadString( - input, this->mutable_csharp_umbrella_namespace())); - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_umbrella_namespace().data(), this->csharp_umbrella_namespace().length(), - ::google::protobuf::internal::WireFormat::PARSE, - "google.protobuf.FileOptions.csharp_umbrella_namespace"); - } else { - goto handle_unusual; - } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; } @@ -7540,16 +7516,6 @@ void FileOptions::SerializeWithCachedSizes( 37, this->csharp_namespace(), output); } - // optional string csharp_umbrella_namespace = 38; - if (has_csharp_umbrella_namespace()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_umbrella_namespace().data(), this->csharp_umbrella_namespace().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.csharp_umbrella_namespace"); - ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( - 38, this->csharp_umbrella_namespace(), output); - } - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -7671,17 +7637,6 @@ void FileOptions::SerializeWithCachedSizes( 37, this->csharp_namespace(), target); } - // optional string csharp_umbrella_namespace = 38; - if (has_csharp_umbrella_namespace()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( - this->csharp_umbrella_namespace().data(), this->csharp_umbrella_namespace().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE, - "google.protobuf.FileOptions.csharp_umbrella_namespace"); - target = - ::google::protobuf::internal::WireFormatLite::WriteStringToArray( - 38, this->csharp_umbrella_namespace(), target); - } - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (unsigned int i = 0, n = this->uninterpreted_option_size(); i < n; i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -7753,7 +7708,7 @@ int FileOptions::ByteSize() const { } } - if (_has_bits_[8 / 32] & 32512) { + if (_has_bits_[8 / 32] & 16128) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; @@ -7788,13 +7743,6 @@ int FileOptions::ByteSize() const { this->csharp_namespace()); } - // optional string csharp_umbrella_namespace = 38; - if (has_csharp_umbrella_namespace()) { - total_size += 2 + - ::google::protobuf::internal::WireFormatLite::StringSize( - this->csharp_umbrella_namespace()); - } - } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -7882,10 +7830,6 @@ void FileOptions::MergeFrom(const FileOptions& from) { set_has_csharp_namespace(); csharp_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_namespace_); } - if (from.has_csharp_umbrella_namespace()) { - set_has_csharp_umbrella_namespace(); - csharp_umbrella_namespace_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.csharp_umbrella_namespace_); - } } _extensions_.MergeFrom(from._extensions_); if (from._internal_metadata_.have_unknown_fields()) { @@ -7931,7 +7875,6 @@ void FileOptions::InternalSwap(FileOptions* other) { std::swap(cc_enable_arenas_, other->cc_enable_arenas_); objc_class_prefix_.Swap(&other->objc_class_prefix_); csharp_namespace_.Swap(&other->csharp_namespace_); - csharp_umbrella_namespace_.Swap(&other->csharp_umbrella_namespace_); uninterpreted_option_.UnsafeArenaSwap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); @@ -8432,59 +8375,6 @@ void FileOptions::InternalSwap(FileOptions* other) { // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) } -// optional string csharp_umbrella_namespace = 38; - bool FileOptions::has_csharp_umbrella_namespace() const { - return (_has_bits_[0] & 0x00004000u) != 0; -} - void FileOptions::set_has_csharp_umbrella_namespace() { - _has_bits_[0] |= 0x00004000u; -} - void FileOptions::clear_has_csharp_umbrella_namespace() { - _has_bits_[0] &= ~0x00004000u; -} - void FileOptions::clear_csharp_umbrella_namespace() { - csharp_umbrella_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_csharp_umbrella_namespace(); -} - const ::std::string& FileOptions::csharp_umbrella_namespace() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_umbrella_namespace) - return csharp_umbrella_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} - void FileOptions::set_csharp_umbrella_namespace(const ::std::string& value) { - set_has_csharp_umbrella_namespace(); - csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_umbrella_namespace) -} - void FileOptions::set_csharp_umbrella_namespace(const char* value) { - set_has_csharp_umbrella_namespace(); - csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_umbrella_namespace) -} - void FileOptions::set_csharp_umbrella_namespace(const char* value, size_t size) { - set_has_csharp_umbrella_namespace(); - csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_umbrella_namespace) -} - ::std::string* FileOptions::mutable_csharp_umbrella_namespace() { - set_has_csharp_umbrella_namespace(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_umbrella_namespace) - return csharp_umbrella_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} - ::std::string* FileOptions::release_csharp_umbrella_namespace() { - clear_has_csharp_umbrella_namespace(); - return csharp_umbrella_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} - void FileOptions::set_allocated_csharp_umbrella_namespace(::std::string* csharp_umbrella_namespace) { - if (csharp_umbrella_namespace != NULL) { - set_has_csharp_umbrella_namespace(); - } else { - clear_has_csharp_umbrella_namespace(); - } - csharp_umbrella_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_umbrella_namespace); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_umbrella_namespace) -} - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 0c564abd..5bebf4fd 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -1849,18 +1849,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { ::std::string* release_csharp_namespace(); void set_allocated_csharp_namespace(::std::string* csharp_namespace); - // optional string csharp_umbrella_namespace = 38; - bool has_csharp_umbrella_namespace() const; - void clear_csharp_umbrella_namespace(); - static const int kCsharpUmbrellaNamespaceFieldNumber = 38; - const ::std::string& csharp_umbrella_namespace() const; - void set_csharp_umbrella_namespace(const ::std::string& value); - void set_csharp_umbrella_namespace(const char* value); - void set_csharp_umbrella_namespace(const char* value, size_t size); - ::std::string* mutable_csharp_umbrella_namespace(); - ::std::string* release_csharp_umbrella_namespace(); - void set_allocated_csharp_umbrella_namespace(::std::string* csharp_umbrella_namespace); - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; int uninterpreted_option_size() const; void clear_uninterpreted_option(); @@ -1904,8 +1892,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void clear_has_objc_class_prefix(); inline void set_has_csharp_namespace(); inline void clear_has_csharp_namespace(); - inline void set_has_csharp_umbrella_namespace(); - inline void clear_has_csharp_umbrella_namespace(); ::google::protobuf::internal::ExtensionSet _extensions_; @@ -1922,7 +1908,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { ::google::protobuf::internal::ArenaStringPtr go_package_; ::google::protobuf::internal::ArenaStringPtr objc_class_prefix_; ::google::protobuf::internal::ArenaStringPtr csharp_namespace_; - ::google::protobuf::internal::ArenaStringPtr csharp_umbrella_namespace_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool java_generic_services_; bool py_generic_services_; @@ -5585,59 +5570,6 @@ inline void FileOptions::set_allocated_csharp_namespace(::std::string* csharp_na // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_namespace) } -// optional string csharp_umbrella_namespace = 38; -inline bool FileOptions::has_csharp_umbrella_namespace() const { - return (_has_bits_[0] & 0x00004000u) != 0; -} -inline void FileOptions::set_has_csharp_umbrella_namespace() { - _has_bits_[0] |= 0x00004000u; -} -inline void FileOptions::clear_has_csharp_umbrella_namespace() { - _has_bits_[0] &= ~0x00004000u; -} -inline void FileOptions::clear_csharp_umbrella_namespace() { - csharp_umbrella_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - clear_has_csharp_umbrella_namespace(); -} -inline const ::std::string& FileOptions::csharp_umbrella_namespace() const { - // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.csharp_umbrella_namespace) - return csharp_umbrella_namespace_.GetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -inline void FileOptions::set_csharp_umbrella_namespace(const ::std::string& value) { - set_has_csharp_umbrella_namespace(); - csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); - // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.csharp_umbrella_namespace) -} -inline void FileOptions::set_csharp_umbrella_namespace(const char* value) { - set_has_csharp_umbrella_namespace(); - csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); - // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.csharp_umbrella_namespace) -} -inline void FileOptions::set_csharp_umbrella_namespace(const char* value, size_t size) { - set_has_csharp_umbrella_namespace(); - csharp_umbrella_namespace_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), - ::std::string(reinterpret_cast(value), size)); - // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.csharp_umbrella_namespace) -} -inline ::std::string* FileOptions::mutable_csharp_umbrella_namespace() { - set_has_csharp_umbrella_namespace(); - // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.csharp_umbrella_namespace) - return csharp_umbrella_namespace_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -inline ::std::string* FileOptions::release_csharp_umbrella_namespace() { - clear_has_csharp_umbrella_namespace(); - return csharp_umbrella_namespace_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); -} -inline void FileOptions::set_allocated_csharp_umbrella_namespace(::std::string* csharp_umbrella_namespace) { - if (csharp_umbrella_namespace != NULL) { - set_has_csharp_umbrella_namespace(); - } else { - clear_has_csharp_umbrella_namespace(); - } - csharp_umbrella_namespace_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), csharp_umbrella_namespace); - // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.csharp_umbrella_namespace) -} - // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 912e4301..a4b64f65 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -354,13 +354,6 @@ message FileOptions { // Namespace for generated classes; defaults to the package. optional string csharp_namespace = 37; - // A nested namespace for the umbrella class, which contains metadata about - // all the messages within the file. This option is helpful for name - // collisions between the umbrella class and an existing type. This will be - // automatically set to 'Proto' if a collision is detected with types being - // generated. - optional string csharp_umbrella_namespace = 38; - // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; -- cgit v1.2.3 From 856ced5d767c7f4d0eb30eb28f5831c16871b149 Mon Sep 17 00:00:00 2001 From: Jie Luo Date: Mon, 27 Apr 2015 14:00:47 -0700 Subject: Field Presence: remove has methods for optional non-message fields in proto3 --- .../google/protobuf/field_presence_test.proto | 24 + .../TestProtos/FieldPresenceTestProtoFile.cs | 781 +++++++++++++++++++++ .../protobuf/compiler/csharp/csharp_enum_field.cc | 79 ++- .../protobuf/compiler/csharp/csharp_helpers.h | 4 + .../protobuf/compiler/csharp/csharp_message.cc | 4 +- .../compiler/csharp/csharp_primitive_field.cc | 84 ++- 6 files changed, 934 insertions(+), 42 deletions(-) create mode 100644 csharp/protos/google/protobuf/field_presence_test.proto create mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/FieldPresenceTestProtoFile.cs (limited to 'src/google/protobuf/compiler') diff --git a/csharp/protos/google/protobuf/field_presence_test.proto b/csharp/protos/google/protobuf/field_presence_test.proto new file mode 100644 index 00000000..43b4f04b --- /dev/null +++ b/csharp/protos/google/protobuf/field_presence_test.proto @@ -0,0 +1,24 @@ +syntax = "proto3"; + +package field_presence_test; + +option java_package = "com.google.protobuf"; +option java_outer_classname = "FieldPresenceTestProto"; +option java_generate_equals_and_hash = true; + +message TestAllTypes { + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + } + message NestedMessage { + optional int32 value = 1; + } + + optional int32 optional_int32 = 1; + optional string optional_string = 2; + optional bytes optional_bytes = 3; + optional NestedEnum optional_nested_enum = 4; + optional NestedMessage optional_nested_message = 5; +} diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/FieldPresenceTestProtoFile.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/FieldPresenceTestProtoFile.cs new file mode 100644 index 00000000..2ea69bc0 --- /dev/null +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/FieldPresenceTestProtoFile.cs @@ -0,0 +1,781 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: protos/google/protobuf/field_presence_test.proto +#pragma warning disable 1591, 0612, 3021 +#region Designer generated code + +using pb = global::Google.ProtocolBuffers; +using pbc = global::Google.ProtocolBuffers.Collections; +using pbd = global::Google.ProtocolBuffers.Descriptors; +using scg = global::System.Collections.Generic; +namespace field_presence_test { + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static partial class FieldPresenceTest { + + #region Extension registration + public static void RegisterAllExtensions(pb::ExtensionRegistry registry) { + } + #endregion + #region Static variables + internal static pbd::MessageDescriptor internal__static_field_presence_test_TestAllTypes__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_field_presence_test_TestAllTypes__FieldAccessorTable; + internal static pbd::MessageDescriptor internal__static_field_presence_test_TestAllTypes_NestedMessage__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_field_presence_test_TestAllTypes_NestedMessage__FieldAccessorTable; + #endregion + #region Descriptor + public static pbd::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbd::FileDescriptor descriptor; + + static FieldPresenceTest() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CjBwcm90b3MvZ29vZ2xlL3Byb3RvYnVmL2ZpZWxkX3ByZXNlbmNlX3Rlc3Qu", + "cHJvdG8SE2ZpZWxkX3ByZXNlbmNlX3Rlc3QivgIKDFRlc3RBbGxUeXBlcxIW", + "Cg5vcHRpb25hbF9pbnQzMhgBIAEoBRIXCg9vcHRpb25hbF9zdHJpbmcYAiAB", + "KAkSFgoOb3B0aW9uYWxfYnl0ZXMYAyABKAwSSgoUb3B0aW9uYWxfbmVzdGVk", + "X2VudW0YBCABKA4yLC5maWVsZF9wcmVzZW5jZV90ZXN0LlRlc3RBbGxUeXBl", + "cy5OZXN0ZWRFbnVtElAKF29wdGlvbmFsX25lc3RlZF9tZXNzYWdlGAUgASgL", + "Mi8uZmllbGRfcHJlc2VuY2VfdGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVz", + "c2FnZRoeCg1OZXN0ZWRNZXNzYWdlEg0KBXZhbHVlGAEgASgFIicKCk5lc3Rl", + "ZEVudW0SBwoDRk9PEAASBwoDQkFSEAESBwoDQkFaEAJCMAoTY29tLmdvb2ds", + "ZS5wcm90b2J1ZkIWRmllbGRQcmVzZW5jZVRlc3RQcm90b6ABAWIGcHJvdG8z")); + pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { + descriptor = root; + internal__static_field_presence_test_TestAllTypes__Descriptor = Descriptor.MessageTypes[0]; + internal__static_field_presence_test_TestAllTypes__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_field_presence_test_TestAllTypes__Descriptor, + new string[] { "OptionalInt32", "OptionalString", "OptionalBytes", "OptionalNestedEnum", "OptionalNestedMessage", }); + internal__static_field_presence_test_TestAllTypes_NestedMessage__Descriptor = internal__static_field_presence_test_TestAllTypes__Descriptor.NestedTypes[0]; + internal__static_field_presence_test_TestAllTypes_NestedMessage__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_field_presence_test_TestAllTypes_NestedMessage__Descriptor, + new string[] { "Value", }); + pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance(); + RegisterAllExtensions(registry); + return registry; + }; + pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData, + new pbd::FileDescriptor[] { + }, assigner); + } + #endregion + + } + #region Messages + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class TestAllTypes : pb::GeneratedMessage { + private TestAllTypes() { } + private static readonly TestAllTypes defaultInstance = new TestAllTypes().MakeReadOnly(); + private static readonly string[] _testAllTypesFieldNames = new string[] { "optional_bytes", "optional_int32", "optional_nested_enum", "optional_nested_message", "optional_string" }; + private static readonly uint[] _testAllTypesFieldTags = new uint[] { 26, 8, 32, 42, 18 }; + public static TestAllTypes DefaultInstance { + get { return defaultInstance; } + } + + public override TestAllTypes DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override TestAllTypes ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::field_presence_test.FieldPresenceTest.internal__static_field_presence_test_TestAllTypes__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::field_presence_test.FieldPresenceTest.internal__static_field_presence_test_TestAllTypes__FieldAccessorTable; } + } + + #region Nested types + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public static partial class Types { + public enum NestedEnum { + FOO = 0, + BAR = 1, + BAZ = 2, + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class NestedMessage : pb::GeneratedMessage { + private NestedMessage() { } + private static readonly NestedMessage defaultInstance = new NestedMessage().MakeReadOnly(); + private static readonly string[] _nestedMessageFieldNames = new string[] { "value" }; + private static readonly uint[] _nestedMessageFieldTags = new uint[] { 8 }; + public static NestedMessage DefaultInstance { + get { return defaultInstance; } + } + + public override NestedMessage DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override NestedMessage ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::field_presence_test.FieldPresenceTest.internal__static_field_presence_test_TestAllTypes_NestedMessage__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::field_presence_test.FieldPresenceTest.internal__static_field_presence_test_TestAllTypes_NestedMessage__FieldAccessorTable; } + } + + public const int ValueFieldNumber = 1; + private int value_; + public int Value { + get { return value_; } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _nestedMessageFieldNames; + if (Value != 0) { + output.WriteInt32(1, field_names[0], Value); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (Value != 0) { + size += pb::CodedOutputStream.ComputeInt32Size(1, Value); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static NestedMessage ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static NestedMessage ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static NestedMessage ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static NestedMessage ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static NestedMessage ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static NestedMessage ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static NestedMessage ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static NestedMessage ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static NestedMessage ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static NestedMessage ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private NestedMessage MakeReadOnly() { + return this; + } + + public static Builder CreateBuilder() { return new Builder(); } + public override Builder ToBuilder() { return CreateBuilder(this); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(NestedMessage prototype) { + return new Builder(prototype); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class Builder : pb::GeneratedBuilder { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() { + result = DefaultInstance; + resultIsReadOnly = true; + } + internal Builder(NestedMessage cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private NestedMessage result; + + private NestedMessage PrepareBuilder() { + if (resultIsReadOnly) { + NestedMessage original = result; + result = new NestedMessage(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override NestedMessage MessageBeingBuilt { + get { return PrepareBuilder(); } + } + + public override Builder Clear() { + result = DefaultInstance; + resultIsReadOnly = true; + return this; + } + + public override Builder Clone() { + if (resultIsReadOnly) { + return new Builder(result); + } else { + return new Builder().MergeFrom(result); + } + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return global::field_presence_test.TestAllTypes.Types.NestedMessage.Descriptor; } + } + + public override NestedMessage DefaultInstanceForType { + get { return global::field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance; } + } + + public override NestedMessage BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is NestedMessage) { + return MergeFrom((NestedMessage) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(NestedMessage other) { + if (other == global::field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance) return this; + PrepareBuilder(); + if (other.Value != 0) { + Value = other.Value; + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::ICodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + PrepareBuilder(); + pb::UnknownFieldSet.Builder unknownFields = null; + uint tag; + string field_name; + while (input.ReadTag(out tag, out field_name)) { + if(tag == 0 && field_name != null) { + int field_ordinal = global::System.Array.BinarySearch(_nestedMessageFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _nestedMessageFieldTags[field_ordinal]; + else { + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + continue; + } + } + switch (tag) { + case 0: { + throw pb::InvalidProtocolBufferException.InvalidTag(); + } + default: { + if (pb::WireFormat.IsEndGroupTag(tag)) { + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + break; + } + case 8: { + input.ReadInt32(ref result.value_); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public int Value { + get { return result.Value; } + set { SetValue(value); } + } + public Builder SetValue(int value) { + PrepareBuilder(); + result.value_ = value; + return this; + } + public Builder ClearValue() { + PrepareBuilder(); + result.value_ = 0; + return this; + } + } + static NestedMessage() { + object.ReferenceEquals(global::field_presence_test.FieldPresenceTest.Descriptor, null); + } + } + + } + #endregion + + public const int OptionalInt32FieldNumber = 1; + private int optionalInt32_; + public int OptionalInt32 { + get { return optionalInt32_; } + } + + public const int OptionalStringFieldNumber = 2; + private string optionalString_ = ""; + public string OptionalString { + get { return optionalString_; } + } + + public const int OptionalBytesFieldNumber = 3; + private pb::ByteString optionalBytes_ = pb::ByteString.Empty; + public pb::ByteString OptionalBytes { + get { return optionalBytes_; } + } + + public const int OptionalNestedEnumFieldNumber = 4; + private global::field_presence_test.TestAllTypes.Types.NestedEnum optionalNestedEnum_ = global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO; + public global::field_presence_test.TestAllTypes.Types.NestedEnum OptionalNestedEnum { + get { return optionalNestedEnum_; } + } + + public const int OptionalNestedMessageFieldNumber = 5; + private bool hasOptionalNestedMessage; + private global::field_presence_test.TestAllTypes.Types.NestedMessage optionalNestedMessage_; + public bool HasOptionalNestedMessage { + get { return hasOptionalNestedMessage; } + } + public global::field_presence_test.TestAllTypes.Types.NestedMessage OptionalNestedMessage { + get { return optionalNestedMessage_ ?? global::field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance; } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _testAllTypesFieldNames; + if (OptionalInt32 != 0) { + output.WriteInt32(1, field_names[1], OptionalInt32); + } + if (OptionalString != "") { + output.WriteString(2, field_names[4], OptionalString); + } + if (OptionalBytes != pb::ByteString.Empty) { + output.WriteBytes(3, field_names[0], OptionalBytes); + } + if (OptionalNestedEnum != global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO) { + output.WriteEnum(4, field_names[2], (int) OptionalNestedEnum, OptionalNestedEnum); + } + if (hasOptionalNestedMessage) { + output.WriteMessage(5, field_names[3], OptionalNestedMessage); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (OptionalInt32 != 0) { + size += pb::CodedOutputStream.ComputeInt32Size(1, OptionalInt32); + } + if (OptionalString != "") { + size += pb::CodedOutputStream.ComputeStringSize(2, OptionalString); + } + if (OptionalBytes != pb::ByteString.Empty) { + size += pb::CodedOutputStream.ComputeBytesSize(3, OptionalBytes); + } + if (OptionalNestedEnum != global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO) { + size += pb::CodedOutputStream.ComputeEnumSize(4, (int) OptionalNestedEnum); + } + if (hasOptionalNestedMessage) { + size += pb::CodedOutputStream.ComputeMessageSize(5, OptionalNestedMessage); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static TestAllTypes ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static TestAllTypes ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static TestAllTypes ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static TestAllTypes ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static TestAllTypes ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static TestAllTypes ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static TestAllTypes ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static TestAllTypes ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static TestAllTypes ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static TestAllTypes ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private TestAllTypes MakeReadOnly() { + return this; + } + + public static Builder CreateBuilder() { return new Builder(); } + public override Builder ToBuilder() { return CreateBuilder(this); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(TestAllTypes prototype) { + return new Builder(prototype); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class Builder : pb::GeneratedBuilder { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() { + result = DefaultInstance; + resultIsReadOnly = true; + } + internal Builder(TestAllTypes cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private TestAllTypes result; + + private TestAllTypes PrepareBuilder() { + if (resultIsReadOnly) { + TestAllTypes original = result; + result = new TestAllTypes(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override TestAllTypes MessageBeingBuilt { + get { return PrepareBuilder(); } + } + + public override Builder Clear() { + result = DefaultInstance; + resultIsReadOnly = true; + return this; + } + + public override Builder Clone() { + if (resultIsReadOnly) { + return new Builder(result); + } else { + return new Builder().MergeFrom(result); + } + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return global::field_presence_test.TestAllTypes.Descriptor; } + } + + public override TestAllTypes DefaultInstanceForType { + get { return global::field_presence_test.TestAllTypes.DefaultInstance; } + } + + public override TestAllTypes BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is TestAllTypes) { + return MergeFrom((TestAllTypes) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(TestAllTypes other) { + if (other == global::field_presence_test.TestAllTypes.DefaultInstance) return this; + PrepareBuilder(); + if (other.OptionalInt32 != 0) { + OptionalInt32 = other.OptionalInt32; + } + if (other.OptionalString != "") { + OptionalString = other.OptionalString; + } + if (other.OptionalBytes != pb::ByteString.Empty) { + OptionalBytes = other.OptionalBytes; + } + if (other.OptionalNestedEnum != global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO) { + OptionalNestedEnum = other.OptionalNestedEnum; + } + if (other.HasOptionalNestedMessage) { + MergeOptionalNestedMessage(other.OptionalNestedMessage); + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::ICodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + PrepareBuilder(); + pb::UnknownFieldSet.Builder unknownFields = null; + uint tag; + string field_name; + while (input.ReadTag(out tag, out field_name)) { + if(tag == 0 && field_name != null) { + int field_ordinal = global::System.Array.BinarySearch(_testAllTypesFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _testAllTypesFieldTags[field_ordinal]; + else { + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + continue; + } + } + switch (tag) { + case 0: { + throw pb::InvalidProtocolBufferException.InvalidTag(); + } + default: { + if (pb::WireFormat.IsEndGroupTag(tag)) { + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + break; + } + case 8: { + input.ReadInt32(ref result.optionalInt32_); + break; + } + case 18: { + input.ReadString(ref result.optionalString_); + break; + } + case 26: { + input.ReadBytes(ref result.optionalBytes_); + break; + } + case 32: { + object unknown; + if(input.ReadEnum(ref result.optionalNestedEnum_, out unknown)) { + } else if(unknown is int) { + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + unknownFields.MergeVarintField(4, (ulong)(int)unknown); + } + break; + } + case 42: { + global::field_presence_test.TestAllTypes.Types.NestedMessage.Builder subBuilder = global::field_presence_test.TestAllTypes.Types.NestedMessage.CreateBuilder(); + if (result.hasOptionalNestedMessage) { + subBuilder.MergeFrom(OptionalNestedMessage); + } + input.ReadMessage(subBuilder, extensionRegistry); + OptionalNestedMessage = subBuilder.BuildPartial(); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public int OptionalInt32 { + get { return result.OptionalInt32; } + set { SetOptionalInt32(value); } + } + public Builder SetOptionalInt32(int value) { + PrepareBuilder(); + result.optionalInt32_ = value; + return this; + } + public Builder ClearOptionalInt32() { + PrepareBuilder(); + result.optionalInt32_ = 0; + return this; + } + + public string OptionalString { + get { return result.OptionalString; } + set { SetOptionalString(value); } + } + public Builder SetOptionalString(string value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.optionalString_ = value; + return this; + } + public Builder ClearOptionalString() { + PrepareBuilder(); + result.optionalString_ = ""; + return this; + } + + public pb::ByteString OptionalBytes { + get { return result.OptionalBytes; } + set { SetOptionalBytes(value); } + } + public Builder SetOptionalBytes(pb::ByteString value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.optionalBytes_ = value; + return this; + } + public Builder ClearOptionalBytes() { + PrepareBuilder(); + result.optionalBytes_ = pb::ByteString.Empty; + return this; + } + + public global::field_presence_test.TestAllTypes.Types.NestedEnum OptionalNestedEnum { + get { return result.OptionalNestedEnum; } + set { SetOptionalNestedEnum(value); } + } + public Builder SetOptionalNestedEnum(global::field_presence_test.TestAllTypes.Types.NestedEnum value) { + PrepareBuilder(); + result.optionalNestedEnum_ = value; + return this; + } + public Builder ClearOptionalNestedEnum() { + PrepareBuilder(); + result.optionalNestedEnum_ = global::field_presence_test.TestAllTypes.Types.NestedEnum.FOO; + return this; + } + + public bool HasOptionalNestedMessage { + get { return result.hasOptionalNestedMessage; } + } + public global::field_presence_test.TestAllTypes.Types.NestedMessage OptionalNestedMessage { + get { return result.OptionalNestedMessage; } + set { SetOptionalNestedMessage(value); } + } + public Builder SetOptionalNestedMessage(global::field_presence_test.TestAllTypes.Types.NestedMessage value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.hasOptionalNestedMessage = true; + result.optionalNestedMessage_ = value; + return this; + } + public Builder SetOptionalNestedMessage(global::field_presence_test.TestAllTypes.Types.NestedMessage.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.hasOptionalNestedMessage = true; + result.optionalNestedMessage_ = builderForValue.Build(); + return this; + } + public Builder MergeOptionalNestedMessage(global::field_presence_test.TestAllTypes.Types.NestedMessage value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + if (result.hasOptionalNestedMessage && + result.optionalNestedMessage_ != global::field_presence_test.TestAllTypes.Types.NestedMessage.DefaultInstance) { + result.optionalNestedMessage_ = global::field_presence_test.TestAllTypes.Types.NestedMessage.CreateBuilder(result.optionalNestedMessage_).MergeFrom(value).BuildPartial(); + } else { + result.optionalNestedMessage_ = value; + } + result.hasOptionalNestedMessage = true; + return this; + } + public Builder ClearOptionalNestedMessage() { + PrepareBuilder(); + result.hasOptionalNestedMessage = false; + result.optionalNestedMessage_ = null; + return this; + } + } + static TestAllTypes() { + object.ReferenceEquals(global::field_presence_test.FieldPresenceTest.Descriptor, null); + } + } + + #endregion + +} + +#endregion Designer generated code diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index d5b1b477..1fbd1c6c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -56,13 +56,17 @@ EnumFieldGenerator::~EnumFieldGenerator() { } void EnumFieldGenerator::GenerateMembers(Writer* writer) { - writer->WriteLine("private bool has$0$;", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("private bool has$0$;", property_name()); + } writer->WriteLine("private $0$ $1$_ = $2$;", type_name(), name(), default_value()); AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return has$0$; }", property_name()); - writer->WriteLine("}"); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return has$0$; }", property_name()); + writer->WriteLine("}"); + } AddPublicMemberAttributes(writer); writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); writer->WriteLine(" get { return $0$_; }", name()); @@ -71,9 +75,11 @@ void EnumFieldGenerator::GenerateMembers(Writer* writer) { void EnumFieldGenerator::GenerateBuilderMembers(Writer* writer) { AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.has$0$; }", property_name()); - writer->WriteLine("}"); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return result.has$0$; }", property_name()); + writer->WriteLine("}"); + } AddPublicMemberAttributes(writer); writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); writer->WriteLine(" get { return result.$0$; }", property_name()); @@ -83,21 +89,29 @@ void EnumFieldGenerator::GenerateBuilderMembers(Writer* writer) { writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), type_name()); writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = true;", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine(" result.has$0$ = true;", property_name()); + } writer->WriteLine(" result.$0$_ = value;", name()); writer->WriteLine(" return this;"); writer->WriteLine("}"); AddDeprecatedFlag(writer); writer->WriteLine("public Builder Clear$0$() {", property_name()); writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = false;", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine(" result.has$0$ = false;", property_name()); + } writer->WriteLine(" result.$0$_ = $1$;", name(), default_value()); writer->WriteLine(" return this;"); writer->WriteLine("}"); } void EnumFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.Has$0$) {", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("if (other.Has$0$) {", property_name()); + } else { + writer->WriteLine("if (other.$0$ != $1$) {", property_name(), default_value()); + } writer->WriteLine(" $0$ = other.$0$;", property_name()); writer->WriteLine("}"); } @@ -110,7 +124,9 @@ void EnumFieldGenerator::GenerateParsingCode(Writer* writer) { writer->WriteLine("object unknown;"); writer->WriteLine("if(input.ReadEnum(ref result.$0$_, out unknown)) {", name()); - writer->WriteLine(" result.has$0$ = true;", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine(" result.has$0$ = true;", property_name()); + } writer->WriteLine("} else if(unknown is int) {"); if (!use_lite_runtime()) { writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now @@ -125,7 +141,11 @@ void EnumFieldGenerator::GenerateParsingCode(Writer* writer) { } void EnumFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if (has$0$) {", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("if (has$0$) {", property_name()); + } else { + writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); + } writer->WriteLine( " output.WriteEnum($0$, field_names[$2$], (int) $1$, $1$);", number(), property_name(), field_ordinal()); @@ -133,7 +153,11 @@ void EnumFieldGenerator::GenerateSerializationCode(Writer* writer) { } void EnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if (has$0$) {", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("if (has$0$) {", property_name()); + } else { + writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); + } writer->WriteLine( " size += pb::CodedOutputStream.ComputeEnumSize($0$, (int) $1$);", number(), property_name()); @@ -141,17 +165,32 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { } void EnumFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("if (has$0$) hash ^= $1$_.GetHashCode();", property_name(), - name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("if (has$0$) {", property_name()); + } else { + writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); + } + writer->WriteLine(" hash ^= $1$_.GetHashCode();", name()); + writer->WriteLine("}"); } void EnumFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine( - "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", - property_name(), name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine( + "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", + property_name(), name()); + } else { + writer->WriteLine( + "if (!$0$_.Equals(other.$0$_)) return false;", name()); + } } void EnumFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", has$1$, $2$_, writer);", - descriptor_->name(), property_name(), name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("PrintField(\"$0$\", has$1$, $2$_, writer);", + descriptor_->name(), property_name(), name()); + } else { + writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", + descriptor_->name(), name()); + } } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h index 8fdd214e..bc77f43a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.h +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h @@ -101,6 +101,10 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, int bool HasRequiredFields(const Descriptor* descriptor); +inline bool SupportFieldPresence(const FileDescriptor* file) { + return file->syntax() != FileDescriptor::SYNTAX_PROTO3; +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index f7c8ddfb..36f41c70 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -279,7 +279,9 @@ void MessageGenerator::Generate(Writer* writer) { } if (optimize_speed()) { - GenerateIsInitialized(writer); + if (SupportFieldPresence(descriptor_->file())) { + GenerateIsInitialized(writer); + } GenerateMessageSerializationMethods(writer); } if (use_lite_runtime()) { diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index 54287b41..10e886eb 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -57,13 +57,17 @@ PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { } void PrimitiveFieldGenerator::GenerateMembers(Writer* writer) { - writer->WriteLine("private bool has$0$;", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("private bool has$0$;", property_name()); + } writer->WriteLine("private $0$ $1$_$2$;", type_name(), name(), has_default_value() ? " = " + default_value() : ""); AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return has$0$; }", property_name()); - writer->WriteLine("}"); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return has$0$; }", property_name()); + writer->WriteLine("}"); + } AddPublicMemberAttributes(writer); writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); writer->WriteLine(" get { return $0$_; }", name()); @@ -72,9 +76,11 @@ void PrimitiveFieldGenerator::GenerateMembers(Writer* writer) { void PrimitiveFieldGenerator::GenerateBuilderMembers(Writer* writer) { AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.has$0$; }", property_name()); - writer->WriteLine("}"); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return result.has$0$; }", property_name()); + writer->WriteLine("}"); + } AddPublicMemberAttributes(writer); writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); writer->WriteLine(" get { return result.$0$; }", property_name()); @@ -85,21 +91,29 @@ void PrimitiveFieldGenerator::GenerateBuilderMembers(Writer* writer) { type_name()); AddNullCheck(writer); writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = true;", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine(" result.has$0$ = true;", property_name()); + } writer->WriteLine(" result.$0$_ = value;", name()); writer->WriteLine(" return this;"); writer->WriteLine("}"); AddDeprecatedFlag(writer); writer->WriteLine("public Builder Clear$0$() {", property_name()); writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = false;", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine(" result.has$0$ = false;", property_name()); + } writer->WriteLine(" result.$0$_ = $1$;", name(), default_value()); writer->WriteLine(" return this;"); writer->WriteLine("}"); } void PrimitiveFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.Has$0$) {", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("if (other.Has$0$) {", property_name()); + } else { + writer->WriteLine("if (other.$0$ != $1$) {", property_name(), default_value()); + } writer->WriteLine(" $0$ = other.$0$;", property_name()); writer->WriteLine("}"); } @@ -109,12 +123,21 @@ void PrimitiveFieldGenerator::GenerateBuildingCode(Writer* writer) { } void PrimitiveFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("result.has$0$ = input.Read$1$(ref result.$2$_);", - property_name(), capitalized_type_name(), name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("result.has$0$ = input.Read$1$(ref result.$2$_);", + property_name(), capitalized_type_name(), name()); + } else { + writer->WriteLine("input.Read$0$(ref result.$1$_);", + capitalized_type_name(), name()); + } } void PrimitiveFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if (has$0$) {", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("if (has$0$) {", property_name()); + } else { + writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); + } writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", capitalized_type_name(), number(), property_name(), field_ordinal()); @@ -122,24 +145,43 @@ void PrimitiveFieldGenerator::GenerateSerializationCode(Writer* writer) { } void PrimitiveFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if (has$0$) {", property_name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("if (has$0$) {", property_name()); + } else { + writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); + } writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", capitalized_type_name(), number(), property_name()); writer->WriteLine("}"); } void PrimitiveFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("if (has$0$) hash ^= $1$_.GetHashCode();", property_name(), - name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("if (has$0$) {", property_name()); + } else { + writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); + } + writer->WriteLine(" hash ^= $1$_.GetHashCode();", name()); + writer->WriteLine("}"); } void PrimitiveFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine( - "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", - property_name(), name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine( + "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", + property_name(), name()); + } else { + writer->WriteLine( + "if (!$0$_.Equals(other.$0$_)) return false;", name()); + } } void PrimitiveFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", has$1$, $2$_, writer);", - descriptor_->name(), property_name(), name()); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("PrintField(\"$0$\", has$1$, $2$_, writer);", + descriptor_->name(), property_name(), name()); + } else { + writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", + descriptor_->name(), name()); + } } } // namespace csharp -- cgit v1.2.3 From 5a811ac6f9d92a6875a7a1e0f1cdb8058640cc62 Mon Sep 17 00:00:00 2001 From: Jie Luo Date: Mon, 27 Apr 2015 14:27:21 -0700 Subject: fix bug for Field Presence --- src/google/protobuf/compiler/csharp/csharp_enum_field.cc | 2 +- src/google/protobuf/compiler/csharp/csharp_primitive_field.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 1fbd1c6c..34d1c5c6 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -170,7 +170,7 @@ void EnumFieldGenerator::WriteHash(Writer* writer) { } else { writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); } - writer->WriteLine(" hash ^= $1$_.GetHashCode();", name()); + writer->WriteLine(" hash ^= $0$_.GetHashCode();", name()); writer->WriteLine("}"); } void EnumFieldGenerator::WriteEquals(Writer* writer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index 10e886eb..a193afda 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -161,7 +161,7 @@ void PrimitiveFieldGenerator::WriteHash(Writer* writer) { } else { writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); } - writer->WriteLine(" hash ^= $1$_.GetHashCode();", name()); + writer->WriteLine(" hash ^= $0$_.GetHashCode();", name()); writer->WriteLine("}"); } void PrimitiveFieldGenerator::WriteEquals(Writer* writer) { -- cgit v1.2.3 From 9a121853236a8c77693f14d21d27987e5832176a Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Mon, 27 Apr 2015 14:47:04 -0700 Subject: Handle un-handled cases of TestOneof2 in unittest Change-Id: I8f082ee3117ed873ab472a539867ff7cae58e8fd --- src/google/protobuf/compiler/cpp/cpp_unittest.cc | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index cc758cf5..9d14a924 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -1392,6 +1392,12 @@ class OneofTest : public testing::Test { case unittest::TestOneof2::kFooString: EXPECT_TRUE(message.has_foo_string()); break; + case unittest::TestOneof2::kFooCord: + EXPECT_TRUE(message.has_foo_cord()); + break; + case unittest::TestOneof2::kFooStringPiece: + EXPECT_TRUE(message.has_foo_string_piece()); + break; case unittest::TestOneof2::kFooBytes: EXPECT_TRUE(message.has_foo_bytes()); break; @@ -1404,6 +1410,9 @@ class OneofTest : public testing::Test { case unittest::TestOneof2::kFoogroup: EXPECT_TRUE(message.has_foogroup()); break; + case unittest::TestOneof2::kFooLazyMessage: + EXPECT_TRUE(message.has_foo_lazy_message()); + break; case unittest::TestOneof2::FOO_NOT_SET: break; } -- cgit v1.2.3 From 46bd60b92f593a62e150c93cb8761148f6830b47 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Mon, 27 Apr 2015 17:44:45 -0700 Subject: Modify directory to use in test Change-Id: Iede1dc4e70427663e0d3c5304fa86b3aebf492b7 --- src/google/protobuf/compiler/command_line_interface_unittest.cc | 6 ++++++ src/google/protobuf/testing/googletest.cc | 4 ++++ 2 files changed, 10 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index a2cbbdc6..e284c791 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -288,6 +288,7 @@ void CommandLineInterfaceTest::Run(const string& command) { if (!disallow_plugins_) { cli_.AllowPlugins("prefix-"); +#ifndef GOOGLE_THIRD_PARTY_PROTOBUF const char* possible_paths[] = { // When building with shared libraries, libtool hides the real executable // in .libs and puts a fake wrapper in the current directory. @@ -316,6 +317,11 @@ void CommandLineInterfaceTest::Run(const string& command) { } if (plugin_path.empty()) { +#else + string plugin_path = "third_party/protobuf/test_plugin"; + + if (access(plugin_path.c_str(), F_OK) != 0) { +#endif // GOOGLE_THIRD_PARTY_PROTOBUF GOOGLE_LOG(ERROR) << "Plugin executable not found. Plugin tests are likely to fail."; } else { diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc index d72fa5c0..5f6a199a 100644 --- a/src/google/protobuf/testing/googletest.cc +++ b/src/google/protobuf/testing/googletest.cc @@ -65,6 +65,7 @@ namespace protobuf { #endif string TestSourceDir() { +#ifndef GOOGLE_THIRD_PARTY_PROTOBUF #ifdef _MSC_VER // Look for the "src" directory. string prefix = "."; @@ -88,6 +89,9 @@ string TestSourceDir() { return result; } #endif +#else + return "third_party/protobuf/src"; +#endif // GOOGLE_THIRD_PARTY_PROTOBUF } namespace { -- cgit v1.2.3 From ec2f2445546b3e63e4102c3541d4330e97cef07e Mon Sep 17 00:00:00 2001 From: Brian Duff Date: Fri, 3 Oct 2014 14:41:43 -0700 Subject: Fix bug with large extension field numbers. Previously, extensions with field numbers greater than 268435455 would result in a compile time error in generated code that looks something like this: Foo.java:3178: error: integer number too large: 3346754610 3346754610); This is because we were trying to represent the tag number (an unsigned int) using a java int constant, but java int constants are signed, and can't exceed Integer.MAX_VALUE. Fixed by declaring it as a long instead, and casting it down to an int in the implementation. This is safe, because the tag value always fits in 32 bis. Change-Id: If2017bacb4e20af667eaeaf9b65ddc2c30a7709f --- .../java/com/google/protobuf/nano/Extension.java | 22 ++++++++++++++-------- .../com/google/protobuf/nano/Extension.java.rej | 13 +++++++++++++ .../protobuf/nano/unittest_extension_nano.proto | 3 +++ .../compiler/javanano/javanano_extension.cc | 2 +- 4 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 javanano/src/main/java/com/google/protobuf/nano/Extension.java.rej (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/Extension.java b/javanano/src/main/java/com/google/protobuf/nano/Extension.java index c29b030f..2d091f01 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/Extension.java +++ b/javanano/src/main/java/com/google/protobuf/nano/Extension.java @@ -74,6 +74,11 @@ public class Extension, T> { public static final int TYPE_SINT32 = InternalNano.TYPE_SINT32; public static final int TYPE_SINT64 = InternalNano.TYPE_SINT64; + // Note: these create...() methods take a long for the tag parameter, + // because tags are represented as unsigned longs, and these values exist + // in generated code as long values. However, they can fit in 32-bits, so + // it's safe to cast them to int without loss of precision. + /** * Creates an {@code Extension} of the given message type and tag number. * Should be used by the generated code only. @@ -81,8 +86,8 @@ public class Extension, T> { * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} */ public static , T extends MessageNano> - Extension createMessageTyped(int type, Class clazz, int tag) { - return new Extension(type, clazz, tag, false); + Extension createMessageTyped(int type, Class clazz, long tag) { + return new Extension(type, clazz, (int) tag, false); } /** @@ -92,8 +97,8 @@ public class Extension, T> { * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP} */ public static , T extends MessageNano> - Extension createRepeatedMessageTyped(int type, Class clazz, int tag) { - return new Extension(type, clazz, tag, true); + Extension createRepeatedMessageTyped(int type, Class clazz, long tag) { + return new Extension(type, clazz, (int) tag, true); } /** @@ -104,8 +109,8 @@ public class Extension, T> { * @param clazz the boxed Java type of this extension */ public static , T> - Extension createPrimitiveTyped(int type, Class clazz, int tag) { - return new PrimitiveExtension(type, clazz, tag, false, 0, 0); + Extension createPrimitiveTyped(int type, Class clazz, long tag) { + return new PrimitiveExtension(type, clazz, (int) tag, false, 0, 0); } /** @@ -117,8 +122,9 @@ public class Extension, T> { */ public static , T> Extension createRepeatedPrimitiveTyped( - int type, Class clazz, int tag, int nonPackedTag, int packedTag) { - return new PrimitiveExtension(type, clazz, tag, true, nonPackedTag, packedTag); + int type, Class clazz, long tag, long nonPackedTag, long packedTag) { + return new PrimitiveExtension(type, clazz, (int) tag, true, + (int) nonPackedTag, (int) packedTag); } /** diff --git a/javanano/src/main/java/com/google/protobuf/nano/Extension.java.rej b/javanano/src/main/java/com/google/protobuf/nano/Extension.java.rej new file mode 100644 index 00000000..465495a7 --- /dev/null +++ b/javanano/src/main/java/com/google/protobuf/nano/Extension.java.rej @@ -0,0 +1,13 @@ +diff a/javanano/src/main/java/com/google/protobuf/nano/Extension.java b/javanano/src/main/java/com/google/protobuf/nano/Extension.java (rejected hunks) +@@ -74,6 +74,11 @@ public class Extension, T> { + public static final int TYPE_SINT32 = 17; + public static final int TYPE_SINT64 = 18; + ++ // Note: these create...() methods take a long for the tag parameter, ++ // because tags are represented as unsigned longs, and these values exist ++ // in generated code as long values. However, they can fit in 32-bits, so ++ // it's safe to cast them to int without loss of precision. ++ + /** + * Creates an {@code Extension} of the given message type and tag number. + * Should be used by the generated code only. diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto index 2a678a80..d1c5766d 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto +++ b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto @@ -21,6 +21,9 @@ message AnotherMessage { message ContainerMessage { extend ExtendableMessage { optional bool another_thing = 100; + // The largest permitted field number, per + // https://developers.google.com/protocol-buffers/docs/proto#simple + optional bool large_field_number = 536870911; } } diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc index 754ed550..0b9d1d8d 100644 --- a/src/google/protobuf/compiler/javanano/javanano_extension.cc +++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc @@ -140,7 +140,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) const { " com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n" " com.google.protobuf.nano.Extension.$type$,\n" " $class$.class,\n" - " $tag_params$);\n"); + " $tag_params$L);\n"); } } // namespace javanano -- cgit v1.2.3 From fb96026b8deb79aa023c9f5c460582e8fea8f331 Mon Sep 17 00:00:00 2001 From: Brian Duff Date: Fri, 9 Jan 2015 13:32:38 -0800 Subject: When no clear() is generated, still initialize fields. https://android-review.googlesource.com/#/c/67890/ removed field initialization from the ctor, making it just call clear() instead. When I added the generate_clear option back (as part of the reftypes compat mode) in https://android-review.googlesource.com/#/c/109530/, I forgot to ensure that what clear() used to do was inlined in the constructor. This change fixes NPEs that are happening for users of reftypes_compat_mode who rely on unset repeated fields being empty arrays rather than null. Change-Id: Idb58746c60f4a4054b7ebb5c3b0e76b16ff88184 --- javanano/pom.xml | 9 ++++++ .../java/com/google/protobuf/nano/NanoTest.java | 6 ++++ .../protobuf/compiler/javanano/javanano_message.cc | 32 ++++++++++++++-------- .../protobuf/compiler/javanano/javanano_message.h | 1 + 4 files changed, 36 insertions(+), 12 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/pom.xml b/javanano/pom.xml index 7a2be9df..64ed4372 100644 --- a/javanano/pom.xml +++ b/javanano/pom.xml @@ -139,6 +139,15 @@ + + + + + target/generated-test-sources diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java index d60e94ff..c81846e5 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java +++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java @@ -36,6 +36,7 @@ import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors; import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas; import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano; import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano; +import com.google.protobuf.nano.NanoReferenceTypesCompat; import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano; import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano; import com.google.protobuf.nano.testext.Extensions; @@ -4381,6 +4382,11 @@ public class NanoTest extends TestCase { assertMapSet(testMap.sfixed64ToSfixed64Field, int64Values, int64Values); } + public void testRepeatedFieldInitializedInReftypesCompatMode() { + NanoReferenceTypesCompat.TestAllTypesNano proto = new NanoReferenceTypesCompat.TestAllTypesNano(); + assertNotNull(proto.repeatedString); + } + private void assertRepeatedPackablesEqual( NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) { // Not using MessageNano.equals() -- that belongs to a separate test. diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 707f6b84..d5cbe9ce 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -288,14 +288,18 @@ void MessageGenerator::Generate(io::Printer* printer) { } printer->Print("}\n"); } else { + printer->Print( + "\n" + "public $classname$() {\n", + "classname", descriptor_->name()); if (params_.generate_clear()) { - printer->Print( - "\n" - "public $classname$() {\n" - " clear();\n" - "}\n", - "classname", descriptor_->name()); + printer->Print(" clear();\n"); + } else { + printer->Indent(); + GenerateFieldInitializers(printer); + printer->Outdent(); } + printer->Print("}\n"); } // Other methods in this class @@ -495,6 +499,15 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { "classname", descriptor_->name()); printer->Indent(); + GenerateFieldInitializers(printer); + + printer->Outdent(); + printer->Print( + " return this;\n" + "}\n"); +} + +void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) { // Clear bit fields. int totalInts = (field_generators_.total_bits() + 31) / 32; for (int i = 0; i < totalInts; i++) { @@ -520,12 +533,7 @@ void MessageGenerator::GenerateClear(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print("unknownFieldData = null;\n"); } - - printer->Outdent(); - printer->Print( - " cachedSize = -1;\n" - " return this;\n" - "}\n"); + printer->Print("cachedSize = -1;\n"); } void MessageGenerator::GenerateEquals(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h index 6f25a3a0..8504aa83 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.h +++ b/src/google/protobuf/compiler/javanano/javanano_message.h @@ -77,6 +77,7 @@ class MessageGenerator { const FieldDescriptor* field); void GenerateClear(io::Printer* printer); + void GenerateFieldInitializers(io::Printer* printer); void GenerateEquals(io::Printer* printer); void GenerateHashCode(io::Printer* printer); -- cgit v1.2.3 From d099a88685bf4b2df1689eb4cc56e75065cb87b1 Mon Sep 17 00:00:00 2001 From: Brian Duff Date: Wed, 1 Oct 2014 13:33:40 -0700 Subject: Add clone() method support for nano. Upstreamed from Another Place (cr/57247854). Change-Id: I2aaf59544c0f5ae21a51891d8a5eeda1dc722c90 --- javanano/pom.xml | 6 +-- .../protobuf/nano/ExtendableMessageNano.java | 7 +++ .../java/com/google/protobuf/nano/FieldArray.java | 17 ++++++- .../java/com/google/protobuf/nano/FieldData.java | 52 +++++++++++++++++++++- .../com/google/protobuf/nano/InternalNano.java | 8 ++++ .../java/com/google/protobuf/nano/MessageNano.java | 8 ++++ .../com/google/protobuf/nano/UnknownFieldData.java | 4 ++ .../java/com/google/protobuf/nano/NanoTest.java | 20 +++++++++ .../protobuf/nano/unittest_extension_nano.proto | 1 + .../compiler/javanano/javanano_enum_field.cc | 8 ++++ .../compiler/javanano/javanano_enum_field.h | 1 + .../protobuf/compiler/javanano/javanano_field.h | 1 + .../compiler/javanano/javanano_generator.cc | 2 + .../protobuf/compiler/javanano/javanano_message.cc | 44 ++++++++++++++++-- .../protobuf/compiler/javanano/javanano_message.h | 1 + .../compiler/javanano/javanano_message_field.cc | 29 ++++++++++++ .../compiler/javanano/javanano_message_field.h | 3 ++ .../protobuf/compiler/javanano/javanano_params.h | 11 ++++- .../compiler/javanano/javanano_primitive_field.cc | 8 ++++ .../compiler/javanano/javanano_primitive_field.h | 1 + 20 files changed, 222 insertions(+), 10 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/pom.xml b/javanano/pom.xml index 64ed4372..3d8cfb9f 100644 --- a/javanano/pom.xml +++ b/javanano/pom.xml @@ -97,19 +97,19 @@ - + - + - + diff --git a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java index b979390d..aeacbbf3 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java @@ -184,4 +184,11 @@ public abstract class ExtendableMessageNano> return (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : unknownFieldData.hashCode()); } + + @Override + public M clone() throws CloneNotSupportedException { + M cloned = (M) super.clone(); + InternalNano.cloneUnknownFieldData(this, cloned); + return cloned; + } } diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java b/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java index cdb66da2..c2044f6a 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java +++ b/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java @@ -37,7 +37,7 @@ package com.google.protobuf.nano; * * Based on {@link android.support.v4.util.SpareArrayCompat}. */ -class FieldArray { +class FieldArray implements Cloneable { private static final FieldData DELETED = new FieldData(); private boolean mGarbage = false; @@ -270,4 +270,19 @@ class FieldArray { } return true; } + + @Override + public final FieldArray clone() { + // Trigger GC so we compact and don't copy DELETED elements. + int size = size(); + FieldArray clone = new FieldArray(size); + System.arraycopy(mFieldNumbers, 0, clone.mFieldNumbers, 0, size); + for (int i = 0; i < size; i++) { + if (mData[i] != null) { + clone.mData[i] = mData[i].clone(); + } + } + clone.mSize = size; + return clone; + } } diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldData.java b/javanano/src/main/java/com/google/protobuf/nano/FieldData.java index 21ead88b..ebebabc8 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/FieldData.java +++ b/javanano/src/main/java/com/google/protobuf/nano/FieldData.java @@ -39,7 +39,7 @@ import java.util.List; * Stores unknown fields. These might be extensions or fields that the generated API doesn't * know about yet. */ -class FieldData { +class FieldData implements Cloneable { private Extension cachedExtension; private Object value; /** The serialised values for this object. Will be cleared if getValue is called */ @@ -187,4 +187,54 @@ class FieldData { return result; } + @Override + public final FieldData clone() { + FieldData clone = new FieldData(); + try { + clone.cachedExtension = cachedExtension; + if (unknownFieldData == null) { + clone.unknownFieldData = null; + } else { + clone.unknownFieldData.addAll(unknownFieldData); + } + + // Whether we need to deep clone value depends on its type. Primitive reference types + // (e.g. Integer, Long etc.) are ok, since they're immutable. We need to clone arrays + // and messages. + if (value == null) { + // No cloning required. + } else if (value instanceof MessageNano) { + clone.value = ((MessageNano) value).clone(); + } else if (value instanceof byte[]) { + clone.value = ((byte[]) value).clone(); + } else if (value instanceof byte[][]) { + byte[][] valueArray = (byte[][]) value; + byte[][] cloneArray = new byte[valueArray.length][]; + clone.value = cloneArray; + for (int i = 0; i < valueArray.length; i++) { + cloneArray[i] = valueArray[i].clone(); + } + } else if (value instanceof boolean[]) { + clone.value = ((boolean[]) value).clone(); + } else if (value instanceof int[]) { + clone.value = ((int[]) value).clone(); + } else if (value instanceof long[]) { + clone.value = ((long[]) value).clone(); + } else if (value instanceof float[]) { + clone.value = ((float[]) value).clone(); + } else if (value instanceof double[]) { + clone.value = ((double[]) value).clone(); + } else if (value instanceof MessageNano[]) { + MessageNano[] valueArray = (MessageNano[]) value; + MessageNano[] cloneArray = new MessageNano[valueArray.length]; + clone.value = cloneArray; + for (int i = 0; i < valueArray.length; i++) { + cloneArray[i] = valueArray[i].clone(); + } + } + return clone; + } catch (CloneNotSupportedException e) { + throw new AssertionError(e); + } + } } diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java index e7ba8d12..f1263df5 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java @@ -536,4 +536,12 @@ public final class InternalNano { } return o.hashCode(); } + + // This avoids having to make FieldArray public. + public static void cloneUnknownFieldData(ExtendableMessageNano original, + ExtendableMessageNano cloned) { + if (original.unknownFieldData != null) { + cloned.unknownFieldData = (FieldArray) original.unknownFieldData.clone(); + } + } } diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java index 81e58571..23475027 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java @@ -187,4 +187,12 @@ public abstract class MessageNano { public String toString() { return MessageNanoPrinter.print(this); } + + /** + * Provides support for cloning. This only works if you specify the generate_clone method. + */ + @Override + public MessageNano clone() throws CloneNotSupportedException { + return (MessageNano) super.clone(); + } } diff --git a/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java b/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java index a17fccf3..b1678d1b 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java +++ b/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java @@ -42,6 +42,10 @@ import java.util.Arrays; final class UnknownFieldData { final int tag; + /** + * Important: this should be treated as immutable, even though it's possible + * to change the array values. + */ final byte[] bytes; UnknownFieldData(int tag, byte[] bytes) { diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java index c81846e5..91cc385f 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java +++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java @@ -3023,6 +3023,10 @@ public class NanoTest extends TestCase { assertTrue(Arrays.equals(floats, message.getExtension(RepeatedExtensions.repeatedFloat))); assertTrue(Arrays.equals(doubles, message.getExtension(RepeatedExtensions.repeatedDouble))); assertTrue(Arrays.equals(enums, message.getExtension(RepeatedExtensions.repeatedEnum))); + + // Clone the message and ensure it's still equal. + Extensions.ExtendableMessage clone = message.clone(); + assertEquals(clone, message); } public void testNullExtensions() throws Exception { @@ -4406,6 +4410,22 @@ public class NanoTest extends TestCase { assertTrue(Arrays.equals(nonPacked.enums, packed.enums)); } + public void testClone() throws Exception { + // A simple message. + AnotherMessage anotherMessage = new AnotherMessage(); + anotherMessage.string = "Hello"; + anotherMessage.value = true; + anotherMessage.integers = new int[] { 1, 2, 3 }; + + AnotherMessage clone = anotherMessage.clone(); + assertEquals(clone, anotherMessage); + + // Verify it was a deep clone - changes to the clone shouldn't affect the + // original. + clone.integers[1] = 100; + assertFalse(clone.equals(anotherMessage)); + } + private void assertHasWireData(MessageNano message, boolean expected) { byte[] bytes = MessageNano.toByteArray(message); int wireLength = bytes.length; diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto index d1c5766d..ca56b3dd 100644 --- a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto +++ b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto @@ -16,6 +16,7 @@ enum AnEnum { message AnotherMessage { optional string string = 1; optional bool value = 2; + repeated int32 integers = 3; } message ContainerMessage { diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc index 8a59d323..99b316bf 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc @@ -498,6 +498,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}\n"); } +void RepeatedEnumFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null && this.$name$.length > 0) {\n" + " cloned.$name$ = this.$name$.clone();\n" + "}\n"); +} + void RepeatedEnumFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h index 00adc61f..b94790d6 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h @@ -106,6 +106,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: void GenerateRepeatedDataSizeCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h index c2cf091c..57c221f4 100644 --- a/src/google/protobuf/compiler/javanano/javanano_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_field.h @@ -83,6 +83,7 @@ class FieldGenerator { virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateEqualsCode(io::Printer* printer) const = 0; virtual void GenerateHashCodeCode(io::Printer* printer) const = 0; + virtual void GenerateFixClonedCode(io::Printer* printer) const {} protected: const Params& params_; diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index b5fbcd5f..5ccac946 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -152,6 +152,8 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, params.set_ignore_services(option_value == "true"); } else if (option_name == "parcelable_messages") { params.set_parcelable_messages(option_value == "true"); + } else if (option_name == "generate_clone") { + params.set_generate_clone(option_value == "true"); } else { *error = "Ignore unknown javanano generator option: " + option_name; } diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index d5cbe9ce..b28ec082 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -136,18 +136,23 @@ void MessageGenerator::Generate(io::Printer* printer) { } if (params_.store_unknown_fields() && params_.parcelable_messages()) { printer->Print( - " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$> {\n", + " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>", "classname", descriptor_->name()); } else if (params_.store_unknown_fields()) { printer->Print( - " com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n", + " com.google.protobuf.nano.ExtendableMessageNano<$classname$>", "classname", descriptor_->name()); } else if (params_.parcelable_messages()) { printer->Print( - " com.google.protobuf.nano.android.ParcelableMessageNano {\n"); + " com.google.protobuf.nano.android.ParcelableMessageNano"); } else { printer->Print( - " com.google.protobuf.nano.MessageNano {\n"); + " com.google.protobuf.nano.MessageNano"); + } + if (params_.generate_clone()) { + printer->Print(" implements java.lang.Cloneable {\n"); + } else { + printer->Print(" {\n"); } printer->Indent(); @@ -306,6 +311,10 @@ void MessageGenerator::Generate(io::Printer* printer) { GenerateClear(printer); + if (params_.generate_clone()) { + GenerateClone(printer); + } + if (params_.generate_equals()) { GenerateEquals(printer); GenerateHashCode(printer); @@ -536,6 +545,33 @@ void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) { printer->Print("cachedSize = -1;\n"); } +void MessageGenerator::GenerateClone(io::Printer* printer) { + printer->Print( + "@Override\n" + "public $classname$ clone() {\n", + "classname", descriptor_->name()); + printer->Indent(); + + printer->Print( + "$classname$ cloned;\n" + "try {\n" + " cloned = ($classname$) super.clone();\n" + "} catch (java.lang.CloneNotSupportedException e) {\n" + " throw new java.lang.AssertionError(e);\n" + "}\n", + "classname", descriptor_->name()); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer); + } + + printer->Outdent(); + printer->Print( + " return cloned;\n" + "}\n" + "\n"); +} + void MessageGenerator::GenerateEquals(io::Printer* printer) { // Don't override if there are no fields. We could generate an // equals method that compares types, but often empty messages diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h index 8504aa83..281ec64f 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.h +++ b/src/google/protobuf/compiler/javanano/javanano_message.h @@ -80,6 +80,7 @@ class MessageGenerator { void GenerateFieldInitializers(io::Printer* printer); void GenerateEquals(io::Printer* printer); void GenerateHashCode(io::Printer* printer); + void GenerateClone(io::Printer* printer); const Params& params_; const Descriptor* descriptor_; diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc index 181c4060..d1d04b52 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc @@ -126,6 +126,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}\n"); } +void MessageFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null) {\n" + " cloned.$name$ = this.$name$.clone();\n" + "}\n"); +} + void MessageFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, @@ -212,6 +220,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}\n"); } +void MessageOneofFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$oneof_name$ != null) {\n" + " cloned.$oneof_name$ = this.$oneof_name$.clone();\n" + "}\n"); +} + void MessageOneofFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { GenerateOneofFieldEquals(descriptor_, variables_, printer); @@ -312,6 +328,19 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}\n"); } +void RepeatedMessageFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null && this.$name$.length > 0) {\n" + " cloned.$name$ = new $type$[this.$name$.length];\n" + " for (int i = 0; i < this.$name$.length; i++) {\n" + " if (this.$name$[i] != null) {\n" + " cloned.$name$[i] = this.$name$[i].clone();\n" + " }\n" + " }\n" + "}\n"); +} + void RepeatedMessageFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h index 6c615f5e..e074735c 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h @@ -58,6 +58,7 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: const FieldDescriptor* descriptor_; @@ -80,6 +81,7 @@ class MessageOneofFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: const FieldDescriptor* descriptor_; @@ -102,6 +104,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: const FieldDescriptor* descriptor_; diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h index 4691f360..77bc717d 100644 --- a/src/google/protobuf/compiler/javanano/javanano_params.h +++ b/src/google/protobuf/compiler/javanano/javanano_params.h @@ -66,6 +66,7 @@ class Params { bool parcelable_messages_; bool reftypes_primitive_enums_; bool generate_clear_; + bool generate_clone_; public: Params(const string & base_name) : @@ -81,7 +82,8 @@ class Params { ignore_services_(false), parcelable_messages_(false), reftypes_primitive_enums_(false), - generate_clear_(true) { + generate_clear_(true), + generate_clone_(false) { } const string& base_name() const { @@ -231,6 +233,13 @@ class Params { bool generate_clear() const { return generate_clear_; } + + void set_generate_clone(bool value) { + generate_clone_ = value; + } + bool generate_clone() const { + return generate_clone_; + } }; } // namespace javanano diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc index 41bad0a6..978abf2c 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc @@ -364,6 +364,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } } +void RepeatedPrimitiveFieldGenerator:: +GenerateFixClonedCode(io::Printer* printer) const { + printer->Print(variables_, + "if (this.$name$ != null && this.$name$.length > 0) {\n" + " cloned.$name$ = this.$name$.clone();\n" + "}\n"); +} + void PrimitiveFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { // We define equality as serialized form equality. If generate_has(), diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h index ca7116ff..a01981dd 100644 --- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h +++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h @@ -131,6 +131,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCodeCode(io::Printer* printer) const; + void GenerateFixClonedCode(io::Printer* printer) const; private: void GenerateRepeatedDataSizeCode(io::Printer* printer) const; -- cgit v1.2.3 From ec19be2f3c7a95f3b7d6d0ff7055daead9284d8d Mon Sep 17 00:00:00 2001 From: Jeff Davidson Date: Wed, 11 Feb 2015 13:12:14 -0800 Subject: Generate @IntDef annotations for nanoproto enums. @IntDef is a support library annotation which allows build tools to determine the valid set of values for a given integer field when that field is intended to be restricted like an enum. This avoids the overhead of enums while still allowing for compile-time type checking in most circumstances. Change-Id: Iee02e0b49a8e069f6456572f538e0a0d301fdfd5 --- javanano/README.md | 23 +++++++++++++ .../protobuf/compiler/javanano/javanano_enum.cc | 40 +++++++++++++++++++--- .../compiler/javanano/javanano_enum_field.cc | 24 ++++++++++--- .../compiler/javanano/javanano_generator.cc | 2 ++ .../protobuf/compiler/javanano/javanano_params.h | 11 +++++- 5 files changed, 91 insertions(+), 9 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/README.md b/javanano/README.md index 7d696aa7..e19b90b1 100644 --- a/javanano/README.md +++ b/javanano/README.md @@ -145,6 +145,7 @@ optional_field_style -> default or accessors enum_style -> c or java ignore_services -> true or false parcelable_messages -> true or false +generate_intdefs -> true or false ``` **java_package=\|\** (no default) @@ -302,6 +303,28 @@ parcelable_messages -> true or false Android-specific option to generate Parcelable messages. +**generate_intdefs={true,false}** (default: false) + Android-specific option to generate @IntDef annotations for enums. + + If turned on, an '@IntDef' annotation (a public @interface) will be + generated for each enum, and every integer parameter and return + value in the generated code meant for this enum will be annotated + with it. This interface is generated with the same name and at the + same place as the enum members' container interfaces described + above under 'enum_style=java', regardless of the enum_style option + used. When this is combined with enum_style=java, the interface + will be both the '@IntDef' annotation and the container of the enum + members; otherwise the interface has an empty body. + + Your app must declare a compile-time dependency on the + android-support-annotations library. + + For more information on how these @IntDef annotations help with + compile-time type safety, see: + https://sites.google.com/a/android.com/tools/tech-docs/support-annotations + and + https://developer.android.com/reference/android/support/annotation/IntDef.html + To use nano protobufs within the Android repo: ---------------------------------------------- diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc index f934b05f..c6e8dfe9 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc @@ -73,13 +73,45 @@ void EnumGenerator::Generate(io::Printer* printer) { "// enum $classname$\n", "classname", descriptor_->name()); + const string classname = RenameJavaKeywords(descriptor_->name()); + // Start of container interface + // If generating intdefs, we use the container interface as the intdef if + // present. Otherwise, we just make an empty @interface parallel to the + // constants. + bool use_intdef = params_.generate_intdefs(); bool use_shell_class = params_.java_enum_style(); - if (use_shell_class) { - printer->Print( - "public interface $classname$ {\n", - "classname", RenameJavaKeywords(descriptor_->name())); + if (use_intdef) { + // @IntDef annotation so tools can enforce correctness + // Annotations will be discarded by the compiler + printer->Print("@java.lang.annotation.Retention(" + "java.lang.annotation.RetentionPolicy.SOURCE)\n" + "@android.support.annotation.IntDef({\n"); printer->Indent(); + for (int i = 0; i < canonical_values_.size(); i++) { + const string constant_name = + RenameJavaKeywords(canonical_values_[i]->name()); + if (use_shell_class) { + printer->Print("$classname$.$name$,\n", + "classname", classname, + "name", constant_name); + } else { + printer->Print("$name$,\n", "name", constant_name); + } + } + printer->Outdent(); + printer->Print("})\n"); + } + if (use_shell_class || use_intdef) { + printer->Print( + "public $at_for_intdef$interface $classname$ {\n", + "classname", classname, + "at_for_intdef", use_intdef ? "@" : ""); + if (use_shell_class) { + printer->Indent(); + } else { + printer->Print("}\n\n"); + } } // Canonical values diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc index 99b316bf..7666db38 100644 --- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc +++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc @@ -76,6 +76,10 @@ void SetEnumVariables(const Params& params, internal::WireFormatLite::MakeTag(descriptor->number(), internal::WireFormat::WireTypeForFieldType(descriptor->type()))); (*variables)["message_name"] = descriptor->containing_type()->name(); + const EnumDescriptor* enum_type = descriptor->enum_type(); + (*variables)["message_type_intdef"] = "@" + + ToJavaName(params, enum_type->name(), true, + enum_type->containing_type(), enum_type->file()); } void LoadEnumValues(const Params& params, @@ -116,8 +120,10 @@ EnumFieldGenerator::~EnumFieldGenerator() {} void EnumFieldGenerator:: GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { - printer->Print(variables_, - "public $type$ $name$;\n"); + if (params_.generate_intdefs()) { + printer->Print(variables_, "$message_type_intdef$\n"); + } + printer->Print(variables_, "public $type$ $name$;\n"); if (params_.generate_has()) { printer->Print(variables_, @@ -256,12 +262,22 @@ AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {} void AccessorEnumFieldGenerator:: GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const { + printer->Print(variables_, "private int $name$_;\n"); + if (params_.generate_intdefs()) { + printer->Print(variables_, "$message_type_intdef$\n"); + } printer->Print(variables_, - "private int $name$_;\n" "public int get$capitalized_name$() {\n" " return $name$_;\n" "}\n" - "public $message_name$ set$capitalized_name$(int value) {\n" + "public $message_name$ set$capitalized_name$("); + if (params_.generate_intdefs()) { + printer->Print(variables_, + "\n" + " $message_type_intdef$ "); + } + printer->Print(variables_, + "int value) {\n" " $name$_ = value;\n" " $set_has$;\n" " return this;\n" diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index 5ccac946..67b25748 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -154,6 +154,8 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, params.set_parcelable_messages(option_value == "true"); } else if (option_name == "generate_clone") { params.set_generate_clone(option_value == "true"); + } else if (option_name == "generate_intdefs") { + params.set_generate_intdefs(option_value == "true"); } else { *error = "Ignore unknown javanano generator option: " + option_name; } diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h index 77bc717d..e3b4bb93 100644 --- a/src/google/protobuf/compiler/javanano/javanano_params.h +++ b/src/google/protobuf/compiler/javanano/javanano_params.h @@ -67,6 +67,7 @@ class Params { bool reftypes_primitive_enums_; bool generate_clear_; bool generate_clone_; + bool generate_intdefs_; public: Params(const string & base_name) : @@ -83,7 +84,8 @@ class Params { parcelable_messages_(false), reftypes_primitive_enums_(false), generate_clear_(true), - generate_clone_(false) { + generate_clone_(false), + generate_intdefs_(false) { } const string& base_name() const { @@ -240,6 +242,13 @@ class Params { bool generate_clone() const { return generate_clone_; } + + void set_generate_intdefs(bool value) { + generate_intdefs_ = value; + } + bool generate_intdefs() const { + return generate_intdefs_; + } }; } // namespace javanano -- cgit v1.2.3 From dac7e02d2b9942953481bbe88241d4bf914ef30c Mon Sep 17 00:00:00 2001 From: Brian Duff Date: Sat, 21 Feb 2015 15:22:43 -0800 Subject: Expose generate_clear as an option. I wasn't able to get the clear() method to inline into the constructor when optimizations are on in proguard. As a result, every message has an extra superfluous kept method assuming the app never uses clear() directly. There are a couple of instances where setting this option false is necessary in order to get code dexing successfully without hitting the method limit, e.g. https://goto.google.com/tltzq In this example, I tried turning on the method/inlining/unique and method/inlining/short optimizations before resorting to adding the generate_clear option, but the method count did not decrease. The clear() methods were contributing over a thousand extra methods. Change-Id: If6a9651d6a59cdf70b1040d8248779710ac73105 --- src/google/protobuf/compiler/javanano/javanano_generator.cc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc index 67b25748..ad215cb7 100644 --- a/src/google/protobuf/compiler/javanano/javanano_generator.cc +++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc @@ -156,6 +156,8 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file, params.set_generate_clone(option_value == "true"); } else if (option_name == "generate_intdefs") { params.set_generate_intdefs(option_value == "true"); + } else if (option_name == "generate_clear") { + params.set_generate_clear(option_value == "true"); } else { *error = "Ignore unknown javanano generator option: " + option_name; } -- cgit v1.2.3 From a69b461e1eee43a277839825f1153b8260a28e87 Mon Sep 17 00:00:00 2001 From: Brian Duff Date: Fri, 20 Mar 2015 11:53:33 -0700 Subject: Inline unknownFieldData{Equals,HashCode} to generated code. It turns out dex (apparently) was inlining these protected final methods from ExtendableMessageNano into every message class. Removing these methods from the base class and inlining their code reduces the method count by 2 methods / message when the store_unknown_fields option is on. Change-Id: I0aa09f2016d39939c4c8b8219601793b8fab301f --- .../protobuf/nano/ExtendableMessageNano.java | 25 ---------------------- .../java/com/google/protobuf/nano/FieldArray.java | 19 +++++++++------- .../protobuf/compiler/javanano/javanano_message.cc | 10 +++++++-- 3 files changed, 19 insertions(+), 35 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java index aeacbbf3..87973d76 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java +++ b/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java @@ -160,31 +160,6 @@ public abstract class ExtendableMessageNano> return true; } - /** - * Returns whether the stored unknown field data in this message is equivalent to that in the - * other message. - * - * @param other the other message. - * @return whether the two sets of unknown field data are equal. - */ - protected final boolean unknownFieldDataEquals(M other) { - if (unknownFieldData == null || unknownFieldData.isEmpty()) { - return other.unknownFieldData == null || other.unknownFieldData.isEmpty(); - } else { - return unknownFieldData.equals(other.unknownFieldData); - } - } - - /** - * Computes the hashcode representing the unknown field data stored in this message. - * - * @return the hashcode for the unknown field data. - */ - protected final int unknownFieldDataHashCode() { - return (unknownFieldData == null || unknownFieldData.isEmpty() - ? 0 : unknownFieldData.hashCode()); - } - @Override public M clone() throws CloneNotSupportedException { M cloned = (M) super.clone(); diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java b/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java index c2044f6a..eca9c0d9 100644 --- a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java +++ b/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java @@ -35,9 +35,12 @@ package com.google.protobuf.nano; * A custom version of {@link android.util.SparseArray} with the minimal API * for storing {@link FieldData} objects. * + *

This class is an internal implementation detail of nano and should not + * be called directly by clients. + * * Based on {@link android.support.v4.util.SpareArrayCompat}. */ -class FieldArray implements Cloneable { +public final class FieldArray implements Cloneable { private static final FieldData DELETED = new FieldData(); private boolean mGarbage = false; @@ -48,7 +51,7 @@ class FieldArray implements Cloneable { /** * Creates a new FieldArray containing no fields. */ - public FieldArray() { + FieldArray() { this(10); } @@ -57,7 +60,7 @@ class FieldArray implements Cloneable { * require any additional memory allocation to store the specified * number of mappings. */ - public FieldArray(int initialCapacity) { + FieldArray(int initialCapacity) { initialCapacity = idealIntArraySize(initialCapacity); mFieldNumbers = new int[initialCapacity]; mData = new FieldData[initialCapacity]; @@ -68,7 +71,7 @@ class FieldArray implements Cloneable { * Gets the FieldData mapped from the specified fieldNumber, or null * if no such mapping has been made. */ - public FieldData get(int fieldNumber) { + FieldData get(int fieldNumber) { int i = binarySearch(fieldNumber); if (i < 0 || mData[i] == DELETED) { @@ -81,7 +84,7 @@ class FieldArray implements Cloneable { /** * Removes the data from the specified fieldNumber, if there was any. */ - public void remove(int fieldNumber) { + void remove(int fieldNumber) { int i = binarySearch(fieldNumber); if (i >= 0 && mData[i] != DELETED) { @@ -118,7 +121,7 @@ class FieldArray implements Cloneable { * Adds a mapping from the specified fieldNumber to the specified data, * replacing the previous mapping if there was one. */ - public void put(int fieldNumber, FieldData data) { + void put(int fieldNumber, FieldData data) { int i = binarySearch(fieldNumber); if (i >= 0) { @@ -167,7 +170,7 @@ class FieldArray implements Cloneable { * Returns the number of key-value mappings that this FieldArray * currently stores. */ - public int size() { + int size() { if (mGarbage) { gc(); } @@ -184,7 +187,7 @@ class FieldArray implements Cloneable { * the value from the indexth key-value mapping that this * FieldArray stores. */ - public FieldData dataAt(int index) { + FieldData dataAt(int index) { if (mGarbage) { gc(); } diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index b28ec082..060d25f0 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -612,7 +612,11 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print( - "return unknownFieldDataEquals(other);\n"); + "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n" + " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n" + "} else {\n" + " return unknownFieldData.equals(other.unknownFieldData);\n" + "}"); } else { printer->Print( "return true;\n"); @@ -642,7 +646,9 @@ void MessageGenerator::GenerateHashCode(io::Printer* printer) { if (params_.store_unknown_fields()) { printer->Print( - "result = 31 * result + unknownFieldDataHashCode();\n"); + "result = 31 * result + \n" + " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n" + " unknownFieldData.hashCode());\n"); } printer->Print("return result;\n"); -- cgit v1.2.3 From 9d546c85bda48c59ba10e240afbf731bd0775bc4 Mon Sep 17 00:00:00 2001 From: Jeff Davidson Date: Thu, 2 Apr 2015 14:46:35 -0700 Subject: Generate a CREATOR for each Parcelable message. This is less ideal from a dex count perspective because it requires a new variable for each message, and because most apps have proguard rules that will ensure that CREATOR classes are retained. However, it is required to be able to use nano protos inside of AIDL files, as the autogenerated AIDL code fails to compile otherwise. This is a substantial benefit as it allows for backwards-compatible parameters and return types in AIDL methods along the lines of safeparcel. Bug: 19084705 Change-Id: I66a2c0424b96cf8ff6b631b186cc4f9407dfc1f4 --- src/google/protobuf/compiler/javanano/javanano_message.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc index 060d25f0..a41da5ae 100644 --- a/src/google/protobuf/compiler/javanano/javanano_message.cc +++ b/src/google/protobuf/compiler/javanano/javanano_message.cc @@ -156,6 +156,17 @@ void MessageGenerator::Generate(io::Printer* printer) { } printer->Indent(); + if (params_.parcelable_messages()) { + printer->Print( + "\n" + "// Used by Parcelable\n" + "@SuppressWarnings({\"unused\"})\n" + "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n" + " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n" + " $classname$>($classname$.class);\n", + "classname", descriptor_->name()); + } + // Nested types and extensions for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer); -- cgit v1.2.3 From d9e3063eb054503a98f8ef74fe0484c0f12210ea Mon Sep 17 00:00:00 2001 From: Jie Luo Date: Fri, 1 May 2015 11:20:50 -0700 Subject: Remove ClsCompliant declarations from C# code --- src/google/protobuf/compiler/csharp/csharp_extension.cc | 8 -------- src/google/protobuf/compiler/csharp/csharp_field_base.cc | 13 ------------- src/google/protobuf/compiler/csharp/csharp_field_base.h | 2 -- src/google/protobuf/compiler/csharp/csharp_generator.cc | 5 +---- src/google/protobuf/compiler/csharp/csharp_message.cc | 5 ----- .../compiler/csharp/csharp_source_generator_base.cc | 5 ----- .../protobuf/compiler/csharp/csharp_source_generator_base.h | 1 - 7 files changed, 1 insertion(+), 38 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc index 5d38f52e..2bac320d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ b/src/google/protobuf/compiler/csharp/csharp_extension.cc @@ -63,11 +63,6 @@ ExtensionGenerator::~ExtensionGenerator() { } void ExtensionGenerator::Generate(Writer* writer) { - if (cls_compliance() - && (GetFieldConstantName(descriptor_).substr(0, 1) == "_")) { - writer->WriteLine("[global::System.CLSCompliant(false)]"); - } - writer->WriteLine("public const int $0$ = $1$;", GetFieldConstantName(descriptor_), SimpleItoa(descriptor_->number())); @@ -80,7 +75,6 @@ void ExtensionGenerator::Generate(Writer* writer) { // "option message_set_wire_format = true; is not supported in Lite runtime extensions."); //} - AddClsComplianceCheck(writer); writer->Write("$0$ ", class_access_level()); writer->WriteLine( "static pb::$3$<$0$, $1$> $2$;", @@ -90,12 +84,10 @@ void ExtensionGenerator::Generate(Writer* writer) { descriptor_->is_repeated() ? "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"); } else if (descriptor_->is_repeated()) { - AddClsComplianceCheck(writer); writer->WriteLine( "$0$ static pb::GeneratedExtensionBase> $2$;", class_access_level(), type_name(), property_name()); } else { - AddClsComplianceCheck(writer); writer->WriteLine("$0$ static pb::GeneratedExtensionBase<$1$> $2$;", class_access_level(), type_name(), property_name()); } diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index ed4d55c4..145b6743 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -79,13 +79,6 @@ void FieldGeneratorBase::AddNullCheck(Writer* writer, const std::string& name) { void FieldGeneratorBase::AddPublicMemberAttributes(Writer* writer) { AddDeprecatedFlag(writer); - AddClsComplianceCheck(writer); -} - -void FieldGeneratorBase::AddClsComplianceCheck(Writer* writer) { - if (cls_compliance() && !is_cls_compliant()) { - writer->WriteLine("[global::System.CLSCompliant(false)]"); - } } std::string FieldGeneratorBase::property_name() { @@ -211,12 +204,6 @@ bool FieldGeneratorBase::is_nullable_type() { } } -bool FieldGeneratorBase::is_cls_compliant() { - CSharpType type = GetCSharpType(descriptor_->type()); - return (type != CSHARPTYPE_UINT32) && (type != CSHARPTYPE_UINT64) - && (UnderscoresToPascalCase(name()).substr(0, 1) != "_"); -} - inline bool IsNaN(double value) { // NaN is never equal to anything, even itself. return value != value; diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index 4f3a7658..311f7a6e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -70,14 +70,12 @@ class FieldGeneratorBase : public SourceGeneratorBase { void AddNullCheck(Writer* writer, const std::string& name); void AddPublicMemberAttributes(Writer* writer); - void AddClsComplianceCheck(Writer* writer); std::string property_name(); std::string name(); std::string type_name(); bool has_default_value(); bool is_nullable_type(); - bool is_cls_compliant(); std::string default_value(); std::string number(); std::string message_or_group(); diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index 61ed37ad..64c4bd7d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -71,10 +71,7 @@ bool Generator::Generate( std::string file_extension = ".cs"; for (int i = 0; i < options.size(); i++) { - if (options[i].first == "no_cls_compliance") { - *error = "Turning off CLS compliance is not implemented yet."; - return false; - } else if (options[i].first == "file_extension") { + if (options[i].first == "file_extension") { file_extension = options[i].second; } else { *error = "Unknown generator option: " + options[i].first; diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 36f41c70..96f7c17c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -262,11 +262,6 @@ void MessageGenerator::Generate(Writer* writer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); - // TODO(jtattermusch): same code for cls compliance is in csharp_extension - if (cls_compliance() - && GetFieldConstantName(fieldDescriptor)[0] == '_') { - writer->WriteLine("[global::System.CLSCompliant(false)]"); - } // Rats: we lose the debug comment here :( writer->WriteLine("public const int $0$ = $1$;", diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index e39911ee..8dfb41d4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -69,11 +69,6 @@ std::string SourceGeneratorBase::class_access_level() { return "public"; // public_classes is always on. } -bool SourceGeneratorBase::cls_compliance() { - // TODO(jtattermusch): implement this based on "cls_compliance" cmdline param. - return true; -} - } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index dbc65d04..1955394e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -48,7 +48,6 @@ class SourceGeneratorBase { virtual ~SourceGeneratorBase(); std::string class_access_level(); - bool cls_compliance(); bool optimize_size() { return optimizeSize_; -- cgit v1.2.3 From 30650d81d9baa446dbc8deb784ba53794cafda5b Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Fri, 1 May 2015 08:57:16 -0400 Subject: Alpha 1 drop of Google's Objective C plugin and runtime support for protobufs. --- .gitignore | 6 + Makefile.am | 124 +- objectivec/DevTools/check_version_stamps.sh | 56 + objectivec/DevTools/generate_descriptors_proto.sh | 36 + objectivec/DevTools/pddm.py | 687 + objectivec/DevTools/pddm_tests.py | 515 + objectivec/GPBArray.h | 535 + objectivec/GPBArray.m | 2499 ++++ objectivec/GPBArray_PackagePrivate.h | 130 + objectivec/GPBBootstrap.h | 84 + objectivec/GPBCodedInputStream.h | 81 + objectivec/GPBCodedInputStream.m | 801 ++ objectivec/GPBCodedInputStream_PackagePrivate.h | 131 + objectivec/GPBCodedOutputStream.h | 340 + objectivec/GPBCodedOutputStream.m | 1229 ++ objectivec/GPBDescriptor.h | 143 + objectivec/GPBDescriptor.m | 888 ++ objectivec/GPBDescriptor_PackagePrivate.h | 293 + objectivec/GPBDictionary.h | 2233 ++++ objectivec/GPBDictionary.m | 12627 +++++++++++++++++++ objectivec/GPBDictionary_PackagePrivate.h | 577 + objectivec/GPBExtensionField.h | 51 + objectivec/GPBExtensionField.m | 525 + objectivec/GPBExtensionField_PackagePrivate.h | 51 + objectivec/GPBExtensionRegistry.h | 46 + objectivec/GPBExtensionRegistry.m | 98 + objectivec/GPBExtensionRegistry_PackagePrivate.h | 40 + objectivec/GPBField.h | 56 + objectivec/GPBField.m | 328 + objectivec/GPBField_PackagePrivate.h | 49 + objectivec/GPBMessage.h | 151 + objectivec/GPBMessage.m | 4735 +++++++ objectivec/GPBMessage_PackagePrivate.h | 124 + objectivec/GPBProtocolBuffers.h | 45 + objectivec/GPBProtocolBuffers.m | 49 + objectivec/GPBProtocolBuffers_RuntimeSupport.h | 41 + objectivec/GPBRootObject.h | 42 + objectivec/GPBRootObject.m | 177 + objectivec/GPBRootObject_PackagePrivate.h | 42 + objectivec/GPBTypes.h | 102 + objectivec/GPBUnknownFieldSet.h | 46 + objectivec/GPBUnknownFieldSet.m | 422 + objectivec/GPBUnknownFieldSet_PackagePrivate.h | 61 + objectivec/GPBUtilities.h | 181 + objectivec/GPBUtilities.m | 1645 +++ objectivec/GPBUtilities_PackagePrivate.h | 426 + objectivec/GPBWellKnownTypes.h | 48 + objectivec/GPBWellKnownTypes.m | 117 + objectivec/GPBWireFormat.h | 68 + objectivec/GPBWireFormat.m | 78 + .../ProtocolBuffers_OSX.xcodeproj/project.pbxproj | 919 ++ .../project.xcworkspace/contents.xcworkspacedata | 7 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../xcschemes/PerformanceTests.xcscheme | 125 + .../xcschemes/ProtocolBuffers.xcscheme | 115 + .../ProtocolBuffers_iOS.xcodeproj/project.pbxproj | 1093 ++ .../project.xcworkspace/contents.xcworkspacedata | 7 + .../xcshareddata/WorkspaceSettings.xcsettings | 8 + .../FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist | 62 + .../8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist | 21 + .../xcschemes/PerformanceTests.xcscheme | 134 + .../xcschemes/ProtocolBuffers.xcscheme | 116 + objectivec/Tests/Filter1.txt | 40 + objectivec/Tests/Filter2.txt | 35 + objectivec/Tests/GPBARCUnittestProtos.m | 57 + objectivec/Tests/GPBArrayTests.m | 3365 +++++ objectivec/Tests/GPBCodedInputStreamTests.m | 290 + objectivec/Tests/GPBCodedOuputStreamTests.m | 321 + objectivec/Tests/GPBConcurrencyTests.m | 157 + objectivec/Tests/GPBDescriptorTests.m | 232 + objectivec/Tests/GPBDictionaryTests+Bool.m | 2421 ++++ objectivec/Tests/GPBDictionaryTests+Int32.m | 3650 ++++++ objectivec/Tests/GPBDictionaryTests+Int64.m | 3650 ++++++ objectivec/Tests/GPBDictionaryTests+String.m | 3362 +++++ objectivec/Tests/GPBDictionaryTests+UInt32.m | 3650 ++++++ objectivec/Tests/GPBDictionaryTests+UInt64.m | 3649 ++++++ objectivec/Tests/GPBDictionaryTests.pddm | 1044 ++ objectivec/Tests/GPBFilteredMessageTests.m | 98 + objectivec/Tests/GPBMessageTests+Merge.m | 700 + objectivec/Tests/GPBMessageTests+Runtime.m | 1978 +++ objectivec/Tests/GPBMessageTests+Serialization.m | 838 ++ objectivec/Tests/GPBMessageTests.m | 1728 +++ objectivec/Tests/GPBPerfTests.m | 306 + objectivec/Tests/GPBStringTests.m | 516 + objectivec/Tests/GPBSwiftTests.swift | 405 + objectivec/Tests/GPBTestUtilities.h | 87 + objectivec/Tests/GPBTestUtilities.m | 2350 ++++ objectivec/Tests/GPBUnittestProtos.m | 56 + objectivec/Tests/GPBUnknownFieldSetTest.m | 255 + objectivec/Tests/GPBUtilitiesTests.m | 363 + objectivec/Tests/GPBWellKnownTypesTest.m | 102 + objectivec/Tests/GPBWireFormatTests.m | 246 + objectivec/Tests/UnitTests-Bridging-Header.h | 6 + objectivec/Tests/UnitTests-Info.plist | 20 + objectivec/Tests/golden_message | Bin 0 -> 493 bytes objectivec/Tests/golden_packed_fields_message | Bin 0 -> 493 bytes objectivec/Tests/iOSTestHarness/AppDelegate.m | 35 + .../AppIcon.appiconset/Contents.json | 116 + .../Images.xcassets/AppIcon.appiconset/iPad6.png | Bin 0 -> 8583 bytes .../AppIcon.appiconset/iPad6@2x.png | Bin 0 -> 17744 bytes .../Images.xcassets/AppIcon.appiconset/iPad7.png | Bin 0 -> 8969 bytes .../AppIcon.appiconset/iPad7@2x.png | Bin 0 -> 18788 bytes .../Images.xcassets/AppIcon.appiconset/iPhone6.png | Bin 0 -> 7021 bytes .../AppIcon.appiconset/iPhone6@2x.png | Bin 0 -> 13348 bytes .../AppIcon.appiconset/iPhone7@2x.png | Bin 0 -> 11128 bytes .../AppIcon.appiconset/iPhone7@3x.png | Bin 0 -> 21792 bytes .../LaunchImage.launchimage/Contents.json | 49 + objectivec/Tests/iOSTestHarness/Info.plist | 43 + objectivec/Tests/iOSTestHarness/LaunchScreen.xib | 33 + .../iOSTestHarness/en.lproj/InfoPlist.strings | 2 + objectivec/Tests/text_format_map_unittest_data.txt | 70 + objectivec/Tests/text_format_unittest_data.txt | 116 + objectivec/Tests/unittest_cycle.proto | 58 + objectivec/Tests/unittest_filter.proto | 71 + objectivec/Tests/unittest_name_mangling.proto | 37 + objectivec/Tests/unittest_objc.proto | 389 + objectivec/Tests/unittest_runtime_proto2.proto | 108 + objectivec/Tests/unittest_runtime_proto3.proto | 101 + objectivec/google/protobuf/Descriptor.pbobjc.h | 1046 ++ objectivec/google/protobuf/Descriptor.pbobjc.m | 2205 ++++ objectivec/google/protobuf/Duration.pbobjc.h | 83 + objectivec/google/protobuf/Duration.pbobjc.m | 85 + objectivec/google/protobuf/Timestamp.pbobjc.h | 94 + objectivec/google/protobuf/Timestamp.pbobjc.m | 85 + src/Makefile.am | 25 + src/google/protobuf/any.proto | 1 + src/google/protobuf/api.proto | 1 + src/google/protobuf/compiler/main.cc | 6 + .../compiler/objectivec/objectivec_enum.cc | 199 + .../protobuf/compiler/objectivec/objectivec_enum.h | 73 + .../compiler/objectivec/objectivec_enum_field.cc | 129 + .../compiler/objectivec/objectivec_enum_field.h | 77 + .../compiler/objectivec/objectivec_extension.cc | 166 + .../compiler/objectivec/objectivec_extension.h | 73 + .../compiler/objectivec/objectivec_field.cc | 474 + .../compiler/objectivec/objectivec_field.h | 166 + .../compiler/objectivec/objectivec_file.cc | 392 + .../protobuf/compiler/objectivec/objectivec_file.h | 94 + .../compiler/objectivec/objectivec_generator.cc | 95 + .../compiler/objectivec/objectivec_generator.h | 60 + .../compiler/objectivec/objectivec_helpers.cc | 1131 ++ .../compiler/objectivec/objectivec_helpers.h | 176 + .../objectivec/objectivec_helpers_unittest.cc | 242 + .../compiler/objectivec/objectivec_map_field.cc | 161 + .../compiler/objectivec/objectivec_map_field.h | 64 + .../compiler/objectivec/objectivec_message.cc | 642 + .../compiler/objectivec/objectivec_message.h | 103 + .../objectivec/objectivec_message_field.cc | 90 + .../compiler/objectivec/objectivec_message_field.h | 71 + .../compiler/objectivec/objectivec_oneof.cc | 139 + .../compiler/objectivec/objectivec_oneof.h | 77 + .../objectivec/objectivec_primitive_field.cc | 162 + .../objectivec/objectivec_primitive_field.h | 82 + src/google/protobuf/descriptor.pb.cc | 4 +- src/google/protobuf/descriptor.proto | 1 + src/google/protobuf/duration.proto | 1 + src/google/protobuf/empty.proto | 1 + src/google/protobuf/field_mask.proto | 1 + src/google/protobuf/source_context.proto | 1 + src/google/protobuf/struct.proto | 1 + src/google/protobuf/timestamp.proto | 1 + src/google/protobuf/type.proto | 1 + .../protobuf/unittest_drop_unknown_fields.proto | 1 + .../protobuf/unittest_preserve_unknown_enum.proto | 1 + src/google/protobuf/wrappers.proto | 1 + 165 files changed, 82460 insertions(+), 3 deletions(-) create mode 100755 objectivec/DevTools/check_version_stamps.sh create mode 100755 objectivec/DevTools/generate_descriptors_proto.sh create mode 100755 objectivec/DevTools/pddm.py create mode 100755 objectivec/DevTools/pddm_tests.py create mode 100644 objectivec/GPBArray.h create mode 100644 objectivec/GPBArray.m create mode 100644 objectivec/GPBArray_PackagePrivate.h create mode 100644 objectivec/GPBBootstrap.h create mode 100644 objectivec/GPBCodedInputStream.h create mode 100644 objectivec/GPBCodedInputStream.m create mode 100644 objectivec/GPBCodedInputStream_PackagePrivate.h create mode 100644 objectivec/GPBCodedOutputStream.h create mode 100644 objectivec/GPBCodedOutputStream.m create mode 100644 objectivec/GPBDescriptor.h create mode 100644 objectivec/GPBDescriptor.m create mode 100644 objectivec/GPBDescriptor_PackagePrivate.h create mode 100644 objectivec/GPBDictionary.h create mode 100644 objectivec/GPBDictionary.m create mode 100644 objectivec/GPBDictionary_PackagePrivate.h create mode 100644 objectivec/GPBExtensionField.h create mode 100644 objectivec/GPBExtensionField.m create mode 100644 objectivec/GPBExtensionField_PackagePrivate.h create mode 100644 objectivec/GPBExtensionRegistry.h create mode 100644 objectivec/GPBExtensionRegistry.m create mode 100644 objectivec/GPBExtensionRegistry_PackagePrivate.h create mode 100644 objectivec/GPBField.h create mode 100644 objectivec/GPBField.m create mode 100644 objectivec/GPBField_PackagePrivate.h create mode 100644 objectivec/GPBMessage.h create mode 100644 objectivec/GPBMessage.m create mode 100644 objectivec/GPBMessage_PackagePrivate.h create mode 100644 objectivec/GPBProtocolBuffers.h create mode 100644 objectivec/GPBProtocolBuffers.m create mode 100644 objectivec/GPBProtocolBuffers_RuntimeSupport.h create mode 100644 objectivec/GPBRootObject.h create mode 100644 objectivec/GPBRootObject.m create mode 100644 objectivec/GPBRootObject_PackagePrivate.h create mode 100644 objectivec/GPBTypes.h create mode 100644 objectivec/GPBUnknownFieldSet.h create mode 100644 objectivec/GPBUnknownFieldSet.m create mode 100644 objectivec/GPBUnknownFieldSet_PackagePrivate.h create mode 100644 objectivec/GPBUtilities.h create mode 100644 objectivec/GPBUtilities.m create mode 100644 objectivec/GPBUtilities_PackagePrivate.h create mode 100644 objectivec/GPBWellKnownTypes.h create mode 100644 objectivec/GPBWellKnownTypes.m create mode 100644 objectivec/GPBWireFormat.h create mode 100644 objectivec/GPBWireFormat.m create mode 100644 objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj create mode 100644 objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme create mode 100644 objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme create mode 100644 objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj create mode 100644 objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings create mode 100644 objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist create mode 100644 objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist create mode 100644 objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme create mode 100644 objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme create mode 100644 objectivec/Tests/Filter1.txt create mode 100644 objectivec/Tests/Filter2.txt create mode 100644 objectivec/Tests/GPBARCUnittestProtos.m create mode 100644 objectivec/Tests/GPBArrayTests.m create mode 100644 objectivec/Tests/GPBCodedInputStreamTests.m create mode 100644 objectivec/Tests/GPBCodedOuputStreamTests.m create mode 100644 objectivec/Tests/GPBConcurrencyTests.m create mode 100644 objectivec/Tests/GPBDescriptorTests.m create mode 100644 objectivec/Tests/GPBDictionaryTests+Bool.m create mode 100644 objectivec/Tests/GPBDictionaryTests+Int32.m create mode 100644 objectivec/Tests/GPBDictionaryTests+Int64.m create mode 100644 objectivec/Tests/GPBDictionaryTests+String.m create mode 100644 objectivec/Tests/GPBDictionaryTests+UInt32.m create mode 100644 objectivec/Tests/GPBDictionaryTests+UInt64.m create mode 100644 objectivec/Tests/GPBDictionaryTests.pddm create mode 100644 objectivec/Tests/GPBFilteredMessageTests.m create mode 100644 objectivec/Tests/GPBMessageTests+Merge.m create mode 100644 objectivec/Tests/GPBMessageTests+Runtime.m create mode 100644 objectivec/Tests/GPBMessageTests+Serialization.m create mode 100644 objectivec/Tests/GPBMessageTests.m create mode 100644 objectivec/Tests/GPBPerfTests.m create mode 100644 objectivec/Tests/GPBStringTests.m create mode 100644 objectivec/Tests/GPBSwiftTests.swift create mode 100644 objectivec/Tests/GPBTestUtilities.h create mode 100644 objectivec/Tests/GPBTestUtilities.m create mode 100644 objectivec/Tests/GPBUnittestProtos.m create mode 100644 objectivec/Tests/GPBUnknownFieldSetTest.m create mode 100644 objectivec/Tests/GPBUtilitiesTests.m create mode 100644 objectivec/Tests/GPBWellKnownTypesTest.m create mode 100644 objectivec/Tests/GPBWireFormatTests.m create mode 100644 objectivec/Tests/UnitTests-Bridging-Header.h create mode 100644 objectivec/Tests/UnitTests-Info.plist create mode 100644 objectivec/Tests/golden_message create mode 100644 objectivec/Tests/golden_packed_fields_message create mode 100644 objectivec/Tests/iOSTestHarness/AppDelegate.m create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png create mode 100644 objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json create mode 100644 objectivec/Tests/iOSTestHarness/Info.plist create mode 100644 objectivec/Tests/iOSTestHarness/LaunchScreen.xib create mode 100644 objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings create mode 100644 objectivec/Tests/text_format_map_unittest_data.txt create mode 100644 objectivec/Tests/text_format_unittest_data.txt create mode 100644 objectivec/Tests/unittest_cycle.proto create mode 100644 objectivec/Tests/unittest_filter.proto create mode 100644 objectivec/Tests/unittest_name_mangling.proto create mode 100644 objectivec/Tests/unittest_objc.proto create mode 100644 objectivec/Tests/unittest_runtime_proto2.proto create mode 100644 objectivec/Tests/unittest_runtime_proto3.proto create mode 100644 objectivec/google/protobuf/Descriptor.pbobjc.h create mode 100644 objectivec/google/protobuf/Descriptor.pbobjc.m create mode 100644 objectivec/google/protobuf/Duration.pbobjc.h create mode 100644 objectivec/google/protobuf/Duration.pbobjc.m create mode 100644 objectivec/google/protobuf/Timestamp.pbobjc.h create mode 100644 objectivec/google/protobuf/Timestamp.pbobjc.m create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_enum.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_enum.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_enum_field.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_extension.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_extension.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_field.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_field.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_file.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_file.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_generator.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_generator.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_helpers.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_helpers.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_map_field.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_map_field.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_message.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_message.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_message_field.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_message_field.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_oneof.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_oneof.h create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc create mode 100644 src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h (limited to 'src/google/protobuf/compiler') diff --git a/.gitignore b/.gitignore index b8ba4892..9a5508de 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,9 @@ src/**/*.trs # JavaBuild output. java/target javanano/target + +# Directories created by opening the Objective C Xcode projects. +objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcuserdata/ +objectivec/ProtocolBuffers_OSX.xcodeproj/xcuserdata/ +objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcuserdata/ +objectivec/ProtocolBuffers_iOS.xcodeproj/xcuserdata/ diff --git a/Makefile.am b/Makefile.am index 4fd93f26..eecffa1f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -197,6 +197,128 @@ javanano_EXTRA_DIST= javanano/README.md \ javanano/pom.xml +objectivec_EXTRA_DIST= \ + objectivec/DevTools/generate_descriptors_proto.sh \ + objectivec/DevTools/pddm.py \ + objectivec/DevTools/pddm_tests.py \ + objectivec/google/protobuf/Descriptor.pbobjc.h \ + objectivec/google/protobuf/Descriptor.pbobjc.m \ + objectivec/google/protobuf/Duration.pbobjc.h \ + objectivec/google/protobuf/Duration.pbobjc.m \ + objectivec/google/protobuf/Timestamp.pbobjc.h \ + objectivec/google/protobuf/Timestamp.pbobjc.m \ + objectivec/GPBArray.h \ + objectivec/GPBArray.m \ + objectivec/GPBArray_PackagePrivate.h \ + objectivec/GPBBootstrap.h \ + objectivec/GPBCodedInputStream.h \ + objectivec/GPBCodedInputStream.m \ + objectivec/GPBCodedInputStream_PackagePrivate.h \ + objectivec/GPBCodedOutputStream.h \ + objectivec/GPBCodedOutputStream.m \ + objectivec/GPBDescriptor.h \ + objectivec/GPBDescriptor.m \ + objectivec/GPBDescriptor_PackagePrivate.h \ + objectivec/GPBDictionary.h \ + objectivec/GPBDictionary.m \ + objectivec/GPBDictionary_PackagePrivate.h \ + objectivec/GPBExtensionField.h \ + objectivec/GPBExtensionField.m \ + objectivec/GPBExtensionField_PackagePrivate.h \ + objectivec/GPBExtensionRegistry.h \ + objectivec/GPBExtensionRegistry.m \ + objectivec/GPBExtensionRegistry_PackagePrivate.h \ + objectivec/GPBField.h \ + objectivec/GPBField.m \ + objectivec/GPBField_PackagePrivate.h \ + objectivec/GPBMessage.h \ + objectivec/GPBMessage.m \ + objectivec/GPBMessage_PackagePrivate.h \ + objectivec/GPBProtocolBuffers.h \ + objectivec/GPBProtocolBuffers.m \ + objectivec/GPBProtocolBuffers_RuntimeSupport.h \ + objectivec/GPBRootObject.h \ + objectivec/GPBRootObject.m \ + objectivec/GPBRootObject_PackagePrivate.h \ + objectivec/GPBTypes.h \ + objectivec/GPBUnknownFieldSet.h \ + objectivec/GPBUnknownFieldSet.m \ + objectivec/GPBUnknownFieldSet_PackagePrivate.h \ + objectivec/GPBUtilities.h \ + objectivec/GPBUtilities.m \ + objectivec/GPBUtilities_PackagePrivate.h \ + objectivec/GPBWellKnownTypes.h \ + objectivec/GPBWellKnownTypes.m \ + objectivec/GPBWireFormat.h \ + objectivec/GPBWireFormat.m \ + objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj \ + objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \ + objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \ + objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist \ + objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist \ + objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \ + objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \ + objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj \ + objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata \ + objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \ + objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \ + objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \ + objectivec/Tests/Filter1.txt \ + objectivec/Tests/Filter2.txt \ + objectivec/Tests/golden_message \ + objectivec/Tests/golden_packed_fields_message \ + objectivec/Tests/GPBARCUnittestProtos.m \ + objectivec/Tests/GPBArrayTests.m \ + objectivec/Tests/GPBCodedInputStreamTests.m \ + objectivec/Tests/GPBCodedOuputStreamTests.m \ + objectivec/Tests/GPBConcurrencyTests.m \ + objectivec/Tests/GPBDescriptorTests.m \ + objectivec/Tests/GPBDictionaryTests+Bool.m \ + objectivec/Tests/GPBDictionaryTests+Int32.m \ + objectivec/Tests/GPBDictionaryTests+Int64.m \ + objectivec/Tests/GPBDictionaryTests+String.m \ + objectivec/Tests/GPBDictionaryTests+UInt32.m \ + objectivec/Tests/GPBDictionaryTests+UInt64.m \ + objectivec/Tests/GPBDictionaryTests.pddm \ + objectivec/Tests/GPBFilteredMessageTests.m \ + objectivec/Tests/GPBMessageTests+Merge.m \ + objectivec/Tests/GPBMessageTests+Runtime.m \ + objectivec/Tests/GPBMessageTests+Serialization.m \ + objectivec/Tests/GPBMessageTests.m \ + objectivec/Tests/GPBPerfTests.m \ + objectivec/Tests/GPBStringTests.m \ + objectivec/Tests/GPBSwiftTests.swift \ + objectivec/Tests/GPBTestUtilities.h \ + objectivec/Tests/GPBTestUtilities.m \ + objectivec/Tests/GPBUnittestProtos.m \ + objectivec/Tests/GPBUnknownFieldSetTest.m \ + objectivec/Tests/GPBUtilitiesTests.m \ + objectivec/Tests/GPBWellKnownTypesTest.m \ + objectivec/Tests/GPBWireFormatTests.m \ + objectivec/Tests/iOSTestHarness/AppDelegate.m \ + objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png \ + objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png \ + objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json \ + objectivec/Tests/iOSTestHarness/Info.plist \ + objectivec/Tests/iOSTestHarness/LaunchScreen.xib \ + objectivec/Tests/text_format_map_unittest_data.txt \ + objectivec/Tests/text_format_unittest_data.txt \ + objectivec/Tests/unittest_cycle.proto \ + objectivec/Tests/unittest_filter.proto \ + objectivec/Tests/unittest_name_mangling.proto \ + objectivec/Tests/unittest_objc.proto \ + objectivec/Tests/unittest_runtime_proto2.proto \ + objectivec/Tests/unittest_runtime_proto3.proto \ + objectivec/Tests/UnitTests-Bridging-Header.h \ + objectivec/Tests/UnitTests-Info.plist python_EXTRA_DIST= \ python/google/protobuf/internal/api_implementation.cc \ @@ -301,7 +423,7 @@ ruby_EXTRA_DIST= \ ruby/tests/generated_code.rb \ ruby/tests/generated_code_test.rb -all_EXTRA_DIST=$(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST) +all_EXTRA_DIST=$(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST) EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \ autogen.sh \ diff --git a/objectivec/DevTools/check_version_stamps.sh b/objectivec/DevTools/check_version_stamps.sh new file mode 100755 index 00000000..5de9ef14 --- /dev/null +++ b/objectivec/DevTools/check_version_stamps.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# This script checks that the runtime version number constant in the compiler +# source and in the runtime source is the same. +# +# A distro can be made of the protobuf sources with only a subset of the +# languages, so if the compiler depended on the Objective C runtime, those +# builds would break. At the same time, we don't want the runtime source +# depending on the compiler sources; so two copies of the constant are needed. + +set -eu + +readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") +readonly ProtoRootDir="${ScriptDir}/../.." + +die() { + echo "Error: $1" + exit 1 +} + +readonly ConstantName=GOOGLE_PROTOBUF_OBJC_GEN_VERSION + +# Collect version from plugin sources. + +readonly PluginSrc="${ProtoRootDir}/src/google/protobuf/compiler/objectivec/objectivec_file.cc" +readonly PluginVersion=$( \ + cat "${PluginSrc}" \ + | sed -n -e "s:const int32_t ${ConstantName} = \([0-9]*\);:\1:p" +) + +if [[ -z "${PluginVersion}" ]] ; then + die "Failed to fine ${ConstantName} in the plugin source (${PluginSrc})." +fi + +# Collect version from runtime sources. + +readonly RuntimeSrc="${ProtoRootDir}/objectivec/GPBBootstrap.h" +readonly RuntimeVersion=$( \ + cat "${RuntimeSrc}" \ + | sed -n -e "s:#define ${ConstantName} \([0-9]*\):\1:p" +) + +if [[ -z "${RuntimeVersion}" ]] ; then + die "Failed to fine ${ConstantName} in the runtime source (${RuntimeSrc})." +fi + +# Compare them. + +if [[ "${PluginVersion}" != "${RuntimeVersion}" ]] ; then + die "Versions don't match! + Plugin: ${PluginVersion} from ${PluginSrc} + Runtime: ${RuntimeVersion} from ${RuntimeSrc} +" +fi + +# Success diff --git a/objectivec/DevTools/generate_descriptors_proto.sh b/objectivec/DevTools/generate_descriptors_proto.sh new file mode 100755 index 00000000..42502bfe --- /dev/null +++ b/objectivec/DevTools/generate_descriptors_proto.sh @@ -0,0 +1,36 @@ +#!/bin/bash + +# This script will generate the common descriptors needed by the Objective C +# runtime. + +# HINT: Flags passed to generate_descriptor_proto.sh will be passed directly +# to make when building protoc. This is particularly useful for passing +# -j4 to run 4 jobs simultaneously. + +set -eu + +readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") +readonly ProtoRootDir="${ScriptDir}/../.." +readonly ProtoC="${ProtoRootDir}/src/protoc" + +pushd "${ProtoRootDir}" > /dev/null + +# Compiler build fails if config.h hasn't been made yet (even if configure/etc. +# have been run, so get that made first). +make $@ config.h + +# Make sure the compiler is current. +cd src +make $@ protoc + +# These really should only be run when the inputs or compiler are newer than +# the outputs. + +# Needed by the runtime. +./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/descriptor.proto + +# Well known types that the library provides helpers for. +./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/timestamp.proto +./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/duration.proto + +popd > /dev/null diff --git a/objectivec/DevTools/pddm.py b/objectivec/DevTools/pddm.py new file mode 100755 index 00000000..d1b53f5a --- /dev/null +++ b/objectivec/DevTools/pddm.py @@ -0,0 +1,687 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2015 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. + +"""PDDM - Poor Developers' Debug-able Macros + +A simple markup that can be added in comments of source so they can then be +expanded out into code. Most of this could be done with CPP macros, but then +developers can't really step through them in the debugger, this way they are +expanded to the same code, but you can debug them. + +Any file can be processed, but the syntax is designed around a C based compiler. +Processed lines start with "//%". There are three types of sections you can +create: Text (left alone), Macro Definitions, and Macro Expansions. There is +no order required between definitions and expansions, all definitions are read +before any expansions are processed (thus, if desired, definitions can be put +at the end of the file to keep them out of the way of the code). + +Macro Definitions are started with "//%PDDM-DEFINE Name(args)" and all lines +afterwards that start with "//%" are included in the definition. Multiple +macros can be defined in one block by just using a another "//%PDDM-DEFINE" +line to start the next macro. Optionally, a macro can be ended with +"//%PDDM-DEFINE-END", this can be useful when you want to make it clear that +trailing blank lines are included in the macro. You can also end a definition +with an expansion. + +Macro Expansions are started by single lines containing +"//%PDDM-EXPAND Name(args)" and then with "//%PDDM-EXPAND-END" or another +expansions. All lines in-between are replaced by the result of the expansion. +The first line of the expansion is always a blank like just for readability. + +Expansion itself is pretty simple, one macro can invoke another macro, but +you cannot nest the invoke of a macro in another macro (i.e. - can't do +"foo(bar(a))", but you can define foo(a) and bar(b) where bar invokes foo() +within its expansion. + +When macros are expanded, the arg references can also add "$O" suffix to the +name (i.e. - "NAME$O") to specify an option to be applied. The options are: + + $S - Replace each character in the value with a space. + $l - Lowercase the first letter of the value. + $L - Lowercase the whole value. + $u - Uppercase the first letter of the value. + $U - Uppercase the whole value. + +Within a macro you can use ## to cause things to get joined together after +expansion (i.e. - "a##b" within a macro will become "ab"). + +Example: + + int foo(MyEnum x) { + switch (x) { + //%PDDM-EXPAND case(Enum_Left, 1) + //%PDDM-EXPAND case(Enum_Center, 2) + //%PDDM-EXPAND case(Enum_Right, 3) + //%PDDM-EXPAND-END + } + + //%PDDM-DEFINE case(_A, _B) + //% case _A: + //% return _B; + + A macro ends at the start of the next one, or an optional %PDDM-DEFINE-END + can be used to avoid adding extra blank lines/returns (or make it clear when + it is desired). + + One macro can invoke another by simply using its name NAME(ARGS). You cannot + nest an invoke inside another (i.e. - NAME1(NAME2(ARGS)) isn't supported). + + Within a macro you can use ## to cause things to get joined together after + processing (i.e. - "a##b" within a macro will become "ab"). + + +""" + +import optparse +import os +import re +import sys + + +# Regex for macro definition. +_MACRO_RE = re.compile(r'(?P\w+)\((?P.*?)\)') +# Regex for macro's argument definition. +_MACRO_ARG_NAME_RE = re.compile(r'^\w+$') + +# Line inserted after each EXPAND. +_GENERATED_CODE_LINE = ( + '// This block of code is generated, do not edit it directly.' +) + + +def _MacroRefRe(macro_names): + # Takes in a list of macro names and makes a regex that will match invokes + # of those macros. + return re.compile(r'\b(?P(?P(%s))\((?P.*?)\))' % + '|'.join(macro_names)) + +def _MacroArgRefRe(macro_arg_names): + # Takes in a list of macro arg names and makes a regex that will match + # uses of those args. + return re.compile(r'\b(?P(%s))(\$(?P

+ * For use by generated code only. + */ + public static enum MethodToInvoke { + IS_INITIALIZED, + PARSE_PARTIAL_FROM, + MERGE_FROM, + MAKE_IMMUTABLE, + NEW_INSTANCE, + NEW_BUILDER; + } + + /** + * A method that implements different types of operations described in {@link MethodToInvoke}. + * Theses different kinds of operations are required to implement message-level operations for + * builders in the runtime. This method bundles those operations to reduce the generated methods + * count. + *

    + *
  • {@code PARSE_PARTIAL_FROM} is parameterized with an {@link CodedInputStream} and + * {@link ExtensionRegistryLite}. It consumes the input stream, parsing the contents into the + * returned protocol buffer. If parsing throws an {@link InvalidProtocolBufferException}, the + * implementation wraps it in a RuntimeException + *
  • {@code NEW_INSTANCE} returns a new instance of the protocol buffer + *
  • {@code IS_INITIALIZED} is parameterized with a {@code Boolean} detailing whether to + * memoize. It returns {@code null} for false and the default instance for true. We optionally + * memoize to support the Builder case, where memoization is not desired. + *
  • {@code NEW_BUILDER} returns a {@code BuilderType} instance. + *
  • {@code MERGE_FROM} is parameterized with a {@code MessageType} and merges the fields from + * that instance into this instance. + *
  • {@code MAKE_IMMUTABLE} sets all internal fields to an immutable state. + *
+ * This method, plus the implementation of the Builder, enables the Builder class to be proguarded + * away entirely on Android. + *

+ * For use by generated code only. + */ + protected abstract Object dynamicMethod( + MethodToInvoke method, + Object... args); + + /** + * Merge some unknown fields into the {@link UnknownFieldSetLite} for this + * message. + * + *

For use by generated code only. + */ + protected final void mergeUnknownFields(UnknownFieldSetLite unknownFields) { + this.unknownFields = UnknownFieldSetLite.concat(this.unknownFields, unknownFields); } @SuppressWarnings("unchecked") @@ -122,24 +189,37 @@ public abstract class GeneratedMessageLite< extends AbstractMessageLite.Builder { private final MessageType defaultInstance; - - /** For use by generated code only. */ - protected UnknownFieldSetLite unknownFields = - UnknownFieldSetLite.getDefaultInstance(); + protected MessageType instance; + protected boolean isBuilt; protected Builder(MessageType defaultInstance) { this.defaultInstance = defaultInstance; + this.instance = (MessageType) defaultInstance.dynamicMethod(MethodToInvoke.NEW_INSTANCE); + isBuilt = false; } - // The default behavior. If a message has required fields in its subtree, - // the generated code will override. - public boolean isInitialized() { - return true; + /** + * Called before any method that would mutate the builder to ensure that it correctly copies + * any state before the write happens to preserve immutability guarantees. + */ + protected void copyOnWrite() { + if (isBuilt) { + MessageType newInstance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE); + newInstance.dynamicMethod(MethodToInvoke.MERGE_FROM, instance); + instance = newInstance; + isBuilt = false; + } + } + + //@Override (Java 1.6 override semantics, but we must support 1.5) + public final boolean isInitialized() { + return GeneratedMessageLite.isInitialized(instance, false /* shouldMemoize */); } //@Override (Java 1.6 override semantics, but we must support 1.5) - public BuilderType clear() { - unknownFields = UnknownFieldSetLite.getDefaultInstance(); + public final BuilderType clear() { + // No need to copy on write since we're dropping the instance anyways. + instance = (MessageType) instance.dynamicMethod(MethodToInvoke.NEW_INSTANCE); return (BuilderType) this; } @@ -151,8 +231,12 @@ public abstract class GeneratedMessageLite< return builder; } - /** All subclasses implement this. */ - public abstract MessageType buildPartial(); + //@Override (Java 1.6 override semantics, but we must support 1.5) + public MessageType buildPartial() { + instance.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE); + isBuilt = true; + return instance; + } //@Override (Java 1.6 override semantics, but we must support 1.5) public final MessageType build() { @@ -162,9 +246,13 @@ public abstract class GeneratedMessageLite< } return result; } - + /** All subclasses implement this. */ - public abstract BuilderType mergeFrom(MessageType message); + public BuilderType mergeFrom(MessageType message) { + copyOnWrite(); + instance.dynamicMethod(MethodToInvoke.MERGE_FROM, message); + return (BuilderType) this; + } public MessageType getDefaultInstanceForType() { return defaultInstance; @@ -181,18 +269,6 @@ public abstract class GeneratedMessageLite< int tag) throws IOException { return unknownFields.mergeFieldFrom(tag, input); } - - /** - * Merge some unknown fields into the {@link UnknownFieldSetLite} for this - * message. - * - *

For use by generated code only. - */ - protected final BuilderType mergeUnknownFields( - final UnknownFieldSetLite unknownFields) { - this.unknownFields = UnknownFieldSetLite.concat(this.unknownFields, unknownFields); - return (BuilderType) this; - } public BuilderType mergeFrom( com.google.protobuf.CodedInputStream input, @@ -259,19 +335,13 @@ public abstract class GeneratedMessageLite< */ protected FieldSet extensions = FieldSet.newFieldSet(); - // -1 => not memoized, 0 => false, 1 => true. - private byte memoizedIsInitialized = -1; - - // The default behavior. If a message has required fields in its subtree, - // the generated code will override. - public boolean isInitialized() { - if (memoizedIsInitialized == -1) { - memoizedIsInitialized = (byte) (extensions.isInitialized() ? 1 : 0); + protected final void mergeExtensionFields(final MessageType other) { + if (extensions.isImmutable()) { + extensions = extensions.clone(); } - - return memoizedIsInitialized == 1; + extensions.mergeFrom(((ExtendableMessage) other).extensions); } - + private void verifyExtensionContainingType( final GeneratedExtension extension) { if (extension.getContainingTypeDefaultInstance() != @@ -420,46 +490,38 @@ public abstract class GeneratedMessageLite< implements ExtendableMessageOrBuilder { protected ExtendableBuilder(MessageType defaultInstance) { super(defaultInstance); - } - - private FieldSet extensions = FieldSet.emptySet(); - private boolean extensionsIsMutable; - - // The default behavior. If a message has required fields in its subtree, - // the generated code will override. - public boolean isInitialized() { - return extensions.isInitialized(); + + // TODO(dweis): This is kind of an unnecessary clone since we construct a + // new instance in the parent constructor which makes the extensions + // immutable. This extra allocation shouldn't matter in practice + // though. + instance.extensions = instance.extensions.clone(); } // For immutable message conversion. void internalSetExtensionSet(FieldSet extensions) { - this.extensions = extensions; + copyOnWrite(); + instance.extensions = extensions; } - @Override - public BuilderType clear() { - extensions.clear(); - extensionsIsMutable = false; - return super.clear(); + // @Override (Java 1.6 override semantics, but we must support 1.5) + protected void copyOnWrite() { + if (!isBuilt) { + return; + } + + super.copyOnWrite(); + instance.extensions = instance.extensions.clone(); } - private void ensureExtensionsIsMutable() { - if (!extensionsIsMutable) { - extensions = extensions.clone(); - extensionsIsMutable = true; + // @Override (Java 1.6 override semantics, but we must support 1.5) + public final MessageType buildPartial() { + if (isBuilt) { + return instance; } - } - /** - * Called by the build code path to create a copy of the extensions for - * building the message. - *

- * For use by generated code only. - */ - protected final FieldSet buildExtensions() { - extensions.makeImmutable(); - extensionsIsMutable = false; - return extensions; + instance.extensions.makeImmutable(); + return super.buildPartial(); } private void verifyExtensionContainingType( @@ -477,22 +539,14 @@ public abstract class GeneratedMessageLite< //@Override (Java 1.6 override semantics, but we must support 1.5) public final boolean hasExtension( final ExtensionLite extension) { - GeneratedExtension extensionLite = - checkIsLite(extension); - - verifyExtensionContainingType(extensionLite); - return extensions.hasField(extensionLite.descriptor); + return instance.hasExtension(extension); } /** Get the number of elements in a repeated extension. */ //@Override (Java 1.6 override semantics, but we must support 1.5) public final int getExtensionCount( final ExtensionLite> extension) { - GeneratedExtension> extensionLite = - checkIsLite(extension); - - verifyExtensionContainingType(extensionLite); - return extensions.getRepeatedFieldCount(extensionLite.descriptor); + return instance.getExtensionCount(extension); } /** Get the value of an extension. */ @@ -500,16 +554,7 @@ public abstract class GeneratedMessageLite< @SuppressWarnings("unchecked") public final Type getExtension( final ExtensionLite extension) { - GeneratedExtension extensionLite = - checkIsLite(extension); - - verifyExtensionContainingType(extensionLite); - final Object value = extensions.getField(extensionLite.descriptor); - if (value == null) { - return extensionLite.defaultValue; - } else { - return (Type) extensionLite.fromFieldSetType(value); - } + return instance.getExtension(extension); } /** Get one element of a repeated extension. */ @@ -518,12 +563,7 @@ public abstract class GeneratedMessageLite< public final Type getExtension( final ExtensionLite> extension, final int index) { - GeneratedExtension> extensionLite = - checkIsLite(extension); - - verifyExtensionContainingType(extensionLite); - return (Type) extensionLite.singularFromFieldSetType( - extensions.getRepeatedField(extensionLite.descriptor, index)); + return instance.getExtension(extension, index); } // This is implemented here only to work around an apparent bug in the @@ -542,9 +582,8 @@ public abstract class GeneratedMessageLite< checkIsLite(extension); verifyExtensionContainingType(extensionLite); - ensureExtensionsIsMutable(); - extensions.setField(extensionLite.descriptor, - extensionLite.toFieldSetType(value)); + copyOnWrite(); + instance.extensions.setField(extensionLite.descriptor, extensionLite.toFieldSetType(value)); return (BuilderType) this; } @@ -556,9 +595,9 @@ public abstract class GeneratedMessageLite< checkIsLite(extension); verifyExtensionContainingType(extensionLite); - ensureExtensionsIsMutable(); - extensions.setRepeatedField(extensionLite.descriptor, index, - extensionLite.singularToFieldSetType(value)); + copyOnWrite(); + instance.extensions.setRepeatedField( + extensionLite.descriptor, index, extensionLite.singularToFieldSetType(value)); return (BuilderType) this; } @@ -570,9 +609,9 @@ public abstract class GeneratedMessageLite< checkIsLite(extension); verifyExtensionContainingType(extensionLite); - ensureExtensionsIsMutable(); - extensions.addRepeatedField(extensionLite.descriptor, - extensionLite.singularToFieldSetType(value)); + copyOnWrite(); + instance.extensions.addRepeatedField( + extensionLite.descriptor, extensionLite.singularToFieldSetType(value)); return (BuilderType) this; } @@ -582,20 +621,10 @@ public abstract class GeneratedMessageLite< GeneratedExtension extensionLite = checkIsLite(extension); verifyExtensionContainingType(extensionLite); - ensureExtensionsIsMutable(); - extensions.clearField(extensionLite.descriptor); + copyOnWrite(); + instance.extensions.clearField(extensionLite.descriptor); return (BuilderType) this; } - - /** Called by subclasses to check if all extensions are initialized. */ - protected boolean extensionsAreInitialized() { - return extensions.isInitialized(); - } - - protected final void mergeExtensionFields(final MessageType other) { - ensureExtensionsIsMutable(); - extensions.mergeFrom(((ExtendableMessage) other).extensions); - } } //----------------------------------------------------------------- @@ -1113,4 +1142,133 @@ public abstract class GeneratedMessageLite< return (BuilderType) defaultInstance.toBuilder(); } } + + /** + * A static helper method for checking if a message is initialized, optionally memoizing. + *

+ * For use by generated code only. + */ + protected static final > boolean isInitialized( + T message, boolean shouldMemoize) { + return message.dynamicMethod(MethodToInvoke.IS_INITIALIZED, shouldMemoize) != null; + } + + protected static final > void makeImmutable(T message) { + message.dynamicMethod(MethodToInvoke.MAKE_IMMUTABLE); + } + + /** + * A static helper method for parsing a partial from input using the extension registry and the + * instance. + */ + static > T parsePartialFrom( + T instance, CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + try { + return (T) instance.dynamicMethod( + MethodToInvoke.PARSE_PARTIAL_FROM, input, extensionRegistry); + } catch (RuntimeException e) { + if (e.getCause() instanceof InvalidProtocolBufferException) { + throw (InvalidProtocolBufferException) e.getCause(); + } + throw e; + } + } + + /** + * A {@link Parser} implementation that delegates to the default instance. + *

+ * For use by generated code only. + */ + protected static class DefaultInstanceBasedParser> + extends AbstractParser { + + private T defaultInstance; + + public DefaultInstanceBasedParser(T defaultInstance) { + this.defaultInstance = defaultInstance; + } + + @Override + public T parsePartialFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry) + throws InvalidProtocolBufferException { + return GeneratedMessageLite.parsePartialFrom(defaultInstance, input, extensionRegistry); + } + } + + protected static IntList newIntList() { + return new IntArrayList(); + } + + protected static IntList newIntList(List toCopy) { + return new IntArrayList(toCopy); + } + + protected static IntList emptyIntList() { + return IntArrayList.emptyList(); + } + + protected static LongList newLongList() { + return new LongArrayList(); + } + + protected static LongList newLongList(List toCopy) { + return new LongArrayList(toCopy); + } + + protected static LongList emptyLongList() { + return LongArrayList.emptyList(); + } + + protected static FloatList newFloatList() { + return new FloatArrayList(); + } + + protected static FloatList newFloatList(List toCopy) { + return new FloatArrayList(toCopy); + } + + protected static FloatList emptyFloatList() { + return FloatArrayList.emptyList(); + } + + protected static DoubleList newDoubleList() { + return new DoubleArrayList(); + } + + protected static DoubleList newDoubleList(List toCopy) { + return new DoubleArrayList(toCopy); + } + + protected static DoubleList emptyDoubleList() { + return DoubleArrayList.emptyList(); + } + + protected static BooleanList newBooleanList() { + return new BooleanArrayList(); + } + + protected static BooleanList newBooleanList(List toCopy) { + return new BooleanArrayList(toCopy); + } + + protected static BooleanList emptyBooleanList() { + return BooleanArrayList.emptyList(); + } + + protected static ProtobufList newProtobufList() { + return new ProtobufArrayList(); + } + + protected static ProtobufList newProtobufList(List toCopy) { + return new ProtobufArrayList(toCopy); + } + + protected static ProtobufList emptyProtobufList() { + return ProtobufArrayList.emptyList(); + } + + protected static LazyStringArrayList emptyLazyStringArrayList() { + return LazyStringArrayList.emptyList(); + } } diff --git a/java/src/main/java/com/google/protobuf/IntArrayList.java b/java/src/main/java/com/google/protobuf/IntArrayList.java new file mode 100644 index 00000000..f7609cc9 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/IntArrayList.java @@ -0,0 +1,242 @@ +// 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. + +package com.google.protobuf; + +import com.google.protobuf.Internal.IntList; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.RandomAccess; + +/** + * An implementation of {@link IntList} on top of a primitive array. + * + * @author dweis@google.com (Daniel Weis) + */ +final class IntArrayList extends AbstractProtobufList implements IntList, RandomAccess { + + private static final int DEFAULT_CAPACITY = 10; + + private static final IntArrayList EMPTY_LIST = new IntArrayList(); + static { + EMPTY_LIST.makeImmutable(); + } + + public static IntArrayList emptyList() { + return EMPTY_LIST; + } + + /** + * The backing store for the list. + */ + private int[] array; + + /** + * The size of the list distinct from the length of the array. That is, it is the number of + * elements set in the list. + */ + private int size; + + /** + * Constructs a new mutable {@code IntArrayList}. + */ + IntArrayList() { + array = new int[DEFAULT_CAPACITY]; + size = 0; + } + + /** + * Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}. + */ + IntArrayList(List other) { + if (other instanceof IntArrayList) { + IntArrayList list = (IntArrayList) other; + array = list.array.clone(); + size = list.size; + } else { + size = other.size(); + array = new int[size]; + for (int i = 0; i < size; i++) { + array[i] = other.get(i); + } + } + } + + @Override + public Integer get(int index) { + return getInt(index); + } + + @Override + public int getInt(int index) { + ensureIndexInRange(index); + return array[index]; + } + + @Override + public int size() { + return size; + } + + @Override + public Integer set(int index, Integer element) { + return setInt(index, element); + } + + @Override + public int setInt(int index, int element) { + ensureIsMutable(); + ensureIndexInRange(index); + int previousValue = array[index]; + array[index] = element; + return previousValue; + } + + @Override + public void add(int index, Integer element) { + addInt(index, element); + } + + /** + * Like {@link #add(Integer)} but more efficient in that it doesn't box the element. + */ + @Override + public void addInt(int element) { + addInt(size, element); + } + + /** + * Like {@link #add(int, Integer)} but more efficient in that it doesn't box the element. + */ + private void addInt(int index, int element) { + ensureIsMutable(); + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); + } + + if (size < array.length) { + // Shift everything over to make room + System.arraycopy(array, index, array, index + 1, size - index); + } else { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + int[] newArray = new int[length]; + + // Copy the first part directly + System.arraycopy(array, 0, newArray, 0, index); + + // Copy the rest shifted over by one to make room + System.arraycopy(array, index, newArray, index + 1, size - index); + array = newArray; + } + + array[index] = element; + size++; + modCount++; + } + + @Override + public boolean addAll(Collection collection) { + ensureIsMutable(); + + if (collection == null) { + throw new NullPointerException(); + } + + // We specialize when adding another IntArrayList to avoid boxing elements. + if (!(collection instanceof IntArrayList)) { + return super.addAll(collection); + } + + IntArrayList list = (IntArrayList) collection; + if (list.size == 0) { + return false; + } + + int overflow = Integer.MAX_VALUE - size; + if (overflow < list.size) { + // We can't actually represent a list this large. + throw new OutOfMemoryError(); + } + + int newSize = size + list.size; + if (newSize > array.length) { + array = Arrays.copyOf(array, newSize); + } + + System.arraycopy(list.array, 0, array, size, list.size); + size = newSize; + modCount++; + return true; + } + + @Override + public boolean remove(Object o) { + ensureIsMutable(); + for (int i = 0; i < size; i++) { + if (o.equals(array[i])) { + System.arraycopy(array, i + 1, array, i, size - i); + size--; + modCount++; + return true; + } + } + return false; + } + + @Override + public Integer remove(int index) { + ensureIsMutable(); + ensureIndexInRange(index); + int value = array[index]; + System.arraycopy(array, index + 1, array, index, size - index); + size--; + modCount++; + return value; + } + + /** + * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an + * {@link IndexOutOfBoundsException} if it is not. + * + * @param index the index to verify is in range + */ + private void ensureIndexInRange(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); + } + } + + private String makeOutOfBoundsExceptionMessage(int index) { + return "Index:" + index + ", Size:" + size; + } +} diff --git a/java/src/main/java/com/google/protobuf/Internal.java b/java/src/main/java/com/google/protobuf/Internal.java index 74bf44c0..20054b79 100644 --- a/java/src/main/java/com/google/protobuf/Internal.java +++ b/java/src/main/java/com/google/protobuf/Internal.java @@ -30,6 +30,7 @@ package com.google.protobuf; +import java.io.IOException; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.util.AbstractList; @@ -532,4 +533,132 @@ public class Internal { } } } + + /** + * Extends {@link List} to add the capability to make the list immutable and inspect if it is + * modifiable. + */ + public static interface ProtobufList extends List { + + /** + * Makes this list immutable. All subsequent modifications will throw an + * {@link UnsupportedOperationException}. + */ + void makeImmutable(); + + /** + * Returns whether this list can be modified via the publicly accessible {@link List} methods. + */ + boolean isModifiable(); + } + + /** + * A {@link java.util.List} implementation that avoids boxing the elements into Integers if + * possible. Does not support null elements. + */ + public static interface IntList extends ProtobufList { + + /** + * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. + */ + int getInt(int index); + + /** + * Like {@link #add(Integer)} but more efficient in that it doesn't box the element. + */ + void addInt(int element); + + /** + * Like {@link #set(int, Integer)} but more efficient in that it doesn't box the element. + */ + int setInt(int index, int element); + } + + /** + * A {@link java.util.List} implementation that avoids boxing the elements into Booleans if + * possible. Does not support null elements. + */ + public static interface BooleanList extends ProtobufList { + + /** + * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. + */ + boolean getBoolean(int index); + + /** + * Like {@link #add(Boolean)} but more efficient in that it doesn't box the element. + */ + void addBoolean(boolean element); + + /** + * Like {@link #set(int, Boolean)} but more efficient in that it doesn't box the element. + */ + boolean setBoolean(int index, boolean element); + } + + /** + * A {@link java.util.List} implementation that avoids boxing the elements into Longs if + * possible. Does not support null elements. + */ + public static interface LongList extends ProtobufList { + + /** + * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. + */ + long getLong(int index); + + /** + * Like {@link #add(Long)} but more efficient in that it doesn't box the element. + */ + void addLong(long element); + + /** + * Like {@link #set(int, Long)} but more efficient in that it doesn't box the element. + */ + long setLong(int index, long element); + } + + /** + * A {@link java.util.List} implementation that avoids boxing the elements into Doubles if + * possible. Does not support null elements. + */ + public static interface DoubleList extends ProtobufList { + + /** + * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. + */ + double getDouble(int index); + + /** + * Like {@link #add(Double)} but more efficient in that it doesn't box the element. + */ + void addDouble(double element); + + /** + * Like {@link #set(int, Double)} but more efficient in that it doesn't box the element. + */ + double setDouble(int index, double element); + } + + /** + * A {@link java.util.List} implementation that avoids boxing the elements into Floats if + * possible. Does not support null elements. + */ + public static interface FloatList extends ProtobufList { + + /** + * Like {@link #get(int)} but more efficient in that it doesn't box the returned value. + */ + float getFloat(int index); + + /** + * Like {@link #add(Float)} but more efficient in that it doesn't box the element. + */ + void addFloat(float element); + + /** + * Like {@link #set(int, Float)} but more efficient in that it doesn't box the element. + */ + float setFloat(int index, float element); + } } diff --git a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java index 2d40a51f..a2997e1c 100644 --- a/java/src/main/java/com/google/protobuf/LazyStringArrayList.java +++ b/java/src/main/java/com/google/protobuf/LazyStringArrayList.java @@ -62,11 +62,20 @@ import java.util.RandomAccess; * * @author jonp@google.com (Jon Perlow) */ -public class LazyStringArrayList extends AbstractList +public class LazyStringArrayList extends AbstractProtobufList implements LazyStringList, RandomAccess { + + private static final LazyStringArrayList EMPTY_LIST = new LazyStringArrayList(); + static { + EMPTY_LIST.makeImmutable(); + } + + static LazyStringArrayList emptyList() { + return EMPTY_LIST; + } - public static final LazyStringList EMPTY = - new LazyStringArrayList().getUnmodifiableView(); + // For compatibility with older runtimes. + public static final LazyStringList EMPTY = EMPTY_LIST; private final List list; @@ -116,12 +125,26 @@ public class LazyStringArrayList extends AbstractList @Override public String set(int index, String s) { + ensureIsMutable(); Object o = list.set(index, s); return asString(o); } @Override public void add(int index, String element) { + ensureIsMutable(); + list.add(index, element); + modCount++; + } + + private void add(int index, ByteString element) { + ensureIsMutable(); + list.add(index, element); + modCount++; + } + + private void add(int index, byte[] element) { + ensureIsMutable(); list.add(index, element); modCount++; } @@ -137,6 +160,7 @@ public class LazyStringArrayList extends AbstractList @Override public boolean addAll(int index, Collection c) { + ensureIsMutable(); // When copying from another LazyStringList, directly copy the underlying // elements rather than forcing each element to be decoded to a String. Collection collection = c instanceof LazyStringList @@ -148,6 +172,7 @@ public class LazyStringArrayList extends AbstractList // @Override public boolean addAllByteString(Collection values) { + ensureIsMutable(); boolean ret = list.addAll(values); modCount++; return ret; @@ -155,6 +180,7 @@ public class LazyStringArrayList extends AbstractList // @Override public boolean addAllByteArray(Collection c) { + ensureIsMutable(); boolean ret = list.addAll(c); modCount++; return ret; @@ -162,6 +188,7 @@ public class LazyStringArrayList extends AbstractList @Override public String remove(int index) { + ensureIsMutable(); Object o = list.remove(index); modCount++; return asString(o); @@ -169,18 +196,21 @@ public class LazyStringArrayList extends AbstractList @Override public void clear() { + ensureIsMutable(); list.clear(); modCount++; } // @Override public void add(ByteString element) { + ensureIsMutable(); list.add(element); modCount++; } // @Override public void add(byte[] element) { + ensureIsMutable(); list.add(element); modCount++; } @@ -207,14 +237,23 @@ public class LazyStringArrayList extends AbstractList // @Override public void set(int index, ByteString s) { - list.set(index, s); + setAndReturn(index, s); + } + + private Object setAndReturn(int index, ByteString s) { + ensureIsMutable(); + return list.set(index, s); } // @Override public void set(int index, byte[] s) { - list.set(index, s); + setAndReturn(index, s); + } + + private Object setAndReturn(int index, byte[] s) { + ensureIsMutable(); + return list.set(index, s); } - private static String asString(Object o) { if (o instanceof String) { @@ -253,6 +292,7 @@ public class LazyStringArrayList extends AbstractList // @Override public void mergeFrom(LazyStringList other) { + ensureIsMutable(); for (Object o : other.getUnderlyingElements()) { if (o instanceof byte[]) { byte[] b = (byte[]) o; @@ -267,20 +307,15 @@ public class LazyStringArrayList extends AbstractList private static class ByteArrayListView extends AbstractList implements RandomAccess { - private final List list; + private final LazyStringArrayList list; - ByteArrayListView(List list) { + ByteArrayListView(LazyStringArrayList list) { this.list = list; } @Override public byte[] get(int index) { - Object o = list.get(index); - byte[] b = asByteArray(o); - if (b != o) { - list.set(index, b); - } - return b; + return list.getByteArray(index); } @Override @@ -290,7 +325,7 @@ public class LazyStringArrayList extends AbstractList @Override public byte[] set(int index, byte[] s) { - Object o = list.set(index, s); + Object o = list.setAndReturn(index, s); modCount++; return asByteArray(o); } @@ -311,25 +346,20 @@ public class LazyStringArrayList extends AbstractList // @Override public List asByteArrayList() { - return new ByteArrayListView(list); + return new ByteArrayListView(this); } private static class ByteStringListView extends AbstractList implements RandomAccess { - private final List list; + private final LazyStringArrayList list; - ByteStringListView(List list) { + ByteStringListView(LazyStringArrayList list) { this.list = list; } @Override public ByteString get(int index) { - Object o = list.get(index); - ByteString b = asByteString(o); - if (b != o) { - list.set(index, b); - } - return b; + return list.getByteString(index); } @Override @@ -339,7 +369,7 @@ public class LazyStringArrayList extends AbstractList @Override public ByteString set(int index, ByteString s) { - Object o = list.set(index, s); + Object o = list.setAndReturn(index, s); modCount++; return asByteString(o); } @@ -360,12 +390,15 @@ public class LazyStringArrayList extends AbstractList // @Override public List asByteStringList() { - return new ByteStringListView(list); + return new ByteStringListView(this); } // @Override public LazyStringList getUnmodifiableView() { - return new UnmodifiableLazyStringList(this); + if (isModifiable()) { + return new UnmodifiableLazyStringList(this); + } + return this; } } diff --git a/java/src/main/java/com/google/protobuf/LongArrayList.java b/java/src/main/java/com/google/protobuf/LongArrayList.java new file mode 100644 index 00000000..298617ff --- /dev/null +++ b/java/src/main/java/com/google/protobuf/LongArrayList.java @@ -0,0 +1,242 @@ +// 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. + +package com.google.protobuf; + +import com.google.protobuf.Internal.LongList; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.RandomAccess; + +/** + * An implementation of {@link LongList} on top of a primitive array. + * + * @author dweis@google.com (Daniel Weis) + */ +final class LongArrayList extends AbstractProtobufList implements LongList, RandomAccess { + + private static final int DEFAULT_CAPACITY = 10; + + private static final LongArrayList EMPTY_LIST = new LongArrayList(); + static { + EMPTY_LIST.makeImmutable(); + } + + public static LongArrayList emptyList() { + return EMPTY_LIST; + } + + /** + * The backing store for the list. + */ + private long[] array; + + /** + * The size of the list distinct from the length of the array. That is, it is the number of + * elements set in the list. + */ + private int size; + + /** + * Constructs a new mutable {@code LongArrayList}. + */ + LongArrayList() { + array = new long[DEFAULT_CAPACITY]; + size = 0; + } + + /** + * Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}. + */ + LongArrayList(List other) { + if (other instanceof LongArrayList) { + LongArrayList list = (LongArrayList) other; + array = list.array.clone(); + size = list.size; + } else { + size = other.size(); + array = new long[size]; + for (int i = 0; i < size; i++) { + array[i] = other.get(i); + } + } + } + + @Override + public Long get(int index) { + return getLong(index); + } + + @Override + public long getLong(int index) { + ensureIndexInRange(index); + return array[index]; + } + + @Override + public int size() { + return size; + } + + @Override + public Long set(int index, Long element) { + return setLong(index, element); + } + + @Override + public long setLong(int index, long element) { + ensureIsMutable(); + ensureIndexInRange(index); + long previousValue = array[index]; + array[index] = element; + return previousValue; + } + + @Override + public void add(int index, Long element) { + addLong(index, element); + } + + /** + * Like {@link #add(Long)} but more efficient in that it doesn't box the element. + */ + @Override + public void addLong(long element) { + addLong(size, element); + } + + /** + * Like {@link #add(int, Long)} but more efficient in that it doesn't box the element. + */ + private void addLong(int index, long element) { + ensureIsMutable(); + if (index < 0 || index > size) { + throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); + } + + if (size < array.length) { + // Shift everything over to make room + System.arraycopy(array, index, array, index + 1, size - index); + } else { + // Resize to 1.5x the size + int length = ((size * 3) / 2) + 1; + long[] newArray = new long[length]; + + // Copy the first part directly + System.arraycopy(array, 0, newArray, 0, index); + + // Copy the rest shifted over by one to make room + System.arraycopy(array, index, newArray, index + 1, size - index); + array = newArray; + } + + array[index] = element; + size++; + modCount++; + } + + @Override + public boolean addAll(Collection collection) { + ensureIsMutable(); + + if (collection == null) { + throw new NullPointerException(); + } + + // We specialize when adding another LongArrayList to avoid boxing elements. + if (!(collection instanceof LongArrayList)) { + return super.addAll(collection); + } + + LongArrayList list = (LongArrayList) collection; + if (list.size == 0) { + return false; + } + + int overflow = Integer.MAX_VALUE - size; + if (overflow < list.size) { + // We can't actually represent a list this large. + throw new OutOfMemoryError(); + } + + int newSize = size + list.size; + if (newSize > array.length) { + array = Arrays.copyOf(array, newSize); + } + + System.arraycopy(list.array, 0, array, size, list.size); + size = newSize; + modCount++; + return true; + } + + @Override + public boolean remove(Object o) { + ensureIsMutable(); + for (int i = 0; i < size; i++) { + if (o.equals(array[i])) { + System.arraycopy(array, i + 1, array, i, size - i); + size--; + modCount++; + return true; + } + } + return false; + } + + @Override + public Long remove(int index) { + ensureIsMutable(); + ensureIndexInRange(index); + long value = array[index]; + System.arraycopy(array, index + 1, array, index, size - index); + size--; + modCount++; + return value; + } + + /** + * Ensures that the provided {@code index} is within the range of {@code [0, size]}. Throws an + * {@link IndexOutOfBoundsException} if it is not. + * + * @param index the index to verify is in range + */ + private void ensureIndexInRange(int index) { + if (index < 0 || index >= size) { + throw new IndexOutOfBoundsException(makeOutOfBoundsExceptionMessage(index)); + } + } + + private String makeOutOfBoundsExceptionMessage(int index) { + return "Index:" + index + ", Size:" + size; + } +} diff --git a/java/src/main/java/com/google/protobuf/MapField.java b/java/src/main/java/com/google/protobuf/MapField.java index 82906d37..b290993c 100644 --- a/java/src/main/java/com/google/protobuf/MapField.java +++ b/java/src/main/java/com/google/protobuf/MapField.java @@ -30,9 +30,11 @@ package com.google.protobuf; +import com.google.protobuf.MapFieldLite.MutatabilityAwareMap; + import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -51,7 +53,7 @@ import java.util.Map; * and getList() concurrently in multiple threads. If write-access is needed, * all access must be synchronized. */ -public class MapField { +public class MapField implements MutabilityOracle { /** * Indicates where the data of this map field is currently stored. * @@ -72,8 +74,9 @@ public class MapField { */ private enum StorageMode {MAP, LIST, BOTH} + private volatile boolean isMutable; private volatile StorageMode mode; - private Map mapData; + private MutatabilityAwareMap mapData; private List listData; // Convert between a map entry Message and a key-value pair. @@ -110,20 +113,19 @@ public class MapField { private MapField( Converter converter, StorageMode mode, - Map mapData, - List listData) { + Map mapData) { this.converter = converter; + this.isMutable = true; this.mode = mode; - this.mapData = mapData; - this.listData = listData; + this.mapData = new MutatabilityAwareMap(this, mapData); + this.listData = null; } private MapField( MapEntry defaultEntry, StorageMode mode, - Map mapData, - List listData) { - this(new ImmutableMessageConverter(defaultEntry), mode, mapData, listData); + Map mapData) { + this(new ImmutableMessageConverter(defaultEntry), mode, mapData); } @@ -131,14 +133,14 @@ public class MapField { public static MapField emptyMapField( MapEntry defaultEntry) { return new MapField( - defaultEntry, StorageMode.MAP, Collections.emptyMap(), null); + defaultEntry, StorageMode.MAP, Collections.emptyMap()); } /** Creates a new mutable empty MapField. */ public static MapField newMapField(MapEntry defaultEntry) { return new MapField( - defaultEntry, StorageMode.MAP, new HashMap(), null); + defaultEntry, StorageMode.MAP, new LinkedHashMap()); } @@ -151,7 +153,7 @@ public class MapField { converter.convertMessageToKeyAndValue(message, map); } - private List convertMapToList(Map mapData) { + private List convertMapToList(MutatabilityAwareMap mapData) { List listData = new ArrayList(); for (Map.Entry entry : mapData.entrySet()) { listData.add( @@ -161,12 +163,12 @@ public class MapField { return listData; } - private Map convertListToMap(List listData) { - Map mapData = new HashMap(); + private MutatabilityAwareMap convertListToMap(List listData) { + Map mapData = new LinkedHashMap(); for (Message item : listData) { convertMessageToKeyAndValue(item, mapData); } - return mapData; + return new MutatabilityAwareMap(this, mapData); } /** Returns the content of this MapField as a read-only Map. */ @@ -199,7 +201,7 @@ public class MapField { } public void clear() { - mapData = new HashMap(); + mapData = new MutatabilityAwareMap(this, new LinkedHashMap()); mode = StorageMode.MAP; } @@ -221,7 +223,7 @@ public class MapField { /** Returns a deep copy of this MapField. */ public MapField copy() { return new MapField( - converter, StorageMode.MAP, MapFieldLite.copy(getMap()), null); + converter, StorageMode.MAP, MapFieldLite.copy(getMap())); } /** Gets the content of this MapField as a read-only List. */ @@ -256,4 +258,29 @@ public class MapField { Message getMapEntryMessageDefaultInstance() { return converter.getMessageDefaultInstance(); } + + /** + * Makes this list immutable. All subsequent modifications will throw an + * {@link UnsupportedOperationException}. + */ + public void makeImmutable() { + isMutable = false; + } + + /** + * Returns whether this field can be modified. + */ + public boolean isMutable() { + return isMutable; + } + + /* (non-Javadoc) + * @see com.google.protobuf.MutabilityOracle#ensureMutable() + */ + @Override + public void ensureMutable() { + if (!isMutable()) { + throw new UnsupportedOperationException(); + } + } } diff --git a/java/src/main/java/com/google/protobuf/MapFieldLite.java b/java/src/main/java/com/google/protobuf/MapFieldLite.java index 7f94c690..c17fa7b1 100644 --- a/java/src/main/java/com/google/protobuf/MapFieldLite.java +++ b/java/src/main/java/com/google/protobuf/MapFieldLite.java @@ -31,9 +31,12 @@ package com.google.protobuf; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; -import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; /** * Internal representation of map fields in generated lite-runtime messages. @@ -41,16 +44,21 @@ import java.util.Map; * This class is a protobuf implementation detail. Users shouldn't use this * class directly. */ -public class MapFieldLite { - private Map mapData; +public class MapFieldLite implements MutabilityOracle { + private MutatabilityAwareMap mapData; + private boolean isMutable; private MapFieldLite(Map mapData) { - this.mapData = mapData; + this.mapData = new MutatabilityAwareMap(this, mapData); + this.isMutable = true; } @SuppressWarnings({"rawtypes", "unchecked"}) private static final MapFieldLite EMPTY_MAP_FIELD = new MapFieldLite(Collections.emptyMap()); + static { + EMPTY_MAP_FIELD.makeImmutable(); + } /** Returns an singleton immutable empty MapFieldLite instance. */ @SuppressWarnings({"unchecked", "cast"}) @@ -60,7 +68,7 @@ public class MapFieldLite { /** Creates a new MapFieldLite instance. */ public static MapFieldLite newMapField() { - return new MapFieldLite(new HashMap()); + return new MapFieldLite(new LinkedHashMap()); } /** Gets the content of this MapField as a read-only Map. */ @@ -168,7 +176,7 @@ public class MapFieldLite { */ @SuppressWarnings("unchecked") static Map copy(Map map) { - Map result = new HashMap(); + Map result = new LinkedHashMap(); for (Map.Entry entry : map.entrySet()) { result.put(entry.getKey(), (V) copy(entry.getValue())); } @@ -179,4 +187,360 @@ public class MapFieldLite { public MapFieldLite copy() { return new MapFieldLite(copy(mapData)); } + + /** + * Makes this field immutable. All subsequent modifications will throw an + * {@link UnsupportedOperationException}. + */ + public void makeImmutable() { + isMutable = false; + } + + /** + * Returns whether this field can be modified. + */ + public boolean isMutable() { + return isMutable; + } + + @Override + public void ensureMutable() { + if (!isMutable()) { + throw new UnsupportedOperationException(); + } + } + + /** + * An internal map that checks for mutability before delegating. + */ + static class MutatabilityAwareMap implements Map { + private final MutabilityOracle mutabilityOracle; + private final Map delegate; + + MutatabilityAwareMap(MutabilityOracle mutabilityOracle, Map delegate) { + this.mutabilityOracle = mutabilityOracle; + this.delegate = delegate; + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + return delegate.containsKey(key); + } + + @Override + public boolean containsValue(Object value) { + return delegate.containsValue(value); + } + + @Override + public V get(Object key) { + return delegate.get(key); + } + + @Override + public V put(K key, V value) { + mutabilityOracle.ensureMutable(); + return delegate.put(key, value); + } + + @Override + public V remove(Object key) { + mutabilityOracle.ensureMutable(); + return delegate.remove(key); + } + + @Override + public void putAll(Map m) { + mutabilityOracle.ensureMutable(); + delegate.putAll(m); + } + + @Override + public void clear() { + mutabilityOracle.ensureMutable(); + delegate.clear(); + } + + @Override + public Set keySet() { + return new MutatabilityAwareSet(mutabilityOracle, delegate.keySet()); + } + + @Override + public Collection values() { + return new MutatabilityAwareCollection(mutabilityOracle, delegate.values()); + } + + @Override + public Set> entrySet() { + return new MutatabilityAwareSet>(mutabilityOracle, delegate.entrySet()); + } + + @Override + public boolean equals(Object o) { + return delegate.equals(o); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public String toString() { + return delegate.toString(); + } + } + + /** + * An internal collection that checks for mutability before delegating. + */ + private static class MutatabilityAwareCollection implements Collection { + private final MutabilityOracle mutabilityOracle; + private final Collection delegate; + + MutatabilityAwareCollection(MutabilityOracle mutabilityOracle, Collection delegate) { + this.mutabilityOracle = mutabilityOracle; + this.delegate = delegate; + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return delegate.contains(o); + } + + @Override + public Iterator iterator() { + return new MutatabilityAwareIterator(mutabilityOracle, delegate.iterator()); + } + + @Override + public Object[] toArray() { + return delegate.toArray(); + } + + @Override + public T[] toArray(T[] a) { + return delegate.toArray(a); + } + + @Override + public boolean add(E e) { + // Unsupported operation in the delegate. + throw new UnsupportedOperationException(); + } + + @Override + public boolean remove(Object o) { + mutabilityOracle.ensureMutable(); + return delegate.remove(o); + } + + @Override + public boolean containsAll(Collection c) { + return delegate.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + // Unsupported operation in the delegate. + throw new UnsupportedOperationException(); + } + + @Override + public boolean removeAll(Collection c) { + mutabilityOracle.ensureMutable(); + return delegate.removeAll(c); + } + + @Override + public boolean retainAll(Collection c) { + mutabilityOracle.ensureMutable(); + return delegate.retainAll(c); + } + + @Override + public void clear() { + mutabilityOracle.ensureMutable(); + delegate.clear(); + } + + @Override + public boolean equals(Object o) { + return delegate.equals(o); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public String toString() { + return delegate.toString(); + } + } + + /** + * An internal set that checks for mutability before delegating. + */ + private static class MutatabilityAwareSet implements Set { + private final MutabilityOracle mutabilityOracle; + private final Set delegate; + + MutatabilityAwareSet(MutabilityOracle mutabilityOracle, Set delegate) { + this.mutabilityOracle = mutabilityOracle; + this.delegate = delegate; + } + + @Override + public int size() { + return delegate.size(); + } + + @Override + public boolean isEmpty() { + return delegate.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return delegate.contains(o); + } + + @Override + public Iterator iterator() { + return new MutatabilityAwareIterator(mutabilityOracle, delegate.iterator()); + } + + @Override + public Object[] toArray() { + return delegate.toArray(); + } + + @Override + public T[] toArray(T[] a) { + return delegate.toArray(a); + } + + @Override + public boolean add(E e) { + mutabilityOracle.ensureMutable(); + return delegate.add(e); + } + + @Override + public boolean remove(Object o) { + mutabilityOracle.ensureMutable(); + return delegate.remove(o); + } + + @Override + public boolean containsAll(Collection c) { + return delegate.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + mutabilityOracle.ensureMutable(); + return delegate.addAll(c); + } + + @Override + public boolean retainAll(Collection c) { + mutabilityOracle.ensureMutable(); + return delegate.retainAll(c); + } + + @Override + public boolean removeAll(Collection c) { + mutabilityOracle.ensureMutable(); + return delegate.removeAll(c); + } + + @Override + public void clear() { + mutabilityOracle.ensureMutable(); + delegate.clear(); + } + + @Override + public boolean equals(Object o) { + return delegate.equals(o); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public String toString() { + return delegate.toString(); + } + } + + /** + * An internal iterator that checks for mutability before delegating. + */ + private static class MutatabilityAwareIterator implements Iterator { + private final MutabilityOracle mutabilityOracle; + private final Iterator delegate; + + MutatabilityAwareIterator(MutabilityOracle mutabilityOracle, Iterator delegate) { + this.mutabilityOracle = mutabilityOracle; + this.delegate = delegate; + } + + @Override + public boolean hasNext() { + return delegate.hasNext(); + } + + @Override + public E next() { + return delegate.next(); + } + + @Override + public void remove() { + mutabilityOracle.ensureMutable(); + delegate.remove(); + } + + @Override + public boolean equals(Object obj) { + return delegate.equals(obj); + } + + @Override + public int hashCode() { + return delegate.hashCode(); + } + + @Override + public String toString() { + return delegate.toString(); + } + } } diff --git a/java/src/main/java/com/google/protobuf/MutabilityOracle.java b/java/src/main/java/com/google/protobuf/MutabilityOracle.java new file mode 100644 index 00000000..82b723c9 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/MutabilityOracle.java @@ -0,0 +1,48 @@ +// 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. + +package com.google.protobuf; + +/** + * Verifies that an object is mutable, throwing if not. + */ +interface MutabilityOracle { + static final MutabilityOracle IMMUTABLE = new MutabilityOracle() { + @Override + public void ensureMutable() { + throw new UnsupportedOperationException(); + } + }; + + /** + * Throws an {@link UnsupportedOperationException} if not mutable. + */ + void ensureMutable(); +} diff --git a/java/src/main/java/com/google/protobuf/ProtobufArrayList.java b/java/src/main/java/com/google/protobuf/ProtobufArrayList.java new file mode 100644 index 00000000..759368c9 --- /dev/null +++ b/java/src/main/java/com/google/protobuf/ProtobufArrayList.java @@ -0,0 +1,95 @@ +// 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. + +package com.google.protobuf; + +import com.google.protobuf.Internal.ProtobufList; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implements {@link ProtobufList} for non-primitive and {@link String} types. + */ +class ProtobufArrayList extends AbstractProtobufList { + + private static final ProtobufArrayList EMPTY_LIST = new ProtobufArrayList(); + static { + EMPTY_LIST.makeImmutable(); + } + + @SuppressWarnings("unchecked") // Guaranteed safe by runtime. + public static ProtobufArrayList emptyList() { + return (ProtobufArrayList) EMPTY_LIST; + } + + private final List list; + + ProtobufArrayList() { + list = new ArrayList(); + } + + ProtobufArrayList(List toCopy) { + list = new ArrayList(toCopy); + } + + @Override + public void add(int index, E element) { + ensureIsMutable(); + list.add(index, element); + modCount++; + } + + @Override + public E get(int index) { + return list.get(index); + } + + @Override + public E remove(int index) { + ensureIsMutable(); + E toReturn = list.remove(index); + modCount++; + return toReturn; + } + + @Override + public E set(int index, E element) { + ensureIsMutable(); + E toReturn = list.set(index, element); + modCount++; + return toReturn; + } + + @Override + public int size() { + return list.size(); + } +} diff --git a/java/src/main/java/com/google/protobuf/TextFormat.java b/java/src/main/java/com/google/protobuf/TextFormat.java index dd2b4600..a79ce559 100644 --- a/java/src/main/java/com/google/protobuf/TextFormat.java +++ b/java/src/main/java/com/google/protobuf/TextFormat.java @@ -1725,7 +1725,7 @@ public final class TextFormat { * {@link #escapeBytes(ByteString)}. Two-digit hex escapes (starting with * "\x") are also recognized. */ - static ByteString unescapeBytes(final CharSequence charString) + public static ByteString unescapeBytes(final CharSequence charString) throws InvalidEscapeSequenceException { // First convert the Java character sequence to UTF-8 bytes. ByteString input = ByteString.copyFromUtf8(charString.toString()); @@ -1808,7 +1808,7 @@ public final class TextFormat { * Thrown by {@link TextFormat#unescapeBytes} and * {@link TextFormat#unescapeText} when an invalid escape sequence is seen. */ - static class InvalidEscapeSequenceException extends IOException { + public static class InvalidEscapeSequenceException extends IOException { private static final long serialVersionUID = -8164033650142593304L; InvalidEscapeSequenceException(final String description) { diff --git a/java/src/test/java/com/google/protobuf/BooleanArrayListTest.java b/java/src/test/java/com/google/protobuf/BooleanArrayListTest.java new file mode 100644 index 00000000..df89c263 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/BooleanArrayListTest.java @@ -0,0 +1,473 @@ +// 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. + +package com.google.protobuf; + +import static java.util.Arrays.asList; + +import junit.framework.TestCase; + +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.Iterator; + +/** + * Tests for {@link BooleanArrayList}. + * + * @author dweis@google.com (Daniel Weis) + */ +public class BooleanArrayListTest extends TestCase { + + private static final BooleanArrayList UNARY_LIST = newImmutableBooleanArrayList(true); + private static final BooleanArrayList TERTIARY_LIST = + newImmutableBooleanArrayList(true, true, false); + + private BooleanArrayList list; + + @Override + protected void setUp() throws Exception { + list = new BooleanArrayList(); + } + + public void testEmptyListReturnsSameInstance() { + assertSame(BooleanArrayList.emptyList(), BooleanArrayList.emptyList()); + } + + public void testEmptyListIsImmutable() { + assertImmutable(BooleanArrayList.emptyList()); + } + + public void testMakeImmutable() { + list.addBoolean(true); + list.addBoolean(false); + list.addBoolean(true); + list.addBoolean(true); + list.makeImmutable(); + assertImmutable(list); + } + + public void testCopyConstructor() { + BooleanArrayList copy = new BooleanArrayList(TERTIARY_LIST); + assertEquals(TERTIARY_LIST, copy); + + copy = new BooleanArrayList(BooleanArrayList.emptyList()); + assertEquals(BooleanArrayList.emptyList(), copy); + + copy = new BooleanArrayList(asList(false, false, true)); + assertEquals(asList(false, false, true), copy); + + copy = new BooleanArrayList(Collections.emptyList()); + assertEquals(BooleanArrayList.emptyList(), copy); + } + + public void testModificationWithIteration() { + list.addAll(asList(true, false, false, true)); + Iterator iterator = list.iterator(); + assertEquals(4, list.size()); + assertEquals(true, (boolean) list.get(0)); + assertEquals(true, (boolean) iterator.next()); + list.set(0, true); + assertEquals(false, (boolean) iterator.next()); + + list.remove(0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + + iterator = list.iterator(); + list.add(0, false); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + } + + public void testGet() { + assertEquals(true, (boolean) TERTIARY_LIST.get(0)); + assertEquals(true, (boolean) TERTIARY_LIST.get(1)); + assertEquals(false, (boolean) TERTIARY_LIST.get(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testGetInt() { + assertEquals(true, TERTIARY_LIST.getBoolean(0)); + assertEquals(true, TERTIARY_LIST.getBoolean(1)); + assertEquals(false, TERTIARY_LIST.getBoolean(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSize() { + assertEquals(0, BooleanArrayList.emptyList().size()); + assertEquals(1, UNARY_LIST.size()); + assertEquals(3, TERTIARY_LIST.size()); + + list.addBoolean(true); + list.addBoolean(false); + list.addBoolean(false); + list.addBoolean(false); + assertEquals(4, list.size()); + + list.remove(0); + assertEquals(3, list.size()); + + list.add(true); + assertEquals(4, list.size()); + } + + public void testSet() { + list.addBoolean(false); + list.addBoolean(false); + + assertEquals(false, (boolean) list.set(0, true)); + assertEquals(true, list.getBoolean(0)); + + assertEquals(false, (boolean) list.set(1, false)); + assertEquals(false, list.getBoolean(1)); + + try { + list.set(-1, true); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.set(2, false); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSetInt() { + list.addBoolean(true); + list.addBoolean(true); + + assertEquals(true, list.setBoolean(0, false)); + assertEquals(false, list.getBoolean(0)); + + assertEquals(true, list.setBoolean(1, false)); + assertEquals(false, list.getBoolean(1)); + + try { + list.setBoolean(-1, false); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.setBoolean(2, true); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAdd() { + assertEquals(0, list.size()); + + assertTrue(list.add(true)); + assertEquals(asList(true), list); + + assertTrue(list.add(false)); + list.add(0, false); + assertEquals(asList(false, true, false), list); + + list.add(0, false); + list.add(0, true); + // Force a resize by getting up to 11 elements. + for (int i = 0; i < 6; i++) { + list.add(true); + } + assertEquals(asList(true, false, false, true, false, true, true, true, true, true, true), list); + + try { + list.add(-1, false); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.add(4, true); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAddInt() { + assertEquals(0, list.size()); + + list.addBoolean(true); + assertEquals(asList(true), list); + + list.addBoolean(false); + assertEquals(asList(true, false), list); + } + + public void testAddAll() { + assertEquals(0, list.size()); + + assertTrue(list.addAll(Collections.singleton(false))); + assertEquals(1, list.size()); + assertEquals(false, (boolean) list.get(0)); + assertEquals(false, list.getBoolean(0)); + + assertTrue(list.addAll(asList(true, false, false, false, true))); + assertEquals(asList(false, true, false, false, false, true), list); + + assertTrue(list.addAll(TERTIARY_LIST)); + assertEquals(asList(false, true, false, false, false, true, true, true, false), list); + + assertFalse(list.addAll(Collections.emptyList())); + assertFalse(list.addAll(BooleanArrayList.emptyList())); + } + + public void testRemove() { + list.addAll(TERTIARY_LIST); + assertEquals(true, (boolean) list.remove(0)); + assertEquals(asList(true, false), list); + + assertTrue(list.remove(Boolean.TRUE)); + assertEquals(asList(false), list); + + assertFalse(list.remove(Boolean.TRUE)); + assertEquals(asList(false), list); + + assertEquals(false, (boolean) list.remove(0)); + assertEquals(asList(), list); + + try { + list.remove(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.remove(0); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + private void assertImmutable(BooleanArrayList list) { + if (list.contains(1)) { + throw new RuntimeException("Cannot test the immutability of lists that contain 1."); + } + + try { + list.add(false); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.add(0, true); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.singletonList(false)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(new BooleanArrayList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.singleton(true)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addBoolean(true); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.clear(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, true); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.setBoolean(0, false); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + + private static BooleanArrayList newImmutableBooleanArrayList(boolean... elements) { + BooleanArrayList list = new BooleanArrayList(); + for (boolean element : elements) { + list.addBoolean(element); + } + list.makeImmutable(); + return list; + } +} diff --git a/java/src/test/java/com/google/protobuf/DescriptorsTest.java b/java/src/test/java/com/google/protobuf/DescriptorsTest.java index 6cfa18d5..edd7fc46 100644 --- a/java/src/test/java/com/google/protobuf/DescriptorsTest.java +++ b/java/src/test/java/com/google/protobuf/DescriptorsTest.java @@ -56,6 +56,7 @@ import protobuf_unittest.UnittestProto.TestAllTypes; import protobuf_unittest.UnittestProto.TestExtremeDefaultValues; import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges; import protobuf_unittest.UnittestProto.TestRequired; +import protobuf_unittest.UnittestProto.TestReservedFields; import protobuf_unittest.UnittestProto.TestService; import junit.framework.TestCase; @@ -687,6 +688,9 @@ public class DescriptorsTest extends TestCase { assertEquals(4, oneofDescriptor.getFieldCount()); assertSame(oneofDescriptor.getField(1), field); + + assertEquals(4, oneofDescriptor.getFields().size()); + assertEquals(oneofDescriptor.getFields().get(1), field); } public void testMessageDescriptorExtensions() throws Exception { @@ -702,6 +706,19 @@ public class DescriptorsTest extends TestCase { assertTrue(TestMultipleExtensionRanges.getDescriptor().isExtensionNumber(4143)); } + public void testReservedFields() { + Descriptor d = TestReservedFields.getDescriptor(); + assertTrue(d.isReservedNumber(2)); + assertFalse(d.isReservedNumber(8)); + assertTrue(d.isReservedNumber(9)); + assertTrue(d.isReservedNumber(10)); + assertTrue(d.isReservedNumber(11)); + assertFalse(d.isReservedNumber(12)); + assertFalse(d.isReservedName("foo")); + assertTrue(d.isReservedName("bar")); + assertTrue(d.isReservedName("baz")); + } + public void testToString() { assertEquals("protobuf_unittest.TestAllTypes.optional_uint64", UnittestProto.TestAllTypes.getDescriptor().findFieldByNumber( diff --git a/java/src/test/java/com/google/protobuf/DoubleArrayListTest.java b/java/src/test/java/com/google/protobuf/DoubleArrayListTest.java new file mode 100644 index 00000000..e7a73d70 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/DoubleArrayListTest.java @@ -0,0 +1,473 @@ +// 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. + +package com.google.protobuf; + +import static java.util.Arrays.asList; + +import junit.framework.TestCase; + +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.Iterator; + +/** + * Tests for {@link DoubleArrayList}. + * + * @author dweis@google.com (Daniel Weis) + */ +public class DoubleArrayListTest extends TestCase { + + private static final DoubleArrayList UNARY_LIST = newImmutableDoubleArrayList(1); + private static final DoubleArrayList TERTIARY_LIST = + newImmutableDoubleArrayList(1, 2, 3); + + private DoubleArrayList list; + + @Override + protected void setUp() throws Exception { + list = new DoubleArrayList(); + } + + public void testEmptyListReturnsSameInstance() { + assertSame(DoubleArrayList.emptyList(), DoubleArrayList.emptyList()); + } + + public void testEmptyListIsImmutable() { + assertImmutable(DoubleArrayList.emptyList()); + } + + public void testMakeImmutable() { + list.addDouble(2); + list.addDouble(4); + list.addDouble(6); + list.addDouble(8); + list.makeImmutable(); + assertImmutable(list); + } + + public void testCopyConstructor() { + DoubleArrayList copy = new DoubleArrayList(TERTIARY_LIST); + assertEquals(TERTIARY_LIST, copy); + + copy = new DoubleArrayList(DoubleArrayList.emptyList()); + assertEquals(DoubleArrayList.emptyList(), copy); + + copy = new DoubleArrayList(asList(1D, 2D, 3D)); + assertEquals(asList(1D, 2D, 3D), copy); + + copy = new DoubleArrayList(Collections.emptyList()); + assertEquals(DoubleArrayList.emptyList(), copy); + } + + public void testModificationWithIteration() { + list.addAll(asList(1D, 2D, 3D, 4D)); + Iterator iterator = list.iterator(); + assertEquals(4, list.size()); + assertEquals(1D, (double) list.get(0)); + assertEquals(1D, (double) iterator.next()); + list.set(0, 1D); + assertEquals(2D, (double) iterator.next()); + + list.remove(0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + + iterator = list.iterator(); + list.add(0, 0D); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + } + + public void testGet() { + assertEquals(1D, (double) TERTIARY_LIST.get(0)); + assertEquals(2D, (double) TERTIARY_LIST.get(1)); + assertEquals(3D, (double) TERTIARY_LIST.get(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testGetInt() { + assertEquals(1D, TERTIARY_LIST.getDouble(0)); + assertEquals(2D, TERTIARY_LIST.getDouble(1)); + assertEquals(3D, TERTIARY_LIST.getDouble(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSize() { + assertEquals(0, DoubleArrayList.emptyList().size()); + assertEquals(1, UNARY_LIST.size()); + assertEquals(3, TERTIARY_LIST.size()); + + list.addDouble(2); + list.addDouble(4); + list.addDouble(6); + list.addDouble(8); + assertEquals(4, list.size()); + + list.remove(0); + assertEquals(3, list.size()); + + list.add(16D); + assertEquals(4, list.size()); + } + + public void testSet() { + list.addDouble(2); + list.addDouble(4); + + assertEquals(2D, (double) list.set(0, 0D)); + assertEquals(0D, list.getDouble(0)); + + assertEquals(4D, (double) list.set(1, 0D)); + assertEquals(0D, list.getDouble(1)); + + try { + list.set(-1, 0D); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.set(2, 0D); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSetInt() { + list.addDouble(2); + list.addDouble(4); + + assertEquals(2D, list.setDouble(0, 0)); + assertEquals(0D, list.getDouble(0)); + + assertEquals(4D, list.setDouble(1, 0)); + assertEquals(0D, list.getDouble(1)); + + try { + list.setDouble(-1, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.setDouble(2, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAdd() { + assertEquals(0, list.size()); + + assertTrue(list.add(2D)); + assertEquals(asList(2D), list); + + assertTrue(list.add(3D)); + list.add(0, 4D); + assertEquals(asList(4D, 2D, 3D), list); + + list.add(0, 1D); + list.add(0, 0D); + // Force a resize by getting up to 11 elements. + for (int i = 0; i < 6; i++) { + list.add(Double.valueOf(5 + i)); + } + assertEquals(asList(0D, 1D, 4D, 2D, 3D, 5D, 6D, 7D, 8D, 9D, 10D), list); + + try { + list.add(-1, 5D); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.add(4, 5D); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAddInt() { + assertEquals(0, list.size()); + + list.addDouble(2); + assertEquals(asList(2D), list); + + list.addDouble(3); + assertEquals(asList(2D, 3D), list); + } + + public void testAddAll() { + assertEquals(0, list.size()); + + assertTrue(list.addAll(Collections.singleton(1D))); + assertEquals(1, list.size()); + assertEquals(1D, (double) list.get(0)); + assertEquals(1D, list.getDouble(0)); + + assertTrue(list.addAll(asList(2D, 3D, 4D, 5D, 6D))); + assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D), list); + + assertTrue(list.addAll(TERTIARY_LIST)); + assertEquals(asList(1D, 2D, 3D, 4D, 5D, 6D, 1D, 2D, 3D), list); + + assertFalse(list.addAll(Collections.emptyList())); + assertFalse(list.addAll(DoubleArrayList.emptyList())); + } + + public void testRemove() { + list.addAll(TERTIARY_LIST); + assertEquals(1D, (double) list.remove(0)); + assertEquals(asList(2D, 3D), list); + + assertTrue(list.remove(Double.valueOf(3))); + assertEquals(asList(2D), list); + + assertFalse(list.remove(Double.valueOf(3))); + assertEquals(asList(2D), list); + + assertEquals(2D, (double) list.remove(0)); + assertEquals(asList(), list); + + try { + list.remove(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.remove(0); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + private void assertImmutable(DoubleArrayList list) { + if (list.contains(1)) { + throw new RuntimeException("Cannot test the immutability of lists that contain 1."); + } + + try { + list.add(1D); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.add(0, 1D); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.singletonList(1D)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(new DoubleArrayList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.singleton(1D)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addDouble(0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.clear(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, 0D); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.setDouble(0, 0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + + private static DoubleArrayList newImmutableDoubleArrayList(double... elements) { + DoubleArrayList list = new DoubleArrayList(); + for (double element : elements) { + list.addDouble(element); + } + list.makeImmutable(); + return list; + } +} diff --git a/java/src/test/java/com/google/protobuf/FloatArrayListTest.java b/java/src/test/java/com/google/protobuf/FloatArrayListTest.java new file mode 100644 index 00000000..8f3e93dc --- /dev/null +++ b/java/src/test/java/com/google/protobuf/FloatArrayListTest.java @@ -0,0 +1,473 @@ +// 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. + +package com.google.protobuf; + +import static java.util.Arrays.asList; + +import junit.framework.TestCase; + +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.Iterator; + +/** + * Tests for {@link FloatArrayList}. + * + * @author dweis@google.com (Daniel Weis) + */ +public class FloatArrayListTest extends TestCase { + + private static final FloatArrayList UNARY_LIST = newImmutableFloatArrayList(1); + private static final FloatArrayList TERTIARY_LIST = + newImmutableFloatArrayList(1, 2, 3); + + private FloatArrayList list; + + @Override + protected void setUp() throws Exception { + list = new FloatArrayList(); + } + + public void testEmptyListReturnsSameInstance() { + assertSame(FloatArrayList.emptyList(), FloatArrayList.emptyList()); + } + + public void testEmptyListIsImmutable() { + assertImmutable(FloatArrayList.emptyList()); + } + + public void testMakeImmutable() { + list.addFloat(2); + list.addFloat(4); + list.addFloat(6); + list.addFloat(8); + list.makeImmutable(); + assertImmutable(list); + } + + public void testCopyConstructor() { + FloatArrayList copy = new FloatArrayList(TERTIARY_LIST); + assertEquals(TERTIARY_LIST, copy); + + copy = new FloatArrayList(FloatArrayList.emptyList()); + assertEquals(FloatArrayList.emptyList(), copy); + + copy = new FloatArrayList(asList(1F, 2F, 3F)); + assertEquals(asList(1F, 2F, 3F), copy); + + copy = new FloatArrayList(Collections.emptyList()); + assertEquals(FloatArrayList.emptyList(), copy); + } + + public void testModificationWithIteration() { + list.addAll(asList(1F, 2F, 3F, 4F)); + Iterator iterator = list.iterator(); + assertEquals(4, list.size()); + assertEquals(1F, (float) list.get(0)); + assertEquals(1F, (float) iterator.next()); + list.set(0, 1F); + assertEquals(2F, (float) iterator.next()); + + list.remove(0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + + iterator = list.iterator(); + list.add(0, 0F); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + } + + public void testGet() { + assertEquals(1F, (float) TERTIARY_LIST.get(0)); + assertEquals(2F, (float) TERTIARY_LIST.get(1)); + assertEquals(3F, (float) TERTIARY_LIST.get(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testGetFloat() { + assertEquals(1F, TERTIARY_LIST.getFloat(0)); + assertEquals(2F, TERTIARY_LIST.getFloat(1)); + assertEquals(3F, TERTIARY_LIST.getFloat(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSize() { + assertEquals(0, FloatArrayList.emptyList().size()); + assertEquals(1, UNARY_LIST.size()); + assertEquals(3, TERTIARY_LIST.size()); + + list.addFloat(2); + list.addFloat(4); + list.addFloat(6); + list.addFloat(8); + assertEquals(4, list.size()); + + list.remove(0); + assertEquals(3, list.size()); + + list.add(16F); + assertEquals(4, list.size()); + } + + public void testSet() { + list.addFloat(2); + list.addFloat(4); + + assertEquals(2F, (float) list.set(0, 0F)); + assertEquals(0F, list.getFloat(0)); + + assertEquals(4F, (float) list.set(1, 0F)); + assertEquals(0F, list.getFloat(1)); + + try { + list.set(-1, 0F); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.set(2, 0F); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSetFloat() { + list.addFloat(2); + list.addFloat(4); + + assertEquals(2F, list.setFloat(0, 0)); + assertEquals(0F, list.getFloat(0)); + + assertEquals(4F, list.setFloat(1, 0)); + assertEquals(0F, list.getFloat(1)); + + try { + list.setFloat(-1, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.setFloat(2, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAdd() { + assertEquals(0, list.size()); + + assertTrue(list.add(2F)); + assertEquals(asList(2F), list); + + assertTrue(list.add(3F)); + list.add(0, 4F); + assertEquals(asList(4F, 2F, 3F), list); + + list.add(0, 1F); + list.add(0, 0F); + // Force a resize by getting up to 11 elements. + for (int i = 0; i < 6; i++) { + list.add(Float.valueOf(5 + i)); + } + assertEquals(asList(0F, 1F, 4F, 2F, 3F, 5F, 6F, 7F, 8F, 9F, 10F), list); + + try { + list.add(-1, 5F); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.add(4, 5F); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAddFloat() { + assertEquals(0, list.size()); + + list.addFloat(2); + assertEquals(asList(2F), list); + + list.addFloat(3); + assertEquals(asList(2F, 3F), list); + } + + public void testAddAll() { + assertEquals(0, list.size()); + + assertTrue(list.addAll(Collections.singleton(1F))); + assertEquals(1, list.size()); + assertEquals(1F, (float) list.get(0)); + assertEquals(1F, list.getFloat(0)); + + assertTrue(list.addAll(asList(2F, 3F, 4F, 5F, 6F))); + assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F), list); + + assertTrue(list.addAll(TERTIARY_LIST)); + assertEquals(asList(1F, 2F, 3F, 4F, 5F, 6F, 1F, 2F, 3F), list); + + assertFalse(list.addAll(Collections.emptyList())); + assertFalse(list.addAll(FloatArrayList.emptyList())); + } + + public void testRemove() { + list.addAll(TERTIARY_LIST); + assertEquals(1F, (float) list.remove(0)); + assertEquals(asList(2F, 3F), list); + + assertTrue(list.remove(Float.valueOf(3))); + assertEquals(asList(2F), list); + + assertFalse(list.remove(Float.valueOf(3))); + assertEquals(asList(2F), list); + + assertEquals(2F, (float) list.remove(0)); + assertEquals(asList(), list); + + try { + list.remove(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.remove(0); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + private void assertImmutable(FloatArrayList list) { + if (list.contains(1)) { + throw new RuntimeException("Cannot test the immutability of lists that contain 1."); + } + + try { + list.add(1F); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.add(0, 1F); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.singletonList(1F)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(new FloatArrayList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.singleton(1F)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addFloat(0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.clear(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, 0F); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.setFloat(0, 0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + + private static FloatArrayList newImmutableFloatArrayList(int... elements) { + FloatArrayList list = new FloatArrayList(); + for (int element : elements) { + list.addFloat(element); + } + list.makeImmutable(); + return list; + } +} diff --git a/java/src/test/java/com/google/protobuf/IntArrayListTest.java b/java/src/test/java/com/google/protobuf/IntArrayListTest.java new file mode 100644 index 00000000..3733eb30 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/IntArrayListTest.java @@ -0,0 +1,473 @@ +// 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. + +package com.google.protobuf; + +import static java.util.Arrays.asList; + +import junit.framework.TestCase; + +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.Iterator; + +/** + * Tests for {@link IntArrayList}. + * + * @author dweis@google.com (Daniel Weis) + */ +public class IntArrayListTest extends TestCase { + + private static final IntArrayList UNARY_LIST = newImmutableIntArrayList(1); + private static final IntArrayList TERTIARY_LIST = + newImmutableIntArrayList(1, 2, 3); + + private IntArrayList list; + + @Override + protected void setUp() throws Exception { + list = new IntArrayList(); + } + + public void testEmptyListReturnsSameInstance() { + assertSame(IntArrayList.emptyList(), IntArrayList.emptyList()); + } + + public void testEmptyListIsImmutable() { + assertImmutable(IntArrayList.emptyList()); + } + + public void testMakeImmutable() { + list.addInt(2); + list.addInt(4); + list.addInt(6); + list.addInt(8); + list.makeImmutable(); + assertImmutable(list); + } + + public void testCopyConstructor() { + IntArrayList copy = new IntArrayList(TERTIARY_LIST); + assertEquals(TERTIARY_LIST, copy); + + copy = new IntArrayList(IntArrayList.emptyList()); + assertEquals(IntArrayList.emptyList(), copy); + + copy = new IntArrayList(asList(1, 2, 3)); + assertEquals(asList(1, 2, 3), copy); + + copy = new IntArrayList(Collections.emptyList()); + assertEquals(IntArrayList.emptyList(), copy); + } + + public void testModificationWithIteration() { + list.addAll(asList(1, 2, 3, 4)); + Iterator iterator = list.iterator(); + assertEquals(4, list.size()); + assertEquals(1, (int) list.get(0)); + assertEquals(1, (int) iterator.next()); + list.set(0, 1); + assertEquals(2, (int) iterator.next()); + + list.remove(0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + + iterator = list.iterator(); + list.add(0, 0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + } + + public void testGet() { + assertEquals(1, (int) TERTIARY_LIST.get(0)); + assertEquals(2, (int) TERTIARY_LIST.get(1)); + assertEquals(3, (int) TERTIARY_LIST.get(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testGetInt() { + assertEquals(1, TERTIARY_LIST.getInt(0)); + assertEquals(2, TERTIARY_LIST.getInt(1)); + assertEquals(3, TERTIARY_LIST.getInt(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSize() { + assertEquals(0, IntArrayList.emptyList().size()); + assertEquals(1, UNARY_LIST.size()); + assertEquals(3, TERTIARY_LIST.size()); + + list.addInt(2); + list.addInt(4); + list.addInt(6); + list.addInt(8); + assertEquals(4, list.size()); + + list.remove(0); + assertEquals(3, list.size()); + + list.add(16); + assertEquals(4, list.size()); + } + + public void testSet() { + list.addInt(2); + list.addInt(4); + + assertEquals(2, (int) list.set(0, 0)); + assertEquals(0, list.getInt(0)); + + assertEquals(4, (int) list.set(1, 0)); + assertEquals(0, list.getInt(1)); + + try { + list.set(-1, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.set(2, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSetInt() { + list.addInt(2); + list.addInt(4); + + assertEquals(2, list.setInt(0, 0)); + assertEquals(0, list.getInt(0)); + + assertEquals(4, list.setInt(1, 0)); + assertEquals(0, list.getInt(1)); + + try { + list.setInt(-1, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.setInt(2, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAdd() { + assertEquals(0, list.size()); + + assertTrue(list.add(2)); + assertEquals(asList(2), list); + + assertTrue(list.add(3)); + list.add(0, 4); + assertEquals(asList(4, 2, 3), list); + + list.add(0, 1); + list.add(0, 0); + // Force a resize by getting up to 11 elements. + for (int i = 0; i < 6; i++) { + list.add(5 + i); + } + assertEquals(asList(0, 1, 4, 2, 3, 5, 6, 7, 8, 9, 10), list); + + try { + list.add(-1, 5); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.add(4, 5); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAddInt() { + assertEquals(0, list.size()); + + list.addInt(2); + assertEquals(asList(2), list); + + list.addInt(3); + assertEquals(asList(2, 3), list); + } + + public void testAddAll() { + assertEquals(0, list.size()); + + assertTrue(list.addAll(Collections.singleton(1))); + assertEquals(1, list.size()); + assertEquals(1, (int) list.get(0)); + assertEquals(1, list.getInt(0)); + + assertTrue(list.addAll(asList(2, 3, 4, 5, 6))); + assertEquals(asList(1, 2, 3, 4, 5, 6), list); + + assertTrue(list.addAll(TERTIARY_LIST)); + assertEquals(asList(1, 2, 3, 4, 5, 6, 1, 2, 3), list); + + assertFalse(list.addAll(Collections.emptyList())); + assertFalse(list.addAll(IntArrayList.emptyList())); + } + + public void testRemove() { + list.addAll(TERTIARY_LIST); + assertEquals(1, (int) list.remove(0)); + assertEquals(asList(2, 3), list); + + assertTrue(list.remove(Integer.valueOf(3))); + assertEquals(asList(2), list); + + assertFalse(list.remove(Integer.valueOf(3))); + assertEquals(asList(2), list); + + assertEquals(2, (int) list.remove(0)); + assertEquals(asList(), list); + + try { + list.remove(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.remove(0); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + private void assertImmutable(IntArrayList list) { + if (list.contains(1)) { + throw new RuntimeException("Cannot test the immutability of lists that contain 1."); + } + + try { + list.add(1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.add(0, 1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.singletonList(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(new IntArrayList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addInt(0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.clear(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, 0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.setInt(0, 0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + + private static IntArrayList newImmutableIntArrayList(int... elements) { + IntArrayList list = new IntArrayList(); + for (int element : elements) { + list.addInt(element); + } + list.makeImmutable(); + return list; + } +} diff --git a/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java index f3012b96..0f42ac50 100644 --- a/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java +++ b/java/src/test/java/com/google/protobuf/LazyStringArrayListTest.java @@ -30,9 +30,13 @@ package com.google.protobuf; +import static java.util.Arrays.asList; + import junit.framework.TestCase; import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.Iterator; import java.util.List; /** @@ -171,4 +175,188 @@ public class LazyStringArrayListTest extends TestCase { assertSame(BYTE_STRING_B, list2.getByteString(1)); assertSame(BYTE_STRING_C, list2.getByteString(2)); } + + public void testModificationWithIteration() { + LazyStringArrayList list = new LazyStringArrayList(); + list.addAll(asList(STRING_A, STRING_B, STRING_C)); + Iterator iterator = list.iterator(); + assertEquals(3, list.size()); + assertEquals(STRING_A, list.get(0)); + assertEquals(STRING_A, iterator.next()); + + // Does not structurally modify. + iterator = list.iterator(); + list.set(0, STRING_B); + iterator.next(); + + list.remove(0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + + iterator = list.iterator(); + list.add(0, STRING_C); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + } + + public void testMakeImmutable() { + LazyStringArrayList list = new LazyStringArrayList(); + list.add(STRING_A); + list.add(STRING_B); + list.add(STRING_C); + list.makeImmutable(); + assertGenericListImmutable(list, STRING_A); + + // LazyStringArrayList has extra methods not covered in the generic + // assertion. + + try { + list.add(BYTE_STRING_A.toByteArray()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.add(BYTE_STRING_A); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAllByteArray(asList(BYTE_STRING_A.toByteArray())); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAllByteString(asList(BYTE_STRING_A)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.mergeFrom(new LazyStringArrayList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, BYTE_STRING_A.toByteArray()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, BYTE_STRING_A); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + + public void testImmutabilityPropagation() { + LazyStringArrayList list = new LazyStringArrayList(); + list.add(STRING_A); + list.makeImmutable(); + + assertGenericListImmutable(list.asByteStringList(), BYTE_STRING_A); + + // Arrays use reference equality so need to retrieve the underlying value + // to properly test deep immutability. + List byteArrayList = list.asByteArrayList(); + assertGenericListImmutable(byteArrayList, byteArrayList.get(0)); + } + + private static void assertGenericListImmutable(List list, T value) { + try { + list.add(value); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.add(0, value); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(asList(value)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, asList(value)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.clear(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(value); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(asList(value)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(asList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(asList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, value); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } } diff --git a/java/src/test/java/com/google/protobuf/LiteTest.java b/java/src/test/java/com/google/protobuf/LiteTest.java index 4d8037fc..8c3b5e5c 100644 --- a/java/src/test/java/com/google/protobuf/LiteTest.java +++ b/java/src/test/java/com/google/protobuf/LiteTest.java @@ -30,9 +30,18 @@ package com.google.protobuf; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; + import com.google.protobuf.UnittestLite; -import com.google.protobuf.UnittestLite.TestAllTypesLite; +import com.google.protobuf.UnittestLite.ForeignEnumLite; +import com.google.protobuf.UnittestLite.ForeignMessageLite; import com.google.protobuf.UnittestLite.TestAllExtensionsLite; +import com.google.protobuf.UnittestLite.TestAllTypesLite; +import com.google.protobuf.UnittestLite.TestAllTypesLite.NestedMessage; +import com.google.protobuf.UnittestLite.TestAllTypesLite.OneofFieldCase; +import com.google.protobuf.UnittestLite.TestAllTypesLite.OptionalGroup; +import com.google.protobuf.UnittestLite.TestAllTypesLite.RepeatedGroup; import com.google.protobuf.UnittestLite.TestNestedExtensionLite; import junit.framework.TestCase; @@ -149,13 +158,1302 @@ public class LiteTest extends TestCase { public void testClone() { TestAllTypesLite.Builder expected = TestAllTypesLite.newBuilder() .setOptionalInt32(123); - assertEquals( - expected.getOptionalInt32(), expected.clone().getOptionalInt32()); + assertEquals( + expected.getOptionalInt32(), expected.clone().getOptionalInt32()); - TestAllExtensionsLite.Builder expected2 = TestAllExtensionsLite.newBuilder() - .setExtension(UnittestLite.optionalInt32ExtensionLite, 123); - assertEquals( - expected2.getExtension(UnittestLite.optionalInt32ExtensionLite), - expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite)); + TestAllExtensionsLite.Builder expected2 = TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalInt32ExtensionLite, 123); + assertEquals( + expected2.getExtension(UnittestLite.optionalInt32ExtensionLite), + expected2.clone().getExtension(UnittestLite.optionalInt32ExtensionLite)); + } + + public void testAddAll() { + try { + TestAllTypesLite.newBuilder() + .addAllRepeatedBytes(null); + fail(); + } catch (NullPointerException e) { + // expected. + } + } + + public void testSanityCopyOnWrite() throws InvalidProtocolBufferException { + // Since builders are implemented as a thin wrapper around a message + // instance, we attempt to verify that we can't cause the builder to modify + // a produced message. + + TestAllTypesLite.Builder builder = TestAllTypesLite.newBuilder(); + TestAllTypesLite message = builder.build(); + TestAllTypesLite messageAfterBuild; + builder.setOptionalBool(true); + assertEquals(false, message.getOptionalBool()); + assertEquals(true, builder.getOptionalBool()); + messageAfterBuild = builder.build(); + assertEquals(true, messageAfterBuild.getOptionalBool()); + assertEquals(false, message.getOptionalBool()); + builder.clearOptionalBool(); + assertEquals(false, builder.getOptionalBool()); + assertEquals(true, messageAfterBuild.getOptionalBool()); + + message = builder.build(); + builder.setOptionalBytes(ByteString.copyFromUtf8("hi")); + assertEquals(ByteString.EMPTY, message.getOptionalBytes()); + assertEquals(ByteString.copyFromUtf8("hi"), builder.getOptionalBytes()); + messageAfterBuild = builder.build(); + assertEquals( + ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes()); + assertEquals(ByteString.EMPTY, message.getOptionalBytes()); + builder.clearOptionalBytes(); + assertEquals(ByteString.EMPTY, builder.getOptionalBytes()); + assertEquals( + ByteString.copyFromUtf8("hi"), messageAfterBuild.getOptionalBytes()); + + message = builder.build(); + builder.setOptionalCord("hi"); + assertEquals("", message.getOptionalCord()); + assertEquals("hi", builder.getOptionalCord()); + messageAfterBuild = builder.build(); + assertEquals("hi", messageAfterBuild.getOptionalCord()); + assertEquals("", message.getOptionalCord()); + builder.clearOptionalCord(); + assertEquals("", builder.getOptionalCord()); + assertEquals("hi", messageAfterBuild.getOptionalCord()); + + message = builder.build(); + builder.setOptionalCordBytes(ByteString.copyFromUtf8("no")); + assertEquals(ByteString.EMPTY, message.getOptionalCordBytes()); + assertEquals(ByteString.copyFromUtf8("no"), builder.getOptionalCordBytes()); + messageAfterBuild = builder.build(); + assertEquals( + ByteString.copyFromUtf8("no"), + messageAfterBuild.getOptionalCordBytes()); + assertEquals(ByteString.EMPTY, message.getOptionalCordBytes()); + builder.clearOptionalCord(); + assertEquals(ByteString.EMPTY, builder.getOptionalCordBytes()); + assertEquals( + ByteString.copyFromUtf8("no"), + messageAfterBuild.getOptionalCordBytes()); + + message = builder.build(); + builder.setOptionalDouble(1); + assertEquals(0D, message.getOptionalDouble()); + assertEquals(1D, builder.getOptionalDouble()); + messageAfterBuild = builder.build(); + assertEquals(1D, messageAfterBuild.getOptionalDouble()); + assertEquals(0D, message.getOptionalDouble()); + builder.clearOptionalDouble(); + assertEquals(0D, builder.getOptionalDouble()); + assertEquals(1D, messageAfterBuild.getOptionalDouble()); + + message = builder.build(); + builder.setOptionalFixed32(1); + assertEquals(0, message.getOptionalFixed32()); + assertEquals(1, builder.getOptionalFixed32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalFixed32()); + assertEquals(0, message.getOptionalFixed32()); + builder.clearOptionalFixed32(); + assertEquals(0, builder.getOptionalFixed32()); + assertEquals(1, messageAfterBuild.getOptionalFixed32()); + + message = builder.build(); + builder.setOptionalFixed64(1); + assertEquals(0L, message.getOptionalFixed64()); + assertEquals(1L, builder.getOptionalFixed64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalFixed64()); + assertEquals(0L, message.getOptionalFixed64()); + builder.clearOptionalFixed64(); + assertEquals(0L, builder.getOptionalFixed64()); + assertEquals(1L, messageAfterBuild.getOptionalFixed64()); + + message = builder.build(); + builder.setOptionalFloat(1); + assertEquals(0F, message.getOptionalFloat()); + assertEquals(1F, builder.getOptionalFloat()); + messageAfterBuild = builder.build(); + assertEquals(1F, messageAfterBuild.getOptionalFloat()); + assertEquals(0F, message.getOptionalFloat()); + builder.clearOptionalFloat(); + assertEquals(0F, builder.getOptionalFloat()); + assertEquals(1F, messageAfterBuild.getOptionalFloat()); + + message = builder.build(); + builder.setOptionalForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); + assertEquals( + ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum()); + assertEquals( + ForeignEnumLite.FOREIGN_LITE_BAR, builder.getOptionalForeignEnum()); + messageAfterBuild = builder.build(); + assertEquals( + ForeignEnumLite.FOREIGN_LITE_BAR, + messageAfterBuild.getOptionalForeignEnum()); + assertEquals( + ForeignEnumLite.FOREIGN_LITE_FOO, message.getOptionalForeignEnum()); + builder.clearOptionalForeignEnum(); + assertEquals( + ForeignEnumLite.FOREIGN_LITE_FOO, builder.getOptionalForeignEnum()); + assertEquals( + ForeignEnumLite.FOREIGN_LITE_BAR, + messageAfterBuild.getOptionalForeignEnum()); + + message = builder.build(); + ForeignMessageLite foreignMessage = ForeignMessageLite.newBuilder() + .setC(1) + .build(); + builder.setOptionalForeignMessage(foreignMessage); + assertEquals( + ForeignMessageLite.getDefaultInstance(), + message.getOptionalForeignMessage()); + assertEquals(foreignMessage, builder.getOptionalForeignMessage()); + messageAfterBuild = builder.build(); + assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage()); + assertEquals( + ForeignMessageLite.getDefaultInstance(), + message.getOptionalForeignMessage()); + builder.clearOptionalForeignMessage(); + assertEquals( + ForeignMessageLite.getDefaultInstance(), + builder.getOptionalForeignMessage()); + assertEquals(foreignMessage, messageAfterBuild.getOptionalForeignMessage()); + + message = builder.build(); + ForeignMessageLite.Builder foreignMessageBuilder = + ForeignMessageLite.newBuilder() + .setC(3); + builder.setOptionalForeignMessage(foreignMessageBuilder); + assertEquals( + ForeignMessageLite.getDefaultInstance(), + message.getOptionalForeignMessage()); + // LITE_RUNTIME doesn't implement equals so we compare on a property and + // ensure the property isn't set on foreignMessage. + assertEquals(3, builder.getOptionalForeignMessage().getC()); + messageAfterBuild = builder.build(); + assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC()); + assertEquals( + ForeignMessageLite.getDefaultInstance(), + message.getOptionalForeignMessage()); + builder.clearOptionalForeignMessage(); + assertEquals( + ForeignMessageLite.getDefaultInstance(), + builder.getOptionalForeignMessage()); + assertEquals(3, messageAfterBuild.getOptionalForeignMessage().getC()); + + message = builder.build(); + OptionalGroup optionalGroup = OptionalGroup.newBuilder() + .setA(1) + .build(); + builder.setOptionalGroup(optionalGroup); + assertEquals( + OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); + assertEquals(optionalGroup, builder.getOptionalGroup()); + messageAfterBuild = builder.build(); + assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup()); + assertEquals( + OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); + builder.clearOptionalGroup(); + assertEquals( + OptionalGroup.getDefaultInstance(), builder.getOptionalGroup()); + assertEquals(optionalGroup, messageAfterBuild.getOptionalGroup()); + + message = builder.build(); + OptionalGroup.Builder optionalGroupBuilder = OptionalGroup.newBuilder() + .setA(3); + builder.setOptionalGroup(optionalGroupBuilder); + assertEquals( + OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); + // LITE_RUNTIME doesn't implement equals so we compare on a property and + // ensure the property isn't set on optionalGroup. + assertEquals(3, builder.getOptionalGroup().getA()); + messageAfterBuild = builder.build(); + assertEquals(3, messageAfterBuild.getOptionalGroup().getA()); + assertEquals( + OptionalGroup.getDefaultInstance(), message.getOptionalGroup()); + builder.clearOptionalGroup(); + assertEquals( + OptionalGroup.getDefaultInstance(), builder.getOptionalGroup()); + assertEquals(3, messageAfterBuild.getOptionalGroup().getA()); + + message = builder.build(); + builder.setOptionalInt32(1); + assertEquals(0, message.getOptionalInt32()); + assertEquals(1, builder.getOptionalInt32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalInt32()); + assertEquals(0, message.getOptionalInt32()); + builder.clearOptionalInt32(); + assertEquals(0, builder.getOptionalInt32()); + assertEquals(1, messageAfterBuild.getOptionalInt32()); + + message = builder.build(); + builder.setOptionalInt64(1); + assertEquals(0L, message.getOptionalInt64()); + assertEquals(1L, builder.getOptionalInt64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalInt64()); + assertEquals(0L, message.getOptionalInt64()); + builder.clearOptionalInt64(); + assertEquals(0L, builder.getOptionalInt64()); + assertEquals(1L, messageAfterBuild.getOptionalInt64()); + + message = builder.build(); + NestedMessage nestedMessage = NestedMessage.newBuilder() + .setBb(1) + .build(); + builder.setOptionalLazyMessage(nestedMessage); + assertEquals( + NestedMessage.getDefaultInstance(), + message.getOptionalLazyMessage()); + assertEquals(nestedMessage, builder.getOptionalLazyMessage()); + messageAfterBuild = builder.build(); + assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage()); + assertEquals( + NestedMessage.getDefaultInstance(), + message.getOptionalLazyMessage()); + builder.clearOptionalLazyMessage(); + assertEquals( + NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage()); + assertEquals(nestedMessage, messageAfterBuild.getOptionalLazyMessage()); + + message = builder.build(); + NestedMessage.Builder nestedMessageBuilder = + NestedMessage.newBuilder() + .setBb(3); + builder.setOptionalLazyMessage(nestedMessageBuilder); + assertEquals( + NestedMessage.getDefaultInstance(), + message.getOptionalLazyMessage()); + // LITE_RUNTIME doesn't implement equals so we compare on a property. + assertEquals(3, builder.getOptionalLazyMessage().getBb()); + messageAfterBuild = builder.build(); + assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb()); + assertEquals( + NestedMessage.getDefaultInstance(), + message.getOptionalLazyMessage()); + builder.clearOptionalLazyMessage(); + assertEquals( + NestedMessage.getDefaultInstance(), builder.getOptionalLazyMessage()); + assertEquals(3, messageAfterBuild.getOptionalLazyMessage().getBb()); + + message = builder.build(); + builder.setOptionalSfixed32(1); + assertEquals(0, message.getOptionalSfixed32()); + assertEquals(1, builder.getOptionalSfixed32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalSfixed32()); + assertEquals(0, message.getOptionalSfixed32()); + builder.clearOptionalSfixed32(); + assertEquals(0, builder.getOptionalSfixed32()); + assertEquals(1, messageAfterBuild.getOptionalSfixed32()); + + message = builder.build(); + builder.setOptionalSfixed64(1); + assertEquals(0L, message.getOptionalSfixed64()); + assertEquals(1L, builder.getOptionalSfixed64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalSfixed64()); + assertEquals(0L, message.getOptionalSfixed64()); + builder.clearOptionalSfixed64(); + assertEquals(0L, builder.getOptionalSfixed64()); + assertEquals(1L, messageAfterBuild.getOptionalSfixed64()); + + message = builder.build(); + builder.setOptionalSint32(1); + assertEquals(0, message.getOptionalSint32()); + assertEquals(1, builder.getOptionalSint32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalSint32()); + builder.clearOptionalSint32(); + assertEquals(0, builder.getOptionalSint32()); + assertEquals(1, messageAfterBuild.getOptionalSint32()); + + message = builder.build(); + builder.setOptionalSint64(1); + assertEquals(0L, message.getOptionalSint64()); + assertEquals(1L, builder.getOptionalSint64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalSint64()); + assertEquals(0L, message.getOptionalSint64()); + builder.clearOptionalSint64(); + assertEquals(0L, builder.getOptionalSint64()); + assertEquals(1L, messageAfterBuild.getOptionalSint64()); + + message = builder.build(); + builder.setOptionalString("hi"); + assertEquals("", message.getOptionalString()); + assertEquals("hi", builder.getOptionalString()); + messageAfterBuild = builder.build(); + assertEquals("hi", messageAfterBuild.getOptionalString()); + assertEquals("", message.getOptionalString()); + builder.clearOptionalString(); + assertEquals("", builder.getOptionalString()); + assertEquals("hi", messageAfterBuild.getOptionalString()); + + message = builder.build(); + builder.setOptionalStringBytes(ByteString.copyFromUtf8("no")); + assertEquals(ByteString.EMPTY, message.getOptionalStringBytes()); + assertEquals( + ByteString.copyFromUtf8("no"), builder.getOptionalStringBytes()); + messageAfterBuild = builder.build(); + assertEquals( + ByteString.copyFromUtf8("no"), + messageAfterBuild.getOptionalStringBytes()); + assertEquals(ByteString.EMPTY, message.getOptionalStringBytes()); + builder.clearOptionalString(); + assertEquals(ByteString.EMPTY, builder.getOptionalStringBytes()); + assertEquals( + ByteString.copyFromUtf8("no"), + messageAfterBuild.getOptionalStringBytes()); + + message = builder.build(); + builder.setOptionalStringPiece("hi"); + assertEquals("", message.getOptionalStringPiece()); + assertEquals("hi", builder.getOptionalStringPiece()); + messageAfterBuild = builder.build(); + assertEquals("hi", messageAfterBuild.getOptionalStringPiece()); + assertEquals("", message.getOptionalStringPiece()); + builder.clearOptionalStringPiece(); + assertEquals("", builder.getOptionalStringPiece()); + assertEquals("hi", messageAfterBuild.getOptionalStringPiece()); + + message = builder.build(); + builder.setOptionalStringPieceBytes(ByteString.copyFromUtf8("no")); + assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes()); + assertEquals( + ByteString.copyFromUtf8("no"), builder.getOptionalStringPieceBytes()); + messageAfterBuild = builder.build(); + assertEquals( + ByteString.copyFromUtf8("no"), + messageAfterBuild.getOptionalStringPieceBytes()); + assertEquals(ByteString.EMPTY, message.getOptionalStringPieceBytes()); + builder.clearOptionalStringPiece(); + assertEquals(ByteString.EMPTY, builder.getOptionalStringPieceBytes()); + assertEquals( + ByteString.copyFromUtf8("no"), + messageAfterBuild.getOptionalStringPieceBytes()); + + message = builder.build(); + builder.setOptionalUint32(1); + assertEquals(0, message.getOptionalUint32()); + assertEquals(1, builder.getOptionalUint32()); + messageAfterBuild = builder.build(); + assertEquals(1, messageAfterBuild.getOptionalUint32()); + assertEquals(0, message.getOptionalUint32()); + builder.clearOptionalUint32(); + assertEquals(0, builder.getOptionalUint32()); + assertEquals(1, messageAfterBuild.getOptionalUint32()); + + message = builder.build(); + builder.setOptionalUint64(1); + assertEquals(0L, message.getOptionalUint64()); + assertEquals(1L, builder.getOptionalUint64()); + messageAfterBuild = builder.build(); + assertEquals(1L, messageAfterBuild.getOptionalUint64()); + assertEquals(0L, message.getOptionalUint64()); + builder.clearOptionalUint64(); + assertEquals(0L, builder.getOptionalUint64()); + assertEquals(1L, messageAfterBuild.getOptionalUint64()); + + message = builder.build(); + builder.addAllRepeatedBool(singletonList(true)); + assertEquals(emptyList(), message.getRepeatedBoolList()); + assertEquals(singletonList(true), builder.getRepeatedBoolList()); + assertEquals(emptyList(), message.getRepeatedBoolList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedBool(); + assertEquals(emptyList(), builder.getRepeatedBoolList()); + assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList()); + + message = builder.build(); + builder.addAllRepeatedBytes(singletonList(ByteString.copyFromUtf8("hi"))); + assertEquals(emptyList(), message.getRepeatedBytesList()); + assertEquals( + singletonList(ByteString.copyFromUtf8("hi")), + builder.getRepeatedBytesList()); + assertEquals(emptyList(), message.getRepeatedBytesList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedBytes(); + assertEquals(emptyList(), builder.getRepeatedBytesList()); + assertEquals( + singletonList(ByteString.copyFromUtf8("hi")), + messageAfterBuild.getRepeatedBytesList()); + + message = builder.build(); + builder.addAllRepeatedCord(singletonList("hi")); + assertEquals(emptyList(), message.getRepeatedCordList()); + assertEquals(singletonList("hi"), builder.getRepeatedCordList()); + assertEquals(emptyList(), message.getRepeatedCordList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedCord(); + assertEquals(emptyList(), builder.getRepeatedCordList()); + assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList()); + + message = builder.build(); + builder.addAllRepeatedDouble(singletonList(1D)); + assertEquals(emptyList(), message.getRepeatedDoubleList()); + assertEquals(singletonList(1D), builder.getRepeatedDoubleList()); + assertEquals(emptyList(), message.getRepeatedDoubleList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedDouble(); + assertEquals(emptyList(), builder.getRepeatedDoubleList()); + assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList()); + + message = builder.build(); + builder.addAllRepeatedFixed32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedFixed32List()); + assertEquals(singletonList(1), builder.getRepeatedFixed32List()); + assertEquals(emptyList(), message.getRepeatedFixed32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFixed32(); + assertEquals(emptyList(), builder.getRepeatedFixed32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List()); + + message = builder.build(); + builder.addAllRepeatedFixed64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedFixed64List()); + assertEquals(singletonList(1L), builder.getRepeatedFixed64List()); + assertEquals(emptyList(), message.getRepeatedFixed64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFixed64(); + assertEquals(emptyList(), builder.getRepeatedFixed64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List()); + + message = builder.build(); + builder.addAllRepeatedFloat(singletonList(1F)); + assertEquals(emptyList(), message.getRepeatedFloatList()); + assertEquals(singletonList(1F), builder.getRepeatedFloatList()); + assertEquals(emptyList(), message.getRepeatedFloatList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFloat(); + assertEquals(emptyList(), builder.getRepeatedFloatList()); + assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList()); + + message = builder.build(); + builder.addAllRepeatedForeignEnum( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR)); + assertEquals(emptyList(), message.getRepeatedForeignEnumList()); + assertEquals( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), + builder.getRepeatedForeignEnumList()); + assertEquals(emptyList(), message.getRepeatedForeignEnumList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedForeignEnum(); + assertEquals(emptyList(), builder.getRepeatedForeignEnumList()); + assertEquals( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), + messageAfterBuild.getRepeatedForeignEnumList()); + + message = builder.build(); + builder.addAllRepeatedForeignMessage(singletonList(foreignMessage)); + assertEquals(emptyList(), message.getRepeatedForeignMessageList()); + assertEquals( + singletonList(foreignMessage), builder.getRepeatedForeignMessageList()); + assertEquals(emptyList(), message.getRepeatedForeignMessageList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedForeignMessage(); + assertEquals(emptyList(), builder.getRepeatedForeignMessageList()); + assertEquals( + singletonList(foreignMessage), + messageAfterBuild.getRepeatedForeignMessageList()); + + message = builder.build(); + builder.addAllRepeatedGroup( + singletonList(RepeatedGroup.getDefaultInstance())); + assertEquals(emptyList(), message.getRepeatedGroupList()); + assertEquals( + singletonList(RepeatedGroup.getDefaultInstance()), + builder.getRepeatedGroupList()); + assertEquals(emptyList(), message.getRepeatedGroupList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedGroup(); + assertEquals(emptyList(), builder.getRepeatedGroupList()); + assertEquals( + singletonList(RepeatedGroup.getDefaultInstance()), + messageAfterBuild.getRepeatedGroupList()); + + message = builder.build(); + builder.addAllRepeatedInt32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedInt32List()); + assertEquals(singletonList(1), builder.getRepeatedInt32List()); + assertEquals(emptyList(), message.getRepeatedInt32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedInt32(); + assertEquals(emptyList(), builder.getRepeatedInt32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List()); + + message = builder.build(); + builder.addAllRepeatedInt64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedInt64List()); + assertEquals(singletonList(1L), builder.getRepeatedInt64List()); + assertEquals(emptyList(), message.getRepeatedInt64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedInt64(); + assertEquals(emptyList(), builder.getRepeatedInt64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List()); + + message = builder.build(); + builder.addAllRepeatedLazyMessage(singletonList(nestedMessage)); + assertEquals(emptyList(), message.getRepeatedLazyMessageList()); + assertEquals( + singletonList(nestedMessage), builder.getRepeatedLazyMessageList()); + assertEquals(emptyList(), message.getRepeatedLazyMessageList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedLazyMessage(); + assertEquals(emptyList(), builder.getRepeatedLazyMessageList()); + assertEquals( + singletonList(nestedMessage), + messageAfterBuild.getRepeatedLazyMessageList()); + + message = builder.build(); + builder.addAllRepeatedSfixed32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedSfixed32List()); + assertEquals(singletonList(1), builder.getRepeatedSfixed32List()); + assertEquals(emptyList(), message.getRepeatedSfixed32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSfixed32(); + assertEquals(emptyList(), builder.getRepeatedSfixed32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List()); + + message = builder.build(); + builder.addAllRepeatedSfixed64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedSfixed64List()); + assertEquals(singletonList(1L), builder.getRepeatedSfixed64List()); + assertEquals(emptyList(), message.getRepeatedSfixed64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSfixed64(); + assertEquals(emptyList(), builder.getRepeatedSfixed64List()); + assertEquals( + singletonList(1L), messageAfterBuild.getRepeatedSfixed64List()); + + message = builder.build(); + builder.addAllRepeatedSint32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedSint32List()); + assertEquals(singletonList(1), builder.getRepeatedSint32List()); + assertEquals(emptyList(), message.getRepeatedSint32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSint32(); + assertEquals(emptyList(), builder.getRepeatedSint32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List()); + + message = builder.build(); + builder.addAllRepeatedSint64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedSint64List()); + assertEquals(singletonList(1L), builder.getRepeatedSint64List()); + assertEquals(emptyList(), message.getRepeatedSint64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSint64(); + assertEquals(emptyList(), builder.getRepeatedSint64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List()); + + message = builder.build(); + builder.addAllRepeatedString(singletonList("hi")); + assertEquals(emptyList(), message.getRepeatedStringList()); + assertEquals(singletonList("hi"), builder.getRepeatedStringList()); + assertEquals(emptyList(), message.getRepeatedStringList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedString(); + assertEquals(emptyList(), builder.getRepeatedStringList()); + assertEquals( + singletonList("hi"), messageAfterBuild.getRepeatedStringList()); + + message = builder.build(); + builder.addAllRepeatedStringPiece(singletonList("hi")); + assertEquals(emptyList(), message.getRepeatedStringPieceList()); + assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList()); + assertEquals(emptyList(), message.getRepeatedStringPieceList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedStringPiece(); + assertEquals(emptyList(), builder.getRepeatedStringPieceList()); + assertEquals( + singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList()); + + message = builder.build(); + builder.addAllRepeatedUint32(singletonList(1)); + assertEquals(emptyList(), message.getRepeatedUint32List()); + assertEquals(singletonList(1), builder.getRepeatedUint32List()); + assertEquals(emptyList(), message.getRepeatedUint32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedUint32(); + assertEquals(emptyList(), builder.getRepeatedUint32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List()); + + message = builder.build(); + builder.addAllRepeatedUint64(singletonList(1L)); + assertEquals(emptyList(), message.getRepeatedUint64List()); + assertEquals(singletonList(1L), builder.getRepeatedUint64List()); + assertEquals(emptyList(), message.getRepeatedUint64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedUint64(); + assertEquals(emptyList(), builder.getRepeatedUint64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List()); + + message = builder.build(); + builder.addRepeatedBool(true); + assertEquals(emptyList(), message.getRepeatedBoolList()); + assertEquals(singletonList(true), builder.getRepeatedBoolList()); + assertEquals(emptyList(), message.getRepeatedBoolList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedBool(); + assertEquals(emptyList(), builder.getRepeatedBoolList()); + assertEquals(singletonList(true), messageAfterBuild.getRepeatedBoolList()); + + message = builder.build(); + builder.addRepeatedBytes(ByteString.copyFromUtf8("hi")); + assertEquals(emptyList(), message.getRepeatedBytesList()); + assertEquals( + singletonList(ByteString.copyFromUtf8("hi")), + builder.getRepeatedBytesList()); + assertEquals(emptyList(), message.getRepeatedBytesList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedBytes(); + assertEquals(emptyList(), builder.getRepeatedBytesList()); + assertEquals( + singletonList(ByteString.copyFromUtf8("hi")), + messageAfterBuild.getRepeatedBytesList()); + + message = builder.build(); + builder.addRepeatedCord("hi"); + assertEquals(emptyList(), message.getRepeatedCordList()); + assertEquals(singletonList("hi"), builder.getRepeatedCordList()); + assertEquals(emptyList(), message.getRepeatedCordList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedCord(); + assertEquals(emptyList(), builder.getRepeatedCordList()); + assertEquals(singletonList("hi"), messageAfterBuild.getRepeatedCordList()); + + message = builder.build(); + builder.addRepeatedDouble(1D); + assertEquals(emptyList(), message.getRepeatedDoubleList()); + assertEquals(singletonList(1D), builder.getRepeatedDoubleList()); + assertEquals(emptyList(), message.getRepeatedDoubleList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedDouble(); + assertEquals(emptyList(), builder.getRepeatedDoubleList()); + assertEquals(singletonList(1D), messageAfterBuild.getRepeatedDoubleList()); + + message = builder.build(); + builder.addRepeatedFixed32(1); + assertEquals(emptyList(), message.getRepeatedFixed32List()); + assertEquals(singletonList(1), builder.getRepeatedFixed32List()); + assertEquals(emptyList(), message.getRepeatedFixed32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFixed32(); + assertEquals(emptyList(), builder.getRepeatedFixed32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedFixed32List()); + + message = builder.build(); + builder.addRepeatedFixed64(1L); + assertEquals(emptyList(), message.getRepeatedFixed64List()); + assertEquals(singletonList(1L), builder.getRepeatedFixed64List()); + assertEquals(emptyList(), message.getRepeatedFixed64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFixed64(); + assertEquals(emptyList(), builder.getRepeatedFixed64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedFixed64List()); + + message = builder.build(); + builder.addRepeatedFloat(1F); + assertEquals(emptyList(), message.getRepeatedFloatList()); + assertEquals(singletonList(1F), builder.getRepeatedFloatList()); + assertEquals(emptyList(), message.getRepeatedFloatList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedFloat(); + assertEquals(emptyList(), builder.getRepeatedFloatList()); + assertEquals(singletonList(1F), messageAfterBuild.getRepeatedFloatList()); + + message = builder.build(); + builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); + assertEquals(emptyList(), message.getRepeatedForeignEnumList()); + assertEquals( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), + builder.getRepeatedForeignEnumList()); + assertEquals(emptyList(), message.getRepeatedForeignEnumList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedForeignEnum(); + assertEquals(emptyList(), builder.getRepeatedForeignEnumList()); + assertEquals( + singletonList(ForeignEnumLite.FOREIGN_LITE_BAR), + messageAfterBuild.getRepeatedForeignEnumList()); + + message = builder.build(); + builder.addRepeatedForeignMessage(foreignMessage); + assertEquals(emptyList(), message.getRepeatedForeignMessageList()); + assertEquals( + singletonList(foreignMessage), builder.getRepeatedForeignMessageList()); + assertEquals(emptyList(), message.getRepeatedForeignMessageList()); + messageAfterBuild = builder.build(); + builder.removeRepeatedForeignMessage(0); + assertEquals(emptyList(), builder.getRepeatedForeignMessageList()); + assertEquals( + singletonList(foreignMessage), + messageAfterBuild.getRepeatedForeignMessageList()); + + message = builder.build(); + builder.addRepeatedGroup(RepeatedGroup.getDefaultInstance()); + assertEquals(emptyList(), message.getRepeatedGroupList()); + assertEquals( + singletonList(RepeatedGroup.getDefaultInstance()), + builder.getRepeatedGroupList()); + assertEquals(emptyList(), message.getRepeatedGroupList()); + messageAfterBuild = builder.build(); + builder.removeRepeatedGroup(0); + assertEquals(emptyList(), builder.getRepeatedGroupList()); + assertEquals( + singletonList(RepeatedGroup.getDefaultInstance()), + messageAfterBuild.getRepeatedGroupList()); + + message = builder.build(); + builder.addRepeatedInt32(1); + assertEquals(emptyList(), message.getRepeatedInt32List()); + assertEquals(singletonList(1), builder.getRepeatedInt32List()); + assertEquals(emptyList(), message.getRepeatedInt32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedInt32(); + assertEquals(emptyList(), builder.getRepeatedInt32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedInt32List()); + + message = builder.build(); + builder.addRepeatedInt64(1L); + assertEquals(emptyList(), message.getRepeatedInt64List()); + assertEquals(singletonList(1L), builder.getRepeatedInt64List()); + assertEquals(emptyList(), message.getRepeatedInt64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedInt64(); + assertEquals(emptyList(), builder.getRepeatedInt64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedInt64List()); + + message = builder.build(); + builder.addRepeatedLazyMessage(nestedMessage); + assertEquals(emptyList(), message.getRepeatedLazyMessageList()); + assertEquals( + singletonList(nestedMessage), builder.getRepeatedLazyMessageList()); + assertEquals(emptyList(), message.getRepeatedLazyMessageList()); + messageAfterBuild = builder.build(); + builder.removeRepeatedLazyMessage(0); + assertEquals(emptyList(), builder.getRepeatedLazyMessageList()); + assertEquals( + singletonList(nestedMessage), + messageAfterBuild.getRepeatedLazyMessageList()); + + message = builder.build(); + builder.addRepeatedSfixed32(1); + assertEquals(emptyList(), message.getRepeatedSfixed32List()); + assertEquals(singletonList(1), builder.getRepeatedSfixed32List()); + assertEquals(emptyList(), message.getRepeatedSfixed32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSfixed32(); + assertEquals(emptyList(), builder.getRepeatedSfixed32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedSfixed32List()); + + message = builder.build(); + builder.addRepeatedSfixed64(1L); + assertEquals(emptyList(), message.getRepeatedSfixed64List()); + assertEquals(singletonList(1L), builder.getRepeatedSfixed64List()); + assertEquals(emptyList(), message.getRepeatedSfixed64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSfixed64(); + assertEquals(emptyList(), builder.getRepeatedSfixed64List()); + assertEquals( + singletonList(1L), messageAfterBuild.getRepeatedSfixed64List()); + + message = builder.build(); + builder.addRepeatedSint32(1); + assertEquals(emptyList(), message.getRepeatedSint32List()); + assertEquals(singletonList(1), builder.getRepeatedSint32List()); + assertEquals(emptyList(), message.getRepeatedSint32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSint32(); + assertEquals(emptyList(), builder.getRepeatedSint32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedSint32List()); + + message = builder.build(); + builder.addRepeatedSint64(1L); + assertEquals(emptyList(), message.getRepeatedSint64List()); + assertEquals(singletonList(1L), builder.getRepeatedSint64List()); + assertEquals(emptyList(), message.getRepeatedSint64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedSint64(); + assertEquals(emptyList(), builder.getRepeatedSint64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedSint64List()); + + message = builder.build(); + builder.addRepeatedString("hi"); + assertEquals(emptyList(), message.getRepeatedStringList()); + assertEquals(singletonList("hi"), builder.getRepeatedStringList()); + assertEquals(emptyList(), message.getRepeatedStringList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedString(); + assertEquals(emptyList(), builder.getRepeatedStringList()); + assertEquals( + singletonList("hi"), messageAfterBuild.getRepeatedStringList()); + + message = builder.build(); + builder.addRepeatedStringPiece("hi"); + assertEquals(emptyList(), message.getRepeatedStringPieceList()); + assertEquals(singletonList("hi"), builder.getRepeatedStringPieceList()); + assertEquals(emptyList(), message.getRepeatedStringPieceList()); + messageAfterBuild = builder.build(); + builder.clearRepeatedStringPiece(); + assertEquals(emptyList(), builder.getRepeatedStringPieceList()); + assertEquals( + singletonList("hi"), messageAfterBuild.getRepeatedStringPieceList()); + + message = builder.build(); + builder.addRepeatedUint32(1); + assertEquals(emptyList(), message.getRepeatedUint32List()); + assertEquals(singletonList(1), builder.getRepeatedUint32List()); + assertEquals(emptyList(), message.getRepeatedUint32List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedUint32(); + assertEquals(emptyList(), builder.getRepeatedUint32List()); + assertEquals(singletonList(1), messageAfterBuild.getRepeatedUint32List()); + + message = builder.build(); + builder.addRepeatedUint64(1L); + assertEquals(emptyList(), message.getRepeatedUint64List()); + assertEquals(singletonList(1L), builder.getRepeatedUint64List()); + assertEquals(emptyList(), message.getRepeatedUint64List()); + messageAfterBuild = builder.build(); + builder.clearRepeatedUint64(); + assertEquals(emptyList(), builder.getRepeatedUint64List()); + assertEquals(singletonList(1L), messageAfterBuild.getRepeatedUint64List()); + + message = builder.build(); + builder.addRepeatedBool(true); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedBoolCount()); + builder.setRepeatedBool(0, false); + assertEquals(true, messageAfterBuild.getRepeatedBool(0)); + assertEquals(false, builder.getRepeatedBool(0)); + builder.clearRepeatedBool(); + + message = builder.build(); + builder.addRepeatedBytes(ByteString.copyFromUtf8("hi")); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedBytesCount()); + builder.setRepeatedBytes(0, ByteString.EMPTY); + assertEquals( + ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedBytes(0)); + assertEquals(ByteString.EMPTY, builder.getRepeatedBytes(0)); + builder.clearRepeatedBytes(); + + message = builder.build(); + builder.addRepeatedCord("hi"); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedCordCount()); + builder.setRepeatedCord(0, ""); + assertEquals("hi", messageAfterBuild.getRepeatedCord(0)); + assertEquals("", builder.getRepeatedCord(0)); + builder.clearRepeatedCord(); + message = builder.build(); + + builder.addRepeatedCordBytes(ByteString.copyFromUtf8("hi")); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedCordCount()); + builder.setRepeatedCord(0, ""); + assertEquals( + ByteString.copyFromUtf8("hi"), messageAfterBuild.getRepeatedCordBytes(0)); + assertEquals(ByteString.EMPTY, builder.getRepeatedCordBytes(0)); + builder.clearRepeatedCord(); + + message = builder.build(); + builder.addRepeatedDouble(1D); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedDoubleCount()); + builder.setRepeatedDouble(0, 0D); + assertEquals(1D, messageAfterBuild.getRepeatedDouble(0)); + assertEquals(0D, builder.getRepeatedDouble(0)); + builder.clearRepeatedDouble(); + + message = builder.build(); + builder.addRepeatedFixed32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedFixed32Count()); + builder.setRepeatedFixed32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedFixed32(0)); + assertEquals(0, builder.getRepeatedFixed32(0)); + builder.clearRepeatedFixed32(); + + message = builder.build(); + builder.addRepeatedFixed64(1L); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedFixed64Count()); + builder.setRepeatedFixed64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedFixed64(0)); + assertEquals(0L, builder.getRepeatedFixed64(0)); + builder.clearRepeatedFixed64(); + + message = builder.build(); + builder.addRepeatedFloat(1F); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedFloatCount()); + builder.setRepeatedFloat(0, 0F); + assertEquals(1F, messageAfterBuild.getRepeatedFloat(0)); + assertEquals(0F, builder.getRepeatedFloat(0)); + builder.clearRepeatedFloat(); + + message = builder.build(); + builder.addRepeatedForeignEnum(ForeignEnumLite.FOREIGN_LITE_BAR); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedForeignEnumCount()); + builder.setRepeatedForeignEnum(0, ForeignEnumLite.FOREIGN_LITE_FOO); + assertEquals( + ForeignEnumLite.FOREIGN_LITE_BAR, + messageAfterBuild.getRepeatedForeignEnum(0)); + assertEquals( + ForeignEnumLite.FOREIGN_LITE_FOO, builder.getRepeatedForeignEnum(0)); + builder.clearRepeatedForeignEnum(); + + message = builder.build(); + builder.addRepeatedForeignMessage(foreignMessage); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedForeignMessageCount()); + builder.setRepeatedForeignMessage( + 0, ForeignMessageLite.getDefaultInstance()); + assertEquals( + foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0)); + assertEquals( + ForeignMessageLite.getDefaultInstance(), + builder.getRepeatedForeignMessage(0)); + builder.clearRepeatedForeignMessage(); + + message = builder.build(); + builder.addRepeatedForeignMessage(foreignMessageBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedForeignMessageCount()); + builder.setRepeatedForeignMessage( + 0, ForeignMessageLite.getDefaultInstance()); + // LITE_RUNTIME doesn't implement equals so we compare on a property. + assertEquals(3, messageAfterBuild.getRepeatedForeignMessage(0).getC()); + assertEquals( + ForeignMessageLite.getDefaultInstance(), + builder.getRepeatedForeignMessage(0)); + builder.clearRepeatedForeignMessage(); + + message = builder.build(); + builder.addRepeatedForeignMessage(0, foreignMessage); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedForeignMessageCount()); + builder.setRepeatedForeignMessage(0, foreignMessageBuilder); + assertEquals( + foreignMessage, messageAfterBuild.getRepeatedForeignMessage(0)); + // LITE_RUNTIME doesn't implement equals so we compare on a property. + assertEquals(3, builder.getRepeatedForeignMessage(0).getC()); + builder.clearRepeatedForeignMessage(); + + message = builder.build(); + RepeatedGroup repeatedGroup = RepeatedGroup.newBuilder() + .setA(1) + .build(); + builder.addRepeatedGroup(repeatedGroup); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedGroupCount()); + builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); + assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0)); + assertEquals( + RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); + builder.clearRepeatedGroup(); + + message = builder.build(); + builder.addRepeatedGroup(0, repeatedGroup); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedGroupCount()); + builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); + assertEquals(repeatedGroup, messageAfterBuild.getRepeatedGroup(0)); + assertEquals( + RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); + builder.clearRepeatedGroup(); + + message = builder.build(); + RepeatedGroup.Builder repeatedGroupBuilder = RepeatedGroup.newBuilder() + .setA(3); + builder.addRepeatedGroup(repeatedGroupBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedGroupCount()); + builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); + // LITE_RUNTIME doesn't implement equals so we compare on a property and + // ensure the property isn't set on repeatedGroup. + assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA()); + assertEquals( + RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); + builder.clearRepeatedGroup(); + + message = builder.build(); + builder.addRepeatedGroup(0, repeatedGroupBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedGroupCount()); + builder.setRepeatedGroup(0, RepeatedGroup.getDefaultInstance()); + // LITE_RUNTIME doesn't implement equals so we compare on a property and + // ensure the property isn't set on repeatedGroup. + assertEquals(3, messageAfterBuild.getRepeatedGroup(0).getA()); + assertEquals( + RepeatedGroup.getDefaultInstance(), builder.getRepeatedGroup(0)); + builder.clearRepeatedGroup(); + + message = builder.build(); + builder.addRepeatedInt32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedInt32Count()); + builder.setRepeatedInt32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedInt32(0)); + assertEquals(0, builder.getRepeatedInt32(0)); + builder.clearRepeatedInt32(); + + message = builder.build(); + builder.addRepeatedInt64(1L); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedInt64Count()); + builder.setRepeatedInt64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedInt64(0)); + assertEquals(0L, builder.getRepeatedInt64(0)); + builder.clearRepeatedInt64(); + + message = builder.build(); + builder.addRepeatedLazyMessage(nestedMessage); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedLazyMessageCount()); + builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); + assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0)); + assertEquals( + NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); + builder.clearRepeatedLazyMessage(); + + message = builder.build(); + builder.addRepeatedLazyMessage(0, nestedMessage); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedLazyMessageCount()); + builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); + assertEquals(nestedMessage, messageAfterBuild.getRepeatedLazyMessage(0)); + assertEquals( + NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); + builder.clearRepeatedLazyMessage(); + + message = builder.build(); + builder.addRepeatedLazyMessage(nestedMessageBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedLazyMessageCount()); + builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); + // LITE_RUNTIME doesn't implement equals so we compare on a property and + // ensure the property isn't set on repeatedGroup. + assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb()); + assertEquals( + NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); + builder.clearRepeatedLazyMessage(); + + message = builder.build(); + builder.addRepeatedLazyMessage(0, nestedMessageBuilder); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedLazyMessageCount()); + builder.setRepeatedLazyMessage(0, NestedMessage.getDefaultInstance()); + // LITE_RUNTIME doesn't implement equals so we compare on a property and + // ensure the property isn't set on repeatedGroup. + assertEquals(3, messageAfterBuild.getRepeatedLazyMessage(0).getBb()); + assertEquals( + NestedMessage.getDefaultInstance(), builder.getRepeatedLazyMessage(0)); + builder.clearRepeatedLazyMessage(); + + message = builder.build(); + builder.addRepeatedSfixed32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedSfixed32Count()); + builder.setRepeatedSfixed32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedSfixed32(0)); + assertEquals(0, builder.getRepeatedSfixed32(0)); + builder.clearRepeatedSfixed32(); + + message = builder.build(); + builder.addRepeatedSfixed64(1L); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedSfixed64Count()); + builder.setRepeatedSfixed64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedSfixed64(0)); + assertEquals(0L, builder.getRepeatedSfixed64(0)); + builder.clearRepeatedSfixed64(); + + message = builder.build(); + builder.addRepeatedSint32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedSint32Count()); + builder.setRepeatedSint32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedSint32(0)); + assertEquals(0, builder.getRepeatedSint32(0)); + builder.clearRepeatedSint32(); + + message = builder.build(); + builder.addRepeatedSint64(1L); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedSint64Count()); + builder.setRepeatedSint64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedSint64(0)); + assertEquals(0L, builder.getRepeatedSint64(0)); + builder.clearRepeatedSint64(); + + message = builder.build(); + builder.addRepeatedString("hi"); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedStringCount()); + builder.setRepeatedString(0, ""); + assertEquals("hi", messageAfterBuild.getRepeatedString(0)); + assertEquals("", builder.getRepeatedString(0)); + builder.clearRepeatedString(); + + message = builder.build(); + builder.addRepeatedStringBytes(ByteString.copyFromUtf8("hi")); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedStringCount()); + builder.setRepeatedString(0, ""); + assertEquals( + ByteString.copyFromUtf8("hi"), + messageAfterBuild.getRepeatedStringBytes(0)); + assertEquals(ByteString.EMPTY, builder.getRepeatedStringBytes(0)); + builder.clearRepeatedString(); + + message = builder.build(); + builder.addRepeatedStringPiece("hi"); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedStringPieceCount()); + builder.setRepeatedStringPiece(0, ""); + assertEquals("hi", messageAfterBuild.getRepeatedStringPiece(0)); + assertEquals("", builder.getRepeatedStringPiece(0)); + builder.clearRepeatedStringPiece(); + + message = builder.build(); + builder.addRepeatedStringPieceBytes(ByteString.copyFromUtf8("hi")); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedStringPieceCount()); + builder.setRepeatedStringPiece(0, ""); + assertEquals( + ByteString.copyFromUtf8("hi"), + messageAfterBuild.getRepeatedStringPieceBytes(0)); + assertEquals(ByteString.EMPTY, builder.getRepeatedStringPieceBytes(0)); + builder.clearRepeatedStringPiece(); + + message = builder.build(); + builder.addRepeatedUint32(1); + messageAfterBuild = builder.build(); + assertEquals(0, message.getRepeatedUint32Count()); + builder.setRepeatedUint32(0, 0); + assertEquals(1, messageAfterBuild.getRepeatedUint32(0)); + assertEquals(0, builder.getRepeatedUint32(0)); + builder.clearRepeatedUint32(); + + message = builder.build(); + builder.addRepeatedUint64(1L); + messageAfterBuild = builder.build(); + assertEquals(0L, message.getRepeatedUint64Count()); + builder.setRepeatedUint64(0, 0L); + assertEquals(1L, messageAfterBuild.getRepeatedUint64(0)); + assertEquals(0L, builder.getRepeatedUint64(0)); + builder.clearRepeatedUint64(); + + message = builder.build(); + assertEquals(0, message.getSerializedSize()); + builder.mergeFrom(TestAllTypesLite.newBuilder() + .setOptionalBool(true) + .build()); + assertEquals(0, message.getSerializedSize()); + assertEquals(true, builder.build().getOptionalBool()); + builder.clearOptionalBool(); + + message = builder.build(); + assertEquals(0, message.getSerializedSize()); + builder.mergeFrom(TestAllTypesLite.newBuilder() + .setOptionalBool(true) + .build()); + assertEquals(0, message.getSerializedSize()); + assertEquals(true, builder.build().getOptionalBool()); + builder.clear(); + assertEquals(0, builder.build().getSerializedSize()); + + message = builder.build(); + assertEquals(0, message.getSerializedSize()); + builder.mergeOptionalForeignMessage(foreignMessage); + assertEquals(0, message.getSerializedSize()); + assertEquals( + foreignMessage.getC(), + builder.build().getOptionalForeignMessage().getC()); + builder.clearOptionalForeignMessage(); + + message = builder.build(); + assertEquals(0, message.getSerializedSize()); + builder.mergeOptionalLazyMessage(nestedMessage); + assertEquals(0, message.getSerializedSize()); + assertEquals( + nestedMessage.getBb(), + builder.build().getOptionalLazyMessage().getBb()); + builder.clearOptionalLazyMessage(); + + message = builder.build(); + builder.setOneofString("hi"); + assertEquals( + OneofFieldCase.ONEOFFIELD_NOT_SET, message.getOneofFieldCase()); + assertEquals(OneofFieldCase.ONEOF_STRING, builder.getOneofFieldCase()); + assertEquals("hi", builder.getOneofString()); + messageAfterBuild = builder.build(); + assertEquals( + OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase()); + assertEquals("hi", messageAfterBuild.getOneofString()); + builder.setOneofUint32(1); + assertEquals( + OneofFieldCase.ONEOF_STRING, messageAfterBuild.getOneofFieldCase()); + assertEquals("hi", messageAfterBuild.getOneofString()); + assertEquals(OneofFieldCase.ONEOF_UINT32, builder.getOneofFieldCase()); + assertEquals(1, builder.getOneofUint32()); + + TestAllExtensionsLite.Builder extendableMessageBuilder = + TestAllExtensionsLite.newBuilder(); + TestAllExtensionsLite extendableMessage = extendableMessageBuilder.build(); + extendableMessageBuilder.setExtension( + UnittestLite.optionalInt32ExtensionLite, 1); + assertFalse(extendableMessage.hasExtension( + UnittestLite.optionalInt32ExtensionLite)); + extendableMessage = extendableMessageBuilder.build(); + assertEquals( + 1, (int) extendableMessageBuilder.getExtension( + UnittestLite.optionalInt32ExtensionLite)); + assertEquals( + 1, (int) extendableMessage.getExtension( + UnittestLite.optionalInt32ExtensionLite)); + extendableMessageBuilder.setExtension( + UnittestLite.optionalInt32ExtensionLite, 3); + assertEquals( + 3, (int) extendableMessageBuilder.getExtension( + UnittestLite.optionalInt32ExtensionLite)); + assertEquals( + 1, (int) extendableMessage.getExtension( + UnittestLite.optionalInt32ExtensionLite)); + extendableMessage = extendableMessageBuilder.build(); + assertEquals( + 3, (int) extendableMessageBuilder.getExtension( + UnittestLite.optionalInt32ExtensionLite)); + assertEquals( + 3, (int) extendableMessage.getExtension( + UnittestLite.optionalInt32ExtensionLite)); + + // No extension registry, so it should be in unknown fields. + extendableMessage = + TestAllExtensionsLite.parseFrom(extendableMessage.toByteArray()); + assertFalse(extendableMessage.hasExtension( + UnittestLite.optionalInt32ExtensionLite)); + + extendableMessageBuilder = extendableMessage.toBuilder(); + extendableMessageBuilder.mergeFrom(TestAllExtensionsLite.newBuilder() + .setExtension(UnittestLite.optionalFixed32ExtensionLite, 11) + .build()); + + extendableMessage = extendableMessageBuilder.build(); + ExtensionRegistryLite registry = ExtensionRegistryLite.newInstance(); + UnittestLite.registerAllExtensions(registry); + extendableMessage = TestAllExtensionsLite.parseFrom( + extendableMessage.toByteArray(), registry); + + // The unknown field was preserved. + assertEquals( + 3, (int) extendableMessage.getExtension( + UnittestLite.optionalInt32ExtensionLite)); + assertEquals( + 11, (int) extendableMessage.getExtension( + UnittestLite.optionalFixed32ExtensionLite)); } } diff --git a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java index 7b201a9d..958b6a7e 100644 --- a/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java +++ b/java/src/test/java/com/google/protobuf/LiteralByteStringTest.java @@ -307,7 +307,8 @@ public class LiteralByteStringTest extends TestCase { public void testToString_returnsCanonicalEmptyString() throws UnsupportedEncodingException{ assertSame(classUnderTest + " must be the same string references", - ByteString.EMPTY.toString(Internal.UTF_8), new LiteralByteString(new byte[]{}).toString(Internal.UTF_8)); + ByteString.EMPTY.toString(Internal.UTF_8), + new LiteralByteString(new byte[]{}).toString(Internal.UTF_8)); } public void testToString_raisesException() throws UnsupportedEncodingException{ diff --git a/java/src/test/java/com/google/protobuf/LongArrayListTest.java b/java/src/test/java/com/google/protobuf/LongArrayListTest.java new file mode 100644 index 00000000..3a52ec7f --- /dev/null +++ b/java/src/test/java/com/google/protobuf/LongArrayListTest.java @@ -0,0 +1,473 @@ +// 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. + +package com.google.protobuf; + +import static java.util.Arrays.asList; + +import junit.framework.TestCase; + +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.Iterator; + +/** + * Tests for {@link LongArrayList}. + * + * @author dweis@google.com (Daniel Weis) + */ +public class LongArrayListTest extends TestCase { + + private static final LongArrayList UNARY_LIST = newImmutableLongArrayList(1); + private static final LongArrayList TERTIARY_LIST = + newImmutableLongArrayList(1, 2, 3); + + private LongArrayList list; + + @Override + protected void setUp() throws Exception { + list = new LongArrayList(); + } + + public void testEmptyListReturnsSameInstance() { + assertSame(LongArrayList.emptyList(), LongArrayList.emptyList()); + } + + public void testEmptyListIsImmutable() { + assertImmutable(LongArrayList.emptyList()); + } + + public void testMakeImmutable() { + list.addLong(2); + list.addLong(4); + list.addLong(6); + list.addLong(8); + list.makeImmutable(); + assertImmutable(list); + } + + public void testCopyConstructor() { + LongArrayList copy = new LongArrayList(TERTIARY_LIST); + assertEquals(TERTIARY_LIST, copy); + + copy = new LongArrayList(LongArrayList.emptyList()); + assertEquals(LongArrayList.emptyList(), copy); + + copy = new LongArrayList(asList(1L, 2L, 3L)); + assertEquals(asList(1L, 2L, 3L), copy); + + copy = new LongArrayList(Collections.emptyList()); + assertEquals(LongArrayList.emptyList(), copy); + } + + public void testModificationWithIteration() { + list.addAll(asList(1L, 2L, 3L, 4L)); + Iterator iterator = list.iterator(); + assertEquals(4, list.size()); + assertEquals(1, (long) list.get(0)); + assertEquals(1, (long) iterator.next()); + list.set(0, 1L); + assertEquals(2, (long) iterator.next()); + + list.remove(0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + + iterator = list.iterator(); + list.add(0, 0L); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + } + + public void testGet() { + assertEquals(1, (long) TERTIARY_LIST.get(0)); + assertEquals(2, (long) TERTIARY_LIST.get(1)); + assertEquals(3, (long) TERTIARY_LIST.get(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testGetLong() { + assertEquals(1, TERTIARY_LIST.getLong(0)); + assertEquals(2, TERTIARY_LIST.getLong(1)); + assertEquals(3, TERTIARY_LIST.getLong(2)); + + try { + TERTIARY_LIST.get(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + TERTIARY_LIST.get(3); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSize() { + assertEquals(0, LongArrayList.emptyList().size()); + assertEquals(1, UNARY_LIST.size()); + assertEquals(3, TERTIARY_LIST.size()); + + list.addLong(2); + list.addLong(4); + list.addLong(6); + list.addLong(8); + assertEquals(4, list.size()); + + list.remove(0); + assertEquals(3, list.size()); + + list.add(16L); + assertEquals(4, list.size()); + } + + public void testSet() { + list.addLong(2); + list.addLong(4); + + assertEquals(2, (long) list.set(0, 0L)); + assertEquals(0, list.getLong(0)); + + assertEquals(4, (long) list.set(1, 0L)); + assertEquals(0, list.getLong(1)); + + try { + list.set(-1, 0L); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.set(2, 0L); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testSetLong() { + list.addLong(2); + list.addLong(4); + + assertEquals(2, list.setLong(0, 0)); + assertEquals(0, list.getLong(0)); + + assertEquals(4, list.setLong(1, 0)); + assertEquals(0, list.getLong(1)); + + try { + list.setLong(-1, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.setLong(2, 0); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAdd() { + assertEquals(0, list.size()); + + assertTrue(list.add(2L)); + assertEquals(asList(2L), list); + + assertTrue(list.add(3L)); + list.add(0, 4L); + assertEquals(asList(4L, 2L, 3L), list); + + list.add(0, 1L); + list.add(0, 0L); + // Force a resize by getting up to 11 elements. + for (int i = 0; i < 6; i++) { + list.add(Long.valueOf(5 + i)); + } + assertEquals(asList(0L, 1L, 4L, 2L, 3L, 5L, 6L, 7L, 8L, 9L, 10L), list); + + try { + list.add(-1, 5L); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.add(4, 5L); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + public void testAddLong() { + assertEquals(0, list.size()); + + list.addLong(2); + assertEquals(asList(2L), list); + + list.addLong(3); + assertEquals(asList(2L, 3L), list); + } + + public void testAddAll() { + assertEquals(0, list.size()); + + assertTrue(list.addAll(Collections.singleton(1L))); + assertEquals(1, list.size()); + assertEquals(1, (long) list.get(0)); + assertEquals(1, list.getLong(0)); + + assertTrue(list.addAll(asList(2L, 3L, 4L, 5L, 6L))); + assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L), list); + + assertTrue(list.addAll(TERTIARY_LIST)); + assertEquals(asList(1L, 2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L), list); + + assertFalse(list.addAll(Collections.emptyList())); + assertFalse(list.addAll(LongArrayList.emptyList())); + } + + public void testRemove() { + list.addAll(TERTIARY_LIST); + assertEquals(1, (long) list.remove(0)); + assertEquals(asList(2L, 3L), list); + + assertTrue(list.remove(3L)); + assertEquals(asList(2L), list); + + assertFalse(list.remove(3L)); + assertEquals(asList(2L), list); + + assertEquals(2, (long) list.remove(0)); + assertEquals(asList(), list); + + try { + list.remove(-1); + fail(); + } catch (IndexOutOfBoundsException e) { + // expected + } + + try { + list.remove(0); + } catch (IndexOutOfBoundsException e) { + // expected + } + } + + private void assertImmutable(LongArrayList list) { + if (list.contains(1)) { + throw new RuntimeException("Cannot test the immutability of lists that contain 1."); + } + + try { + list.add(1L); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.add(0, 1L); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.singletonList(1L)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(new LongArrayList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.singleton(1L)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addLong(0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.clear(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, 0L); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.setLong(0, 0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + + private static LongArrayList newImmutableLongArrayList(long... elements) { + LongArrayList list = new LongArrayList(); + for (long element : elements) { + list.addLong(element); + } + list.makeImmutable(); + return list; + } +} diff --git a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java index 22dbeb76..6cff689f 100644 --- a/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java +++ b/java/src/test/java/com/google/protobuf/MapForProto2LiteTest.java @@ -36,6 +36,11 @@ import map_lite_test.MapForProto2TestProto.TestUnknownEnumValue; import junit.framework.TestCase; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + /** * Unit tests for map fields. */ @@ -170,6 +175,140 @@ public class MapForProto2LiteTest extends TestCase { assertEquals(0, message.getStringToInt32Field().size()); } + public void testSanityCopyOnWrite() throws InvalidProtocolBufferException { + // Since builders are implemented as a thin wrapper around a message + // instance, we attempt to verify that we can't cause the builder to modify + // a produced message. + + TestMap.Builder builder = TestMap.newBuilder(); + TestMap message = builder.build(); + Map intMap = builder.getMutableInt32ToInt32Field(); + intMap.put(1, 2); + assertTrue(message.getInt32ToInt32Field().isEmpty()); + message = builder.build(); + try { + intMap.put(2, 3); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + builder.getMutableInt32ToInt32Field().put(2, 3); + assertEquals(newMap(1, 2), message.getInt32ToInt32Field()); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + } + + public void testMutableMapLifecycle() { + TestMap.Builder builder = TestMap.newBuilder(); + Map intMap = builder.getMutableInt32ToInt32Field(); + intMap.put(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + try { + intMap.put(2, 3); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + builder.getMutableInt32ToInt32Field().put(2, 3); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + + Map enumMap = builder.getMutableInt32ToEnumField(); + enumMap.put(1, TestMap.EnumValue.BAR); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); + try { + enumMap.put(2, TestMap.EnumValue.FOO); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField()); + builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO); + assertEquals( + newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), + builder.getInt32ToEnumField()); + + Map stringMap = builder.getMutableInt32ToStringField(); + stringMap.put(1, "1"); + assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); + try { + stringMap.put(2, "2"); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, "1"), builder.getInt32ToStringField()); + builder.getMutableInt32ToStringField().put(2, "2"); + assertEquals( + newMap(1, "1", 2, "2"), + builder.getInt32ToStringField()); + + Map messageMap = builder.getMutableInt32ToMessageField(); + messageMap.put(1, TestMap.MessageValue.getDefaultInstance()); + assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), + builder.build().getInt32ToMessageField()); + try { + messageMap.put(2, TestMap.MessageValue.getDefaultInstance()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), + builder.getInt32ToMessageField()); + builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance()); + assertEquals( + newMap(1, TestMap.MessageValue.getDefaultInstance(), + 2, TestMap.MessageValue.getDefaultInstance()), + builder.getInt32ToMessageField()); + } + + public void testMutableMapLifecycle_collections() { + TestMap.Builder builder = TestMap.newBuilder(); + Map intMap = builder.getMutableInt32ToInt32Field(); + intMap.put(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + try { + intMap.remove(2); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.entrySet().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.entrySet().iterator().remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.keySet().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.values().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.values().iterator().remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, 2), intMap); + assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + } + public void testGettersAndSetters() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); @@ -274,4 +413,26 @@ public class MapForProto2LiteTest extends TestCase { assertEquals(54321, messageWithUnknownEnums.getInt32ToInt32Field().get(2).intValue()); } + + public void testIterationOrder() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + TestMap message = builder.build(); + + assertEquals(Arrays.asList("1", "2", "3"), + new ArrayList(message.getStringToInt32Field().keySet())); + } + + private static Map newMap(K key1, V value1) { + Map map = new HashMap(); + map.put(key1, value1); + return map; + } + + private static Map newMap(K key1, V value1, K key2, V value2) { + Map map = new HashMap(); + map.put(key1, value1); + map.put(key2, value2); + return map; + } } diff --git a/java/src/test/java/com/google/protobuf/MapForProto2Test.java b/java/src/test/java/com/google/protobuf/MapForProto2Test.java index 78cba1b4..7e984040 100644 --- a/java/src/test/java/com/google/protobuf/MapForProto2Test.java +++ b/java/src/test/java/com/google/protobuf/MapForProto2Test.java @@ -40,6 +40,7 @@ import map_test.MapForProto2TestProto.TestUnknownEnumValue; import junit.framework.TestCase; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -177,6 +178,116 @@ public class MapForProto2Test extends TestCase { assertEquals(0, message.getInt32ToMessageField().size()); assertEquals(0, message.getStringToInt32Field().size()); } + + public void testMutableMapLifecycle() { + TestMap.Builder builder = TestMap.newBuilder(); + Map intMap = builder.getMutableInt32ToInt32Field(); + intMap.put(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + try { + intMap.put(2, 3); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + builder.getMutableInt32ToInt32Field().put(2, 3); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + + Map enumMap = builder.getMutableInt32ToEnumField(); + enumMap.put(1, TestMap.EnumValue.BAR); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); + try { + enumMap.put(2, TestMap.EnumValue.FOO); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField()); + builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO); + assertEquals( + newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), + builder.getInt32ToEnumField()); + + Map stringMap = builder.getMutableInt32ToStringField(); + stringMap.put(1, "1"); + assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); + try { + stringMap.put(2, "2"); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, "1"), builder.getInt32ToStringField()); + builder.getMutableInt32ToStringField().put(2, "2"); + assertEquals( + newMap(1, "1", 2, "2"), + builder.getInt32ToStringField()); + + Map messageMap = builder.getMutableInt32ToMessageField(); + messageMap.put(1, TestMap.MessageValue.getDefaultInstance()); + assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), + builder.build().getInt32ToMessageField()); + try { + messageMap.put(2, TestMap.MessageValue.getDefaultInstance()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), + builder.getInt32ToMessageField()); + builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance()); + assertEquals( + newMap(1, TestMap.MessageValue.getDefaultInstance(), + 2, TestMap.MessageValue.getDefaultInstance()), + builder.getInt32ToMessageField()); + } + + public void testMutableMapLifecycle_collections() { + TestMap.Builder builder = TestMap.newBuilder(); + Map intMap = builder.getMutableInt32ToInt32Field(); + intMap.put(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + try { + intMap.remove(2); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.entrySet().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.entrySet().iterator().remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.keySet().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.values().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.values().iterator().remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, 2), intMap); + assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + } public void testGettersAndSetters() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); @@ -513,4 +624,41 @@ public class MapForProto2Test extends TestCase { assertEquals(2, message.getRecursiveMapField().get(1).getValue()); assertEquals(4, message.getRecursiveMapField().get(3).getValue()); } + + public void testIterationOrder() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + TestMap message = builder.build(); + + assertEquals(Arrays.asList("1", "2", "3"), + new ArrayList(message.getStringToInt32Field().keySet())); + } + + // Regression test for b/20494788 + public void testMapInitializationOrder() throws Exception { + assertEquals("RedactAllTypes", map_test.RedactAllTypes + .getDefaultInstance().getDescriptorForType().getName()); + + map_test.Message1.Builder builder = + map_test.Message1.newBuilder(); + builder.getMutableMapField().put("key", true); + map_test.Message1 message = builder.build(); + Message mapEntry = (Message) message.getRepeatedField( + message.getDescriptorForType().findFieldByName("map_field"), 0); + assertEquals(2, mapEntry.getAllFields().size()); + } + + private static Map newMap(K key1, V value1) { + Map map = new HashMap(); + map.put(key1, value1); + return map; + } + + private static Map newMap(K key1, V value1, K key2, V value2) { + Map map = new HashMap(); + map.put(key1, value1); + map.put(key2, value2); + return map; + } } + diff --git a/java/src/test/java/com/google/protobuf/MapTest.java b/java/src/test/java/com/google/protobuf/MapTest.java index b8e67b7c..0509be15 100644 --- a/java/src/test/java/com/google/protobuf/MapTest.java +++ b/java/src/test/java/com/google/protobuf/MapTest.java @@ -41,6 +41,7 @@ import map_test.MapTestProto.TestOnChangeEventPropagation; import junit.framework.TestCase; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -178,7 +179,117 @@ public class MapTest extends TestCase { assertEquals(0, message.getInt32ToMessageField().size()); assertEquals(0, message.getStringToInt32Field().size()); } + + public void testMutableMapLifecycle() { + TestMap.Builder builder = TestMap.newBuilder(); + Map intMap = builder.getMutableInt32ToInt32Field(); + intMap.put(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + try { + intMap.put(2, 3); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + builder.getMutableInt32ToInt32Field().put(2, 3); + assertEquals(newMap(1, 2, 2, 3), builder.getInt32ToInt32Field()); + + Map enumMap = builder.getMutableInt32ToEnumField(); + enumMap.put(1, TestMap.EnumValue.BAR); + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.build().getInt32ToEnumField()); + try { + enumMap.put(2, TestMap.EnumValue.FOO); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, TestMap.EnumValue.BAR), builder.getInt32ToEnumField()); + builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO); + assertEquals( + newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO), + builder.getInt32ToEnumField()); + + Map stringMap = builder.getMutableInt32ToStringField(); + stringMap.put(1, "1"); + assertEquals(newMap(1, "1"), builder.build().getInt32ToStringField()); + try { + stringMap.put(2, "2"); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, "1"), builder.getInt32ToStringField()); + builder.getMutableInt32ToStringField().put(2, "2"); + assertEquals( + newMap(1, "1", 2, "2"), + builder.getInt32ToStringField()); + + Map messageMap = builder.getMutableInt32ToMessageField(); + messageMap.put(1, TestMap.MessageValue.getDefaultInstance()); + assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), + builder.build().getInt32ToMessageField()); + try { + messageMap.put(2, TestMap.MessageValue.getDefaultInstance()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, TestMap.MessageValue.getDefaultInstance()), + builder.getInt32ToMessageField()); + builder.getMutableInt32ToMessageField().put(2, TestMap.MessageValue.getDefaultInstance()); + assertEquals( + newMap(1, TestMap.MessageValue.getDefaultInstance(), + 2, TestMap.MessageValue.getDefaultInstance()), + builder.getInt32ToMessageField()); + } + public void testMutableMapLifecycle_collections() { + TestMap.Builder builder = TestMap.newBuilder(); + Map intMap = builder.getMutableInt32ToInt32Field(); + intMap.put(1, 2); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + try { + intMap.remove(2); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.entrySet().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.entrySet().iterator().remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.keySet().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.values().remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + try { + intMap.values().iterator().remove(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + assertEquals(newMap(1, 2), intMap); + assertEquals(newMap(1, 2), builder.getInt32ToInt32Field()); + assertEquals(newMap(1, 2), builder.build().getInt32ToInt32Field()); + } + public void testGettersAndSetters() throws Exception { TestMap.Builder builder = TestMap.newBuilder(); TestMap message = builder.build(); @@ -611,4 +722,26 @@ public class MapTest extends TestCase { assertEquals(data.get(entry.getKey()) + 1, entry.getValue().intValue()); } } + + public void testIterationOrder() throws Exception { + TestMap.Builder builder = TestMap.newBuilder(); + setMapValues(builder); + TestMap message = builder.build(); + + assertEquals(Arrays.asList("1", "2", "3"), + new ArrayList(message.getStringToInt32Field().keySet())); + } + + private static Map newMap(K key1, V value1) { + Map map = new HashMap(); + map.put(key1, value1); + return map; + } + + private static Map newMap(K key1, V value1, K key2, V value2) { + Map map = new HashMap(); + map.put(key1, value1); + map.put(key2, value2); + return map; + } } diff --git a/java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java b/java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java new file mode 100644 index 00000000..f9f5e9c7 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/ProtobufArrayListTest.java @@ -0,0 +1,303 @@ +// 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. + +package com.google.protobuf; + +import static java.util.Arrays.asList; + +import junit.framework.TestCase; + +import java.util.Collections; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.List; + +/** + * Tests for {@link ProtobufArrayList}. + */ +public class ProtobufArrayListTest extends TestCase { + + private static final ProtobufArrayList UNARY_LIST = newImmutableProtoArrayList(1); + private static final ProtobufArrayList TERTIARY_LIST = + newImmutableProtoArrayList(1, 2, 3); + + private ProtobufArrayList list; + + @Override + protected void setUp() throws Exception { + list = new ProtobufArrayList(); + } + + public void testEmptyListReturnsSameInstance() { + assertSame(ProtobufArrayList.emptyList(), ProtobufArrayList.emptyList()); + } + + public void testEmptyListIsImmutable() { + assertImmutable(ProtobufArrayList.emptyList()); + } + + public void testCopyConstructor() { + ProtobufArrayList copy = new ProtobufArrayList(TERTIARY_LIST); + assertEquals(TERTIARY_LIST, copy); + + copy = new ProtobufArrayList(IntArrayList.emptyList()); + assertEquals(ProtobufArrayList.emptyList(), copy); + + copy = new ProtobufArrayList(asList(1, 2, 3)); + assertEquals(asList(1, 2, 3), copy); + + copy = new ProtobufArrayList(Collections.emptyList()); + assertEquals(ProtobufArrayList.emptyList(), copy); + } + + public void testModificationWithIteration() { + list.addAll(asList(1, 2, 3, 4)); + Iterator iterator = list.iterator(); + assertEquals(4, list.size()); + assertEquals(1, (int) list.get(0)); + assertEquals(1, (int) iterator.next()); + + list.remove(0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + + iterator = list.iterator(); + list.set(0, 1); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + + iterator = list.iterator(); + list.add(0, 0); + try { + iterator.next(); + fail(); + } catch (ConcurrentModificationException e) { + // expected + } + } + + public void testMakeImmutable() { + list.add(2); + list.add(4); + list.add(6); + list.add(8); + list.makeImmutable(); + assertImmutable(list); + } + + public void testRemove() { + list.add(2); + list.add(4); + list.add(6); + + list.remove(1); + assertEquals(asList(2, 6), list); + + list.remove(1); + assertEquals(asList(2), list); + + list.remove(0); + assertEquals(asList(), list); + } + + public void testGet() { + list.add(2); + list.add(6); + + assertEquals(2, (int) list.get(0)); + assertEquals(6, (int) list.get(1)); + } + + public void testSet() { + list.add(2); + list.add(6); + + list.set(0, 1); + assertEquals(1, (int) list.get(0)); + list.set(1, 2); + assertEquals(2, (int) list.get(1)); + } + + private void assertImmutable(List list) { + if (list.contains(1)) { + throw new RuntimeException("Cannot test the immutability of lists that contain 1."); + } + + try { + list.add(1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.add(0, 1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(Collections.singletonList(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(new ProtobufArrayList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.addAll(0, Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.clear(); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(1); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.remove(new Object()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.removeAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.emptyList()); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(Collections.singleton(1)); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.retainAll(UNARY_LIST); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + + try { + list.set(0, 0); + fail(); + } catch (UnsupportedOperationException e) { + // expected + } + } + + private static ProtobufArrayList newImmutableProtoArrayList(int... elements) { + ProtobufArrayList list = new ProtobufArrayList(); + for (int element : elements) { + list.add(element); + } + list.makeImmutable(); + return list; + } +} diff --git a/java/src/test/java/com/google/protobuf/field_presence_test.proto b/java/src/test/java/com/google/protobuf/field_presence_test.proto index 8d8ea8ef..8f3ca8c6 100644 --- a/java/src/test/java/com/google/protobuf/field_presence_test.proto +++ b/java/src/test/java/com/google/protobuf/field_presence_test.proto @@ -45,15 +45,15 @@ message TestAllTypes { BAZ = 2; } message NestedMessage { - optional int32 value = 1; + int32 value = 1; } - optional int32 optional_int32 = 1; - optional string optional_string = 2; - optional bytes optional_bytes = 3; - optional NestedEnum optional_nested_enum = 4; - optional NestedMessage optional_nested_message = 5; - optional protobuf_unittest.TestRequired optional_proto2_message = 6; + int32 optional_int32 = 1; + string optional_string = 2; + bytes optional_bytes = 3; + NestedEnum optional_nested_enum = 4; + NestedMessage optional_nested_message = 5; + protobuf_unittest.TestRequired optional_proto2_message = 6; oneof oneof_field { int32 oneof_int32 = 11; @@ -75,12 +75,12 @@ message TestAllTypes { } message TestOptionalFieldsOnly { - optional int32 optional_int32 = 1; - optional string optional_string = 2; - optional bytes optional_bytes = 3; - optional TestAllTypes.NestedEnum optional_nested_enum = 4; - optional TestAllTypes.NestedMessage optional_nested_message = 5; - optional protobuf_unittest.TestRequired optional_proto2_message = 6; + int32 optional_int32 = 1; + string optional_string = 2; + bytes optional_bytes = 3; + TestAllTypes.NestedEnum optional_nested_enum = 4; + TestAllTypes.NestedMessage optional_nested_message = 5; + protobuf_unittest.TestRequired optional_proto2_message = 6; } message TestRepeatedFieldsOnly { diff --git a/java/src/test/java/com/google/protobuf/map_initialization_order_test.proto b/java/src/test/java/com/google/protobuf/map_initialization_order_test.proto new file mode 100644 index 00000000..b02ac599 --- /dev/null +++ b/java/src/test/java/com/google/protobuf/map_initialization_order_test.proto @@ -0,0 +1,61 @@ +// 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. + +// Regression test for a map initilaization order bug. The bug only manifests +// when: +// 1. A message contains map fields and is also extendable. +// 2. There is a file-level extension defined in the same file referencing +// the above message as the extension type. +// 3. The program executes in the following order: +// a. getDescriptor() is called on another message in the same file. +// b. use protobuf reflection to access the map field. +// The symptom is a NullPointerException being thrown. +syntax = "proto2"; + +package map_test; + +option java_package = "map_test"; +option java_outer_classname = "MapInitializationOrderTest"; +option java_multiple_files = true; + +// Mirrors the structure of +// javatests/com/google/cloud/common/logging/logging_test.proto. + +message Message1 { + map map_field = 1; + extensions 1000 to max; +} + +extend Message1 { + optional Message1 recursive_extension = 1001; +} + +message RedactAllTypes { +} diff --git a/java/src/test/java/com/google/protobuf/map_test.proto b/java/src/test/java/com/google/protobuf/map_test.proto index bf692c22..2f7709be 100644 --- a/java/src/test/java/com/google/protobuf/map_test.proto +++ b/java/src/test/java/com/google/protobuf/map_test.proto @@ -39,7 +39,7 @@ option java_generate_equals_and_hash = true; message TestMap { message MessageValue { - optional int32 value = 1; + int32 value = 1; } enum EnumValue { FOO = 0; @@ -60,5 +60,5 @@ message TestMap { // propagate the onChange event and mark its parent dirty when a change // is made to a map field. message TestOnChangeEventPropagation { - optional TestMap optional_message = 1; + TestMap optional_message = 1; } diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py index f7a58ca0..970b1a88 100755 --- a/python/google/protobuf/descriptor.py +++ b/python/google/protobuf/descriptor.py @@ -245,9 +245,6 @@ class Descriptor(_NestedDescriptorBase): is_extendable: Does this type define any extension ranges? - options: (descriptor_pb2.MessageOptions) Protocol message options or None - to use default message options. - oneofs: (list of OneofDescriptor) The list of descriptors for oneof fields in this message. oneofs_by_name: (dict str -> OneofDescriptor) Same objects as in |oneofs|, @@ -265,7 +262,7 @@ class Descriptor(_NestedDescriptorBase): file=None, serialized_start=None, serialized_end=None, syntax=None): _message.Message._CheckCalledFromGeneratedFile() - return _message.Message._GetMessageDescriptor(full_name) + return _message.default_pool.FindMessageTypeByName(full_name) # NOTE(tmarek): The file argument redefining a builtin is nothing we can # fix right now since we don't know how many clients already rely on the @@ -495,9 +492,9 @@ class FieldDescriptor(DescriptorBase): has_default_value=True, containing_oneof=None): _message.Message._CheckCalledFromGeneratedFile() if is_extension: - return _message.Message._GetExtensionDescriptor(full_name) + return _message.default_pool.FindExtensionByName(full_name) else: - return _message.Message._GetFieldDescriptor(full_name) + return _message.default_pool.FindFieldByName(full_name) def __init__(self, name, full_name, index, number, type, cpp_type, label, default_value, message_type, enum_type, containing_type, @@ -528,14 +525,9 @@ class FieldDescriptor(DescriptorBase): self.containing_oneof = containing_oneof if api_implementation.Type() == 'cpp': if is_extension: - # pylint: disable=protected-access - self._cdescriptor = ( - _message.Message._GetExtensionDescriptor(full_name)) - # pylint: enable=protected-access + self._cdescriptor = _message.default_pool.FindExtensionByName(full_name) else: - # pylint: disable=protected-access - self._cdescriptor = _message.Message._GetFieldDescriptor(full_name) - # pylint: enable=protected-access + self._cdescriptor = _message.default_pool.FindFieldByName(full_name) else: self._cdescriptor = None @@ -592,7 +584,7 @@ class EnumDescriptor(_NestedDescriptorBase): containing_type=None, options=None, file=None, serialized_start=None, serialized_end=None): _message.Message._CheckCalledFromGeneratedFile() - return _message.Message._GetEnumDescriptor(full_name) + return _message.default_pool.FindEnumTypeByName(full_name) def __init__(self, name, full_name, filename, values, containing_type=None, options=None, file=None, @@ -677,7 +669,7 @@ class OneofDescriptor(object): def __new__(cls, name, full_name, index, containing_type, fields): _message.Message._CheckCalledFromGeneratedFile() - return _message.Message._GetOneofDescriptor(full_name) + return _message.default_pool.FindOneofByName(full_name) def __init__(self, name, full_name, index, containing_type, fields): """Arguments are as described in the attribute description above.""" @@ -788,12 +780,8 @@ class FileDescriptor(DescriptorBase): dependencies=None, syntax=None): # FileDescriptor() is called from various places, not only from generated # files, to register dynamic proto files and messages. - # TODO(amauryfa): Expose BuildFile() as a public function and make this - # constructor an implementation detail. if serialized_pb: - # pylint: disable=protected-access2 - return _message.Message._BuildFile(serialized_pb) - # pylint: enable=protected-access + return _message.default_pool.AddSerializedFile(serialized_pb) else: return super(FileDescriptor, cls).__new__(cls) @@ -814,9 +802,7 @@ class FileDescriptor(DescriptorBase): if (api_implementation.Type() == 'cpp' and self.serialized_pb is not None): - # pylint: disable=protected-access - _message.Message._BuildFile(self.serialized_pb) - # pylint: enable=protected-access + _message.default_pool.AddSerializedFile(self.serialized_pb) def CopyToProto(self, proto): """Copies this to a descriptor_pb2.FileDescriptorProto. @@ -864,10 +850,10 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, file_descriptor_proto = descriptor_pb2.FileDescriptorProto() file_descriptor_proto.message_type.add().MergeFrom(desc_proto) - # Generate a random name for this proto file to prevent conflicts with - # any imported ones. We need to specify a file name so BuildFile accepts - # our FileDescriptorProto, but it is not important what that file name - # is actually set to. + # Generate a random name for this proto file to prevent conflicts with any + # imported ones. We need to specify a file name so the descriptor pool + # accepts our FileDescriptorProto, but it is not important what that file + # name is actually set to. proto_name = str(uuid.uuid4()) if package: @@ -877,10 +863,8 @@ def MakeDescriptor(desc_proto, package='', build_file_if_cpp=True, else: file_descriptor_proto.name = proto_name + '.proto' - # pylint: disable=protected-access - result = _message.Message._BuildFile( - file_descriptor_proto.SerializeToString()) - # pylint: enable=protected-access + _message.default_pool.Add(file_descriptor_proto) + result = _message.default_pool.FindFileByName(file_descriptor_proto.name) if _USE_C_DESCRIPTORS: return result.message_types_by_name[desc_proto.name] diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py index 7e7701f8..1244ba7c 100644 --- a/python/google/protobuf/descriptor_pool.py +++ b/python/google/protobuf/descriptor_pool.py @@ -113,6 +113,20 @@ class DescriptorPool(object): self._internal_db.Add(file_desc_proto) + def AddSerializedFile(self, serialized_file_desc_proto): + """Adds the FileDescriptorProto and its types to this pool. + + Args: + serialized_file_desc_proto: A bytes string, serialization of the + FileDescriptorProto to add. + """ + + # pylint: disable=g-import-not-at-top + from google.protobuf import descriptor_pb2 + file_desc_proto = descriptor_pb2.FileDescriptorProto.FromString( + serialized_file_desc_proto) + self.Add(file_desc_proto) + def AddDescriptor(self, desc): """Adds a Descriptor to the pool, non-recursively. @@ -320,17 +334,17 @@ class DescriptorPool(object): file_descriptor, None, scope)) for index, extension_proto in enumerate(file_proto.extension): - extension_desc = self.MakeFieldDescriptor( + extension_desc = self._MakeFieldDescriptor( extension_proto, file_proto.package, index, is_extension=True) extension_desc.containing_type = self._GetTypeFromScope( file_descriptor.package, extension_proto.extendee, scope) - self.SetFieldType(extension_proto, extension_desc, + self._SetFieldType(extension_proto, extension_desc, file_descriptor.package, scope) file_descriptor.extensions_by_name[extension_desc.name] = ( extension_desc) for desc_proto in file_proto.message_type: - self.SetAllFieldTypes(file_proto.package, desc_proto, scope) + self._SetAllFieldTypes(file_proto.package, desc_proto, scope) if file_proto.package: desc_proto_prefix = _PrefixWithDot(file_proto.package) @@ -381,10 +395,11 @@ class DescriptorPool(object): enums = [ self._ConvertEnumDescriptor(enum, desc_name, file_desc, None, scope) for enum in desc_proto.enum_type] - fields = [self.MakeFieldDescriptor(field, desc_name, index) + fields = [self._MakeFieldDescriptor(field, desc_name, index) for index, field in enumerate(desc_proto.field)] extensions = [ - self.MakeFieldDescriptor(extension, desc_name, index, is_extension=True) + self._MakeFieldDescriptor(extension, desc_name, index, + is_extension=True) for index, extension in enumerate(desc_proto.extension)] oneofs = [ descriptor.OneofDescriptor(desc.name, '.'.join((desc_name, desc.name)), @@ -464,8 +479,8 @@ class DescriptorPool(object): self._enum_descriptors[enum_name] = desc return desc - def MakeFieldDescriptor(self, field_proto, message_name, index, - is_extension=False): + def _MakeFieldDescriptor(self, field_proto, message_name, index, + is_extension=False): """Creates a field descriptor from a FieldDescriptorProto. For message and enum type fields, this method will do a look up @@ -506,7 +521,7 @@ class DescriptorPool(object): extension_scope=None, options=field_proto.options) - def SetAllFieldTypes(self, package, desc_proto, scope): + def _SetAllFieldTypes(self, package, desc_proto, scope): """Sets all the descriptor's fields's types. This method also sets the containing types on any extensions. @@ -527,18 +542,18 @@ class DescriptorPool(object): nested_package = '.'.join([package, desc_proto.name]) for field_proto, field_desc in zip(desc_proto.field, main_desc.fields): - self.SetFieldType(field_proto, field_desc, nested_package, scope) + self._SetFieldType(field_proto, field_desc, nested_package, scope) for extension_proto, extension_desc in ( zip(desc_proto.extension, main_desc.extensions)): extension_desc.containing_type = self._GetTypeFromScope( nested_package, extension_proto.extendee, scope) - self.SetFieldType(extension_proto, extension_desc, nested_package, scope) + self._SetFieldType(extension_proto, extension_desc, nested_package, scope) for nested_type in desc_proto.nested_type: - self.SetAllFieldTypes(nested_package, nested_type, scope) + self._SetAllFieldTypes(nested_package, nested_type, scope) - def SetFieldType(self, field_proto, field_desc, package, scope): + def _SetFieldType(self, field_proto, field_desc, package, scope): """Sets the field's type, cpp_type, message_type and enum_type. Args: diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py index d976f9e1..72c2fa01 100755 --- a/python/google/protobuf/internal/containers.py +++ b/python/google/protobuf/internal/containers.py @@ -41,6 +41,146 @@ are: __author__ = 'petar@google.com (Petar Petrov)' +import sys + +if sys.version_info[0] < 3: + # We would use collections.MutableMapping all the time, but in Python 2 it + # doesn't define __slots__. This causes two significant problems: + # + # 1. we can't disallow arbitrary attribute assignment, even if our derived + # classes *do* define __slots__. + # + # 2. we can't safely derive a C type from it without __slots__ defined (the + # interpreter expects to find a dict at tp_dictoffset, which we can't + # robustly provide. And we don't want an instance dict anyway. + # + # So this is the Python 2.7 definition of Mapping/MutableMapping functions + # verbatim, except that: + # 1. We declare __slots__. + # 2. We don't declare this as a virtual base class. The classes defined + # in collections are the interesting base classes, not us. + # + # Note: deriving from object is critical. It is the only thing that makes + # this a true type, allowing us to derive from it in C++ cleanly and making + # __slots__ properly disallow arbitrary element assignment. + from collections import Mapping as _Mapping + + class Mapping(object): + __slots__ = () + + def get(self, key, default=None): + try: + return self[key] + except KeyError: + return default + + def __contains__(self, key): + try: + self[key] + except KeyError: + return False + else: + return True + + def iterkeys(self): + return iter(self) + + def itervalues(self): + for key in self: + yield self[key] + + def iteritems(self): + for key in self: + yield (key, self[key]) + + def keys(self): + return list(self) + + def items(self): + return [(key, self[key]) for key in self] + + def values(self): + return [self[key] for key in self] + + # Mappings are not hashable by default, but subclasses can change this + __hash__ = None + + def __eq__(self, other): + if not isinstance(other, _Mapping): + return NotImplemented + return dict(self.items()) == dict(other.items()) + + def __ne__(self, other): + return not (self == other) + + class MutableMapping(Mapping): + __slots__ = () + + __marker = object() + + def pop(self, key, default=__marker): + try: + value = self[key] + except KeyError: + if default is self.__marker: + raise + return default + else: + del self[key] + return value + + def popitem(self): + try: + key = next(iter(self)) + except StopIteration: + raise KeyError + value = self[key] + del self[key] + return key, value + + def clear(self): + try: + while True: + self.popitem() + except KeyError: + pass + + def update(*args, **kwds): + if len(args) > 2: + raise TypeError("update() takes at most 2 positional " + "arguments ({} given)".format(len(args))) + elif not args: + raise TypeError("update() takes at least 1 argument (0 given)") + self = args[0] + other = args[1] if len(args) >= 2 else () + + if isinstance(other, Mapping): + for key in other: + self[key] = other[key] + elif hasattr(other, "keys"): + for key in other.keys(): + self[key] = other[key] + else: + for key, value in other: + self[key] = value + for key, value in kwds.items(): + self[key] = value + + def setdefault(self, key, default=None): + try: + return self[key] + except KeyError: + self[key] = default + return default + + _Mapping.register(Mapping) + +else: + # In Python 3 we can just use MutableMapping directly, because it defines + # __slots__. + from collections import MutableMapping + + class BaseContainer(object): """Base container class.""" @@ -286,3 +426,160 @@ class RepeatedCompositeFieldContainer(BaseContainer): raise TypeError('Can only compare repeated composite fields against ' 'other repeated composite fields.') return self._values == other._values + + +class ScalarMap(MutableMapping): + + """Simple, type-checked, dict-like container for holding repeated scalars.""" + + # Disallows assignment to other attributes. + __slots__ = ['_key_checker', '_value_checker', '_values', '_message_listener'] + + def __init__(self, message_listener, key_checker, value_checker): + """ + Args: + message_listener: A MessageListener implementation. + The ScalarMap will call this object's Modified() method when it + is modified. + key_checker: A type_checkers.ValueChecker instance to run on keys + inserted into this container. + value_checker: A type_checkers.ValueChecker instance to run on values + inserted into this container. + """ + self._message_listener = message_listener + self._key_checker = key_checker + self._value_checker = value_checker + self._values = {} + + def __getitem__(self, key): + try: + return self._values[key] + except KeyError: + key = self._key_checker.CheckValue(key) + val = self._value_checker.DefaultValue() + self._values[key] = val + return val + + def __contains__(self, item): + return item in self._values + + # We need to override this explicitly, because our defaultdict-like behavior + # will make the default implementation (from our base class) always insert + # the key. + def get(self, key, default=None): + if key in self: + return self[key] + else: + return default + + def __setitem__(self, key, value): + checked_key = self._key_checker.CheckValue(key) + checked_value = self._value_checker.CheckValue(value) + self._values[checked_key] = checked_value + self._message_listener.Modified() + + def __delitem__(self, key): + del self._values[key] + self._message_listener.Modified() + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def MergeFrom(self, other): + self._values.update(other._values) + self._message_listener.Modified() + + # This is defined in the abstract base, but we can do it much more cheaply. + def clear(self): + self._values.clear() + self._message_listener.Modified() + + +class MessageMap(MutableMapping): + + """Simple, type-checked, dict-like container for with submessage values.""" + + # Disallows assignment to other attributes. + __slots__ = ['_key_checker', '_values', '_message_listener', + '_message_descriptor'] + + def __init__(self, message_listener, message_descriptor, key_checker): + """ + Args: + message_listener: A MessageListener implementation. + The ScalarMap will call this object's Modified() method when it + is modified. + key_checker: A type_checkers.ValueChecker instance to run on keys + inserted into this container. + value_checker: A type_checkers.ValueChecker instance to run on values + inserted into this container. + """ + self._message_listener = message_listener + self._message_descriptor = message_descriptor + self._key_checker = key_checker + self._values = {} + + def __getitem__(self, key): + try: + return self._values[key] + except KeyError: + key = self._key_checker.CheckValue(key) + new_element = self._message_descriptor._concrete_class() + new_element._SetListener(self._message_listener) + self._values[key] = new_element + self._message_listener.Modified() + + return new_element + + def get_or_create(self, key): + """get_or_create() is an alias for getitem (ie. map[key]). + + Args: + key: The key to get or create in the map. + + This is useful in cases where you want to be explicit that the call is + mutating the map. This can avoid lint errors for statements like this + that otherwise would appear to be pointless statements: + + msg.my_map[key] + """ + return self[key] + + # We need to override this explicitly, because our defaultdict-like behavior + # will make the default implementation (from our base class) always insert + # the key. + def get(self, key, default=None): + if key in self: + return self[key] + else: + return default + + def __contains__(self, item): + return item in self._values + + def __setitem__(self, key, value): + raise ValueError('May not set values directly, call my_map[key].foo = 5') + + def __delitem__(self, key): + del self._values[key] + self._message_listener.Modified() + + def __len__(self): + return len(self._values) + + def __iter__(self): + return iter(self._values) + + def MergeFrom(self, other): + for key in other: + self[key].MergeFrom(other[key]) + # self._message_listener.Modified() not required here, because + # mutations to submessages already propagate. + + # This is defined in the abstract base, but we can do it much more cheaply. + def clear(self): + self._values.clear() + self._message_listener.Modified() diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py index 0f500606..3837eaea 100755 --- a/python/google/protobuf/internal/decoder.py +++ b/python/google/protobuf/internal/decoder.py @@ -732,6 +732,50 @@ def MessageSetItemDecoder(extensions_by_number): return DecodeItem +# -------------------------------------------------------------------- + +def MapDecoder(field_descriptor, new_default, is_message_map): + """Returns a decoder for a map field.""" + + key = field_descriptor + tag_bytes = encoder.TagBytes(field_descriptor.number, + wire_format.WIRETYPE_LENGTH_DELIMITED) + tag_len = len(tag_bytes) + local_DecodeVarint = _DecodeVarint + # Can't read _concrete_class yet; might not be initialized. + message_type = field_descriptor.message_type + + def DecodeMap(buffer, pos, end, message, field_dict): + submsg = message_type._concrete_class() + value = field_dict.get(key) + if value is None: + value = field_dict.setdefault(key, new_default(message)) + while 1: + # Read length. + (size, pos) = local_DecodeVarint(buffer, pos) + new_pos = pos + size + if new_pos > end: + raise _DecodeError('Truncated message.') + # Read sub-message. + submsg.Clear() + if submsg._InternalParse(buffer, pos, new_pos) != new_pos: + # The only reason _InternalParse would return early is if it + # encountered an end-group tag. + raise _DecodeError('Unexpected end-group tag.') + + if is_message_map: + value[submsg.key].MergeFrom(submsg.value) + else: + value[submsg.key] = submsg.value + + # Predict that the next tag is another copy of the same repeated field. + pos = new_pos + tag_len + if buffer[new_pos:pos] != tag_bytes or new_pos == end: + # Prediction failed. Return. + return new_pos + + return DecodeMap + # -------------------------------------------------------------------- # Optimization is not as heavy here because calls to SkipField() are rare, # except for handling end-group tags. diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py index 56fe14e9..8416e157 100644 --- a/python/google/protobuf/internal/descriptor_database_test.py +++ b/python/google/protobuf/internal/descriptor_database_test.py @@ -35,7 +35,6 @@ __author__ = 'matthewtoia@google.com (Matt Toia)' import unittest - from google.protobuf import descriptor_pb2 from google.protobuf.internal import factory_test2_pb2 from google.protobuf import descriptor_database diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py index 7d145f42..d159cc62 100644 --- a/python/google/protobuf/internal/descriptor_pool_test.py +++ b/python/google/protobuf/internal/descriptor_pool_test.py @@ -37,6 +37,7 @@ __author__ = 'matthewtoia@google.com (Matt Toia)' import os import unittest +import unittest from google.protobuf import unittest_pb2 from google.protobuf import descriptor_pb2 from google.protobuf.internal import api_implementation @@ -226,6 +227,13 @@ class DescriptorPoolTest(unittest.TestCase): db.Add(self.factory_test2_fd) self.testFindMessageTypeByName() + def testAddSerializedFile(self): + db = descriptor_database.DescriptorDatabase() + self.pool = descriptor_pool.DescriptorPool(db) + self.pool.AddSerializedFile(self.factory_test1_fd.SerializeToString()) + self.pool.AddSerializedFile(self.factory_test2_fd.SerializeToString()) + self.testFindMessageTypeByName() + def testComplexNesting(self): test1_desc = descriptor_pb2.FileDescriptorProto.FromString( descriptor_pool_test1_pb2.DESCRIPTOR.serialized_pb) @@ -510,6 +518,43 @@ class AddDescriptorTest(unittest.TestCase): 'protobuf_unittest.TestAllTypes') +@unittest.skipIf( + api_implementation.Type() != 'cpp', + 'default_pool is only supported by the C++ implementation') +class DefaultPoolTest(unittest.TestCase): + + def testFindMethods(self): + # pylint: disable=g-import-not-at-top + from google.protobuf.pyext import _message + pool = _message.default_pool + self.assertIs( + pool.FindFileByName('google/protobuf/unittest.proto'), + unittest_pb2.DESCRIPTOR) + self.assertIs( + pool.FindMessageTypeByName('protobuf_unittest.TestAllTypes'), + unittest_pb2.TestAllTypes.DESCRIPTOR) + self.assertIs( + pool.FindFieldByName('protobuf_unittest.TestAllTypes.optional_int32'), + unittest_pb2.TestAllTypes.DESCRIPTOR.fields_by_name['optional_int32']) + self.assertIs( + pool.FindExtensionByName('protobuf_unittest.optional_int32_extension'), + unittest_pb2.DESCRIPTOR.extensions_by_name['optional_int32_extension']) + self.assertIs( + pool.FindEnumTypeByName('protobuf_unittest.ForeignEnum'), + unittest_pb2.ForeignEnum.DESCRIPTOR) + self.assertIs( + pool.FindOneofByName('protobuf_unittest.TestAllTypes.oneof_field'), + unittest_pb2.TestAllTypes.DESCRIPTOR.oneofs_by_name['oneof_field']) + + def testAddFileDescriptor(self): + # pylint: disable=g-import-not-at-top + from google.protobuf.pyext import _message + pool = _message.default_pool + file_desc = descriptor_pb2.FileDescriptorProto(name='some/file.proto') + pool.Add(file_desc) + pool.AddSerializedFile(file_desc.SerializeToString()) + + TEST1_FILE = ProtoFile( 'google/protobuf/internal/descriptor_pool_test1.proto', 'google.protobuf.python.internal', diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py index 335caee6..26866f3a 100755 --- a/python/google/protobuf/internal/descriptor_test.py +++ b/python/google/protobuf/internal/descriptor_test.py @@ -35,8 +35,8 @@ __author__ = 'robinson@google.com (Will Robinson)' import sys -import unittest +import unittest from google.protobuf import unittest_custom_options_pb2 from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_pb2 diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py index 38a5138a..752f4eab 100755 --- a/python/google/protobuf/internal/encoder.py +++ b/python/google/protobuf/internal/encoder.py @@ -314,7 +314,7 @@ def MessageSizer(field_number, is_repeated, is_packed): # -------------------------------------------------------------------- -# MessageSet is special. +# MessageSet is special: it needs custom logic to compute its size properly. def MessageSetItemSizer(field_number): @@ -339,6 +339,32 @@ def MessageSetItemSizer(field_number): return FieldSize +# -------------------------------------------------------------------- +# Map is special: it needs custom logic to compute its size properly. + + +def MapSizer(field_descriptor): + """Returns a sizer for a map field.""" + + # Can't look at field_descriptor.message_type._concrete_class because it may + # not have been initialized yet. + message_type = field_descriptor.message_type + message_sizer = MessageSizer(field_descriptor.number, False, False) + + def FieldSize(map_value): + total = 0 + for key in map_value: + value = map_value[key] + # It's wasteful to create the messages and throw them away one second + # later since we'll do the same for the actual encode. But there's not an + # obvious way to avoid this within the current design without tons of code + # duplication. + entry_msg = message_type._concrete_class(key=key, value=value) + total += message_sizer(entry_msg) + return total + + return FieldSize + # ==================================================================== # Encoders! @@ -786,3 +812,30 @@ def MessageSetItemEncoder(field_number): return write(end_bytes) return EncodeField + + +# -------------------------------------------------------------------- +# As before, Map is special. + + +def MapEncoder(field_descriptor): + """Encoder for extensions of MessageSet. + + Maps always have a wire format like this: + message MapEntry { + key_type key = 1; + value_type value = 2; + } + repeated MapEntry map = N; + """ + # Can't look at field_descriptor.message_type._concrete_class because it may + # not have been initialized yet. + message_type = field_descriptor.message_type + encode_message = MessageEncoder(field_descriptor.number, False, False) + + def EncodeField(write, value): + for key in value: + entry_msg = message_type._concrete_class(key=key, value=value[key]) + encode_message(write, entry_msg) + + return EncodeField diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py index ccc5860b..5c07cbe6 100755 --- a/python/google/protobuf/internal/generator_test.py +++ b/python/google/protobuf/internal/generator_test.py @@ -42,7 +42,6 @@ further ensures that we can use Python protocol message objects as we expect. __author__ = 'robinson@google.com (Will Robinson)' import unittest - from google.protobuf.internal import test_bad_identifiers_pb2 from google.protobuf import unittest_custom_options_pb2 from google.protobuf import unittest_import_pb2 diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py index 626c3fc9..b8694f96 100644 --- a/python/google/protobuf/internal/message_factory_test.py +++ b/python/google/protobuf/internal/message_factory_test.py @@ -35,7 +35,6 @@ __author__ = 'matthewtoia@google.com (Matt Toia)' import unittest - from google.protobuf import descriptor_pb2 from google.protobuf.internal import factory_test1_pb2 from google.protobuf.internal import factory_test2_pb2 diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py index 4ecaa1c7..320ff0d2 100755 --- a/python/google/protobuf/internal/message_test.py +++ b/python/google/protobuf/internal/message_test.py @@ -50,7 +50,9 @@ import pickle import sys import unittest +import unittest from google.protobuf.internal import _parameterized +from google.protobuf import map_unittest_pb2 from google.protobuf import unittest_pb2 from google.protobuf import unittest_proto3_arena_pb2 from google.protobuf.internal import api_implementation @@ -125,10 +127,17 @@ class MessageTest(unittest.TestCase): self.assertEqual(unpickled_message, golden_message) def testPositiveInfinity(self, message_module): - golden_data = (b'\x5D\x00\x00\x80\x7F' - b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' - b'\xCD\x02\x00\x00\x80\x7F' - b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F') + if message_module is unittest_pb2: + golden_data = (b'\x5D\x00\x00\x80\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' + b'\xCD\x02\x00\x00\x80\x7F' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\x7F') + else: + golden_data = (b'\x5D\x00\x00\x80\x7F' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\x7F' + b'\xCA\x02\x04\x00\x00\x80\x7F' + b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\x7F') + golden_message = message_module.TestAllTypes() golden_message.ParseFromString(golden_data) self.assertTrue(IsPosInf(golden_message.optional_float)) @@ -138,10 +147,17 @@ class MessageTest(unittest.TestCase): self.assertEqual(golden_data, golden_message.SerializeToString()) def testNegativeInfinity(self, message_module): - golden_data = (b'\x5D\x00\x00\x80\xFF' - b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' - b'\xCD\x02\x00\x00\x80\xFF' - b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF') + if message_module is unittest_pb2: + golden_data = (b'\x5D\x00\x00\x80\xFF' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' + b'\xCD\x02\x00\x00\x80\xFF' + b'\xD1\x02\x00\x00\x00\x00\x00\x00\xF0\xFF') + else: + golden_data = (b'\x5D\x00\x00\x80\xFF' + b'\x61\x00\x00\x00\x00\x00\x00\xF0\xFF' + b'\xCA\x02\x04\x00\x00\x80\xFF' + b'\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xF0\xFF') + golden_message = message_module.TestAllTypes() golden_message.ParseFromString(golden_data) self.assertTrue(IsNegInf(golden_message.optional_float)) @@ -1034,64 +1050,132 @@ class Proto2Test(unittest.TestCase): self.assertEqual(len(parsing_merge.Extensions[ unittest_pb2.TestParsingMerge.repeated_ext]), 3) + def testPythonicInit(self): + message = unittest_pb2.TestAllTypes( + optional_int32=100, + optional_fixed32=200, + optional_float=300.5, + optional_bytes=b'x', + optionalgroup={'a': 400}, + optional_nested_message={'bb': 500}, + optional_nested_enum='BAZ', + repeatedgroup=[{'a': 600}, + {'a': 700}], + repeated_nested_enum=['FOO', unittest_pb2.TestAllTypes.BAR], + default_int32=800, + oneof_string='y') + self.assertTrue(isinstance(message, unittest_pb2.TestAllTypes)) + self.assertEqual(100, message.optional_int32) + self.assertEqual(200, message.optional_fixed32) + self.assertEqual(300.5, message.optional_float) + self.assertEqual(b'x', message.optional_bytes) + self.assertEqual(400, message.optionalgroup.a) + self.assertTrue(isinstance(message.optional_nested_message, + unittest_pb2.TestAllTypes.NestedMessage)) + self.assertEqual(500, message.optional_nested_message.bb) + self.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + self.assertEqual(2, len(message.repeatedgroup)) + self.assertEqual(600, message.repeatedgroup[0].a) + self.assertEqual(700, message.repeatedgroup[1].a) + self.assertEqual(2, len(message.repeated_nested_enum)) + self.assertEqual(unittest_pb2.TestAllTypes.FOO, + message.repeated_nested_enum[0]) + self.assertEqual(unittest_pb2.TestAllTypes.BAR, + message.repeated_nested_enum[1]) + self.assertEqual(800, message.default_int32) + self.assertEqual('y', message.oneof_string) + self.assertFalse(message.HasField('optional_int64')) + self.assertEqual(0, len(message.repeated_float)) + self.assertEqual(42, message.default_int64) + + message = unittest_pb2.TestAllTypes(optional_nested_enum=u'BAZ') + self.assertEqual(unittest_pb2.TestAllTypes.BAZ, + message.optional_nested_enum) + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes( + optional_nested_message={'INVALID_NESTED_FIELD': 17}) + + with self.assertRaises(TypeError): + unittest_pb2.TestAllTypes( + optional_nested_message={'bb': 'INVALID_VALUE_TYPE'}) + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes(optional_nested_enum='INVALID_LABEL') + + with self.assertRaises(ValueError): + unittest_pb2.TestAllTypes(repeated_nested_enum='FOO') + # Class to test proto3-only features/behavior (updated field presence & enums) class Proto3Test(unittest.TestCase): + # Utility method for comparing equality with a map. + def assertMapIterEquals(self, map_iter, dict_value): + # Avoid mutating caller's copy. + dict_value = dict(dict_value) + + for k, v in map_iter: + self.assertEqual(v, dict_value[k]) + del dict_value[k] + + self.assertEqual({}, dict_value) + def testFieldPresence(self): message = unittest_proto3_arena_pb2.TestAllTypes() # We can't test presence of non-repeated, non-submessage fields. with self.assertRaises(ValueError): - message.HasField("optional_int32") + message.HasField('optional_int32') with self.assertRaises(ValueError): - message.HasField("optional_float") + message.HasField('optional_float') with self.assertRaises(ValueError): - message.HasField("optional_string") + message.HasField('optional_string') with self.assertRaises(ValueError): - message.HasField("optional_bool") + message.HasField('optional_bool') # But we can still test presence of submessage fields. - self.assertFalse(message.HasField("optional_nested_message")) + self.assertFalse(message.HasField('optional_nested_message')) # As with proto2, we can't test presence of fields that don't exist, or # repeated fields. with self.assertRaises(ValueError): - message.HasField("field_doesnt_exist") + message.HasField('field_doesnt_exist') with self.assertRaises(ValueError): - message.HasField("repeated_int32") + message.HasField('repeated_int32') with self.assertRaises(ValueError): - message.HasField("repeated_nested_message") + message.HasField('repeated_nested_message') # Fields should default to their type-specific default. self.assertEqual(0, message.optional_int32) self.assertEqual(0, message.optional_float) - self.assertEqual("", message.optional_string) + self.assertEqual('', message.optional_string) self.assertEqual(False, message.optional_bool) self.assertEqual(0, message.optional_nested_message.bb) # Setting a submessage should still return proper presence information. message.optional_nested_message.bb = 0 - self.assertTrue(message.HasField("optional_nested_message")) + self.assertTrue(message.HasField('optional_nested_message')) # Set the fields to non-default values. message.optional_int32 = 5 message.optional_float = 1.1 - message.optional_string = "abc" + message.optional_string = 'abc' message.optional_bool = True message.optional_nested_message.bb = 15 # Clearing the fields unsets them and resets their value to default. - message.ClearField("optional_int32") - message.ClearField("optional_float") - message.ClearField("optional_string") - message.ClearField("optional_bool") - message.ClearField("optional_nested_message") + message.ClearField('optional_int32') + message.ClearField('optional_float') + message.ClearField('optional_string') + message.ClearField('optional_bool') + message.ClearField('optional_nested_message') self.assertEqual(0, message.optional_int32) self.assertEqual(0, message.optional_float) - self.assertEqual("", message.optional_string) + self.assertEqual('', message.optional_string) self.assertEqual(False, message.optional_bool) self.assertEqual(0, message.optional_nested_message.bb) @@ -1113,6 +1197,393 @@ class Proto3Test(unittest.TestCase): self.assertEqual(1234567, m2.optional_nested_enum) self.assertEqual(7654321, m2.repeated_nested_enum[0]) + # Map isn't really a proto3-only feature. But there is no proto2 equivalent + # of google/protobuf/map_unittest.proto right now, so it's not easy to + # test both with the same test like we do for the other proto2/proto3 tests. + # (google/protobuf/map_protobuf_unittest.proto is very different in the set + # of messages and fields it contains). + def testScalarMapDefaults(self): + msg = map_unittest_pb2.TestMap() + + # Scalars start out unset. + self.assertFalse(-123 in msg.map_int32_int32) + self.assertFalse(-2**33 in msg.map_int64_int64) + self.assertFalse(123 in msg.map_uint32_uint32) + self.assertFalse(2**33 in msg.map_uint64_uint64) + self.assertFalse('abc' in msg.map_string_string) + self.assertFalse(888 in msg.map_int32_enum) + + # Accessing an unset key returns the default. + self.assertEqual(0, msg.map_int32_int32[-123]) + self.assertEqual(0, msg.map_int64_int64[-2**33]) + self.assertEqual(0, msg.map_uint32_uint32[123]) + self.assertEqual(0, msg.map_uint64_uint64[2**33]) + self.assertEqual('', msg.map_string_string['abc']) + self.assertEqual(0, msg.map_int32_enum[888]) + + # It also sets the value in the map + self.assertTrue(-123 in msg.map_int32_int32) + self.assertTrue(-2**33 in msg.map_int64_int64) + self.assertTrue(123 in msg.map_uint32_uint32) + self.assertTrue(2**33 in msg.map_uint64_uint64) + self.assertTrue('abc' in msg.map_string_string) + self.assertTrue(888 in msg.map_int32_enum) + + self.assertTrue(isinstance(msg.map_string_string['abc'], unicode)) + + # Accessing an unset key still throws TypeError of the type of the key + # is incorrect. + with self.assertRaises(TypeError): + msg.map_string_string[123] + + self.assertFalse(123 in msg.map_string_string) + + def testMapGet(self): + # Need to test that get() properly returns the default, even though the dict + # has defaultdict-like semantics. + msg = map_unittest_pb2.TestMap() + + self.assertIsNone(msg.map_int32_int32.get(5)) + self.assertEquals(10, msg.map_int32_int32.get(5, 10)) + self.assertIsNone(msg.map_int32_int32.get(5)) + + msg.map_int32_int32[5] = 15 + self.assertEquals(15, msg.map_int32_int32.get(5)) + + self.assertIsNone(msg.map_int32_foreign_message.get(5)) + self.assertEquals(10, msg.map_int32_foreign_message.get(5, 10)) + + submsg = msg.map_int32_foreign_message[5] + self.assertIs(submsg, msg.map_int32_foreign_message.get(5)) + + def testScalarMap(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_int32)) + self.assertFalse(5 in msg.map_int32_int32) + + msg.map_int32_int32[-123] = -456 + msg.map_int64_int64[-2**33] = -2**34 + msg.map_uint32_uint32[123] = 456 + msg.map_uint64_uint64[2**33] = 2**34 + msg.map_string_string['abc'] = '123' + msg.map_int32_enum[888] = 2 + + self.assertEqual([], msg.FindInitializationErrors()) + + self.assertEqual(1, len(msg.map_string_string)) + + # Bad key. + with self.assertRaises(TypeError): + msg.map_string_string[123] = '123' + + # Verify that trying to assign a bad key doesn't actually add a member to + # the map. + self.assertEqual(1, len(msg.map_string_string)) + + # Bad value. + with self.assertRaises(TypeError): + msg.map_string_string['123'] = 123 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + # Bad key. + with self.assertRaises(TypeError): + msg2.map_string_string[123] = '123' + + # Bad value. + with self.assertRaises(TypeError): + msg2.map_string_string['123'] = 123 + + self.assertEqual(-456, msg2.map_int32_int32[-123]) + self.assertEqual(-2**34, msg2.map_int64_int64[-2**33]) + self.assertEqual(456, msg2.map_uint32_uint32[123]) + self.assertEqual(2**34, msg2.map_uint64_uint64[2**33]) + self.assertEqual('123', msg2.map_string_string['abc']) + self.assertEqual(2, msg2.map_int32_enum[888]) + + def testStringUnicodeConversionInMap(self): + msg = map_unittest_pb2.TestMap() + + unicode_obj = u'\u1234' + bytes_obj = unicode_obj.encode('utf8') + + msg.map_string_string[bytes_obj] = bytes_obj + + (key, value) = msg.map_string_string.items()[0] + + self.assertEqual(key, unicode_obj) + self.assertEqual(value, unicode_obj) + + self.assertTrue(isinstance(key, unicode)) + self.assertTrue(isinstance(value, unicode)) + + def testMessageMap(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_foreign_message)) + self.assertFalse(5 in msg.map_int32_foreign_message) + + msg.map_int32_foreign_message[123] + # get_or_create() is an alias for getitem. + msg.map_int32_foreign_message.get_or_create(-456) + + self.assertEqual(2, len(msg.map_int32_foreign_message)) + self.assertIn(123, msg.map_int32_foreign_message) + self.assertIn(-456, msg.map_int32_foreign_message) + self.assertEqual(2, len(msg.map_int32_foreign_message)) + + # Bad key. + with self.assertRaises(TypeError): + msg.map_int32_foreign_message['123'] + + # Can't assign directly to submessage. + with self.assertRaises(ValueError): + msg.map_int32_foreign_message[999] = msg.map_int32_foreign_message[123] + + # Verify that trying to assign a bad key doesn't actually add a member to + # the map. + self.assertEqual(2, len(msg.map_int32_foreign_message)) + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(2, len(msg2.map_int32_foreign_message)) + self.assertIn(123, msg2.map_int32_foreign_message) + self.assertIn(-456, msg2.map_int32_foreign_message) + self.assertEqual(2, len(msg2.map_int32_foreign_message)) + + def testMergeFrom(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[12] = 34 + msg.map_int32_int32[56] = 78 + msg.map_int64_int64[22] = 33 + msg.map_int32_foreign_message[111].c = 5 + msg.map_int32_foreign_message[222].c = 10 + + msg2 = map_unittest_pb2.TestMap() + msg2.map_int32_int32[12] = 55 + msg2.map_int64_int64[88] = 99 + msg2.map_int32_foreign_message[222].c = 15 + + msg2.MergeFrom(msg) + + self.assertEqual(34, msg2.map_int32_int32[12]) + self.assertEqual(78, msg2.map_int32_int32[56]) + self.assertEqual(33, msg2.map_int64_int64[22]) + self.assertEqual(99, msg2.map_int64_int64[88]) + self.assertEqual(5, msg2.map_int32_foreign_message[111].c) + self.assertEqual(10, msg2.map_int32_foreign_message[222].c) + + # Verify that there is only one entry per key, even though the MergeFrom + # may have internally created multiple entries for a single key in the + # list representation. + as_dict = {} + for key in msg2.map_int32_foreign_message: + self.assertFalse(key in as_dict) + as_dict[key] = msg2.map_int32_foreign_message[key].c + + self.assertEqual({111: 5, 222: 10}, as_dict) + + # Special case: test that delete of item really removes the item, even if + # there might have physically been duplicate keys due to the previous merge. + # This is only a special case for the C++ implementation which stores the + # map as an array. + del msg2.map_int32_int32[12] + self.assertFalse(12 in msg2.map_int32_int32) + + del msg2.map_int32_foreign_message[222] + self.assertFalse(222 in msg2.map_int32_foreign_message) + + def testIntegerMapWithLongs(self): + msg = map_unittest_pb2.TestMap() + msg.map_int32_int32[long(-123)] = long(-456) + msg.map_int64_int64[long(-2**33)] = long(-2**34) + msg.map_uint32_uint32[long(123)] = long(456) + msg.map_uint64_uint64[long(2**33)] = long(2**34) + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(-456, msg2.map_int32_int32[-123]) + self.assertEqual(-2**34, msg2.map_int64_int64[-2**33]) + self.assertEqual(456, msg2.map_uint32_uint32[123]) + self.assertEqual(2**34, msg2.map_uint64_uint64[2**33]) + + def testMapAssignmentCausesPresence(self): + msg = map_unittest_pb2.TestMapSubmessage() + msg.test_map.map_int32_int32[123] = 456 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMapSubmessage() + msg2.ParseFromString(serialized) + + self.assertEqual(msg, msg2) + + # Now test that various mutations of the map properly invalidate the + # cached size of the submessage. + msg.test_map.map_int32_int32[888] = 999 + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_int32.clear() + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + def testMapAssignmentCausesPresenceForSubmessages(self): + msg = map_unittest_pb2.TestMapSubmessage() + msg.test_map.map_int32_foreign_message[123].c = 5 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMapSubmessage() + msg2.ParseFromString(serialized) + + self.assertEqual(msg, msg2) + + # Now test that various mutations of the map properly invalidate the + # cached size of the submessage. + msg.test_map.map_int32_foreign_message[888].c = 7 + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_foreign_message[888].MergeFrom( + msg.test_map.map_int32_foreign_message[123]) + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + msg.test_map.map_int32_foreign_message.clear() + serialized = msg.SerializeToString() + msg2.ParseFromString(serialized) + self.assertEqual(msg, msg2) + + def testModifyMapWhileIterating(self): + msg = map_unittest_pb2.TestMap() + + string_string_iter = iter(msg.map_string_string) + int32_foreign_iter = iter(msg.map_int32_foreign_message) + + msg.map_string_string['abc'] = '123' + msg.map_int32_foreign_message[5].c = 5 + + with self.assertRaises(RuntimeError): + for key in string_string_iter: + pass + + with self.assertRaises(RuntimeError): + for key in int32_foreign_iter: + pass + + def testSubmessageMap(self): + msg = map_unittest_pb2.TestMap() + + submsg = msg.map_int32_foreign_message[111] + self.assertIs(submsg, msg.map_int32_foreign_message[111]) + self.assertTrue(isinstance(submsg, unittest_pb2.ForeignMessage)) + + submsg.c = 5 + + serialized = msg.SerializeToString() + msg2 = map_unittest_pb2.TestMap() + msg2.ParseFromString(serialized) + + self.assertEqual(5, msg2.map_int32_foreign_message[111].c) + + # Doesn't allow direct submessage assignment. + with self.assertRaises(ValueError): + msg.map_int32_foreign_message[88] = unittest_pb2.ForeignMessage() + + def testMapIteration(self): + msg = map_unittest_pb2.TestMap() + + for k, v in msg.map_int32_int32.iteritems(): + # Should not be reached. + self.assertTrue(False) + + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + self.assertEqual(3, len(msg.map_int32_int32)) + + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(msg.map_int32_int32.iteritems(), matching_dict) + + def testMapIterationClearMessage(self): + # Iterator needs to work even if message and map are deleted. + msg = map_unittest_pb2.TestMap() + + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + + it = msg.map_int32_int32.iteritems() + del msg + + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(it, matching_dict) + + def testMapConstruction(self): + msg = map_unittest_pb2.TestMap(map_int32_int32={1: 2, 3: 4}) + self.assertEqual(2, msg.map_int32_int32[1]) + self.assertEqual(4, msg.map_int32_int32[3]) + + msg = map_unittest_pb2.TestMap( + map_int32_foreign_message={3: unittest_pb2.ForeignMessage(c=5)}) + self.assertEqual(5, msg.map_int32_foreign_message[3].c) + + def testMapValidAfterFieldCleared(self): + # Map needs to work even if field is cleared. + # For the C++ implementation this tests the correctness of + # ScalarMapContainer::Release() + msg = map_unittest_pb2.TestMap() + map = msg.map_int32_int32 + + map[2] = 4 + map[3] = 6 + map[4] = 8 + + msg.ClearField('map_int32_int32') + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(map.iteritems(), matching_dict) + + def testMapIterValidAfterFieldCleared(self): + # Map iterator needs to work even if field is cleared. + # For the C++ implementation this tests the correctness of + # ScalarMapContainer::Release() + msg = map_unittest_pb2.TestMap() + + msg.map_int32_int32[2] = 4 + msg.map_int32_int32[3] = 6 + msg.map_int32_int32[4] = 8 + + it = msg.map_int32_int32.iteritems() + + msg.ClearField('map_int32_int32') + matching_dict = {2: 4, 3: 6, 4: 8} + self.assertMapIterEquals(it, matching_dict) + + def testMapDelete(self): + msg = map_unittest_pb2.TestMap() + + self.assertEqual(0, len(msg.map_int32_int32)) + + msg.map_int32_int32[4] = 6 + self.assertEqual(1, len(msg.map_int32_int32)) + + with self.assertRaises(KeyError): + del msg.map_int32_int32[88] + + del msg.map_int32_int32[4] + self.assertEqual(0, len(msg.map_int32_int32)) + + class ValidTypeNamesTest(unittest.TestCase): diff --git a/python/google/protobuf/internal/proto_builder_test.py b/python/google/protobuf/internal/proto_builder_test.py index b1e57f35..edaf3fa3 100644 --- a/python/google/protobuf/internal/proto_builder_test.py +++ b/python/google/protobuf/internal/proto_builder_test.py @@ -32,6 +32,7 @@ """Tests for google.protobuf.proto_builder.""" +import collections import unittest from google.protobuf import descriptor_pb2 @@ -43,10 +44,11 @@ from google.protobuf import text_format class ProtoBuilderTest(unittest.TestCase): def setUp(self): - self._fields = { - 'foo': descriptor_pb2.FieldDescriptorProto.TYPE_INT64, - 'bar': descriptor_pb2.FieldDescriptorProto.TYPE_STRING, - } + self.ordered_fields = collections.OrderedDict([ + ('foo', descriptor_pb2.FieldDescriptorProto.TYPE_INT64), + ('bar', descriptor_pb2.FieldDescriptorProto.TYPE_STRING), + ]) + self._fields = dict(self.ordered_fields) def testMakeSimpleProtoClass(self): """Test that we can create a proto class.""" @@ -59,6 +61,17 @@ class ProtoBuilderTest(unittest.TestCase): self.assertMultiLineEqual( 'bar: "asdf"\nfoo: 12345\n', text_format.MessageToString(proto)) + def testOrderedFields(self): + """Test that the field order is maintained when given an OrderedDict.""" + proto_cls = proto_builder.MakeSimpleProtoClass( + self.ordered_fields, + full_name='net.proto2.python.public.proto_builder_test.OrderedTest') + proto = proto_cls() + proto.foo = 12345 + proto.bar = 'asdf' + self.assertMultiLineEqual( + 'foo: 12345\nbar: "asdf"\n', text_format.MessageToString(proto)) + def testMakeSameProtoClassTwice(self): """Test that the DescriptorPool is used.""" pool = descriptor_pool.DescriptorPool() diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py index 54f584ae..ca9f7675 100755 --- a/python/google/protobuf/internal/python_message.py +++ b/python/google/protobuf/internal/python_message.py @@ -61,9 +61,11 @@ if sys.version_info[0] < 3: except ImportError: from StringIO import StringIO as BytesIO import copy_reg as copyreg + _basestring = basestring else: from io import BytesIO import copyreg + _basestring = str import struct import weakref @@ -77,6 +79,7 @@ from google.protobuf.internal import type_checkers from google.protobuf.internal import wire_format from google.protobuf import descriptor as descriptor_mod from google.protobuf import message as message_mod +from google.protobuf import symbol_database from google.protobuf import text_format _FieldDescriptor = descriptor_mod.FieldDescriptor @@ -101,6 +104,7 @@ def InitMessage(descriptor, cls): for field in descriptor.fields: _AttachFieldHelpers(cls, field) + descriptor._concrete_class = cls # pylint: disable=protected-access _AddEnumValues(descriptor, cls) _AddInitMethod(descriptor, cls) _AddPropertiesForFields(descriptor, cls) @@ -198,12 +202,37 @@ def _IsMessageSetExtension(field): field.label == _FieldDescriptor.LABEL_OPTIONAL) +def _IsMapField(field): + return (field.type == _FieldDescriptor.TYPE_MESSAGE and + field.message_type.has_options and + field.message_type.GetOptions().map_entry) + + +def _IsMessageMapField(field): + value_type = field.message_type.fields_by_name["value"] + return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE + + def _AttachFieldHelpers(cls, field_descriptor): is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED) - is_packed = (field_descriptor.has_options and - field_descriptor.GetOptions().packed) - - if _IsMessageSetExtension(field_descriptor): + is_packable = (is_repeated and + wire_format.IsTypePackable(field_descriptor.type)) + if not is_packable: + is_packed = False + elif field_descriptor.containing_type.syntax == "proto2": + is_packed = (field_descriptor.has_options and + field_descriptor.GetOptions().packed) + else: + has_packed_false = (field_descriptor.has_options and + field_descriptor.GetOptions().HasField("packed") and + field_descriptor.GetOptions().packed == False) + is_packed = not has_packed_false + is_map_entry = _IsMapField(field_descriptor) + + if is_map_entry: + field_encoder = encoder.MapEncoder(field_descriptor) + sizer = encoder.MapSizer(field_descriptor) + elif _IsMessageSetExtension(field_descriptor): field_encoder = encoder.MessageSetItemEncoder(field_descriptor.number) sizer = encoder.MessageSetItemSizer(field_descriptor.number) else: @@ -228,9 +257,16 @@ def _AttachFieldHelpers(cls, field_descriptor): if field_descriptor.containing_oneof is not None: oneof_descriptor = field_descriptor - field_decoder = type_checkers.TYPE_TO_DECODER[decode_type]( - field_descriptor.number, is_repeated, is_packed, - field_descriptor, field_descriptor._default_constructor) + if is_map_entry: + is_message_map = _IsMessageMapField(field_descriptor) + + field_decoder = decoder.MapDecoder( + field_descriptor, _GetInitializeDefaultForMap(field_descriptor), + is_message_map) + else: + field_decoder = type_checkers.TYPE_TO_DECODER[decode_type]( + field_descriptor.number, is_repeated, is_packed, + field_descriptor, field_descriptor._default_constructor) cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor) @@ -265,6 +301,26 @@ def _AddEnumValues(descriptor, cls): setattr(cls, enum_value.name, enum_value.number) +def _GetInitializeDefaultForMap(field): + if field.label != _FieldDescriptor.LABEL_REPEATED: + raise ValueError('map_entry set on non-repeated field %s' % ( + field.name)) + fields_by_name = field.message_type.fields_by_name + key_checker = type_checkers.GetTypeChecker(fields_by_name['key']) + + value_field = fields_by_name['value'] + if _IsMessageMapField(field): + def MakeMessageMapDefault(message): + return containers.MessageMap( + message._listener_for_children, value_field.message_type, key_checker) + return MakeMessageMapDefault + else: + value_checker = type_checkers.GetTypeChecker(value_field) + def MakePrimitiveMapDefault(message): + return containers.ScalarMap( + message._listener_for_children, key_checker, value_checker) + return MakePrimitiveMapDefault + def _DefaultValueConstructorForField(field): """Returns a function which returns a default value for a field. @@ -279,6 +335,9 @@ def _DefaultValueConstructorForField(field): value may refer back to |message| via a weak reference. """ + if _IsMapField(field): + return _GetInitializeDefaultForMap(field) + if field.label == _FieldDescriptor.LABEL_REPEATED: if field.has_default_value and field.default_value != []: raise ValueError('Repeated field default value not empty list: %s' % ( @@ -329,7 +388,22 @@ def _ReraiseTypeErrorWithFieldName(message_name, field_name): def _AddInitMethod(message_descriptor, cls): """Adds an __init__ method to cls.""" - fields = message_descriptor.fields + + def _GetIntegerEnumValue(enum_type, value): + """Convert a string or integer enum value to an integer. + + If the value is a string, it is converted to the enum value in + enum_type with the same name. If the value is not a string, it's + returned as-is. (No conversion or bounds-checking is done.) + """ + if isinstance(value, _basestring): + try: + return enum_type.values_by_name[value].number + except KeyError: + raise ValueError('Enum type %s: unknown label "%s"' % ( + enum_type.full_name, value)) + return value + def init(self, **kwargs): self._cached_byte_size = 0 self._cached_byte_size_dirty = len(kwargs) > 0 @@ -352,19 +426,37 @@ def _AddInitMethod(message_descriptor, cls): if field.label == _FieldDescriptor.LABEL_REPEATED: copy = field._default_constructor(self) if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite - for val in field_value: - copy.add().MergeFrom(val) + if _IsMapField(field): + if _IsMessageMapField(field): + for key in field_value: + copy[key].MergeFrom(field_value[key]) + else: + copy.update(field_value) + else: + for val in field_value: + if isinstance(val, dict): + copy.add(**val) + else: + copy.add().MergeFrom(val) else: # Scalar + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + field_value = [_GetIntegerEnumValue(field.enum_type, val) + for val in field_value] copy.extend(field_value) self._fields[field] = copy elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: copy = field._default_constructor(self) + new_val = field_value + if isinstance(field_value, dict): + new_val = field.message_type._concrete_class(**field_value) try: - copy.MergeFrom(field_value) + copy.MergeFrom(new_val) except TypeError: _ReraiseTypeErrorWithFieldName(message_descriptor.name, field_name) self._fields[field] = copy else: + if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM: + field_value = _GetIntegerEnumValue(field.enum_type, field_value) try: setattr(self, field_name, field_value) except TypeError: @@ -758,6 +850,26 @@ def _AddHasExtensionMethod(cls): return extension_handle in self._fields cls.HasExtension = HasExtension +def _UnpackAny(msg): + type_url = msg.type_url + db = symbol_database.Default() + + if not type_url: + return None + + # TODO(haberman): For now we just strip the hostname. Better logic will be + # required. + type_name = type_url.split("/")[-1] + descriptor = db.pool.FindMessageTypeByName(type_name) + + if descriptor is None: + return None + + message_class = db.GetPrototype(descriptor) + message = message_class() + + message.ParseFromString(msg.value) + return message def _AddEqualsMethod(message_descriptor, cls): """Helper for _AddMessageMethods().""" @@ -769,6 +881,12 @@ def _AddEqualsMethod(message_descriptor, cls): if self is other: return True + if self.DESCRIPTOR.full_name == "google.protobuf.Any": + any_a = _UnpackAny(self) + any_b = _UnpackAny(other) + if any_a and any_b: + return any_a == any_b + if not self.ListFields() == other.ListFields(): return False @@ -961,6 +1079,9 @@ def _AddIsInitializedMethod(message_descriptor, cls): for field, value in list(self._fields.items()): # dict can change size! if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: if field.label == _FieldDescriptor.LABEL_REPEATED: + if (field.message_type.has_options and + field.message_type.GetOptions().map_entry): + continue for element in value: if not element.IsInitialized(): if errors is not None: @@ -996,16 +1117,26 @@ def _AddIsInitializedMethod(message_descriptor, cls): else: name = field.name - if field.label == _FieldDescriptor.LABEL_REPEATED: + if _IsMapField(field): + if _IsMessageMapField(field): + for key in value: + element = value[key] + prefix = "%s[%d]." % (name, key) + sub_errors = element.FindInitializationErrors() + errors += [prefix + error for error in sub_errors] + else: + # ScalarMaps can't have any initialization errors. + pass + elif field.label == _FieldDescriptor.LABEL_REPEATED: for i in xrange(len(value)): element = value[i] prefix = "%s[%d]." % (name, i) sub_errors = element.FindInitializationErrors() - errors += [ prefix + error for error in sub_errors ] + errors += [prefix + error for error in sub_errors] else: prefix = name + "." sub_errors = value.FindInitializationErrors() - errors += [ prefix + error for error in sub_errors ] + errors += [prefix + error for error in sub_errors] return errors diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py index ae79c78b..4eca4989 100755 --- a/python/google/protobuf/internal/reflection_test.py +++ b/python/google/protobuf/internal/reflection_test.py @@ -39,8 +39,8 @@ import copy import gc import operator import struct -import unittest +import unittest from google.protobuf import unittest_import_pb2 from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 @@ -1798,8 +1798,8 @@ class ReflectionTest(unittest.TestCase): def testBadArguments(self): # Some of these assertions used to segfault. from google.protobuf.pyext import _message - self.assertRaises(TypeError, _message.Message._GetFieldDescriptor, 3) - self.assertRaises(TypeError, _message.Message._GetExtensionDescriptor, 42) + self.assertRaises(TypeError, _message.default_pool.FindFieldByName, 3) + self.assertRaises(TypeError, _message.default_pool.FindExtensionByName, 42) self.assertRaises(TypeError, unittest_pb2.TestAllTypes().__getattribute__, 42) diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py index de462124..9967255a 100755 --- a/python/google/protobuf/internal/service_reflection_test.py +++ b/python/google/protobuf/internal/service_reflection_test.py @@ -35,7 +35,6 @@ __author__ = 'petar@google.com (Petar Petrov)' import unittest - from google.protobuf import unittest_pb2 from google.protobuf import service_reflection from google.protobuf import service @@ -81,7 +80,7 @@ class FooUnitTest(unittest.TestCase): self.assertEqual('Method Bar not implemented.', rpc_controller.failure_message) self.assertEqual(None, self.callback_response) - + class MyServiceImpl(unittest_pb2.TestService): def Foo(self, rpc_controller, request, done): self.foo_called = True diff --git a/python/google/protobuf/internal/symbol_database_test.py b/python/google/protobuf/internal/symbol_database_test.py index c888aff7..80b83bc2 100644 --- a/python/google/protobuf/internal/symbol_database_test.py +++ b/python/google/protobuf/internal/symbol_database_test.py @@ -33,7 +33,6 @@ """Tests for google.protobuf.symbol_database.""" import unittest - from google.protobuf import unittest_pb2 from google.protobuf import symbol_database diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py index d84e3836..0cbdbad9 100755 --- a/python/google/protobuf/internal/test_util.py +++ b/python/google/protobuf/internal/test_util.py @@ -75,7 +75,8 @@ def SetAllNonLazyFields(message): message.optional_string = u'115' message.optional_bytes = b'116' - message.optionalgroup.a = 117 + if IsProto2(message): + message.optionalgroup.a = 117 message.optional_nested_message.bb = 118 message.optional_foreign_message.c = 119 message.optional_import_message.d = 120 @@ -109,7 +110,8 @@ def SetAllNonLazyFields(message): message.repeated_string.append(u'215') message.repeated_bytes.append(b'216') - message.repeatedgroup.add().a = 217 + if IsProto2(message): + message.repeatedgroup.add().a = 217 message.repeated_nested_message.add().bb = 218 message.repeated_foreign_message.add().c = 219 message.repeated_import_message.add().d = 220 @@ -140,7 +142,8 @@ def SetAllNonLazyFields(message): message.repeated_string.append(u'315') message.repeated_bytes.append(b'316') - message.repeatedgroup.add().a = 317 + if IsProto2(message): + message.repeatedgroup.add().a = 317 message.repeated_nested_message.add().bb = 318 message.repeated_foreign_message.add().c = 319 message.repeated_import_message.add().d = 320 @@ -396,7 +399,8 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertTrue(message.HasField('optional_string')) test_case.assertTrue(message.HasField('optional_bytes')) - test_case.assertTrue(message.HasField('optionalgroup')) + if IsProto2(message): + test_case.assertTrue(message.HasField('optionalgroup')) test_case.assertTrue(message.HasField('optional_nested_message')) test_case.assertTrue(message.HasField('optional_foreign_message')) test_case.assertTrue(message.HasField('optional_import_message')) @@ -430,7 +434,8 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual('115', message.optional_string) test_case.assertEqual(b'116', message.optional_bytes) - test_case.assertEqual(117, message.optionalgroup.a) + if IsProto2(message): + test_case.assertEqual(117, message.optionalgroup.a) test_case.assertEqual(118, message.optional_nested_message.bb) test_case.assertEqual(119, message.optional_foreign_message.c) test_case.assertEqual(120, message.optional_import_message.d) @@ -463,7 +468,8 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual(2, len(message.repeated_string)) test_case.assertEqual(2, len(message.repeated_bytes)) - test_case.assertEqual(2, len(message.repeatedgroup)) + if IsProto2(message): + test_case.assertEqual(2, len(message.repeatedgroup)) test_case.assertEqual(2, len(message.repeated_nested_message)) test_case.assertEqual(2, len(message.repeated_foreign_message)) test_case.assertEqual(2, len(message.repeated_import_message)) @@ -491,7 +497,8 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual('215', message.repeated_string[0]) test_case.assertEqual(b'216', message.repeated_bytes[0]) - test_case.assertEqual(217, message.repeatedgroup[0].a) + if IsProto2(message): + test_case.assertEqual(217, message.repeatedgroup[0].a) test_case.assertEqual(218, message.repeated_nested_message[0].bb) test_case.assertEqual(219, message.repeated_foreign_message[0].c) test_case.assertEqual(220, message.repeated_import_message[0].d) @@ -521,7 +528,8 @@ def ExpectAllFieldsSet(test_case, message): test_case.assertEqual('315', message.repeated_string[1]) test_case.assertEqual(b'316', message.repeated_bytes[1]) - test_case.assertEqual(317, message.repeatedgroup[1].a) + if IsProto2(message): + test_case.assertEqual(317, message.repeatedgroup[1].a) test_case.assertEqual(318, message.repeated_nested_message[1].bb) test_case.assertEqual(319, message.repeated_foreign_message[1].c) test_case.assertEqual(320, message.repeated_import_message[1].d) diff --git a/python/google/protobuf/internal/text_encoding_test.py b/python/google/protobuf/internal/text_encoding_test.py index 27896b94..5df13b78 100755 --- a/python/google/protobuf/internal/text_encoding_test.py +++ b/python/google/protobuf/internal/text_encoding_test.py @@ -33,7 +33,6 @@ """Tests for google.protobuf.text_encoding.""" import unittest - from google.protobuf import text_encoding TEST_VALUES = [ diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index bf7e06ee..06bd1ee5 100755 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -37,8 +37,10 @@ __author__ = 'kenton@google.com (Kenton Varda)' import re import unittest +import unittest from google.protobuf.internal import _parameterized +from google.protobuf import map_unittest_pb2 from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 from google.protobuf import unittest_proto3_arena_pb2 @@ -309,31 +311,6 @@ class TextFormatTest(TextFormatBase): r'"unknown_field".'), text_format.Parse, text, message) - def testParseGroupNotClosed(self, message_module): - message = message_module.TestAllTypes() - text = 'RepeatedGroup: <' - self.assertRaisesRegexp( - text_format.ParseError, '1:16 : Expected ">".', - text_format.Parse, text, message) - - text = 'RepeatedGroup: {' - self.assertRaisesRegexp( - text_format.ParseError, '1:16 : Expected "}".', - text_format.Parse, text, message) - - def testParseEmptyGroup(self, message_module): - message = message_module.TestAllTypes() - text = 'OptionalGroup: {}' - text_format.Parse(text, message) - self.assertTrue(message.HasField('optionalgroup')) - - message.Clear() - - message = message_module.TestAllTypes() - text = 'OptionalGroup: <>' - text_format.Parse(text, message) - self.assertTrue(message.HasField('optionalgroup')) - def testParseBadEnumValue(self, message_module): message = message_module.TestAllTypes() text = 'optional_nested_enum: BARR' @@ -408,6 +385,14 @@ class TextFormatTest(TextFormatBase): # Ideally the schemas would be made more similar so these tests could pass. class OnlyWorksWithProto2RightNowTests(TextFormatBase): + def testPrintAllFieldsPointy(self, message_module): + message = unittest_pb2.TestAllTypes() + test_util.SetAllFields(message) + self.CompareToGoldenFile( + self.RemoveRedundantZeros( + text_format.MessageToString(message, pointy_brackets=True)), + 'text_format_unittest_data_pointy_oneof.txt') + def testParseGolden(self): golden_text = '\n'.join(self.ReadGolden('text_format_unittest_data.txt')) parsed_message = unittest_pb2.TestAllTypes() @@ -471,8 +456,49 @@ class OnlyWorksWithProto2RightNowTests(TextFormatBase): test_util.SetAllFields(message) self.assertEquals(message, parsed_message) + def testPrintMap(self): + message = map_unittest_pb2.TestMap() -# Tests of proto2-only features (MessageSet and extensions). + message.map_int32_int32[-123] = -456 + message.map_int64_int64[-2**33] = -2**34 + message.map_uint32_uint32[123] = 456 + message.map_uint64_uint64[2**33] = 2**34 + message.map_string_string["abc"] = "123" + message.map_int32_foreign_message[111].c = 5 + + # Maps are serialized to text format using their underlying repeated + # representation. + self.CompareToGoldenText( + text_format.MessageToString(message), + 'map_int32_int32 {\n' + ' key: -123\n' + ' value: -456\n' + '}\n' + 'map_int64_int64 {\n' + ' key: -8589934592\n' + ' value: -17179869184\n' + '}\n' + 'map_uint32_uint32 {\n' + ' key: 123\n' + ' value: 456\n' + '}\n' + 'map_uint64_uint64 {\n' + ' key: 8589934592\n' + ' value: 17179869184\n' + '}\n' + 'map_string_string {\n' + ' key: "abc"\n' + ' value: "123"\n' + '}\n' + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 5\n' + ' }\n' + '}\n') + + +# Tests of proto2-only features (MessageSet, extensions, etc.). class Proto2Tests(TextFormatBase): def testPrintMessageSet(self): @@ -620,6 +646,69 @@ class Proto2Tests(TextFormatBase): 'have multiple "optional_int32" fields.'), text_format.Parse, text, message) + def testParseGroupNotClosed(self): + message = unittest_pb2.TestAllTypes() + text = 'RepeatedGroup: <' + self.assertRaisesRegexp( + text_format.ParseError, '1:16 : Expected ">".', + text_format.Parse, text, message) + text = 'RepeatedGroup: {' + self.assertRaisesRegexp( + text_format.ParseError, '1:16 : Expected "}".', + text_format.Parse, text, message) + + def testParseEmptyGroup(self): + message = unittest_pb2.TestAllTypes() + text = 'OptionalGroup: {}' + text_format.Parse(text, message) + self.assertTrue(message.HasField('optionalgroup')) + + message.Clear() + + message = unittest_pb2.TestAllTypes() + text = 'OptionalGroup: <>' + text_format.Parse(text, message) + self.assertTrue(message.HasField('optionalgroup')) + + # Maps aren't really proto2-only, but our test schema only has maps for + # proto2. + def testParseMap(self): + text = ('map_int32_int32 {\n' + ' key: -123\n' + ' value: -456\n' + '}\n' + 'map_int64_int64 {\n' + ' key: -8589934592\n' + ' value: -17179869184\n' + '}\n' + 'map_uint32_uint32 {\n' + ' key: 123\n' + ' value: 456\n' + '}\n' + 'map_uint64_uint64 {\n' + ' key: 8589934592\n' + ' value: 17179869184\n' + '}\n' + 'map_string_string {\n' + ' key: "abc"\n' + ' value: "123"\n' + '}\n' + 'map_int32_foreign_message {\n' + ' key: 111\n' + ' value {\n' + ' c: 5\n' + ' }\n' + '}\n') + message = map_unittest_pb2.TestMap() + text_format.Parse(text, message) + + self.assertEqual(-456, message.map_int32_int32[-123]) + self.assertEqual(-2**34, message.map_int64_int64[-2**33]) + self.assertEqual(456, message.map_uint32_uint32[123]) + self.assertEqual(2**34, message.map_uint64_uint64[2**33]) + self.assertEqual("123", message.map_string_string["abc"]) + self.assertEqual(5, message.map_int32_foreign_message[111].c) + class TokenizerTest(unittest.TestCase): diff --git a/python/google/protobuf/internal/type_checkers.py b/python/google/protobuf/internal/type_checkers.py index 76c056c4..f20e526a 100755 --- a/python/google/protobuf/internal/type_checkers.py +++ b/python/google/protobuf/internal/type_checkers.py @@ -129,6 +129,9 @@ class IntValueChecker(object): proposed_value = self._TYPE(proposed_value) return proposed_value + def DefaultValue(self): + return 0 + class EnumValueChecker(object): @@ -146,6 +149,9 @@ class EnumValueChecker(object): raise ValueError('Unknown enum value: %d' % proposed_value) return proposed_value + def DefaultValue(self): + return self._enum_type.values[0].number + class UnicodeValueChecker(object): @@ -171,6 +177,9 @@ class UnicodeValueChecker(object): (proposed_value)) return proposed_value + def DefaultValue(self): + return u"" + class Int32ValueChecker(IntValueChecker): # We're sure to use ints instead of longs here since comparison may be more diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py index 9337ae8a..1b81ae79 100755 --- a/python/google/protobuf/internal/unknown_fields_test.py +++ b/python/google/protobuf/internal/unknown_fields_test.py @@ -36,7 +36,6 @@ __author__ = 'bohdank@google.com (Bohdan Koval)' import unittest - from google.protobuf import unittest_mset_pb2 from google.protobuf import unittest_pb2 from google.protobuf import unittest_proto3_arena_pb2 diff --git a/python/google/protobuf/internal/wire_format_test.py b/python/google/protobuf/internal/wire_format_test.py index 5cd7fcb9..78dc1167 100755 --- a/python/google/protobuf/internal/wire_format_test.py +++ b/python/google/protobuf/internal/wire_format_test.py @@ -35,7 +35,6 @@ __author__ = 'robinson@google.com (Will Robinson)' import unittest - from google.protobuf import message from google.protobuf.internal import wire_format diff --git a/python/google/protobuf/proto_builder.py b/python/google/protobuf/proto_builder.py index 1fa28f1a..7489cf63 100644 --- a/python/google/protobuf/proto_builder.py +++ b/python/google/protobuf/proto_builder.py @@ -30,6 +30,7 @@ """Dynamic Protobuf class creator.""" +import collections import hashlib import os @@ -59,7 +60,9 @@ def MakeSimpleProtoClass(fields, full_name, pool=None): Note: this doesn't validate field names! Args: - fields: dict of {name: field_type} mappings for each field in the proto. + fields: dict of {name: field_type} mappings for each field in the proto. If + this is an OrderedDict the order will be maintained, otherwise the + fields will be sorted by name. full_name: str, the fully-qualified name of the proto type. pool: optional DescriptorPool instance. Returns: @@ -73,12 +76,19 @@ def MakeSimpleProtoClass(fields, full_name, pool=None): # The factory's DescriptorPool doesn't know about this class yet. pass + # Get a list of (name, field_type) tuples from the fields dict. If fields was + # an OrderedDict we keep the order, but otherwise we sort the field to ensure + # consistent ordering. + field_items = fields.items() + if not isinstance(fields, collections.OrderedDict): + field_items = sorted(field_items) + # Use a consistent file name that is unlikely to conflict with any imported # proto files. fields_hash = hashlib.sha1() - for f_name, f_type in sorted(fields.items()): - fields_hash.update(f_name.encode('utf8')) - fields_hash.update(str(f_type).encode('utf8')) + for f_name, f_type in field_items: + fields_hash.update(f_name.encode('utf-8')) + fields_hash.update(str(f_type).encode('utf-8')) proto_file_name = fields_hash.hexdigest() + '.proto' package, name = full_name.rsplit('.', 1) @@ -87,7 +97,7 @@ def MakeSimpleProtoClass(fields, full_name, pool=None): file_proto.package = package desc_proto = file_proto.message_type.add() desc_proto.name = name - for f_number, (f_name, f_type) in enumerate(sorted(fields.items()), 1): + for f_number, (f_name, f_type) in enumerate(field_items, 1): field_proto = desc_proto.field.add() field_proto.name = f_name field_proto.number = f_number diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc index e77d0bb9..2160757b 100644 --- a/python/google/protobuf/pyext/descriptor.cc +++ b/python/google/protobuf/pyext/descriptor.cc @@ -43,8 +43,6 @@ #include #include -#define C(str) const_cast(str) - #if PY_MAJOR_VERSION >= 3 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize #define PyString_Check PyUnicode_Check @@ -257,8 +255,14 @@ namespace descriptor { // Creates or retrieve a Python descriptor of the specified type. // Objects are interned: the same descriptor will return the same object if it // was kept alive. +// 'was_created' is an optional pointer to a bool, and is set to true if a new +// object was allocated. // Always return a new reference. -PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor) { +PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor, + bool* was_created) { + if (was_created) { + *was_created = false; + } if (descriptor == NULL) { PyErr_BadInternalCall(); return NULL; @@ -283,6 +287,9 @@ PyObject* NewInternedDescriptor(PyTypeObject* type, const void* descriptor) { GetDescriptorPool()->interned_descriptors->insert( std::make_pair(descriptor, reinterpret_cast(py_descriptor))); + if (was_created) { + *was_created = true; + } return reinterpret_cast(py_descriptor); } @@ -298,9 +305,7 @@ static PyGetSetDef Getters[] = { PyTypeObject PyBaseDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - // Keep the fully qualified _message symbol in a line for opensource. - "google.protobuf.internal._message." - "DescriptorBase", // tp_name + FULL_MODULE_NAME ".DescriptorBase", // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize (destructor)Dealloc, // tp_dealloc @@ -357,7 +362,7 @@ static PyObject* GetFullName(PyBaseDescriptor* self, void *closure) { } static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { - return PyFileDescriptor_New(_GetDescriptor(self)->file()); + return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file()); } static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) { @@ -367,17 +372,6 @@ static PyObject* GetConcreteClass(PyBaseDescriptor* self, void *closure) { return concrete_class; } -static int SetConcreteClass(PyBaseDescriptor *self, PyObject *value, - void *closure) { - // This attribute is also set from reflection.py. Check that it's actually a - // no-op. - if (value != cdescriptor_pool::GetMessageClass( - GetDescriptorPool(), _GetDescriptor(self))) { - PyErr_SetString(PyExc_AttributeError, "Cannot change _concrete_class"); - } - return 0; -} - static PyObject* GetFieldsByName(PyBaseDescriptor* self, void *closure) { return NewMessageFieldsByName(_GetDescriptor(self)); } @@ -452,7 +446,7 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { const Descriptor* containing_type = _GetDescriptor(self)->containing_type(); if (containing_type) { - return PyMessageDescriptor_New(containing_type); + return PyMessageDescriptor_FromDescriptor(containing_type); } else { Py_RETURN_NONE; } @@ -515,29 +509,34 @@ static PyObject* GetSyntax(PyBaseDescriptor *self, void *closure) { } static PyGetSetDef Getters[] = { - { C("name"), (getter)GetName, NULL, "Last name", NULL}, - { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, - { C("_concrete_class"), (getter)GetConcreteClass, (setter)SetConcreteClass, "concrete class", NULL}, - { C("file"), (getter)GetFile, NULL, "File descriptor", NULL}, - - { C("fields"), (getter)GetFieldsSeq, NULL, "Fields sequence", NULL}, - { C("fields_by_name"), (getter)GetFieldsByName, NULL, "Fields by name", NULL}, - { C("fields_by_number"), (getter)GetFieldsByNumber, NULL, "Fields by number", NULL}, - { C("nested_types"), (getter)GetNestedTypesSeq, NULL, "Nested types sequence", NULL}, - { C("nested_types_by_name"), (getter)GetNestedTypesByName, NULL, "Nested types by name", NULL}, - { C("extensions"), (getter)GetExtensions, NULL, "Extensions Sequence", NULL}, - { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL}, - { C("extension_ranges"), (getter)GetExtensionRanges, NULL, "Extension ranges", NULL}, - { C("enum_types"), (getter)GetEnumsSeq, NULL, "Enum sequence", NULL}, - { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enum types by name", NULL}, - { C("enum_values_by_name"), (getter)GetEnumValuesByName, NULL, "Enum values by name", NULL}, - { C("oneofs_by_name"), (getter)GetOneofsByName, NULL, "Oneofs by name", NULL}, - { C("oneofs"), (getter)GetOneofsSeq, NULL, "Oneofs by name", NULL}, - { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL}, - { C("is_extendable"), (getter)IsExtendable, (setter)NULL, NULL, NULL}, - { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, - { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, - { C("syntax"), (getter)GetSyntax, (setter)NULL, "Syntax", NULL}, + { "name", (getter)GetName, NULL, "Last name"}, + { "full_name", (getter)GetFullName, NULL, "Full name"}, + { "_concrete_class", (getter)GetConcreteClass, NULL, "concrete class"}, + { "file", (getter)GetFile, NULL, "File descriptor"}, + + { "fields", (getter)GetFieldsSeq, NULL, "Fields sequence"}, + { "fields_by_name", (getter)GetFieldsByName, NULL, "Fields by name"}, + { "fields_by_number", (getter)GetFieldsByNumber, NULL, "Fields by number"}, + { "nested_types", (getter)GetNestedTypesSeq, NULL, "Nested types sequence"}, + { "nested_types_by_name", (getter)GetNestedTypesByName, NULL, + "Nested types by name"}, + { "extensions", (getter)GetExtensions, NULL, "Extensions Sequence"}, + { "extensions_by_name", (getter)GetExtensionsByName, NULL, + "Extensions by name"}, + { "extension_ranges", (getter)GetExtensionRanges, NULL, "Extension ranges"}, + { "enum_types", (getter)GetEnumsSeq, NULL, "Enum sequence"}, + { "enum_types_by_name", (getter)GetEnumTypesByName, NULL, + "Enum types by name"}, + { "enum_values_by_name", (getter)GetEnumValuesByName, NULL, + "Enum values by name"}, + { "oneofs_by_name", (getter)GetOneofsByName, NULL, "Oneofs by name"}, + { "oneofs", (getter)GetOneofsSeq, NULL, "Oneofs by name"}, + { "containing_type", (getter)GetContainingType, (setter)SetContainingType, + "Containing type"}, + { "is_extendable", (getter)IsExtendable, (setter)NULL}, + { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, + { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, {NULL} }; @@ -552,9 +551,7 @@ static PyMethodDef Methods[] = { PyTypeObject PyMessageDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - // Keep the fully qualified _message symbol in a line for opensource. - C("google.protobuf.internal._message." - "MessageDescriptor"), // tp_name + FULL_MODULE_NAME ".MessageDescriptor", // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize 0, // tp_dealloc @@ -573,7 +570,7 @@ PyTypeObject PyMessageDescriptor_Type = { 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags - C("A Message Descriptor"), // tp_doc + "A Message Descriptor", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare @@ -586,10 +583,10 @@ PyTypeObject PyMessageDescriptor_Type = { &descriptor::PyBaseDescriptor_Type, // tp_base }; -PyObject* PyMessageDescriptor_New( +PyObject* PyMessageDescriptor_FromDescriptor( const Descriptor* message_descriptor) { return descriptor::NewInternedDescriptor( - &PyMessageDescriptor_Type, message_descriptor); + &PyMessageDescriptor_Type, message_descriptor, NULL); } const Descriptor* PyMessageDescriptor_AsDescriptor(PyObject* obj) { @@ -715,7 +712,7 @@ static PyObject* GetCDescriptor(PyObject *self, void *closure) { static PyObject *GetEnumType(PyBaseDescriptor *self, void *closure) { const EnumDescriptor* enum_type = _GetDescriptor(self)->enum_type(); if (enum_type) { - return PyEnumDescriptor_New(enum_type); + return PyEnumDescriptor_FromDescriptor(enum_type); } else { Py_RETURN_NONE; } @@ -728,7 +725,7 @@ static int SetEnumType(PyBaseDescriptor *self, PyObject *value, void *closure) { static PyObject *GetMessageType(PyBaseDescriptor *self, void *closure) { const Descriptor* message_type = _GetDescriptor(self)->message_type(); if (message_type) { - return PyMessageDescriptor_New(message_type); + return PyMessageDescriptor_FromDescriptor(message_type); } else { Py_RETURN_NONE; } @@ -743,7 +740,7 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { const Descriptor* containing_type = _GetDescriptor(self)->containing_type(); if (containing_type) { - return PyMessageDescriptor_New(containing_type); + return PyMessageDescriptor_FromDescriptor(containing_type); } else { Py_RETURN_NONE; } @@ -758,7 +755,7 @@ static PyObject* GetExtensionScope(PyBaseDescriptor *self, void *closure) { const Descriptor* extension_scope = _GetDescriptor(self)->extension_scope(); if (extension_scope) { - return PyMessageDescriptor_New(extension_scope); + return PyMessageDescriptor_FromDescriptor(extension_scope); } else { Py_RETURN_NONE; } @@ -768,7 +765,7 @@ static PyObject* GetContainingOneof(PyBaseDescriptor *self, void *closure) { const OneofDescriptor* containing_oneof = _GetDescriptor(self)->containing_oneof(); if (containing_oneof) { - return PyOneofDescriptor_New(containing_oneof); + return PyOneofDescriptor_FromDescriptor(containing_oneof); } else { Py_RETURN_NONE; } @@ -803,26 +800,30 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, static PyGetSetDef Getters[] = { - { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, - { C("name"), (getter)GetName, NULL, "Unqualified name", NULL}, - { C("type"), (getter)GetType, NULL, "C++ Type", NULL}, - { C("cpp_type"), (getter)GetCppType, NULL, "C++ Type", NULL}, - { C("label"), (getter)GetLabel, NULL, "Label", NULL}, - { C("number"), (getter)GetNumber, NULL, "Number", NULL}, - { C("index"), (getter)GetIndex, NULL, "Index", NULL}, - { C("default_value"), (getter)GetDefaultValue, NULL, "Default Value", NULL}, - { C("has_default_value"), (getter)HasDefaultValue, NULL, NULL, NULL}, - { C("is_extension"), (getter)IsExtension, NULL, "ID", NULL}, - { C("id"), (getter)GetID, NULL, "ID", NULL}, - { C("_cdescriptor"), (getter)GetCDescriptor, NULL, "HAACK REMOVE ME", NULL}, - - { C("message_type"), (getter)GetMessageType, (setter)SetMessageType, "Message type", NULL}, - { C("enum_type"), (getter)GetEnumType, (setter)SetEnumType, "Enum type", NULL}, - { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL}, - { C("extension_scope"), (getter)GetExtensionScope, (setter)NULL, "Extension scope", NULL}, - { C("containing_oneof"), (getter)GetContainingOneof, (setter)SetContainingOneof, "Containing oneof", NULL}, - { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, - { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, + { "full_name", (getter)GetFullName, NULL, "Full name"}, + { "name", (getter)GetName, NULL, "Unqualified name"}, + { "type", (getter)GetType, NULL, "C++ Type"}, + { "cpp_type", (getter)GetCppType, NULL, "C++ Type"}, + { "label", (getter)GetLabel, NULL, "Label"}, + { "number", (getter)GetNumber, NULL, "Number"}, + { "index", (getter)GetIndex, NULL, "Index"}, + { "default_value", (getter)GetDefaultValue, NULL, "Default Value"}, + { "has_default_value", (getter)HasDefaultValue}, + { "is_extension", (getter)IsExtension, NULL, "ID"}, + { "id", (getter)GetID, NULL, "ID"}, + { "_cdescriptor", (getter)GetCDescriptor, NULL, "HAACK REMOVE ME"}, + + { "message_type", (getter)GetMessageType, (setter)SetMessageType, + "Message type"}, + { "enum_type", (getter)GetEnumType, (setter)SetEnumType, "Enum type"}, + { "containing_type", (getter)GetContainingType, (setter)SetContainingType, + "Containing type"}, + { "extension_scope", (getter)GetExtensionScope, (setter)NULL, + "Extension scope"}, + { "containing_oneof", (getter)GetContainingOneof, (setter)SetContainingOneof, + "Containing oneof"}, + { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, + { "_options", (getter)NULL, (setter)SetOptions, "Options"}, {NULL} }; @@ -835,8 +836,7 @@ static PyMethodDef Methods[] = { PyTypeObject PyFieldDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - C("google.protobuf.internal." - "_message.FieldDescriptor"), // tp_name + FULL_MODULE_NAME ".FieldDescriptor", // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize 0, // tp_dealloc @@ -855,7 +855,7 @@ PyTypeObject PyFieldDescriptor_Type = { 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags - C("A Field Descriptor"), // tp_doc + "A Field Descriptor", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare @@ -868,10 +868,10 @@ PyTypeObject PyFieldDescriptor_Type = { &descriptor::PyBaseDescriptor_Type, // tp_base }; -PyObject* PyFieldDescriptor_New( +PyObject* PyFieldDescriptor_FromDescriptor( const FieldDescriptor* field_descriptor) { return descriptor::NewInternedDescriptor( - &PyFieldDescriptor_Type, field_descriptor); + &PyFieldDescriptor_Type, field_descriptor, NULL); } const FieldDescriptor* PyFieldDescriptor_AsDescriptor(PyObject* obj) { @@ -900,7 +900,7 @@ static PyObject* GetName(PyBaseDescriptor *self, void *closure) { } static PyObject* GetFile(PyBaseDescriptor *self, void *closure) { - return PyFileDescriptor_New(_GetDescriptor(self)->file()); + return PyFileDescriptor_FromDescriptor(_GetDescriptor(self)->file()); } static PyObject* GetEnumvaluesByName(PyBaseDescriptor* self, void *closure) { @@ -919,7 +919,7 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { const Descriptor* containing_type = _GetDescriptor(self)->containing_type(); if (containing_type) { - return PyMessageDescriptor_New(containing_type); + return PyMessageDescriptor_FromDescriptor(containing_type); } else { Py_RETURN_NONE; } @@ -964,16 +964,19 @@ static PyMethodDef Methods[] = { }; static PyGetSetDef Getters[] = { - { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, - { C("name"), (getter)GetName, NULL, "last name", NULL}, - { C("file"), (getter)GetFile, NULL, "File descriptor", NULL}, - { C("values"), (getter)GetEnumvaluesSeq, NULL, "values", NULL}, - { C("values_by_name"), (getter)GetEnumvaluesByName, NULL, "Enumvalues by name", NULL}, - { C("values_by_number"), (getter)GetEnumvaluesByNumber, NULL, "Enumvalues by number", NULL}, - - { C("containing_type"), (getter)GetContainingType, (setter)SetContainingType, "Containing type", NULL}, - { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, - { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, + { "full_name", (getter)GetFullName, NULL, "Full name"}, + { "name", (getter)GetName, NULL, "last name"}, + { "file", (getter)GetFile, NULL, "File descriptor"}, + { "values", (getter)GetEnumvaluesSeq, NULL, "values"}, + { "values_by_name", (getter)GetEnumvaluesByName, NULL, + "Enum values by name"}, + { "values_by_number", (getter)GetEnumvaluesByNumber, NULL, + "Enum values by number"}, + + { "containing_type", (getter)GetContainingType, (setter)SetContainingType, + "Containing type"}, + { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, + { "_options", (getter)NULL, (setter)SetOptions, "Options"}, {NULL} }; @@ -981,9 +984,7 @@ static PyGetSetDef Getters[] = { PyTypeObject PyEnumDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - // Keep the fully qualified _message symbol in a line for opensource. - C("google.protobuf.internal._message." - "EnumDescriptor"), // tp_name + FULL_MODULE_NAME ".EnumDescriptor", // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize 0, // tp_dealloc @@ -1002,7 +1003,7 @@ PyTypeObject PyEnumDescriptor_Type = { 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags - C("A Enum Descriptor"), // tp_doc + "A Enum Descriptor", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare @@ -1015,10 +1016,10 @@ PyTypeObject PyEnumDescriptor_Type = { &descriptor::PyBaseDescriptor_Type, // tp_base }; -PyObject* PyEnumDescriptor_New( +PyObject* PyEnumDescriptor_FromDescriptor( const EnumDescriptor* enum_descriptor) { return descriptor::NewInternedDescriptor( - &PyEnumDescriptor_Type, enum_descriptor); + &PyEnumDescriptor_Type, enum_descriptor, NULL); } namespace enumvalue_descriptor { @@ -1042,7 +1043,7 @@ static PyObject* GetIndex(PyBaseDescriptor *self, void *closure) { } static PyObject* GetType(PyBaseDescriptor *self, void *closure) { - return PyEnumDescriptor_New(_GetDescriptor(self)->type()); + return PyEnumDescriptor_FromDescriptor(_GetDescriptor(self)->type()); } static PyObject* GetHasOptions(PyBaseDescriptor *self, void *closure) { @@ -1069,13 +1070,13 @@ static int SetOptions(PyBaseDescriptor *self, PyObject *value, static PyGetSetDef Getters[] = { - { C("name"), (getter)GetName, NULL, "name", NULL}, - { C("number"), (getter)GetNumber, NULL, "number", NULL}, - { C("index"), (getter)GetIndex, NULL, "index", NULL}, - { C("type"), (getter)GetType, NULL, "index", NULL}, + { "name", (getter)GetName, NULL, "name"}, + { "number", (getter)GetNumber, NULL, "number"}, + { "index", (getter)GetIndex, NULL, "index"}, + { "type", (getter)GetType, NULL, "index"}, - { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, - { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, + { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, + { "_options", (getter)NULL, (setter)SetOptions, "Options"}, {NULL} }; @@ -1088,8 +1089,7 @@ static PyMethodDef Methods[] = { PyTypeObject PyEnumValueDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - C("google.protobuf.internal." - "_message.EnumValueDescriptor"), // tp_name + FULL_MODULE_NAME ".EnumValueDescriptor", // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize 0, // tp_dealloc @@ -1108,7 +1108,7 @@ PyTypeObject PyEnumValueDescriptor_Type = { 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags - C("A EnumValue Descriptor"), // tp_doc + "A EnumValue Descriptor", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare @@ -1121,10 +1121,10 @@ PyTypeObject PyEnumValueDescriptor_Type = { &descriptor::PyBaseDescriptor_Type, // tp_base }; -PyObject* PyEnumValueDescriptor_New( +PyObject* PyEnumValueDescriptor_FromDescriptor( const EnumValueDescriptor* enumvalue_descriptor) { return descriptor::NewInternedDescriptor( - &PyEnumValueDescriptor_Type, enumvalue_descriptor); + &PyEnumValueDescriptor_Type, enumvalue_descriptor, NULL); } namespace file_descriptor { @@ -1218,18 +1218,20 @@ static PyObject* CopyToProto(PyFileDescriptor *self, PyObject *target) { } static PyGetSetDef Getters[] = { - { C("name"), (getter)GetName, NULL, "name", NULL}, - { C("package"), (getter)GetPackage, NULL, "package", NULL}, - { C("serialized_pb"), (getter)GetSerializedPb, NULL, NULL, NULL}, - { C("message_types_by_name"), (getter)GetMessageTypesByName, NULL, "Messages by name", NULL}, - { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enums by name", NULL}, - { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL}, - { C("dependencies"), (getter)GetDependencies, NULL, "Dependencies", NULL}, - { C("public_dependencies"), (getter)GetPublicDependencies, NULL, "Dependencies", NULL}, - - { C("has_options"), (getter)GetHasOptions, (setter)SetHasOptions, "Has Options", NULL}, - { C("_options"), (getter)NULL, (setter)SetOptions, "Options", NULL}, - { C("syntax"), (getter)GetSyntax, (setter)NULL, "Syntax", NULL}, + { "name", (getter)GetName, NULL, "name"}, + { "package", (getter)GetPackage, NULL, "package"}, + { "serialized_pb", (getter)GetSerializedPb}, + { "message_types_by_name", (getter)GetMessageTypesByName, NULL, + "Messages by name"}, + { "enum_types_by_name", (getter)GetEnumTypesByName, NULL, "Enums by name"}, + { "extensions_by_name", (getter)GetExtensionsByName, NULL, + "Extensions by name"}, + { "dependencies", (getter)GetDependencies, NULL, "Dependencies"}, + { "public_dependencies", (getter)GetPublicDependencies, NULL, "Dependencies"}, + + { "has_options", (getter)GetHasOptions, (setter)SetHasOptions, "Has Options"}, + { "_options", (getter)NULL, (setter)SetOptions, "Options"}, + { "syntax", (getter)GetSyntax, (setter)NULL, "Syntax"}, {NULL} }; @@ -1243,11 +1245,10 @@ static PyMethodDef Methods[] = { PyTypeObject PyFileDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - C("google.protobuf.internal." - "_message.FileDescriptor"), // tp_name + FULL_MODULE_NAME ".FileDescriptor", // tp_name sizeof(PyFileDescriptor), // tp_basicsize 0, // tp_itemsize - (destructor)file_descriptor::Dealloc, // tp_dealloc + (destructor)file_descriptor::Dealloc, // tp_dealloc 0, // tp_print 0, // tp_getattr 0, // tp_setattr @@ -1263,7 +1264,7 @@ PyTypeObject PyFileDescriptor_Type = { 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags - C("A File Descriptor"), // tp_doc + "A File Descriptor", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare @@ -1284,23 +1285,28 @@ PyTypeObject PyFileDescriptor_Type = { PyObject_Del, // tp_free }; -PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor) { - return descriptor::NewInternedDescriptor( - &PyFileDescriptor_Type, file_descriptor); +PyObject* PyFileDescriptor_FromDescriptor( + const FileDescriptor* file_descriptor) { + return PyFileDescriptor_FromDescriptorWithSerializedPb(file_descriptor, + NULL); } -PyObject* PyFileDescriptor_NewWithPb( +PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb( const FileDescriptor* file_descriptor, PyObject *serialized_pb) { - PyObject* py_descriptor = PyFileDescriptor_New(file_descriptor); + bool was_created; + PyObject* py_descriptor = descriptor::NewInternedDescriptor( + &PyFileDescriptor_Type, file_descriptor, &was_created); if (py_descriptor == NULL) { return NULL; } - if (serialized_pb != NULL) { + if (was_created) { PyFileDescriptor* cfile_descriptor = reinterpret_cast(py_descriptor); Py_XINCREF(serialized_pb); cfile_descriptor->serialized_pb = serialized_pb; } + // TODO(amauryfa): In the case of a cached object, check that serialized_pb + // is the same as before. return py_descriptor; } @@ -1333,19 +1339,19 @@ static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) { const Descriptor* containing_type = _GetDescriptor(self)->containing_type(); if (containing_type) { - return PyMessageDescriptor_New(containing_type); + return PyMessageDescriptor_FromDescriptor(containing_type); } else { Py_RETURN_NONE; } } static PyGetSetDef Getters[] = { - { C("name"), (getter)GetName, NULL, "Name", NULL}, - { C("full_name"), (getter)GetFullName, NULL, "Full name", NULL}, - { C("index"), (getter)GetIndex, NULL, "Index", NULL}, + { "name", (getter)GetName, NULL, "Name"}, + { "full_name", (getter)GetFullName, NULL, "Full name"}, + { "index", (getter)GetIndex, NULL, "Index"}, - { C("containing_type"), (getter)GetContainingType, NULL, "Containing type", NULL}, - { C("fields"), (getter)GetFields, NULL, "Fields", NULL}, + { "containing_type", (getter)GetContainingType, NULL, "Containing type"}, + { "fields", (getter)GetFields, NULL, "Fields"}, {NULL} }; @@ -1353,8 +1359,7 @@ static PyGetSetDef Getters[] = { PyTypeObject PyOneofDescriptor_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - C("google.protobuf.internal." - "_message.OneofDescriptor"), // tp_name + FULL_MODULE_NAME ".OneofDescriptor", // tp_name sizeof(PyBaseDescriptor), // tp_basicsize 0, // tp_itemsize 0, // tp_dealloc @@ -1373,7 +1378,7 @@ PyTypeObject PyOneofDescriptor_Type = { 0, // tp_setattro 0, // tp_as_buffer Py_TPFLAGS_DEFAULT, // tp_flags - C("A Oneof Descriptor"), // tp_doc + "A Oneof Descriptor", // tp_doc 0, // tp_traverse 0, // tp_clear 0, // tp_richcompare @@ -1386,10 +1391,10 @@ PyTypeObject PyOneofDescriptor_Type = { &descriptor::PyBaseDescriptor_Type, // tp_base }; -PyObject* PyOneofDescriptor_New( +PyObject* PyOneofDescriptor_FromDescriptor( const OneofDescriptor* oneof_descriptor) { return descriptor::NewInternedDescriptor( - &PyOneofDescriptor_Type, oneof_descriptor); + &PyOneofDescriptor_Type, oneof_descriptor, NULL); } // Add a enum values to a type dictionary. diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h index ba6e7298..b2550406 100644 --- a/python/google/protobuf/pyext/descriptor.h +++ b/python/google/protobuf/pyext/descriptor.h @@ -48,21 +48,24 @@ extern PyTypeObject PyEnumValueDescriptor_Type; extern PyTypeObject PyFileDescriptor_Type; extern PyTypeObject PyOneofDescriptor_Type; -// Return a new reference to a Descriptor object. +// Wraps a Descriptor in a Python object. // The C++ pointer is usually borrowed from the global DescriptorPool. // In any case, it must stay alive as long as the Python object. -PyObject* PyMessageDescriptor_New(const Descriptor* descriptor); -PyObject* PyFieldDescriptor_New(const FieldDescriptor* descriptor); -PyObject* PyEnumDescriptor_New(const EnumDescriptor* descriptor); -PyObject* PyEnumValueDescriptor_New(const EnumValueDescriptor* descriptor); -PyObject* PyOneofDescriptor_New(const OneofDescriptor* descriptor); -PyObject* PyFileDescriptor_New(const FileDescriptor* file_descriptor); +// Returns a new reference. +PyObject* PyMessageDescriptor_FromDescriptor(const Descriptor* descriptor); +PyObject* PyFieldDescriptor_FromDescriptor(const FieldDescriptor* descriptor); +PyObject* PyEnumDescriptor_FromDescriptor(const EnumDescriptor* descriptor); +PyObject* PyEnumValueDescriptor_FromDescriptor( + const EnumValueDescriptor* descriptor); +PyObject* PyOneofDescriptor_FromDescriptor(const OneofDescriptor* descriptor); +PyObject* PyFileDescriptor_FromDescriptor( + const FileDescriptor* file_descriptor); // Alternate constructor of PyFileDescriptor, used when we already have a // serialized FileDescriptorProto that can be cached. // Returns a new reference. -PyObject* PyFileDescriptor_NewWithPb(const FileDescriptor* file_descriptor, - PyObject* serialized_pb); +PyObject* PyFileDescriptor_FromDescriptorWithSerializedPb( + const FileDescriptor* file_descriptor, PyObject* serialized_pb); // Return the C++ descriptor pointer. // This function checks the parameter type; on error, return NULL with a Python diff --git a/python/google/protobuf/pyext/descriptor_containers.cc b/python/google/protobuf/pyext/descriptor_containers.cc index 06edebf8..92e11e31 100644 --- a/python/google/protobuf/pyext/descriptor_containers.cc +++ b/python/google/protobuf/pyext/descriptor_containers.cc @@ -898,7 +898,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_New(item); + return PyFieldDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -956,7 +956,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyMessageDescriptor_New(item); + return PyMessageDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1006,7 +1006,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumDescriptor_New(item); + return PyEnumDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1082,7 +1082,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumValueDescriptor_New(item); + return PyEnumValueDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1124,7 +1124,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_New(item); + return PyFieldDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1174,7 +1174,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyOneofDescriptor_New(item); + return PyOneofDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1238,7 +1238,7 @@ static ItemDescriptor GetByNumber(PyContainer* self, int number) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumValueDescriptor_New(item); + return PyEnumValueDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1302,7 +1302,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_New(item); + return PyFieldDescriptor_FromDescriptor(item); } static int GetItemIndex(ItemDescriptor item) { @@ -1354,7 +1354,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyMessageDescriptor_New(item); + return PyMessageDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1400,7 +1400,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyEnumDescriptor_New(item); + return PyEnumDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1446,7 +1446,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFieldDescriptor_New(item); + return PyFieldDescriptor_FromDescriptor(item); } static const string& GetItemName(ItemDescriptor item) { @@ -1488,7 +1488,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFileDescriptor_New(item); + return PyFileDescriptor_FromDescriptor(item); } static DescriptorContainerDef ContainerDef = { @@ -1522,7 +1522,7 @@ static ItemDescriptor GetByIndex(PyContainer* self, int index) { } static PyObject* NewObjectFromItem(ItemDescriptor item) { - return PyFileDescriptor_New(item); + return PyFileDescriptor_FromDescriptor(item); } static DescriptorContainerDef ContainerDef = { diff --git a/python/google/protobuf/pyext/descriptor_containers.h b/python/google/protobuf/pyext/descriptor_containers.h index d81537de..8fbdaff9 100644 --- a/python/google/protobuf/pyext/descriptor_containers.h +++ b/python/google/protobuf/pyext/descriptor_containers.h @@ -28,6 +28,9 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__ + // Mappings and Sequences of descriptors. // They implement containers like fields_by_name, EnumDescriptor.values... // See descriptor_containers.cc for more description. @@ -92,4 +95,6 @@ PyObject* NewFilePublicDependencies(const FileDescriptor* descriptor); } // namespace python } // namespace protobuf + } // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_DESCRIPTOR_CONTAINERS_H__ diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc index bc3077bc..ecd90847 100644 --- a/python/google/protobuf/pyext/descriptor_pool.cc +++ b/python/google/protobuf/pyext/descriptor_pool.cc @@ -35,10 +35,9 @@ #include #include #include +#include #include -#define C(str) const_cast(str) - #if PY_MAJOR_VERSION >= 3 #define PyString_FromStringAndSize PyUnicode_FromStringAndSize #if PY_VERSION_HEX < 0x03030000 @@ -108,11 +107,11 @@ PyObject* FindMessageByName(PyDescriptorPool* self, PyObject* arg) { self->pool->FindMessageTypeByName(string(name, name_size)); if (message_descriptor == NULL) { - PyErr_Format(PyExc_TypeError, "Couldn't find message %.200s", name); + PyErr_Format(PyExc_KeyError, "Couldn't find message %.200s", name); return NULL; } - return PyMessageDescriptor_New(message_descriptor); + return PyMessageDescriptor_FromDescriptor(message_descriptor); } // Add a message class to our database. @@ -158,6 +157,24 @@ PyObject *GetMessageClass(PyDescriptorPool* self, } } +PyObject* FindFileByName(PyDescriptorPool* self, PyObject* arg) { + Py_ssize_t name_size; + char* name; + if (PyString_AsStringAndSize(arg, &name, &name_size) < 0) { + return NULL; + } + + const FileDescriptor* file_descriptor = + self->pool->FindFileByName(string(name, name_size)); + if (file_descriptor == NULL) { + PyErr_Format(PyExc_KeyError, "Couldn't find file %.200s", + name); + return NULL; + } + + return PyFileDescriptor_FromDescriptor(file_descriptor); +} + PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) { Py_ssize_t name_size; char* name; @@ -168,12 +185,12 @@ PyObject* FindFieldByName(PyDescriptorPool* self, PyObject* arg) { const FieldDescriptor* field_descriptor = self->pool->FindFieldByName(string(name, name_size)); if (field_descriptor == NULL) { - PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", + PyErr_Format(PyExc_KeyError, "Couldn't find field %.200s", name); return NULL; } - return PyFieldDescriptor_New(field_descriptor); + return PyFieldDescriptor_FromDescriptor(field_descriptor); } PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) { @@ -186,11 +203,11 @@ PyObject* FindExtensionByName(PyDescriptorPool* self, PyObject* arg) { const FieldDescriptor* field_descriptor = self->pool->FindExtensionByName(string(name, name_size)); if (field_descriptor == NULL) { - PyErr_Format(PyExc_TypeError, "Couldn't find field %.200s", name); + PyErr_Format(PyExc_KeyError, "Couldn't find extension field %.200s", name); return NULL; } - return PyFieldDescriptor_New(field_descriptor); + return PyFieldDescriptor_FromDescriptor(field_descriptor); } PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) { @@ -203,11 +220,11 @@ PyObject* FindEnumTypeByName(PyDescriptorPool* self, PyObject* arg) { const EnumDescriptor* enum_descriptor = self->pool->FindEnumTypeByName(string(name, name_size)); if (enum_descriptor == NULL) { - PyErr_Format(PyExc_TypeError, "Couldn't find enum %.200s", name); + PyErr_Format(PyExc_KeyError, "Couldn't find enum %.200s", name); return NULL; } - return PyEnumDescriptor_New(enum_descriptor); + return PyEnumDescriptor_FromDescriptor(enum_descriptor); } PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) { @@ -220,70 +237,13 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg) { const OneofDescriptor* oneof_descriptor = self->pool->FindOneofByName(string(name, name_size)); if (oneof_descriptor == NULL) { - PyErr_Format(PyExc_TypeError, "Couldn't find oneof %.200s", name); + PyErr_Format(PyExc_KeyError, "Couldn't find oneof %.200s", name); return NULL; } - return PyOneofDescriptor_New(oneof_descriptor); + return PyOneofDescriptor_FromDescriptor(oneof_descriptor); } -static PyMethodDef Methods[] = { - { C("FindFieldByName"), - (PyCFunction)FindFieldByName, - METH_O, - C("Searches for a field descriptor by full name.") }, - { C("FindExtensionByName"), - (PyCFunction)FindExtensionByName, - METH_O, - C("Searches for extension descriptor by full name.") }, - {NULL} -}; - -} // namespace cdescriptor_pool - -PyTypeObject PyDescriptorPool_Type = { - PyVarObject_HEAD_INIT(&PyType_Type, 0) - C("google.protobuf.internal." - "_message.DescriptorPool"), // tp_name - sizeof(PyDescriptorPool), // tp_basicsize - 0, // tp_itemsize - (destructor)cdescriptor_pool::Dealloc, // tp_dealloc - 0, // tp_print - 0, // tp_getattr - 0, // tp_setattr - 0, // tp_compare - 0, // tp_repr - 0, // tp_as_number - 0, // tp_as_sequence - 0, // tp_as_mapping - 0, // tp_hash - 0, // tp_call - 0, // tp_str - 0, // tp_getattro - 0, // tp_setattro - 0, // tp_as_buffer - Py_TPFLAGS_DEFAULT, // tp_flags - C("A Descriptor Pool"), // tp_doc - 0, // tp_traverse - 0, // tp_clear - 0, // tp_richcompare - 0, // tp_weaklistoffset - 0, // tp_iter - 0, // tp_iternext - cdescriptor_pool::Methods, // tp_methods - 0, // tp_members - 0, // tp_getset - 0, // tp_base - 0, // tp_dict - 0, // tp_descr_get - 0, // tp_descr_set - 0, // tp_dictoffset - 0, // tp_init - 0, // tp_alloc - 0, // tp_new - PyObject_Del, // tp_free -}; - // The code below loads new Descriptors from a serialized FileDescriptorProto. @@ -301,6 +261,7 @@ class BuildFileErrorCollector : public DescriptorPool::ErrorCollector { if (!had_errors) { error_message += ("Invalid proto descriptor for file \"" + filename + "\":\n"); + had_errors = true; } // As this only happens on failure and will result in the program not // running at all, no effort is made to optimize this string manipulation. @@ -311,7 +272,7 @@ class BuildFileErrorCollector : public DescriptorPool::ErrorCollector { bool had_errors; }; -PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) { +PyObject* AddSerializedFile(PyDescriptorPool* self, PyObject* serialized_pb) { char* message_type; Py_ssize_t message_len; @@ -330,13 +291,14 @@ PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) { const FileDescriptor* generated_file = DescriptorPool::generated_pool()->FindFileByName(file_proto.name()); if (generated_file != NULL) { - return PyFileDescriptor_NewWithPb(generated_file, serialized_pb); + return PyFileDescriptor_FromDescriptorWithSerializedPb( + generated_file, serialized_pb); } BuildFileErrorCollector error_collector; const FileDescriptor* descriptor = - GetDescriptorPool()->pool->BuildFileCollectingErrors(file_proto, - &error_collector); + self->pool->BuildFileCollectingErrors(file_proto, + &error_collector); if (descriptor == NULL) { PyErr_Format(PyExc_TypeError, "Couldn't build proto file into descriptor pool!\n%s", @@ -344,9 +306,84 @@ PyObject* Python_BuildFile(PyObject* ignored, PyObject* serialized_pb) { return NULL; } - return PyFileDescriptor_NewWithPb(descriptor, serialized_pb); + return PyFileDescriptor_FromDescriptorWithSerializedPb( + descriptor, serialized_pb); +} + +PyObject* Add(PyDescriptorPool* self, PyObject* file_descriptor_proto) { + ScopedPyObjectPtr serialized_pb( + PyObject_CallMethod(file_descriptor_proto, "SerializeToString", NULL)); + if (serialized_pb == NULL) { + return NULL; + } + return AddSerializedFile(self, serialized_pb); } +static PyMethodDef Methods[] = { + { "Add", (PyCFunction)Add, METH_O, + "Adds the FileDescriptorProto and its types to this pool." }, + { "AddSerializedFile", (PyCFunction)AddSerializedFile, METH_O, + "Adds a serialized FileDescriptorProto to this pool." }, + + { "FindFileByName", (PyCFunction)FindFileByName, METH_O, + "Searches for a file descriptor by its .proto name." }, + { "FindMessageTypeByName", (PyCFunction)FindMessageByName, METH_O, + "Searches for a message descriptor by full name." }, + { "FindFieldByName", (PyCFunction)FindFieldByName, METH_O, + "Searches for a field descriptor by full name." }, + { "FindExtensionByName", (PyCFunction)FindExtensionByName, METH_O, + "Searches for extension descriptor by full name." }, + { "FindEnumTypeByName", (PyCFunction)FindEnumTypeByName, METH_O, + "Searches for enum type descriptor by full name." }, + { "FindOneofByName", (PyCFunction)FindOneofByName, METH_O, + "Searches for oneof descriptor by full name." }, + {NULL} +}; + +} // namespace cdescriptor_pool + +PyTypeObject PyDescriptorPool_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + FULL_MODULE_NAME ".DescriptorPool", // tp_name + sizeof(PyDescriptorPool), // tp_basicsize + 0, // tp_itemsize + (destructor)cdescriptor_pool::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A Descriptor Pool", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + 0, // tp_iter + 0, // tp_iternext + cdescriptor_pool::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init + 0, // tp_alloc + 0, // tp_new + PyObject_Del, // tp_free +}; + static PyDescriptorPool* global_cdescriptor_pool = NULL; bool InitDescriptorPool() { diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h index 4e494b89..efb1abeb 100644 --- a/python/google/protobuf/pyext/descriptor_pool.h +++ b/python/google/protobuf/pyext/descriptor_pool.h @@ -95,6 +95,8 @@ const Descriptor* FindMessageTypeByName(PyDescriptorPool* self, const Descriptor* RegisterMessageClass( PyDescriptorPool* self, PyObject* message_class, PyObject* descriptor); +// The function below are also exposed as methods of the DescriptorPool type. + // Retrieves the Python class registered with the given message descriptor. // // Returns a *borrowed* reference if found, otherwise returns NULL with an @@ -134,12 +136,8 @@ PyObject* FindOneofByName(PyDescriptorPool* self, PyObject* arg); } // namespace cdescriptor_pool -// Implement the Python "_BuildFile" method, it takes a serialized -// FileDescriptorProto, and adds it to the C++ DescriptorPool. -// It returns a new FileDescriptor object, or NULL when an exception is raised. -PyObject* Python_BuildFile(PyObject* ignored, PyObject* args); - // Retrieve the global descriptor pool owned by the _message module. +// Returns a *borrowed* reference. PyDescriptorPool* GetDescriptorPool(); // Initialize objects used by this module. diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc index 8e38fc42..b8d18f8d 100644 --- a/python/google/protobuf/pyext/extension_dict.cc +++ b/python/google/protobuf/pyext/extension_dict.cc @@ -51,16 +51,6 @@ namespace python { namespace extension_dict { -// TODO(tibell): Always use self->message for clarity, just like in -// RepeatedCompositeContainer. -static Message* GetMessage(ExtensionDict* self) { - if (self->parent != NULL) { - return self->parent->message; - } else { - return self->message; - } -} - PyObject* len(ExtensionDict* self) { #if PY_MAJOR_VERSION >= 3 return PyLong_FromLong(PyDict_Size(self->values)); @@ -89,7 +79,7 @@ int ReleaseExtension(ExtensionDict* self, } } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { if (cmessage::ReleaseSubMessage( - GetMessage(self), descriptor, + self->parent, descriptor, reinterpret_cast(extension)) < 0) { return -1; } @@ -109,7 +99,7 @@ PyObject* subscript(ExtensionDict* self, PyObject* key) { if (descriptor->label() != FieldDescriptor::LABEL_REPEATED && descriptor->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { - return cmessage::InternalGetScalar(self->parent, descriptor); + return cmessage::InternalGetScalar(self->parent->message, descriptor); } PyObject* value = PyDict_GetItem(self->values, key); @@ -266,8 +256,7 @@ static PyMethodDef Methods[] = { PyTypeObject ExtensionDict_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - "google.protobuf.internal." - "cpp._message.ExtensionDict", // tp_name + FULL_MODULE_NAME ".ExtensionDict", // tp_name sizeof(ExtensionDict), // tp_basicsize 0, // tp_itemsize (destructor)extension_dict::dealloc, // tp_dealloc diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc index a2b357b2..a4843e8d 100644 --- a/python/google/protobuf/pyext/message.cc +++ b/python/google/protobuf/pyext/message.cc @@ -59,6 +59,8 @@ #include #include #include +#include +#include #include #include @@ -93,9 +95,9 @@ static const FieldDescriptor* GetFieldDescriptor( static const Descriptor* GetMessageDescriptor(PyTypeObject* cls); static string GetMessageName(CMessage* self); int InternalReleaseFieldByDescriptor( + CMessage* self, const FieldDescriptor* field_descriptor, - PyObject* composite_field, - Message* parent_message); + PyObject* composite_field); } // namespace cmessage // --------------------------------------------------------------------- @@ -127,10 +129,29 @@ static int VisitCompositeField(const FieldDescriptor* descriptor, Visitor visitor) { if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - RepeatedCompositeContainer* container = - reinterpret_cast(child); - if (visitor.VisitRepeatedCompositeContainer(container) == -1) - return -1; + if (descriptor->is_map()) { + const Descriptor* entry_type = descriptor->message_type(); + const FieldDescriptor* value_type = + entry_type->FindFieldByName("value"); + if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + MessageMapContainer* container = + reinterpret_cast(child); + if (visitor.VisitMessageMapContainer(container) == -1) { + return -1; + } + } else { + ScalarMapContainer* container = + reinterpret_cast(child); + if (visitor.VisitScalarMapContainer(container) == -1) { + return -1; + } + } + } else { + RepeatedCompositeContainer* container = + reinterpret_cast(child); + if (visitor.VisitRepeatedCompositeContainer(container) == -1) + return -1; + } } else { RepeatedScalarContainer* container = reinterpret_cast(child); @@ -444,7 +465,7 @@ static int MaybeReleaseOverlappingOneofField( } if (InternalReleaseFieldByDescriptor( - existing_field, child_message, message) < 0) { + cmessage, existing_field, child_message) < 0) { return -1; } return PyDict_DelItemString(cmessage->composite_fields, field_name); @@ -483,6 +504,16 @@ struct FixupMessageReference : public ChildVisitor { return 0; } + int VisitScalarMapContainer(ScalarMapContainer* container) { + container->message = message_; + return 0; + } + + int VisitMessageMapContainer(MessageMapContainer* container) { + container->message = message_; + return 0; + } + private: Message* message_; }; @@ -500,6 +531,9 @@ int AssureWritable(CMessage* self) { self->message->GetDescriptor()); self->message = prototype->New(); self->owner.reset(self->message); + // Cascade the new owner to eventual children: even if this message is + // empty, some submessages or repeated containers might exist already. + SetOwner(self, self->owner); } else { // Otherwise, we need a mutable child message. if (AssureWritable(self->parent) == -1) @@ -520,8 +554,9 @@ int AssureWritable(CMessage* self) { // When a CMessage is made writable its Message pointer is updated // to point to a new mutable Message. When that happens we need to // update any references to the old, read-only CMessage. There are - // three places such references occur: RepeatedScalarContainer, - // RepeatedCompositeContainer, and ExtensionDict. + // five places such references occur: RepeatedScalarContainer, + // RepeatedCompositeContainer, ScalarMapContainer, MessageMapContainer, + // and ExtensionDict. if (self->extensions != NULL) self->extensions->message = self->message; if (ForEachCompositeField(self, FixupMessageReference(self->message)) == -1) @@ -583,15 +618,43 @@ const FieldDescriptor* GetExtensionDescriptor(PyObject* extension) { return PyFieldDescriptor_AsDescriptor(extension); } +// If value is a string, convert it into an enum value based on the labels in +// descriptor, otherwise simply return value. Always returns a new reference. +static PyObject* GetIntegerEnumValue(const FieldDescriptor& descriptor, + PyObject* value) { + if (PyString_Check(value) || PyUnicode_Check(value)) { + const EnumDescriptor* enum_descriptor = descriptor.enum_type(); + if (enum_descriptor == NULL) { + PyErr_SetString(PyExc_TypeError, "not an enum field"); + return NULL; + } + char* enum_label; + Py_ssize_t size; + if (PyString_AsStringAndSize(value, &enum_label, &size) < 0) { + return NULL; + } + const EnumValueDescriptor* enum_value_descriptor = + enum_descriptor->FindValueByName(string(enum_label, size)); + if (enum_value_descriptor == NULL) { + PyErr_SetString(PyExc_ValueError, "unknown enum label"); + return NULL; + } + return PyInt_FromLong(enum_value_descriptor->number()); + } + Py_INCREF(value); + return value; +} + // If cmessage_list is not NULL, this function releases values into the // container CMessages instead of just removing. Repeated composite container // needs to do this to make sure CMessages stay alive if they're still // referenced after deletion. Repeated scalar container doesn't need to worry. int InternalDeleteRepeatedField( - Message* message, + CMessage* self, const FieldDescriptor* field_descriptor, PyObject* slice, PyObject* cmessage_list) { + Message* message = self->message; Py_ssize_t length, from, to, step, slice_length; const Reflection* reflection = message->GetReflection(); int min, max; @@ -665,7 +728,7 @@ int InternalDeleteRepeatedField( CMessage* last_cmessage = reinterpret_cast( PyList_GET_ITEM(cmessage_list, PyList_GET_SIZE(cmessage_list) - 1)); repeated_composite_container::ReleaseLastTo( - field_descriptor, message, last_cmessage); + self, field_descriptor, last_cmessage); if (PySequence_DelItem(cmessage_list, -1) < 0) { return -1; } @@ -696,16 +759,90 @@ int InitAttributes(CMessage* self, PyObject* kwargs) { PyString_AsString(name)); return -1; } - if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { + if (descriptor->is_map()) { + ScopedPyObjectPtr map(GetAttr(self, name)); + const FieldDescriptor* value_descriptor = + descriptor->message_type()->FindFieldByName("value"); + if (value_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + Py_ssize_t map_pos = 0; + PyObject* map_key; + PyObject* map_value; + while (PyDict_Next(value, &map_pos, &map_key, &map_value)) { + ScopedPyObjectPtr function_return; + function_return.reset(PyObject_GetItem(map.get(), map_key)); + if (function_return.get() == NULL) { + return -1; + } + ScopedPyObjectPtr ok(PyObject_CallMethod( + function_return.get(), "MergeFrom", "O", map_value)); + if (ok.get() == NULL) { + return -1; + } + } + } else { + ScopedPyObjectPtr function_return; + function_return.reset( + PyObject_CallMethod(map.get(), "update", "O", value)); + if (function_return.get() == NULL) { + return -1; + } + } + } else if (descriptor->label() == FieldDescriptor::LABEL_REPEATED) { ScopedPyObjectPtr container(GetAttr(self, name)); if (container == NULL) { return -1; } if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (repeated_composite_container::Extend( - reinterpret_cast(container.get()), - value) - == NULL) { + RepeatedCompositeContainer* rc_container = + reinterpret_cast(container.get()); + ScopedPyObjectPtr iter(PyObject_GetIter(value)); + if (iter == NULL) { + PyErr_SetString(PyExc_TypeError, "Value must be iterable"); + return -1; + } + ScopedPyObjectPtr next; + while ((next.reset(PyIter_Next(iter))) != NULL) { + PyObject* kwargs = (PyDict_Check(next) ? next.get() : NULL); + ScopedPyObjectPtr new_msg( + repeated_composite_container::Add(rc_container, NULL, kwargs)); + if (new_msg == NULL) { + return -1; + } + if (kwargs == NULL) { + // next was not a dict, it's a message we need to merge + ScopedPyObjectPtr merged( + MergeFrom(reinterpret_cast(new_msg.get()), next)); + if (merged == NULL) { + return -1; + } + } + } + if (PyErr_Occurred()) { + // Check to see how PyIter_Next() exited. + return -1; + } + } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + RepeatedScalarContainer* rs_container = + reinterpret_cast(container.get()); + ScopedPyObjectPtr iter(PyObject_GetIter(value)); + if (iter == NULL) { + PyErr_SetString(PyExc_TypeError, "Value must be iterable"); + return -1; + } + ScopedPyObjectPtr next; + while ((next.reset(PyIter_Next(iter))) != NULL) { + ScopedPyObjectPtr enum_value(GetIntegerEnumValue(*descriptor, next)); + if (enum_value == NULL) { + return -1; + } + ScopedPyObjectPtr new_msg( + repeated_scalar_container::Append(rs_container, enum_value)); + if (new_msg == NULL) { + return -1; + } + } + if (PyErr_Occurred()) { + // Check to see how PyIter_Next() exited. return -1; } } else { @@ -721,12 +858,26 @@ int InitAttributes(CMessage* self, PyObject* kwargs) { if (message == NULL) { return -1; } - if (MergeFrom(reinterpret_cast(message.get()), - value) == NULL) { - return -1; + CMessage* cmessage = reinterpret_cast(message.get()); + if (PyDict_Check(value)) { + if (InitAttributes(cmessage, value) < 0) { + return -1; + } + } else { + ScopedPyObjectPtr merged(MergeFrom(cmessage, value)); + if (merged == NULL) { + return -1; + } } } else { - if (SetAttr(self, name, value) < 0) { + ScopedPyObjectPtr new_val; + if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) { + new_val.reset(GetIntegerEnumValue(*descriptor, value)); + if (new_val == NULL) { + return -1; + } + } + if (SetAttr(self, name, (new_val == NULL) ? value : new_val) < 0) { return -1; } } @@ -789,7 +940,6 @@ static PyObject* New(PyTypeObject* type, } self->message = default_message->New(); self->owner.reset(self->message); - return reinterpret_cast(self); } @@ -830,6 +980,16 @@ struct ClearWeakReferences : public ChildVisitor { return 0; } + int VisitScalarMapContainer(ScalarMapContainer* container) { + container->parent = NULL; + return 0; + } + + int VisitMessageMapContainer(MessageMapContainer* container) { + container->parent = NULL; + return 0; + } + int VisitCMessage(CMessage* cmessage, const FieldDescriptor* field_descriptor) { cmessage->parent = NULL; @@ -1064,6 +1224,16 @@ struct SetOwnerVisitor : public ChildVisitor { return 0; } + int VisitScalarMapContainer(ScalarMapContainer* container) { + scalar_map_container::SetOwner(container, new_owner_); + return 0; + } + + int VisitMessageMapContainer(MessageMapContainer* container) { + message_map_container::SetOwner(container, new_owner_); + return 0; + } + int VisitCMessage(CMessage* cmessage, const FieldDescriptor* field_descriptor) { return SetOwner(cmessage, new_owner_); @@ -1084,11 +1254,11 @@ int SetOwner(CMessage* self, const shared_ptr& new_owner) { // Releases the message specified by 'field' and returns the // pointer. If the field does not exist a new message is created using // 'descriptor'. The caller takes ownership of the returned pointer. -Message* ReleaseMessage(Message* message, +Message* ReleaseMessage(CMessage* self, const Descriptor* descriptor, const FieldDescriptor* field_descriptor) { - Message* released_message = message->GetReflection()->ReleaseMessage( - message, field_descriptor, message_factory); + Message* released_message = self->message->GetReflection()->ReleaseMessage( + self->message, field_descriptor, message_factory); // ReleaseMessage will return NULL which differs from // child_cmessage->message, if the field does not exist. In this case, // the latter points to the default instance via a const_cast<>, so we @@ -1102,12 +1272,12 @@ Message* ReleaseMessage(Message* message, return released_message; } -int ReleaseSubMessage(Message* message, +int ReleaseSubMessage(CMessage* self, const FieldDescriptor* field_descriptor, CMessage* child_cmessage) { // Release the Message shared_ptr released_message(ReleaseMessage( - message, child_cmessage->message->GetDescriptor(), field_descriptor)); + self, child_cmessage->message->GetDescriptor(), field_descriptor)); child_cmessage->message = released_message.get(); child_cmessage->owner.swap(released_message); child_cmessage->parent = NULL; @@ -1119,8 +1289,8 @@ int ReleaseSubMessage(Message* message, struct ReleaseChild : public ChildVisitor { // message must outlive this object. - explicit ReleaseChild(Message* parent_message) : - parent_message_(parent_message) {} + explicit ReleaseChild(CMessage* parent) : + parent_(parent) {} int VisitRepeatedCompositeContainer(RepeatedCompositeContainer* container) { return repeated_composite_container::Release( @@ -1132,23 +1302,33 @@ struct ReleaseChild : public ChildVisitor { reinterpret_cast(container)); } + int VisitScalarMapContainer(ScalarMapContainer* container) { + return scalar_map_container::Release( + reinterpret_cast(container)); + } + + int VisitMessageMapContainer(MessageMapContainer* container) { + return message_map_container::Release( + reinterpret_cast(container)); + } + int VisitCMessage(CMessage* cmessage, const FieldDescriptor* field_descriptor) { - return ReleaseSubMessage(parent_message_, field_descriptor, + return ReleaseSubMessage(parent_, field_descriptor, reinterpret_cast(cmessage)); } - Message* parent_message_; + CMessage* parent_; }; int InternalReleaseFieldByDescriptor( + CMessage* self, const FieldDescriptor* field_descriptor, - PyObject* composite_field, - Message* parent_message) { + PyObject* composite_field) { return VisitCompositeField( field_descriptor, composite_field, - ReleaseChild(parent_message)); + ReleaseChild(self)); } PyObject* ClearFieldByDescriptor( @@ -1200,8 +1380,8 @@ PyObject* ClearField(CMessage* self, PyObject* arg) { // Only release the field if there's a possibility that there are // references to it. if (composite_field != NULL) { - if (InternalReleaseFieldByDescriptor(field_descriptor, - composite_field, message) < 0) { + if (InternalReleaseFieldByDescriptor(self, field_descriptor, + composite_field) < 0) { return NULL; } PyDict_DelItem(self->composite_fields, arg); @@ -1219,7 +1399,7 @@ PyObject* ClearField(CMessage* self, PyObject* arg) { PyObject* Clear(CMessage* self) { AssureWritable(self); - if (ForEachCompositeField(self, ReleaseChild(self->message)) == -1) + if (ForEachCompositeField(self, ReleaseChild(self)) == -1) return NULL; // The old ExtensionDict still aliases this CMessage, but all its @@ -1582,7 +1762,8 @@ static PyObject* ListFields(CMessage* self) { } if (fields[i]->is_extension()) { - ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(fields[i])); + ScopedPyObjectPtr extension_field( + PyFieldDescriptor_FromDescriptor(fields[i])); if (extension_field == NULL) { return NULL; } @@ -1616,7 +1797,8 @@ static PyObject* ListFields(CMessage* self) { PyErr_SetString(PyExc_ValueError, "bad string"); return NULL; } - ScopedPyObjectPtr field_descriptor(PyFieldDescriptor_New(fields[i])); + ScopedPyObjectPtr field_descriptor( + PyFieldDescriptor_FromDescriptor(fields[i])); if (field_descriptor == NULL) { return NULL; } @@ -1683,10 +1865,8 @@ static PyObject* RichCompare(CMessage* self, PyObject* other, int opid) { } } -PyObject* InternalGetScalar( - CMessage* self, - const FieldDescriptor* field_descriptor) { - Message* message = self->message; +PyObject* InternalGetScalar(const Message* message, + const FieldDescriptor* field_descriptor) { const Reflection* reflection = message->GetReflection(); if (!CheckFieldBelongsToMessage(field_descriptor, message)) { @@ -1739,12 +1919,12 @@ PyObject* InternalGetScalar( if (!message->GetReflection()->SupportsUnknownEnumValues() && !message->GetReflection()->HasField(*message, field_descriptor)) { // Look for the value in the unknown fields. - UnknownFieldSet* unknown_field_set = - message->GetReflection()->MutableUnknownFields(message); - for (int i = 0; i < unknown_field_set->field_count(); ++i) { - if (unknown_field_set->field(i).number() == + const UnknownFieldSet& unknown_field_set = + message->GetReflection()->GetUnknownFields(*message); + for (int i = 0; i < unknown_field_set.field_count(); ++i) { + if (unknown_field_set.field(i).number() == field_descriptor->number()) { - result = PyInt_FromLong(unknown_field_set->field(i).varint()); + result = PyInt_FromLong(unknown_field_set.field(i).varint()); break; } } @@ -1793,21 +1973,16 @@ PyObject* InternalGetSubMessage( return reinterpret_cast(cmsg); } -int InternalSetScalar( - CMessage* self, +int InternalSetNonOneofScalar( + Message* message, const FieldDescriptor* field_descriptor, PyObject* arg) { - Message* message = self->message; const Reflection* reflection = message->GetReflection(); if (!CheckFieldBelongsToMessage(field_descriptor, message)) { return -1; } - if (MaybeReleaseOverlappingOneofField(self, field_descriptor) < 0) { - return -1; - } - switch (field_descriptor->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: { GOOGLE_CHECK_GET_INT32(arg, value, -1); @@ -1878,6 +2053,21 @@ int InternalSetScalar( return 0; } +int InternalSetScalar( + CMessage* self, + const FieldDescriptor* field_descriptor, + PyObject* arg) { + if (!CheckFieldBelongsToMessage(field_descriptor, self->message)) { + return -1; + } + + if (MaybeReleaseOverlappingOneofField(self, field_descriptor) < 0) { + return -1; + } + + return InternalSetNonOneofScalar(self->message, field_descriptor, arg); +} + PyObject* FromString(PyTypeObject* cls, PyObject* serialized) { PyObject* py_cmsg = PyObject_CallObject( reinterpret_cast(cls), NULL); @@ -1955,7 +2145,8 @@ static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) { // which was built previously. for (int i = 0; i < message_descriptor->enum_type_count(); ++i) { const EnumDescriptor* enum_descriptor = message_descriptor->enum_type(i); - ScopedPyObjectPtr enum_type(PyEnumDescriptor_New(enum_descriptor)); + ScopedPyObjectPtr enum_type( + PyEnumDescriptor_FromDescriptor(enum_descriptor)); if (enum_type == NULL) { return NULL; } @@ -1993,7 +2184,7 @@ static PyObject* AddDescriptors(PyObject* cls, PyObject* descriptor) { // which was defined previously. for (int i = 0; i < message_descriptor->extension_count(); ++i) { const google::protobuf::FieldDescriptor* field = message_descriptor->extension(i); - ScopedPyObjectPtr extension_field(PyFieldDescriptor_New(field)); + ScopedPyObjectPtr extension_field(PyFieldDescriptor_FromDescriptor(field)); if (extension_field == NULL) { return NULL; } @@ -2097,26 +2288,6 @@ PyObject* SetState(CMessage* self, PyObject* state) { } // CMessage static methods: -PyObject* _GetMessageDescriptor(PyObject* unused, PyObject* arg) { - return cdescriptor_pool::FindMessageByName(GetDescriptorPool(), arg); -} - -PyObject* _GetFieldDescriptor(PyObject* unused, PyObject* arg) { - return cdescriptor_pool::FindFieldByName(GetDescriptorPool(), arg); -} - -PyObject* _GetExtensionDescriptor(PyObject* unused, PyObject* arg) { - return cdescriptor_pool::FindExtensionByName(GetDescriptorPool(), arg); -} - -PyObject* _GetEnumDescriptor(PyObject* unused, PyObject* arg) { - return cdescriptor_pool::FindEnumTypeByName(GetDescriptorPool(), arg); -} - -PyObject* _GetOneofDescriptor(PyObject* unused, PyObject* arg) { - return cdescriptor_pool::FindOneofByName(GetDescriptorPool(), arg); -} - PyObject* _CheckCalledFromGeneratedFile(PyObject* unused, PyObject* unused_arg) { if (!_CalledFromGeneratedFile(1)) { @@ -2188,21 +2359,6 @@ static PyMethodDef Methods[] = { "or None if no field is set." }, // Static Methods. - { "_BuildFile", (PyCFunction)Python_BuildFile, METH_O | METH_STATIC, - "Registers a new protocol buffer file in the global C++ descriptor pool." }, - { "_GetMessageDescriptor", (PyCFunction)_GetMessageDescriptor, - METH_O | METH_STATIC, "Finds a message descriptor in the message pool." }, - { "_GetFieldDescriptor", (PyCFunction)_GetFieldDescriptor, - METH_O | METH_STATIC, "Finds a field descriptor in the message pool." }, - { "_GetExtensionDescriptor", (PyCFunction)_GetExtensionDescriptor, - METH_O | METH_STATIC, - "Finds a extension descriptor in the message pool." }, - { "_GetEnumDescriptor", (PyCFunction)_GetEnumDescriptor, - METH_O | METH_STATIC, - "Finds an enum descriptor in the message pool." }, - { "_GetOneofDescriptor", (PyCFunction)_GetOneofDescriptor, - METH_O | METH_STATIC, - "Finds an oneof descriptor in the message pool." }, { "_CheckCalledFromGeneratedFile", (PyCFunction)_CheckCalledFromGeneratedFile, METH_NOARGS | METH_STATIC, "Raises TypeError if the caller is not in a _pb2.py file."}, @@ -2234,6 +2390,31 @@ PyObject* GetAttr(CMessage* self, PyObject* name) { reinterpret_cast(self), name); } + if (field_descriptor->is_map()) { + PyObject* py_container = NULL; + const Descriptor* entry_type = field_descriptor->message_type(); + const FieldDescriptor* value_type = entry_type->FindFieldByName("value"); + if (value_type->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + PyObject* value_class = cdescriptor_pool::GetMessageClass( + GetDescriptorPool(), value_type->message_type()); + if (value_class == NULL) { + return NULL; + } + py_container = message_map_container::NewContainer(self, field_descriptor, + value_class); + } else { + py_container = scalar_map_container::NewContainer(self, field_descriptor); + } + if (py_container == NULL) { + return NULL; + } + if (!SetCompositeField(self, name, py_container)) { + Py_DECREF(py_container); + return NULL; + } + return py_container; + } + if (field_descriptor->label() == FieldDescriptor::LABEL_REPEATED) { PyObject* py_container = NULL; if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { @@ -2267,7 +2448,7 @@ PyObject* GetAttr(CMessage* self, PyObject* name) { return sub_message; } - return InternalGetScalar(self, field_descriptor); + return InternalGetScalar(self->message, field_descriptor); } int SetAttr(CMessage* self, PyObject* name, PyObject* value) { @@ -2304,9 +2485,7 @@ int SetAttr(CMessage* self, PyObject* name, PyObject* value) { PyTypeObject CMessage_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - // Keep the fully qualified _message symbol in a line for opensource. - "google.protobuf.pyext._message." - "CMessage", // tp_name + FULL_MODULE_NAME ".CMessage", // tp_name sizeof(CMessage), // tp_basicsize 0, // tp_itemsize (destructor)cmessage::Dealloc, // tp_dealloc @@ -2401,7 +2580,7 @@ void InitGlobals() { k_extensions_by_name = PyString_FromString("_extensions_by_name"); k_extensions_by_number = PyString_FromString("_extensions_by_number"); - message_factory = new DynamicMessageFactory(GetDescriptorPool()->pool); + message_factory = new DynamicMessageFactory(); message_factory->SetDelegateToGeneratedFactory(true); } @@ -2469,6 +2648,61 @@ bool InitProto2MessageModule(PyObject *m) { reinterpret_cast( &RepeatedCompositeContainer_Type)); + // ScalarMapContainer_Type derives from our MutableMapping type. + PyObject* containers = + PyImport_ImportModule("google.protobuf.internal.containers"); + if (containers == NULL) { + return false; + } + + PyObject* mutable_mapping = + PyObject_GetAttrString(containers, "MutableMapping"); + Py_DECREF(containers); + + if (mutable_mapping == NULL) { + return false; + } + + if (!PyObject_TypeCheck(mutable_mapping, &PyType_Type)) { + Py_DECREF(mutable_mapping); + return false; + } + + ScalarMapContainer_Type.tp_base = + reinterpret_cast(mutable_mapping); + + if (PyType_Ready(&ScalarMapContainer_Type) < 0) { + return false; + } + + PyModule_AddObject(m, "ScalarMapContainer", + reinterpret_cast(&ScalarMapContainer_Type)); + + if (PyType_Ready(&ScalarMapIterator_Type) < 0) { + return false; + } + + PyModule_AddObject(m, "ScalarMapIterator", + reinterpret_cast(&ScalarMapIterator_Type)); + + Py_INCREF(mutable_mapping); + MessageMapContainer_Type.tp_base = + reinterpret_cast(mutable_mapping); + + if (PyType_Ready(&MessageMapContainer_Type) < 0) { + return false; + } + + PyModule_AddObject(m, "MessageMapContainer", + reinterpret_cast(&MessageMapContainer_Type)); + + if (PyType_Ready(&MessageMapIterator_Type) < 0) { + return false; + } + + PyModule_AddObject(m, "MessageMapIterator", + reinterpret_cast(&MessageMapIterator_Type)); + ExtensionDict_Type.tp_hash = PyObject_HashNotImplemented; if (PyType_Ready(&ExtensionDict_Type) < 0) { return false; @@ -2478,6 +2712,12 @@ bool InitProto2MessageModule(PyObject *m) { m, "ExtensionDict", reinterpret_cast(&ExtensionDict_Type)); + // Expose the DescriptorPool used to hold all descriptors added from generated + // pb2.py files. + Py_INCREF(GetDescriptorPool()); // PyModule_AddObject steals a reference. + PyModule_AddObject( + m, "default_pool", reinterpret_cast(GetDescriptorPool())); + // This implementation provides full Descriptor types, we advertise it so that // descriptor.py can use them in replacement of the Python classes. PyModule_AddIntConstant(m, "_USE_C_DESCRIPTORS", 1); diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h index 2f2da795..7360b207 100644 --- a/python/google/protobuf/pyext/message.h +++ b/python/google/protobuf/pyext/message.h @@ -120,7 +120,7 @@ CMessage* NewEmptyMessage(PyObject* type, const Descriptor* descriptor); // A new message will be created if this is a read-only default instance. // // Corresponds to reflection api method ReleaseMessage. -int ReleaseSubMessage(Message* message, +int ReleaseSubMessage(CMessage* self, const FieldDescriptor* field_descriptor, CMessage* child_cmessage); @@ -144,7 +144,7 @@ PyObject* InternalGetSubMessage( // by slice will be removed from cmessage_list by this function. // // Corresponds to reflection api method RemoveLast. -int InternalDeleteRepeatedField(Message* message, +int InternalDeleteRepeatedField(CMessage* self, const FieldDescriptor* field_descriptor, PyObject* slice, PyObject* cmessage_list); @@ -153,10 +153,15 @@ int InternalSetScalar(CMessage* self, const FieldDescriptor* field_descriptor, PyObject* value); +// Sets the specified scalar value to the message. Requires it is not a Oneof. +int InternalSetNonOneofScalar(Message* message, + const FieldDescriptor* field_descriptor, + PyObject* arg); + // Retrieves the specified scalar value from the message. // // Returns a new python reference. -PyObject* InternalGetScalar(CMessage* self, +PyObject* InternalGetScalar(const Message* message, const FieldDescriptor* field_descriptor); // Clears the message, removing all contained data. Extension dictionary and @@ -279,7 +284,7 @@ extern PyObject* kint64min_py; extern PyObject* kint64max_py; extern PyObject* kuint64max_py; -#define C(str) const_cast(str) +#define FULL_MODULE_NAME "google.protobuf.pyext._message" void FormatTypeError(PyObject* arg, char* expected_types); template diff --git a/python/google/protobuf/pyext/message_map_container.cc b/python/google/protobuf/pyext/message_map_container.cc new file mode 100644 index 00000000..ab8d8fb9 --- /dev/null +++ b/python/google/protobuf/pyext/message_map_container.cc @@ -0,0 +1,540 @@ +// 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. + +// Author: haberman@google.com (Josh Haberman) + +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace python { + +struct MessageMapIterator { + PyObject_HEAD; + + // This dict contains the full contents of what we want to iterate over. + // There's no way to avoid building this, because the list representation + // (which is canonical) can contain duplicate keys. So at the very least we + // need a set that lets us skip duplicate keys. And at the point that we're + // doing that, we might as well just build the actual dict we're iterating + // over and use dict's built-in iterator. + PyObject* dict; + + // An iterator on dict. + PyObject* iter; + + // A pointer back to the container, so we can notice changes to the version. + MessageMapContainer* container; + + // The version of the map when we took the iterator to it. + // + // We store this so that if the map is modified during iteration we can throw + // an error. + uint64 version; +}; + +static MessageMapIterator* GetIter(PyObject* obj) { + return reinterpret_cast(obj); +} + +namespace message_map_container { + +static MessageMapContainer* GetMap(PyObject* obj) { + return reinterpret_cast(obj); +} + +// The private constructor of MessageMapContainer objects. +PyObject* NewContainer(CMessage* parent, + const google::protobuf::FieldDescriptor* parent_field_descriptor, + PyObject* concrete_class) { + if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { + return NULL; + } + + PyObject* obj = PyType_GenericAlloc(&MessageMapContainer_Type, 0); + if (obj == NULL) { + return PyErr_Format(PyExc_RuntimeError, + "Could not allocate new container."); + } + + MessageMapContainer* self = GetMap(obj); + + self->message = parent->message; + self->parent = parent; + self->parent_field_descriptor = parent_field_descriptor; + self->owner = parent->owner; + self->version = 0; + + self->key_field_descriptor = + parent_field_descriptor->message_type()->FindFieldByName("key"); + self->value_field_descriptor = + parent_field_descriptor->message_type()->FindFieldByName("value"); + + self->message_dict = PyDict_New(); + if (self->message_dict == NULL) { + return PyErr_Format(PyExc_RuntimeError, + "Could not allocate message dict."); + } + + Py_INCREF(concrete_class); + self->subclass_init = concrete_class; + + if (self->key_field_descriptor == NULL || + self->value_field_descriptor == NULL) { + Py_DECREF(obj); + return PyErr_Format(PyExc_KeyError, + "Map entry descriptor did not have key/value fields"); + } + + return obj; +} + +// Initializes the underlying Message object of "to" so it becomes a new parent +// repeated scalar, and copies all the values from "from" to it. A child scalar +// container can be released by passing it as both from and to (e.g. making it +// the recipient of the new parent message and copying the values from itself). +static int InitializeAndCopyToParentContainer( + MessageMapContainer* from, + MessageMapContainer* to) { + // For now we require from == to, re-evaluate if we want to support deep copy + // as in repeated_composite_container.cc. + GOOGLE_DCHECK(from == to); + Message* old_message = from->message; + Message* new_message = old_message->New(); + to->parent = NULL; + to->parent_field_descriptor = from->parent_field_descriptor; + to->message = new_message; + to->owner.reset(new_message); + + vector fields; + fields.push_back(from->parent_field_descriptor); + old_message->GetReflection()->SwapFields(old_message, new_message, fields); + return 0; +} + +static PyObject* GetCMessage(MessageMapContainer* self, Message* entry) { + // Get or create the CMessage object corresponding to this message. + Message* message = entry->GetReflection()->MutableMessage( + entry, self->value_field_descriptor); + ScopedPyObjectPtr key(PyLong_FromVoidPtr(message)); + PyObject* ret = PyDict_GetItem(self->message_dict, key); + + if (ret == NULL) { + CMessage* cmsg = cmessage::NewEmptyMessage(self->subclass_init, + message->GetDescriptor()); + ret = reinterpret_cast(cmsg); + + if (cmsg == NULL) { + return NULL; + } + cmsg->owner = self->owner; + cmsg->message = message; + cmsg->parent = self->parent; + + if (PyDict_SetItem(self->message_dict, key, ret) < 0) { + Py_DECREF(ret); + return NULL; + } + } else { + Py_INCREF(ret); + } + + return ret; +} + +int Release(MessageMapContainer* self) { + InitializeAndCopyToParentContainer(self, self); + return 0; +} + +void SetOwner(MessageMapContainer* self, + const shared_ptr& new_owner) { + self->owner = new_owner; +} + +Py_ssize_t Length(PyObject* _self) { + MessageMapContainer* self = GetMap(_self); + google::protobuf::Message* message = self->message; + return message->GetReflection()->FieldSize(*message, + self->parent_field_descriptor); +} + +int MapKeyMatches(MessageMapContainer* self, const Message* entry, + PyObject* key) { + // TODO(haberman): do we need more strict type checking? + ScopedPyObjectPtr entry_key( + cmessage::InternalGetScalar(entry, self->key_field_descriptor)); + int ret = PyObject_RichCompareBool(key, entry_key, Py_EQ); + return ret; +} + +int SetItem(PyObject *_self, PyObject *key, PyObject *v) { + if (v) { + PyErr_Format(PyExc_ValueError, + "Direct assignment of submessage not allowed"); + return -1; + } + + // Now we know that this is a delete, not a set. + + MessageMapContainer* self = GetMap(_self); + cmessage::AssureWritable(self->parent); + + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + size_t size = + reflection->FieldSize(*message, self->parent_field_descriptor); + + // Right now the Reflection API doesn't support map lookup, so we implement it + // via linear search. We need to search from the end because the underlying + // representation can have duplicates if a user calls MergeFrom(); the last + // one needs to win. + // + // TODO(haberman): add lookup API to Reflection API. + bool found = false; + for (int i = size - 1; i >= 0; i--) { + Message* entry = reflection->MutableRepeatedMessage( + message, self->parent_field_descriptor, i); + int matches = MapKeyMatches(self, entry, key); + if (matches < 0) return -1; + if (matches) { + found = true; + if (i != size - 1) { + reflection->SwapElements(message, self->parent_field_descriptor, i, + size - 1); + } + reflection->RemoveLast(message, self->parent_field_descriptor); + + // Can't exit now, the repeated field representation of maps allows + // duplicate keys, and we have to be sure to remove all of them. + } + } + + if (!found) { + PyErr_Format(PyExc_KeyError, "Key not present in map"); + return -1; + } + + self->version++; + + return 0; +} + +PyObject* GetIterator(PyObject *_self) { + MessageMapContainer* self = GetMap(_self); + + ScopedPyObjectPtr obj(PyType_GenericAlloc(&MessageMapIterator_Type, 0)); + if (obj == NULL) { + return PyErr_Format(PyExc_KeyError, "Could not allocate iterator"); + } + + MessageMapIterator* iter = GetIter(obj); + + Py_INCREF(self); + iter->container = self; + iter->version = self->version; + iter->dict = PyDict_New(); + if (iter->dict == NULL) { + return PyErr_Format(PyExc_RuntimeError, + "Could not allocate dict for iterator."); + } + + // Build the entire map into a dict right now. Start from the beginning so + // that later entries win in the case of duplicates. + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + + // Right now the Reflection API doesn't support map lookup, so we implement it + // via linear search. We need to search from the end because the underlying + // representation can have duplicates if a user calls MergeFrom(); the last + // one needs to win. + // + // TODO(haberman): add lookup API to Reflection API. + size_t size = + reflection->FieldSize(*message, self->parent_field_descriptor); + for (int i = size - 1; i >= 0; i--) { + Message* entry = reflection->MutableRepeatedMessage( + message, self->parent_field_descriptor, i); + ScopedPyObjectPtr key( + cmessage::InternalGetScalar(entry, self->key_field_descriptor)); + if (PyDict_SetItem(iter->dict, key.get(), GetCMessage(self, entry)) < 0) { + return PyErr_Format(PyExc_RuntimeError, + "SetItem failed in iterator construction."); + } + } + + iter->iter = PyObject_GetIter(iter->dict); + + return obj.release(); +} + +PyObject* GetItem(PyObject* _self, PyObject* key) { + MessageMapContainer* self = GetMap(_self); + cmessage::AssureWritable(self->parent); + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + + // Right now the Reflection API doesn't support map lookup, so we implement it + // via linear search. We need to search from the end because the underlying + // representation can have duplicates if a user calls MergeFrom(); the last + // one needs to win. + // + // TODO(haberman): add lookup API to Reflection API. + size_t size = + reflection->FieldSize(*message, self->parent_field_descriptor); + for (int i = size - 1; i >= 0; i--) { + Message* entry = reflection->MutableRepeatedMessage( + message, self->parent_field_descriptor, i); + int matches = MapKeyMatches(self, entry, key); + if (matches < 0) return NULL; + if (matches) { + return GetCMessage(self, entry); + } + } + + // Key is not already present; insert a new entry. + Message* entry = + reflection->AddMessage(message, self->parent_field_descriptor); + + self->version++; + + if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor, + key) < 0) { + reflection->RemoveLast(message, self->parent_field_descriptor); + return NULL; + } + + return GetCMessage(self, entry); +} + +PyObject* Contains(PyObject* _self, PyObject* key) { + MessageMapContainer* self = GetMap(_self); + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + + // Right now the Reflection API doesn't support map lookup, so we implement it + // via linear search. + // + // TODO(haberman): add lookup API to Reflection API. + size_t size = + reflection->FieldSize(*message, self->parent_field_descriptor); + for (int i = 0; i < size; i++) { + Message* entry = reflection->MutableRepeatedMessage( + message, self->parent_field_descriptor, i); + int matches = MapKeyMatches(self, entry, key); + if (matches < 0) return NULL; + if (matches) { + Py_RETURN_TRUE; + } + } + + Py_RETURN_FALSE; +} + +PyObject* Clear(PyObject* _self) { + MessageMapContainer* self = GetMap(_self); + cmessage::AssureWritable(self->parent); + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + + self->version++; + reflection->ClearField(message, self->parent_field_descriptor); + + Py_RETURN_NONE; +} + +PyObject* Get(PyObject* self, PyObject* args) { + PyObject* key; + PyObject* default_value = NULL; + if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) { + return NULL; + } + + ScopedPyObjectPtr is_present(Contains(self, key)); + if (is_present.get() == NULL) { + return NULL; + } + + if (PyObject_IsTrue(is_present.get())) { + return GetItem(self, key); + } else { + if (default_value != NULL) { + Py_INCREF(default_value); + return default_value; + } else { + Py_RETURN_NONE; + } + } +} + +static PyMappingMethods MpMethods = { + Length, // mp_length + GetItem, // mp_subscript + SetItem, // mp_ass_subscript +}; + +static void Dealloc(PyObject* _self) { + MessageMapContainer* self = GetMap(_self); + self->owner.reset(); + Py_DECREF(self->message_dict); + Py_TYPE(_self)->tp_free(_self); +} + +static PyMethodDef Methods[] = { + { "__contains__", (PyCFunction)Contains, METH_O, + "Tests whether the map contains this element."}, + { "clear", (PyCFunction)Clear, METH_NOARGS, + "Removes all elements from the map."}, + { "get", Get, METH_VARARGS, + "Gets the value for the given key if present, or otherwise a default" }, + { "get_or_create", GetItem, METH_O, + "Alias for getitem, useful to make explicit that the map is mutated." }, + /* + { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + "Makes a deep copy of the class." }, + { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, + "Outputs picklable representation of the repeated field." }, + */ + {NULL, NULL}, +}; + +} // namespace message_map_container + +namespace message_map_iterator { + +static void Dealloc(PyObject* _self) { + MessageMapIterator* self = GetIter(_self); + Py_DECREF(self->dict); + Py_DECREF(self->iter); + Py_DECREF(self->container); + Py_TYPE(_self)->tp_free(_self); +} + +PyObject* IterNext(PyObject* _self) { + MessageMapIterator* self = GetIter(_self); + + // This won't catch mutations to the map performed by MergeFrom(); no easy way + // to address that. + if (self->version != self->container->version) { + return PyErr_Format(PyExc_RuntimeError, + "Map modified during iteration."); + } + + return PyIter_Next(self->iter); +} + +} // namespace message_map_iterator + +PyTypeObject MessageMapContainer_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + FULL_MODULE_NAME ".MessageMapContainer", // tp_name + sizeof(MessageMapContainer), // tp_basicsize + 0, // tp_itemsize + message_map_container::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + &message_map_container::MpMethods, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A map container for message", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + message_map_container::GetIterator, // tp_iter + 0, // tp_iternext + message_map_container::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init +}; + +PyTypeObject MessageMapIterator_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + FULL_MODULE_NAME ".MessageMapIterator", // tp_name + sizeof(MessageMapIterator), // tp_basicsize + 0, // tp_itemsize + message_map_iterator::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A scalar map iterator", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + PyObject_SelfIter, // tp_iter + message_map_iterator::IterNext, // tp_iternext + 0, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init +}; + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/message_map_container.h b/python/google/protobuf/pyext/message_map_container.h new file mode 100644 index 00000000..4ca0aecc --- /dev/null +++ b/python/google/protobuf/pyext/message_map_container.h @@ -0,0 +1,117 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__ + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif + +#include + +namespace google { +namespace protobuf { + +class Message; + +using internal::shared_ptr; + +namespace python { + +struct CMessage; + +struct MessageMapContainer { + PyObject_HEAD; + + // This is the top-level C++ Message object that owns the whole + // proto tree. Every Python MessageMapContainer holds a + // reference to it in order to keep it alive as long as there's a + // Python object that references any part of the tree. + shared_ptr owner; + + // Pointer to the C++ Message that contains this container. The + // MessageMapContainer does not own this pointer. + Message* message; + + // Weak reference to a parent CMessage object (i.e. may be NULL.) + // + // Used to make sure all ancestors are also mutable when first + // modifying the container. + CMessage* parent; + + // Pointer to the parent's descriptor that describes this + // field. Used together with the parent's message when making a + // default message instance mutable. + // The pointer is owned by the global DescriptorPool. + const FieldDescriptor* parent_field_descriptor; + const FieldDescriptor* key_field_descriptor; + const FieldDescriptor* value_field_descriptor; + + // A callable that is used to create new child messages. + PyObject* subclass_init; + + // A dict mapping Message* -> CMessage. + PyObject* message_dict; + + // We bump this whenever we perform a mutation, to invalidate existing + // iterators. + uint64 version; +}; + +extern PyTypeObject MessageMapContainer_Type; +extern PyTypeObject MessageMapIterator_Type; + +namespace message_map_container { + +// Builds a MessageMapContainer object, from a parent message and a +// field descriptor. +extern PyObject* NewContainer(CMessage* parent, + const FieldDescriptor* parent_field_descriptor, + PyObject* concrete_class); + +// Releases the messages in the container to a new message. +// +// Returns 0 on success, -1 on failure. +int Release(MessageMapContainer* self); + +// Set the owner field of self and any children of self. +void SetOwner(MessageMapContainer* self, + const shared_ptr& new_owner); + +} // namespace message_map_container +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_MESSAGE_MAP_CONTAINER_H__ diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc index 0fe98e73..86b75d0f 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.cc +++ b/python/google/protobuf/pyext/repeated_composite_container.cc @@ -367,8 +367,8 @@ int AssignSubscript(RepeatedCompositeContainer* self, } // Delete from the underlying Message, if any. - if (self->message != NULL) { - if (cmessage::InternalDeleteRepeatedField(self->message, + if (self->parent != NULL) { + if (cmessage::InternalDeleteRepeatedField(self->parent, self->parent_field_descriptor, slice, self->child_messages) < 0) { @@ -572,47 +572,35 @@ static PyObject* Pop(RepeatedCompositeContainer* self, return item; } -// The caller takes ownership of the returned Message. -Message* ReleaseLast(const FieldDescriptor* field, - const Descriptor* type, - Message* message) { +// Release field of parent message and transfer the ownership to target. +void ReleaseLastTo(CMessage* parent, + const FieldDescriptor* field, + CMessage* target) { + GOOGLE_CHECK_NOTNULL(parent); GOOGLE_CHECK_NOTNULL(field); - GOOGLE_CHECK_NOTNULL(type); - GOOGLE_CHECK_NOTNULL(message); + GOOGLE_CHECK_NOTNULL(target); - Message* released_message = message->GetReflection()->ReleaseLast( - message, field); + shared_ptr released_message( + parent->message->GetReflection()->ReleaseLast(parent->message, field)); // TODO(tibell): Deal with proto1. // ReleaseMessage will return NULL which differs from // child_cmessage->message, if the field does not exist. In this case, // the latter points to the default instance via a const_cast<>, so we // have to reset it to a new mutable object since we are taking ownership. - if (released_message == NULL) { + if (released_message.get() == NULL) { const Message* prototype = - cmessage::GetMessageFactory()->GetPrototype(type); + cmessage::GetMessageFactory()->GetPrototype( + target->message->GetDescriptor()); GOOGLE_CHECK_NOTNULL(prototype); - return prototype->New(); - } else { - return released_message; + released_message.reset(prototype->New()); } -} -// Release field of message and transfer the ownership to cmessage. -void ReleaseLastTo(const FieldDescriptor* field, - Message* message, - CMessage* cmessage) { - GOOGLE_CHECK_NOTNULL(field); - GOOGLE_CHECK_NOTNULL(message); - GOOGLE_CHECK_NOTNULL(cmessage); - - shared_ptr released_message( - ReleaseLast(field, cmessage->message->GetDescriptor(), message)); - cmessage->parent = NULL; - cmessage->parent_field_descriptor = NULL; - cmessage->message = released_message.get(); - cmessage->read_only = false; - cmessage::SetOwner(cmessage, released_message); + target->parent = NULL; + target->parent_field_descriptor = NULL; + target->message = released_message.get(); + target->read_only = false; + cmessage::SetOwner(target, released_message); } // Called to release a container using @@ -635,7 +623,7 @@ int Release(RepeatedCompositeContainer* self) { for (Py_ssize_t i = size - 1; i >= 0; --i) { CMessage* child_cmessage = reinterpret_cast( PyList_GET_ITEM(self->child_messages, i)); - ReleaseLastTo(field, message, child_cmessage); + ReleaseLastTo(self->parent, field, child_cmessage); } // Detach from containing message. @@ -732,9 +720,7 @@ static PyMethodDef Methods[] = { PyTypeObject RepeatedCompositeContainer_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - // Keep the fully qualified _message symbol in a line for opensource. - "google.protobuf.pyext._message." - "RepeatedCompositeContainer", // tp_name + FULL_MODULE_NAME ".RepeatedCompositeContainer", // tp_name sizeof(RepeatedCompositeContainer), // tp_basicsize 0, // tp_itemsize (destructor)repeated_composite_container::Dealloc, // tp_dealloc diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h index ce7cee0f..e0f21360 100644 --- a/python/google/protobuf/pyext/repeated_composite_container.h +++ b/python/google/protobuf/pyext/repeated_composite_container.h @@ -161,13 +161,13 @@ int SetOwner(RepeatedCompositeContainer* self, const shared_ptr& new_owner); // Removes the last element of the repeated message field 'field' on -// the Message 'message', and transfers the ownership of the released -// Message to 'cmessage'. +// the Message 'parent', and transfers the ownership of the released +// Message to 'target'. // // Corresponds to reflection api method ReleaseMessage. -void ReleaseLastTo(const FieldDescriptor* field, - Message* message, - CMessage* cmessage); +void ReleaseLastTo(CMessage* parent, + const FieldDescriptor* field, + CMessage* target); } // namespace repeated_composite_container } // namespace python diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc index 110a4c85..fd196836 100644 --- a/python/google/protobuf/pyext/repeated_scalar_container.cc +++ b/python/google/protobuf/pyext/repeated_scalar_container.cc @@ -102,7 +102,7 @@ static int AssignItem(RepeatedScalarContainer* self, if (arg == NULL) { ScopedPyObjectPtr py_index(PyLong_FromLong(index)); - return cmessage::InternalDeleteRepeatedField(message, field_descriptor, + return cmessage::InternalDeleteRepeatedField(self->parent, field_descriptor, py_index, NULL); } @@ -470,7 +470,7 @@ static int AssSubscript(RepeatedScalarContainer* self, if (value == NULL) { return cmessage::InternalDeleteRepeatedField( - message, field_descriptor, slice, NULL); + self->parent, field_descriptor, slice, NULL); } if (!create_list) { @@ -769,9 +769,7 @@ static PyMethodDef Methods[] = { PyTypeObject RepeatedScalarContainer_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) - // Keep the fully qualified _message symbol in a line for opensource. - "google.protobuf.pyext._message." - "RepeatedScalarContainer", // tp_name + FULL_MODULE_NAME ".RepeatedScalarContainer", // tp_name sizeof(RepeatedScalarContainer), // tp_basicsize 0, // tp_itemsize (destructor)repeated_scalar_container::Dealloc, // tp_dealloc diff --git a/python/google/protobuf/pyext/scalar_map_container.cc b/python/google/protobuf/pyext/scalar_map_container.cc new file mode 100644 index 00000000..6f731d27 --- /dev/null +++ b/python/google/protobuf/pyext/scalar_map_container.cc @@ -0,0 +1,514 @@ +// 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. + +// Author: haberman@google.com (Josh Haberman) + +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace python { + +struct ScalarMapIterator { + PyObject_HEAD; + + // This dict contains the full contents of what we want to iterate over. + // There's no way to avoid building this, because the list representation + // (which is canonical) can contain duplicate keys. So at the very least we + // need a set that lets us skip duplicate keys. And at the point that we're + // doing that, we might as well just build the actual dict we're iterating + // over and use dict's built-in iterator. + PyObject* dict; + + // An iterator on dict. + PyObject* iter; + + // A pointer back to the container, so we can notice changes to the version. + ScalarMapContainer* container; + + // The version of the map when we took the iterator to it. + // + // We store this so that if the map is modified during iteration we can throw + // an error. + uint64 version; +}; + +static ScalarMapIterator* GetIter(PyObject* obj) { + return reinterpret_cast(obj); +} + +namespace scalar_map_container { + +static ScalarMapContainer* GetMap(PyObject* obj) { + return reinterpret_cast(obj); +} + +// The private constructor of ScalarMapContainer objects. +PyObject *NewContainer( + CMessage* parent, const google::protobuf::FieldDescriptor* parent_field_descriptor) { + if (!CheckFieldBelongsToMessage(parent_field_descriptor, parent->message)) { + return NULL; + } + + ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapContainer_Type, 0)); + if (obj.get() == NULL) { + return PyErr_Format(PyExc_RuntimeError, + "Could not allocate new container."); + } + + ScalarMapContainer* self = GetMap(obj); + + self->message = parent->message; + self->parent = parent; + self->parent_field_descriptor = parent_field_descriptor; + self->owner = parent->owner; + self->version = 0; + + self->key_field_descriptor = + parent_field_descriptor->message_type()->FindFieldByName("key"); + self->value_field_descriptor = + parent_field_descriptor->message_type()->FindFieldByName("value"); + + if (self->key_field_descriptor == NULL || + self->value_field_descriptor == NULL) { + return PyErr_Format(PyExc_KeyError, + "Map entry descriptor did not have key/value fields"); + } + + return obj.release(); +} + +// Initializes the underlying Message object of "to" so it becomes a new parent +// repeated scalar, and copies all the values from "from" to it. A child scalar +// container can be released by passing it as both from and to (e.g. making it +// the recipient of the new parent message and copying the values from itself). +static int InitializeAndCopyToParentContainer( + ScalarMapContainer* from, + ScalarMapContainer* to) { + // For now we require from == to, re-evaluate if we want to support deep copy + // as in repeated_scalar_container.cc. + GOOGLE_DCHECK(from == to); + Message* old_message = from->message; + Message* new_message = old_message->New(); + to->parent = NULL; + to->parent_field_descriptor = from->parent_field_descriptor; + to->message = new_message; + to->owner.reset(new_message); + + vector fields; + fields.push_back(from->parent_field_descriptor); + old_message->GetReflection()->SwapFields(old_message, new_message, fields); + return 0; +} + +int Release(ScalarMapContainer* self) { + return InitializeAndCopyToParentContainer(self, self); +} + +void SetOwner(ScalarMapContainer* self, + const shared_ptr& new_owner) { + self->owner = new_owner; +} + +Py_ssize_t Length(PyObject* _self) { + ScalarMapContainer* self = GetMap(_self); + google::protobuf::Message* message = self->message; + return message->GetReflection()->FieldSize(*message, + self->parent_field_descriptor); +} + +int MapKeyMatches(ScalarMapContainer* self, const Message* entry, + PyObject* key) { + // TODO(haberman): do we need more strict type checking? + ScopedPyObjectPtr entry_key( + cmessage::InternalGetScalar(entry, self->key_field_descriptor)); + int ret = PyObject_RichCompareBool(key, entry_key, Py_EQ); + return ret; +} + +PyObject* GetItem(PyObject* _self, PyObject* key) { + ScalarMapContainer* self = GetMap(_self); + + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + + // Right now the Reflection API doesn't support map lookup, so we implement it + // via linear search. + // + // TODO(haberman): add lookup API to Reflection API. + size_t size = reflection->FieldSize(*message, self->parent_field_descriptor); + for (int i = size - 1; i >= 0; i--) { + const Message& entry = reflection->GetRepeatedMessage( + *message, self->parent_field_descriptor, i); + int matches = MapKeyMatches(self, &entry, key); + if (matches < 0) return NULL; + if (matches) { + return cmessage::InternalGetScalar(&entry, self->value_field_descriptor); + } + } + + // Need to add a new entry. + Message* entry = + reflection->AddMessage(message, self->parent_field_descriptor); + PyObject* ret = NULL; + + if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor, + key) >= 0) { + ret = cmessage::InternalGetScalar(entry, self->value_field_descriptor); + } + + self->version++; + + // If there was a type error above, it set the Python exception. + return ret; +} + +int SetItem(PyObject *_self, PyObject *key, PyObject *v) { + ScalarMapContainer* self = GetMap(_self); + cmessage::AssureWritable(self->parent); + + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + size_t size = + reflection->FieldSize(*message, self->parent_field_descriptor); + self->version++; + + if (v) { + // Set item. + // + // Right now the Reflection API doesn't support map lookup, so we implement + // it via linear search. + // + // TODO(haberman): add lookup API to Reflection API. + for (int i = size - 1; i >= 0; i--) { + Message* entry = reflection->MutableRepeatedMessage( + message, self->parent_field_descriptor, i); + int matches = MapKeyMatches(self, entry, key); + if (matches < 0) return -1; + if (matches) { + return cmessage::InternalSetNonOneofScalar( + entry, self->value_field_descriptor, v); + } + } + + // Key is not already present; insert a new entry. + Message* entry = + reflection->AddMessage(message, self->parent_field_descriptor); + + if (cmessage::InternalSetNonOneofScalar(entry, self->key_field_descriptor, + key) < 0 || + cmessage::InternalSetNonOneofScalar(entry, self->value_field_descriptor, + v) < 0) { + reflection->RemoveLast(message, self->parent_field_descriptor); + return -1; + } + + return 0; + } else { + bool found = false; + for (int i = size - 1; i >= 0; i--) { + Message* entry = reflection->MutableRepeatedMessage( + message, self->parent_field_descriptor, i); + int matches = MapKeyMatches(self, entry, key); + if (matches < 0) return -1; + if (matches) { + found = true; + if (i != size - 1) { + reflection->SwapElements(message, self->parent_field_descriptor, i, + size - 1); + } + reflection->RemoveLast(message, self->parent_field_descriptor); + + // Can't exit now, the repeated field representation of maps allows + // duplicate keys, and we have to be sure to remove all of them. + } + } + + if (found) { + return 0; + } else { + PyErr_Format(PyExc_KeyError, "Key not present in map"); + return -1; + } + } +} + +PyObject* GetIterator(PyObject *_self) { + ScalarMapContainer* self = GetMap(_self); + + ScopedPyObjectPtr obj(PyType_GenericAlloc(&ScalarMapIterator_Type, 0)); + if (obj == NULL) { + return PyErr_Format(PyExc_KeyError, "Could not allocate iterator"); + } + + ScalarMapIterator* iter = GetIter(obj.get()); + + Py_INCREF(self); + iter->container = self; + iter->version = self->version; + iter->dict = PyDict_New(); + if (iter->dict == NULL) { + return PyErr_Format(PyExc_RuntimeError, + "Could not allocate dict for iterator."); + } + + // Build the entire map into a dict right now. Start from the beginning so + // that later entries win in the case of duplicates. + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + + // Right now the Reflection API doesn't support map lookup, so we implement it + // via linear search. We need to search from the end because the underlying + // representation can have duplicates if a user calls MergeFrom(); the last + // one needs to win. + // + // TODO(haberman): add lookup API to Reflection API. + size_t size = + reflection->FieldSize(*message, self->parent_field_descriptor); + for (int i = 0; i < size; i++) { + Message* entry = reflection->MutableRepeatedMessage( + message, self->parent_field_descriptor, i); + ScopedPyObjectPtr key( + cmessage::InternalGetScalar(entry, self->key_field_descriptor)); + ScopedPyObjectPtr val( + cmessage::InternalGetScalar(entry, self->value_field_descriptor)); + if (PyDict_SetItem(iter->dict, key.get(), val.get()) < 0) { + return PyErr_Format(PyExc_RuntimeError, + "SetItem failed in iterator construction."); + } + } + + + iter->iter = PyObject_GetIter(iter->dict); + + + return obj.release(); +} + +PyObject* Clear(PyObject* _self) { + ScalarMapContainer* self = GetMap(_self); + cmessage::AssureWritable(self->parent); + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + + reflection->ClearField(message, self->parent_field_descriptor); + + Py_RETURN_NONE; +} + +PyObject* Contains(PyObject* _self, PyObject* key) { + ScalarMapContainer* self = GetMap(_self); + + Message* message = self->message; + const Reflection* reflection = message->GetReflection(); + + // Right now the Reflection API doesn't support map lookup, so we implement it + // via linear search. + // + // TODO(haberman): add lookup API to Reflection API. + size_t size = reflection->FieldSize(*message, self->parent_field_descriptor); + for (int i = size - 1; i >= 0; i--) { + const Message& entry = reflection->GetRepeatedMessage( + *message, self->parent_field_descriptor, i); + int matches = MapKeyMatches(self, &entry, key); + if (matches < 0) return NULL; + if (matches) { + Py_RETURN_TRUE; + } + } + + Py_RETURN_FALSE; +} + +PyObject* Get(PyObject* self, PyObject* args) { + PyObject* key; + PyObject* default_value = NULL; + if (PyArg_ParseTuple(args, "O|O", &key, &default_value) < 0) { + return NULL; + } + + ScopedPyObjectPtr is_present(Contains(self, key)); + if (is_present.get() == NULL) { + return NULL; + } + + if (PyObject_IsTrue(is_present.get())) { + return GetItem(self, key); + } else { + if (default_value != NULL) { + Py_INCREF(default_value); + return default_value; + } else { + Py_RETURN_NONE; + } + } +} + +static PyMappingMethods MpMethods = { + Length, // mp_length + GetItem, // mp_subscript + SetItem, // mp_ass_subscript +}; + +static void Dealloc(PyObject* _self) { + ScalarMapContainer* self = GetMap(_self); + self->owner.reset(); + Py_TYPE(_self)->tp_free(_self); +} + +static PyMethodDef Methods[] = { + { "__contains__", Contains, METH_O, + "Tests whether a key is a member of the map." }, + { "clear", (PyCFunction)Clear, METH_NOARGS, + "Removes all elements from the map." }, + { "get", Get, METH_VARARGS, + "Gets the value for the given key if present, or otherwise a default" }, + /* + { "__deepcopy__", (PyCFunction)DeepCopy, METH_VARARGS, + "Makes a deep copy of the class." }, + { "__reduce__", (PyCFunction)Reduce, METH_NOARGS, + "Outputs picklable representation of the repeated field." }, + */ + {NULL, NULL}, +}; + +} // namespace scalar_map_container + +namespace scalar_map_iterator { + +static void Dealloc(PyObject* _self) { + ScalarMapIterator* self = GetIter(_self); + Py_DECREF(self->dict); + Py_DECREF(self->iter); + Py_DECREF(self->container); + Py_TYPE(_self)->tp_free(_self); +} + +PyObject* IterNext(PyObject* _self) { + ScalarMapIterator* self = GetIter(_self); + + // This won't catch mutations to the map performed by MergeFrom(); no easy way + // to address that. + if (self->version != self->container->version) { + return PyErr_Format(PyExc_RuntimeError, + "Map modified during iteration."); + } + + return PyIter_Next(self->iter); +} + +} // namespace scalar_map_iterator + +PyTypeObject ScalarMapContainer_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + FULL_MODULE_NAME ".ScalarMapContainer", // tp_name + sizeof(ScalarMapContainer), // tp_basicsize + 0, // tp_itemsize + scalar_map_container::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + &scalar_map_container::MpMethods, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A scalar map container", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + scalar_map_container::GetIterator, // tp_iter + 0, // tp_iternext + scalar_map_container::Methods, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init +}; + +PyTypeObject ScalarMapIterator_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + FULL_MODULE_NAME ".ScalarMapIterator", // tp_name + sizeof(ScalarMapIterator), // tp_basicsize + 0, // tp_itemsize + scalar_map_iterator::Dealloc, // tp_dealloc + 0, // tp_print + 0, // tp_getattr + 0, // tp_setattr + 0, // tp_compare + 0, // tp_repr + 0, // tp_as_number + 0, // tp_as_sequence + 0, // tp_as_mapping + 0, // tp_hash + 0, // tp_call + 0, // tp_str + 0, // tp_getattro + 0, // tp_setattro + 0, // tp_as_buffer + Py_TPFLAGS_DEFAULT, // tp_flags + "A scalar map iterator", // tp_doc + 0, // tp_traverse + 0, // tp_clear + 0, // tp_richcompare + 0, // tp_weaklistoffset + PyObject_SelfIter, // tp_iter + scalar_map_iterator::IterNext, // tp_iternext + 0, // tp_methods + 0, // tp_members + 0, // tp_getset + 0, // tp_base + 0, // tp_dict + 0, // tp_descr_get + 0, // tp_descr_set + 0, // tp_dictoffset + 0, // tp_init +}; + +} // namespace python +} // namespace protobuf +} // namespace google diff --git a/python/google/protobuf/pyext/scalar_map_container.h b/python/google/protobuf/pyext/scalar_map_container.h new file mode 100644 index 00000000..254e6e98 --- /dev/null +++ b/python/google/protobuf/pyext/scalar_map_container.h @@ -0,0 +1,110 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__ +#define GOOGLE_PROTOBUF_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__ + +#include + +#include +#ifndef _SHARED_PTR_H +#include +#endif + +#include + +namespace google { +namespace protobuf { + +class Message; + +using internal::shared_ptr; + +namespace python { + +struct CMessage; + +struct ScalarMapContainer { + PyObject_HEAD; + + // This is the top-level C++ Message object that owns the whole + // proto tree. Every Python ScalarMapContainer holds a + // reference to it in order to keep it alive as long as there's a + // Python object that references any part of the tree. + shared_ptr owner; + + // Pointer to the C++ Message that contains this container. The + // ScalarMapContainer does not own this pointer. + Message* message; + + // Weak reference to a parent CMessage object (i.e. may be NULL.) + // + // Used to make sure all ancestors are also mutable when first + // modifying the container. + CMessage* parent; + + // Pointer to the parent's descriptor that describes this + // field. Used together with the parent's message when making a + // default message instance mutable. + // The pointer is owned by the global DescriptorPool. + const FieldDescriptor* parent_field_descriptor; + const FieldDescriptor* key_field_descriptor; + const FieldDescriptor* value_field_descriptor; + + // We bump this whenever we perform a mutation, to invalidate existing + // iterators. + uint64 version; +}; + +extern PyTypeObject ScalarMapContainer_Type; +extern PyTypeObject ScalarMapIterator_Type; + +namespace scalar_map_container { + +// Builds a ScalarMapContainer object, from a parent message and a +// field descriptor. +extern PyObject *NewContainer( + CMessage* parent, const FieldDescriptor* parent_field_descriptor); + +// Releases the messages in the container to a new message. +// +// Returns 0 on success, -1 on failure. +int Release(ScalarMapContainer* self); + +// Set the owner field of self and any children of self. +void SetOwner(ScalarMapContainer* self, + const shared_ptr& new_owner); + +} // namespace scalar_map_container +} // namespace python +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_PYTHON_CPP_SCALAR_MAP_CONTAINER_H__ diff --git a/python/google/protobuf/reflection.py b/python/google/protobuf/reflection.py index 55e653a0..82fca661 100755 --- a/python/google/protobuf/reflection.py +++ b/python/google/protobuf/reflection.py @@ -144,7 +144,6 @@ class GeneratedProtocolMessageType(type): _InitMessage(descriptor, cls) superclass = super(GeneratedProtocolMessageType, cls) superclass.__init__(name, bases, dictionary) - setattr(descriptor, '_concrete_class', cls) def ParseMessage(descriptor, byte_str): diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index a47ce3e3..8cbd6822 100755 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -100,6 +100,10 @@ def MessageToString(message, as_utf8=False, as_one_line=False, return result.rstrip() return result +def _IsMapEntry(field): + return (field.type == descriptor.FieldDescriptor.TYPE_MESSAGE and + field.message_type.has_options and + field.message_type.GetOptions().map_entry) def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False, pointy_brackets=False, use_index_order=False, @@ -108,7 +112,19 @@ def PrintMessage(message, out, indent=0, as_utf8=False, as_one_line=False, if use_index_order: fields.sort(key=lambda x: x[0].index) for field, value in fields: - if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: + if _IsMapEntry(field): + for key in value: + # This is slow for maps with submessage entires because it copies the + # entire tree. Unfortunately this would take significant refactoring + # of this file to work around. + # + # TODO(haberman): refactor and optimize if this becomes an issue. + entry_submsg = field.message_type._concrete_class( + key=key, value=value[key]) + PrintField(field, entry_submsg, out, indent, as_utf8, as_one_line, + pointy_brackets=pointy_brackets, + use_index_order=use_index_order, float_format=float_format) + elif field.label == descriptor.FieldDescriptor.LABEL_REPEATED: for element in value: PrintField(field, element, out, indent, as_utf8, as_one_line, pointy_brackets=pointy_brackets, @@ -367,6 +383,7 @@ def _MergeField(tokenizer, message, allow_multiple_scalars): message_descriptor.full_name, name)) if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + is_map_entry = _IsMapEntry(field) tokenizer.TryConsume(':') if tokenizer.TryConsume('<'): @@ -378,6 +395,8 @@ def _MergeField(tokenizer, message, allow_multiple_scalars): if field.label == descriptor.FieldDescriptor.LABEL_REPEATED: if field.is_extension: sub_message = message.Extensions[field].add() + elif is_map_entry: + sub_message = field.message_type._concrete_class() else: sub_message = getattr(message, field.name).add() else: @@ -391,6 +410,14 @@ def _MergeField(tokenizer, message, allow_multiple_scalars): if tokenizer.AtEnd(): raise tokenizer.ParseErrorPreviousToken('Expected "%s".' % (end_token)) _MergeField(tokenizer, sub_message, allow_multiple_scalars) + + if is_map_entry: + value_cpptype = field.message_type.fields_by_name['value'].cpp_type + if value_cpptype == descriptor.FieldDescriptor.CPPTYPE_MESSAGE: + value = getattr(message, field.name)[sub_message.key] + value.MergeFrom(sub_message.value) + else: + getattr(message, field.name)[sub_message.key] = sub_message.value else: _MergeScalarField(tokenizer, message, field, allow_multiple_scalars) @@ -701,13 +728,16 @@ class _Tokenizer(object): String literals (whether bytes or text) can come in multiple adjacent tokens which are automatically concatenated, like in C or Python. This method only consumes one token. + + Raises: + ParseError: When the wrong format data is found. """ text = self.token if len(text) < 1 or text[0] not in ('\'', '"'): - raise self._ParseError('Expected string but found: "%r"' % text) + raise self._ParseError('Expected string but found: %r' % (text,)) if len(text) < 2 or text[-1] != text[0]: - raise self._ParseError('String missing ending quote.') + raise self._ParseError('String missing ending quote: %r' % (text,)) try: result = text_encoding.CUnescape(text[1:-1]) diff --git a/python/setup.py b/python/setup.py index a1365fba..5c321f50 100755 --- a/python/setup.py +++ b/python/setup.py @@ -91,6 +91,7 @@ def GenerateUnittestProtos(): if not os.path.exists("../.git"): return + generate_proto("../src/google/protobuf/map_unittest.proto") generate_proto("../src/google/protobuf/unittest.proto") generate_proto("../src/google/protobuf/unittest_custom_options.proto") generate_proto("../src/google/protobuf/unittest_import.proto") diff --git a/ruby/tests/generated_code.proto b/ruby/tests/generated_code.proto index b1d63232..42d82a6b 100644 --- a/ruby/tests/generated_code.proto +++ b/ruby/tests/generated_code.proto @@ -3,17 +3,17 @@ syntax = "proto3"; package A.B.C; message TestMessage { - optional int32 optional_int32 = 1; - optional int64 optional_int64 = 2; - optional uint32 optional_uint32 = 3; - optional uint64 optional_uint64 = 4; - optional bool optional_bool = 5; - optional double optional_double = 6; - optional float optional_float = 7; - optional string optional_string = 8; - optional bytes optional_bytes = 9; - optional TestEnum optional_enum = 10; - optional TestMessage optional_msg = 11; + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + bool optional_bool = 5; + double optional_double = 6; + float optional_float = 7; + string optional_string = 8; + bytes optional_bytes = 9; + TestEnum optional_enum = 10; + TestMessage optional_msg = 11; repeated int32 repeated_int32 = 21; repeated int64 repeated_int64 = 22; @@ -53,10 +53,10 @@ message TestMessage { map map_string_bool = 70; message NestedMessage { - optional int32 foo = 1; + int32 foo = 1; } - optional NestedMessage nested_message = 80; + NestedMessage nested_message = 80; } enum TestEnum { diff --git a/src/Makefile.am b/src/Makefile.am index fd10b789..2ecf6028 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -88,6 +88,7 @@ nobase_include_HEADERS = \ google/protobuf/stubs/type_traits.h \ google/protobuf/any.pb.h \ google/protobuf/api.pb.h \ + google/protobuf/any.h \ google/protobuf/arena.h \ google/protobuf/arenastring.h \ google/protobuf/descriptor_database.h \ @@ -186,6 +187,7 @@ libprotobuf_la_SOURCES = \ $(libprotobuf_lite_la_SOURCES) \ google/protobuf/any.pb.cc \ google/protobuf/api.pb.cc \ + google/protobuf/any.cc \ google/protobuf/descriptor.cc \ google/protobuf/descriptor_database.cc \ google/protobuf/descriptor.pb.cc \ @@ -264,6 +266,8 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_enum.cc \ google/protobuf/compiler/java/java_enum_field.cc \ google/protobuf/compiler/java/java_enum_field.h \ + google/protobuf/compiler/java/java_enum_field_lite.cc \ + google/protobuf/compiler/java/java_enum_field_lite.h \ google/protobuf/compiler/java/java_enum.h \ google/protobuf/compiler/java/java_extension.cc \ google/protobuf/compiler/java/java_extension.h \ @@ -278,22 +282,38 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_helpers.h \ google/protobuf/compiler/java/java_lazy_message_field.cc \ google/protobuf/compiler/java/java_lazy_message_field.h \ + google/protobuf/compiler/java/java_lazy_message_field_lite.cc\ + google/protobuf/compiler/java/java_lazy_message_field_lite.h \ google/protobuf/compiler/java/java_map_field.cc \ google/protobuf/compiler/java/java_map_field.h \ + google/protobuf/compiler/java/java_map_field_lite.cc \ + google/protobuf/compiler/java/java_map_field_lite.h \ google/protobuf/compiler/java/java_message.cc \ + google/protobuf/compiler/java/java_message_lite.cc \ + google/protobuf/compiler/java/java_message_builder.cc \ + google/protobuf/compiler/java/java_message_builder_lite.cc \ google/protobuf/compiler/java/java_message_field.cc \ google/protobuf/compiler/java/java_message_field.h \ + google/protobuf/compiler/java/java_message_field_lite.cc \ + google/protobuf/compiler/java/java_message_field_lite.h \ google/protobuf/compiler/java/java_message.h \ + google/protobuf/compiler/java/java_message_lite.h \ + google/protobuf/compiler/java/java_message_builder.h \ + google/protobuf/compiler/java/java_message_builder_lite.h \ google/protobuf/compiler/java/java_name_resolver.cc \ google/protobuf/compiler/java/java_name_resolver.h \ google/protobuf/compiler/java/java_primitive_field.cc \ google/protobuf/compiler/java/java_primitive_field.h \ + google/protobuf/compiler/java/java_primitive_field_lite.cc \ + google/protobuf/compiler/java/java_primitive_field_lite.h \ google/protobuf/compiler/java/java_shared_code_generator.cc \ google/protobuf/compiler/java/java_shared_code_generator.h \ google/protobuf/compiler/java/java_service.cc \ google/protobuf/compiler/java/java_service.h \ google/protobuf/compiler/java/java_string_field.cc \ google/protobuf/compiler/java/java_string_field.h \ + google/protobuf/compiler/java/java_string_field_lite.cc \ + google/protobuf/compiler/java/java_string_field_lite.h \ google/protobuf/compiler/java/java_doc_comment.cc \ google/protobuf/compiler/java/java_doc_comment.h \ google/protobuf/compiler/javanano/javanano_enum.cc \ @@ -381,6 +401,7 @@ protoc_SOURCES = google/protobuf/compiler/main.cc # Tests ============================================================== protoc_inputs = \ + google/protobuf/any_test.proto \ google/protobuf/map_lite_unittest.proto \ google/protobuf/map_proto2_unittest.proto \ google/protobuf/map_unittest.proto \ @@ -419,6 +440,7 @@ EXTRA_DIST = \ google/protobuf/testdata/golden_message_proto3 \ google/protobuf/testdata/golden_packed_fields_message \ google/protobuf/testdata/bad_utf8_string \ + google/protobuf/testdata/map_test_data.txt \ google/protobuf/testdata/text_format_unittest_data.txt \ google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt \ google/protobuf/testdata/text_format_unittest_data_pointy.txt \ @@ -443,6 +465,8 @@ protoc_lite_outputs = \ protoc_outputs = \ $(protoc_lite_outputs) \ + google/protobuf/any_test.pb.cc \ + google/protobuf/any_test.pb.h \ google/protobuf/map_proto2_unittest.pb.cc \ google/protobuf/map_proto2_unittest.pb.h \ google/protobuf/map_unittest.pb.cc \ @@ -543,6 +567,7 @@ protobuf_test_SOURCES = \ google/protobuf/stubs/stringprintf_unittest.cc \ google/protobuf/stubs/template_util_unittest.cc \ google/protobuf/stubs/type_traits_unittest.cc \ + google/protobuf/any_test.cc \ google/protobuf/arenastring_unittest.cc \ google/protobuf/arena_unittest.cc \ google/protobuf/descriptor_database_unittest.cc \ @@ -604,6 +629,8 @@ nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs) protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lite_test_SOURCES = \ + google/protobuf/arena_test_util.cc \ + google/protobuf/arena_test_util.h \ google/protobuf/lite_unittest.cc \ google/protobuf/map_lite_test_util.cc \ google/protobuf/map_lite_test_util.h \ diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc new file mode 100644 index 00000000..c66fdfad --- /dev/null +++ b/src/google/protobuf/any.cc @@ -0,0 +1,100 @@ +// 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 + +namespace google { +namespace protobuf { +namespace internal { + +namespace { +string GetTypeUrl(const Descriptor* message) { + return string(kTypeGoogleApisComPrefix) + message->full_name(); +} + +} // namespace + +const char kAnyFullTypeName[] = "google.protobuf.Any"; +const char kTypeGoogleApisComPrefix[] = "type.googleapis.com/"; + +AnyMetadata::AnyMetadata(UrlType* type_url, ValueType* value) + : type_url_(type_url), value_(value) { +} + +void AnyMetadata::PackFrom(const Message& message) { + type_url_->SetNoArena(&::google::protobuf::internal::GetEmptyString(), + GetTypeUrl(message.GetDescriptor())); + message.SerializeToString(value_->MutableNoArena( + &::google::protobuf::internal::GetEmptyStringAlreadyInited())); +} + +bool AnyMetadata::UnpackTo(Message* message) const { + if (!InternalIs(message->GetDescriptor())) { + return false; + } + return message->ParseFromString( + value_->GetNoArena(&::google::protobuf::internal::GetEmptyString())); +} + +bool AnyMetadata::InternalIs(const Descriptor* descriptor) const { + return type_url_->GetNoArena( + &::google::protobuf::internal::GetEmptyString()) == + GetTypeUrl(descriptor); +} + +bool ParseAnyTypeUrl(const string& type_url, string* full_type_name) { + const int prefix_len = strlen(kTypeGoogleApisComPrefix); + if (strncmp(type_url.c_str(), kTypeGoogleApisComPrefix, prefix_len) == 0) { + full_type_name->assign(type_url.data() + prefix_len, + type_url.size() - prefix_len); + return true; + } + return true; +} + + +bool GetAnyFieldDescriptors(const Message& message, + const FieldDescriptor** type_url_field, + const FieldDescriptor** value_field) { + const Descriptor* descriptor = message.GetDescriptor(); + if (descriptor->full_name() != kAnyFullTypeName) { + return false; + } + *type_url_field = descriptor->FindFieldByNumber(1); + *value_field = descriptor->FindFieldByNumber(2); + return (*type_url_field != NULL && + (*type_url_field)->type() == FieldDescriptor::TYPE_STRING && + *value_field != NULL && + (*value_field)->type() == FieldDescriptor::TYPE_BYTES); +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h new file mode 100644 index 00000000..757b45aa --- /dev/null +++ b/src/google/protobuf/any.h @@ -0,0 +1,90 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_ANY_H__ +#define GOOGLE_PROTOBUF_ANY_H__ + +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +// Helper class used to implement google::protobuf::Any. +class AnyMetadata { + typedef ArenaStringPtr UrlType; + typedef ArenaStringPtr ValueType; + public: + // AnyMetadata does not take ownership of "type_url" and "value". + AnyMetadata(UrlType* type_url, ValueType* value); + + void PackFrom(const Message& message); + + bool UnpackTo(Message* message) const; + + template + bool Is() const { + return InternalIs(T::default_instance().GetDescriptor()); + } + + private: + bool InternalIs(const Descriptor* message) const; + + UrlType* type_url_; + ValueType* value_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata); +}; + +extern const char kAnyFullTypeName[]; // "google.protobuf.Any". +extern const char kTypeGoogleApisComPrefix[]; // "type.googleapis.com/". + +// Get the proto type name from Any::type_url value. For example, passing +// "type.googleapis.com/rpc.QueryOrigin" will return "rpc.QueryOrigin" in +// *full_type_name. Returns false if type_url does not start with +// "type.googleapis.com". +bool ParseAnyTypeUrl(const string& type_url, string* full_type_name); + +// See if message is of type google.protobuf.Any, if so, return the descriptors +// for "type_url" and "value" fields. +bool GetAnyFieldDescriptors(const Message& message, + const FieldDescriptor** type_url_field, + const FieldDescriptor** value_field); + +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_ANY_H__ diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index 75cc8754..2c492b04 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -111,13 +111,21 @@ static void MergeFromFail(int line) { // =================================================================== +void Any::PackFrom(const ::google::protobuf::Message& message) { + _any_metadata_.PackFrom(message); +} + +bool Any::UnpackTo(::google::protobuf::Message* message) const { + return _any_metadata_.UnpackTo(message); +} + #ifndef _MSC_VER const int Any::kTypeUrlFieldNumber; const int Any::kValueFieldNumber; #endif // !_MSC_VER Any::Any() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL), _any_metadata_(&type_url_, &value_) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Any) } @@ -128,7 +136,8 @@ void Any::InitAsDefaultInstance() { Any::Any(const Any& from) : ::google::protobuf::Message(), - _internal_metadata_(NULL) { + _internal_metadata_(NULL), + _any_metadata_(&type_url_, &value_) { SharedCtor(); MergeFrom(from); // @@protoc_insertion_point(copy_constructor:google.protobuf.Any) @@ -316,9 +325,9 @@ int Any::ByteSize() const { void Any::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Any* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Any* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -378,7 +387,7 @@ void Any::InternalSwap(Any* other) { // Any // optional string type_url = 1; - void Any::clear_type_url() { +void Any::clear_type_url() { type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Any::type_url() const { @@ -421,7 +430,7 @@ void Any::InternalSwap(Any* other) { } // optional bytes value = 2; - void Any::clear_value() { +void Any::clear_value() { value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Any::value() const { diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h index b2c238c1..c324c4af 100644 --- a/src/google/protobuf/any.pb.h +++ b/src/google/protobuf/any.pb.h @@ -27,6 +27,7 @@ #include #include #include +#include "google/protobuf/any.h" // @@protoc_insertion_point(includes) namespace google { @@ -56,6 +57,14 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message { static const ::google::protobuf::Descriptor* descriptor(); static const Any& default_instance(); + // implements Any ----------------------------------------------- + + void PackFrom(const ::google::protobuf::Message& message); + bool UnpackTo(::google::protobuf::Message* message) const; + template bool Is() const { + return _any_metadata_.Is(); + } + void Swap(Any* other); // implements Message ---------------------------------------------- @@ -127,6 +136,7 @@ class LIBPROTOBUF_EXPORT Any : public ::google::protobuf::Message { ::google::protobuf::internal::ArenaStringPtr type_url_; ::google::protobuf::internal::ArenaStringPtr value_; mutable int _cached_size_; + ::google::protobuf::internal::AnyMetadata _any_metadata_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fany_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto(); diff --git a/src/google/protobuf/any_test.cc b/src/google/protobuf/any_test.cc new file mode 100644 index 00000000..1bfaa63d --- /dev/null +++ b/src/google/protobuf/any_test.cc @@ -0,0 +1,89 @@ +// 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 +#include + +namespace google { +namespace protobuf { +namespace { + +TEST(AnyTest, TestPackAndUnpack) { + protobuf_unittest::TestAny submessage; + submessage.set_int32_value(12345); + protobuf_unittest::TestAny message; + message.mutable_any_value()->PackFrom(submessage); + + string data = message.SerializeAsString(); + + ASSERT_TRUE(message.ParseFromString(data)); + EXPECT_TRUE(message.has_any_value()); + ASSERT_TRUE(message.any_value().UnpackTo(&submessage)); + EXPECT_EQ(12345, submessage.int32_value()); +} + +TEST(AnyTest, TestPackAndUnpackAny) { + // We can pack a Any message inside another Any message. + protobuf_unittest::TestAny submessage; + submessage.set_int32_value(12345); + google::protobuf::Any any; + any.PackFrom(submessage); + protobuf_unittest::TestAny message; + message.mutable_any_value()->PackFrom(any); + + string data = message.SerializeAsString(); + + ASSERT_TRUE(message.ParseFromString(data)); + EXPECT_TRUE(message.has_any_value()); + ASSERT_TRUE(message.any_value().UnpackTo(&any)); + ASSERT_TRUE(any.UnpackTo(&submessage)); + EXPECT_EQ(12345, submessage.int32_value()); +} + +TEST(AnyTest, TestIs) { + protobuf_unittest::TestAny submessage; + submessage.set_int32_value(12345); + google::protobuf::Any any; + any.PackFrom(submessage); + ASSERT_TRUE(any.ParseFromString(any.SerializeAsString())); + EXPECT_TRUE(any.Is()); + EXPECT_FALSE(any.Is()); + + protobuf_unittest::TestAny message; + message.mutable_any_value()->PackFrom(any); + ASSERT_TRUE(message.ParseFromString(message.SerializeAsString())); + EXPECT_FALSE(message.any_value().Is()); + EXPECT_TRUE(message.any_value().Is()); +} + +} // namespace +} // namespace protobuf + +} // namespace google diff --git a/src/google/protobuf/any_test.proto b/src/google/protobuf/any_test.proto new file mode 100644 index 00000000..0c5b30ba --- /dev/null +++ b/src/google/protobuf/any_test.proto @@ -0,0 +1,41 @@ +// 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. + +syntax = "proto3"; + +package protobuf_unittest; + +import "google/protobuf/any.proto"; + +message TestAny { + int32 int32_value = 1; + google.protobuf.Any any_value = 2; + repeated google.protobuf.Any repeated_any_value = 3; +} diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index b34ce803..434320dc 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -162,7 +162,7 @@ const int Api::kSourceContextFieldNumber; #endif // !_MSC_VER Api::Api() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Api) } @@ -230,7 +230,7 @@ Api* Api::New(::google::protobuf::Arena* arena) const { void Api::Clear() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (source_context_ != NULL) delete source_context_; + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; methods_.Clear(); options_.Clear(); @@ -266,26 +266,31 @@ bool Api::MergePartialFromCodedStream( case 2: { if (tag == 18) { parse_methods: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_methods: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_methods())); } else { goto handle_unusual; } - if (input->ExpectTag(18)) goto parse_methods; - if (input->ExpectTag(26)) goto parse_options; + if (input->ExpectTag(18)) goto parse_loop_methods; + if (input->ExpectTag(26)) goto parse_loop_options; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.Option options = 3; case 3: { if (tag == 26) { - parse_options: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_options())); } else { goto handle_unusual; } - if (input->ExpectTag(26)) goto parse_options; + if (input->ExpectTag(26)) goto parse_loop_options; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(34)) goto parse_version; break; } @@ -483,9 +488,9 @@ int Api::ByteSize() const { void Api::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Api* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Api* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -553,7 +558,7 @@ void Api::InternalSwap(Api* other) { // Api // optional string name = 1; - void Api::clear_name() { +void Api::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Api::name() const { @@ -596,10 +601,10 @@ void Api::InternalSwap(Api* other) { } // repeated .google.protobuf.Method methods = 2; - int Api::methods_size() const { +int Api::methods_size() const { return methods_.size(); } - void Api::clear_methods() { +void Api::clear_methods() { methods_.Clear(); } const ::google::protobuf::Method& Api::methods(int index) const { @@ -626,10 +631,10 @@ Api::mutable_methods() { } // repeated .google.protobuf.Option options = 3; - int Api::options_size() const { +int Api::options_size() const { return options_.size(); } - void Api::clear_options() { +void Api::clear_options() { options_.Clear(); } const ::google::protobuf::Option& Api::options(int index) const { @@ -656,7 +661,7 @@ Api::mutable_options() { } // optional string version = 4; - void Api::clear_version() { +void Api::clear_version() { version_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Api::version() const { @@ -699,11 +704,11 @@ Api::mutable_options() { } // optional .google.protobuf.SourceContext source_context = 5; - bool Api::has_source_context() const { +bool Api::has_source_context() const { return !_is_default_instance_ && source_context_ != NULL; } - void Api::clear_source_context() { - if (source_context_ != NULL) delete source_context_; +void Api::clear_source_context() { + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; } const ::google::protobuf::SourceContext& Api::source_context() const { @@ -749,7 +754,7 @@ const int Method::kOptionsFieldNumber; #endif // !_MSC_VER Method::Method() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Method) } @@ -929,12 +934,15 @@ bool Method::MergePartialFromCodedStream( case 6: { if (tag == 50) { parse_options: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_options())); } else { goto handle_unusual; } - if (input->ExpectTag(50)) goto parse_options; + if (input->ExpectTag(50)) goto parse_loop_options; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -1119,9 +1127,9 @@ int Method::ByteSize() const { void Method::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Method* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Method* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1196,7 +1204,7 @@ void Method::InternalSwap(Method* other) { // Method // optional string name = 1; - void Method::clear_name() { +void Method::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Method::name() const { @@ -1239,7 +1247,7 @@ void Method::InternalSwap(Method* other) { } // optional string request_type_url = 2; - void Method::clear_request_type_url() { +void Method::clear_request_type_url() { request_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Method::request_type_url() const { @@ -1282,7 +1290,7 @@ void Method::InternalSwap(Method* other) { } // optional bool request_streaming = 3; - void Method::clear_request_streaming() { +void Method::clear_request_streaming() { request_streaming_ = false; } bool Method::request_streaming() const { @@ -1296,7 +1304,7 @@ void Method::InternalSwap(Method* other) { } // optional string response_type_url = 4; - void Method::clear_response_type_url() { +void Method::clear_response_type_url() { response_type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Method::response_type_url() const { @@ -1339,7 +1347,7 @@ void Method::InternalSwap(Method* other) { } // optional bool response_streaming = 5; - void Method::clear_response_streaming() { +void Method::clear_response_streaming() { response_streaming_ = false; } bool Method::response_streaming() const { @@ -1353,10 +1361,10 @@ void Method::InternalSwap(Method* other) { } // repeated .google.protobuf.Option options = 6; - int Method::options_size() const { +int Method::options_size() const { return options_.size(); } - void Method::clear_options() { +void Method::clear_options() { options_.Clear(); } const ::google::protobuf::Option& Method::options(int index) const { diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h index f459af0f..985adc5d 100644 --- a/src/google/protobuf/api.pb.h +++ b/src/google/protobuf/api.pb.h @@ -466,7 +466,7 @@ inline bool Api::has_source_context() const { return !_is_default_instance_ && source_context_ != NULL; } inline void Api::clear_source_context() { - if (source_context_ != NULL) delete source_context_; + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; } inline const ::google::protobuf::SourceContext& Api::source_context() const { @@ -690,6 +690,8 @@ Method::mutable_options() { } #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc index f7059d26..96009645 100755 --- a/src/google/protobuf/arena.cc +++ b/src/google/protobuf/arena.cc @@ -29,7 +29,6 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include -#include #ifdef ADDRESS_SANITIZER #include @@ -155,10 +154,16 @@ void Arena::AddListNode(void* elem, void (*cleanup)(void*)) { reinterpret_cast(node))); } -void* Arena::AllocateAligned(size_t n) { +void* Arena::AllocateAligned(const std::type_info* allocated, size_t n) { // Align n to next multiple of 8 (from Hacker's Delight, Chapter 3.) n = (n + 7) & -8; + // Monitor allocation if needed. + if (GOOGLE_PREDICT_FALSE(hooks_cookie_ != NULL) && + options_.on_arena_allocation != NULL) { + options_.on_arena_allocation(allocated, n, hooks_cookie_); + } + // If this thread already owns a block in this arena then try to use that. // This fast path optimizes the case where multiple threads allocate from the // same arena. diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h index b48bef92..4adcd677 100644 --- a/src/google/protobuf/arena.h +++ b/src/google/protobuf/arena.h @@ -28,12 +28,12 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// This header is logically internal, but is made public because it is used -// from protocol-compiler-generated code, which may reside in other components. - #ifndef GOOGLE_PROTOBUF_ARENA_H__ #define GOOGLE_PROTOBUF_ARENA_H__ +#if __cplusplus >= 201103L +#include +#endif #include #include @@ -113,10 +113,13 @@ struct ArenaOptions { void (*on_arena_reset)(Arena* arena, void* cookie, uint64 space_used); void (*on_arena_destruction)(Arena* arena, void* cookie, uint64 space_used); - // type_name is promised to be a static string - its lifetime extends to - // match program's lifetime. - void (*on_arena_allocation)(const char* type_name, uint64 alloc_size, - Arena* arena, void* cookie); + // type_info is promised to be static - its lifetime extends to + // match program's lifetime (It is given by typeid operator). + // Note: typeid(void) will be passed as allocated_type every time we + // intentionally want to avoid monitoring an allocation. (i.e. internal + // allocations for managing the arena) + void (*on_arena_allocation)(const std::type_info* allocated_type, + uint64 alloc_size, void* cookie); ArenaOptions() : start_block_size(kDefaultStartBlockSize), @@ -137,6 +140,14 @@ struct ArenaOptions { static const size_t kDefaultMaxBlockSize = 8192; }; +// Support for non-RTTI environments. (The metrics hooks API uses type +// information.) +#ifndef GOOGLE_PROTOBUF_NO_RTTI +#define RTTI_TYPE_ID(type) (&typeid(type)) +#else +#define RTTI_TYPE_ID(type) (NULL) +#endif + // Arena allocator. Arena allocation replaces ordinary (heap-based) allocation // with new/delete, and improves performance by aggregating allocations into // larger blocks and freeing allocations all at once. Protocol messages are @@ -146,6 +157,44 @@ struct ArenaOptions { // This is a thread-safe implementation: multiple threads may allocate from the // arena concurrently. Destruction is not thread-safe and the destructing // thread must synchronize with users of the arena first. +// +// An arena provides two allocation interfaces: CreateMessage, which works +// for arena-enabled proto2 message types as well as other types that satisfy +// the appropriate protocol (described below), and Create, which works for +// any arbitrary type T. CreateMessage is better when the type T supports it, +// because this interface (i) passes the arena pointer to the created object so +// that its sub-objects and internal allocations can use the arena too, and (ii) +// elides the object's destructor call when possible. Create does not place +// any special requirements on the type T, and will invoke the object's +// destructor when the arena is destroyed. +// +// The arena message allocation protocol, required by CreateMessage, is as +// follows: +// +// - The type T must have (at least) two constructors: a constructor with no +// arguments, called when a T is allocated on the heap; and a constructor with +// a google::protobuf::Arena* argument, called when a T is allocated on an arena. If the +// second constructor is called with a NULL arena pointer, it must be +// equivalent to invoking the first (no-argument) constructor. +// +// - The type T must have a particular type trait: a nested type +// |InternalArenaConstructable_|. This is usually a typedef to |void|. If no +// such type trait exists, then the instantiation CreateMessage will fail +// to compile. +// +// - The type T *may* have the type trait |DestructorSkippable_|. If this type +// trait is present in the type, then its destructor will not be called if and +// only if it was passed a non-NULL arena pointer. If this type trait is not +// present on the type, then its destructor is always called when the +// containing arena is destroyed. +// +// - One- and two-user-argument forms of CreateMessage() also exist that +// forward these constructor arguments to T's constructor: for example, +// CreateMessage(Arena*, arg1, arg2) forwards to a constructor T(Arena*, +// arg1, arg2). +// +// This protocol is implemented by all arena-enabled proto2 message classes as +// well as RepeatedPtrField. class LIBPROTOBUF_EXPORT Arena { public: // Arena constructor taking custom options. See ArenaOptions below for @@ -172,8 +221,10 @@ class LIBPROTOBUF_EXPORT Arena { // compilation error will occur. // // RepeatedField and RepeatedPtrField may also be instantiated directly on an - // arena with this method: they act as "arena-capable message types" for the - // purposes of the Arena API. + // arena with this method. + // + // This function also accepts any type T that satisfies the arena message + // allocation protocol, documented above. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* CreateMessage(::google::protobuf::Arena* arena) { if (arena == NULL) { @@ -183,17 +234,55 @@ class LIBPROTOBUF_EXPORT Arena { } } + // One-argument form of CreateMessage. This is useful for constructing objects + // that implement the arena message construction protocol described above but + // take additional constructor arguments. + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE + static T* CreateMessage(::google::protobuf::Arena* arena, const Arg& arg) { + if (arena == NULL) { + return new T(NULL, arg); + } else { + return arena->CreateMessageInternal(static_cast(0), + arg); + } + } + + // Two-argument form of CreateMessage. This is useful for constructing objects + // that implement the arena message construction protocol described above but + // take additional constructor arguments. + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE + static T* CreateMessage(::google::protobuf::Arena* arena, + const Arg1& arg1, + const Arg2& arg2) { + if (arena == NULL) { + return new T(NULL, arg1, arg2); + } else { + return arena->CreateMessageInternal(static_cast(0), + arg1, arg2); + } + } + // API to create any objects on the arena. Note that only the object will // be created on the arena; the underlying ptrs (in case of a proto2 message) // will be still heap allocated. Proto messages should usually be allocated // with CreateMessage() instead. + // + // Note that even if T satisfies the arena message construction protocol + // (InternalArenaConstructable_ trait and optional DestructorSkippable_ + // trait), as described above, this function does not follow the protocol; + // instead, it treats T as a black-box type, just as if it did not have these + // traits. Specifically, T's constructor arguments will always be only those + // passed to Create() -- no additional arena pointer is implicitly added. + // Furthermore, the destructor will always be called at arena destruction time + // (unless the destructor is trivial). Hence, from T's point of view, it is as + // if the object were allocated on the heap (except that the underlying memory + // is obtained from the arena). template GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena) { if (arena == NULL) { return new T(); } else { - return arena->CreateInternal( - SkipDeleteList(static_cast(0))); + return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value); } } @@ -203,7 +292,7 @@ class LIBPROTOBUF_EXPORT Arena { if (arena == NULL) { return new T(arg); } else { - return arena->CreateInternal(SkipDeleteList(static_cast(0)), + return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, arg); } } @@ -214,9 +303,8 @@ class LIBPROTOBUF_EXPORT Arena { if (arena == NULL) { return new T(arg1, arg2); } else { - return arena->CreateInternal(SkipDeleteList(static_cast(0)), - arg1, - arg2); + return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, + arg1, arg2); } } @@ -229,10 +317,8 @@ class LIBPROTOBUF_EXPORT Arena { if (arena == NULL) { return new T(arg1, arg2, arg3); } else { - return arena->CreateInternal(SkipDeleteList(static_cast(0)), - arg1, - arg2, - arg3); + return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, + arg1, arg2, arg3); } } @@ -246,20 +332,95 @@ class LIBPROTOBUF_EXPORT Arena { if (arena == NULL) { return new T(arg1, arg2, arg3, arg4); } else { - return arena->CreateInternal(SkipDeleteList(static_cast(0)), - arg1, - arg2, - arg3, - arg4); + return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, + arg1, arg2, arg3, arg4); } } - // Create an array of object type T on the arena. Type T must have a trivial - // constructor, as it will not be invoked when created on the arena. + // Version of the above with five constructor arguments for the created + // object. + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, + const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, + const Arg5& arg5) { + if (arena == NULL) { + return new T(arg1, arg2, arg3, arg4, arg5); + } else { + return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, + arg1, arg2, arg3, arg4, arg5); + } + } + + // Version of the above with six constructor arguments for the created + // object. + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, + const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, + const Arg5& arg5, const Arg6& arg6) { + if (arena == NULL) { + return new T(arg1, arg2, arg3, arg4, arg5, arg6); + } else { + return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, + arg1, arg2, arg3, arg4, arg5, arg6); + } + } + + // Version of the above with seven constructor arguments for the created + // object. + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, + const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, + const Arg5& arg5, const Arg6& arg6, + const Arg7& arg7) { + if (arena == NULL) { + return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } else { + return arena->CreateInternal(google::protobuf::internal::has_trivial_destructor::value, + arg1, arg2, arg3, arg4, arg5, arg6, arg7); + } + } + + // Version of the above with eight constructor arguments for the created + // object. + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* Create(::google::protobuf::Arena* arena, + const Arg1& arg1, const Arg2& arg2, + const Arg3& arg3, const Arg4& arg4, + const Arg5& arg5, const Arg6& arg6, + const Arg7& arg7, const Arg8& arg8) { + if (arena == NULL) { + return new T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } else { + return arena->CreateInternal( + google::protobuf::internal::has_trivial_destructor::value, + arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + } + } + + // Create an array of object type T on the arena *without* invoking the + // constructor of T. If `arena` is null, then the return value should be freed + // with `delete[] x;` (or `::operator delete[](x);`). + // To ensure safe uses, this function checks at compile time + // (when compiled as C++11) that T is trivially default-constructible and + // trivially destructible. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE static T* CreateArray(::google::protobuf::Arena* arena, size_t num_elements) { +#if __cplusplus >= 201103L + static_assert(std::is_trivially_default_constructible::value, + "CreateArray requires a trivially constructible type"); + static_assert(std::is_trivially_destructible::value, + "CreateArray requires a trivially destructible type"); +#endif if (arena == NULL) { - return new T[num_elements]; + return static_cast(::operator new[](num_elements * sizeof(T))); } else { return arena->CreateInternalRawArray(num_elements); } @@ -374,27 +535,26 @@ class LIBPROTOBUF_EXPORT Arena { // wrap them in static functions. static ThreadCache& thread_cache(); #elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) - // Android ndk does not support __thread keyword so we use a custom thread + // Android ndk does not support GOOGLE_THREAD_LOCAL keyword so we use a custom thread // local storage class we implemented. - // iOS also does not support the __thread keyword. + // iOS also does not support the GOOGLE_THREAD_LOCAL keyword. static ThreadCache& thread_cache(); #else static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_; static ThreadCache& thread_cache() { return thread_cache_; } #endif - // SFINAE for skipping addition to delete list for a Type. This is mainly to - // skip proto2/proto1 message objects with cc_enable_arenas=true from being - // part of the delete list. Also, note, compiler will optimize out the branch - // in CreateInternal. - // + // SFINAE for skipping addition to delete list for a message type when created + // with CreateMessage. This is mainly to skip proto2/proto1 message objects + // with cc_enable_arenas=true from being part of the delete list. Also, note, + // compiler will optimize out the branch in CreateInternal. template static inline bool SkipDeleteList(typename T::DestructorSkippable_*) { return true; } - // For non message objects, we skip addition to delete list if the object has - // a trivial destructor. + // For message objects that don't have the DestructorSkippable_ trait, we + // always add to the delete list. template static inline bool SkipDeleteList(...) { return google::protobuf::internal::has_trivial_destructor::value; @@ -419,14 +579,15 @@ class LIBPROTOBUF_EXPORT Arena { // Just allocate the required size for the given type assuming the // type has a trivial constructor. template GOOGLE_ATTRIBUTE_ALWAYS_INLINE - inline T* CreateInternalRawArray(uint32 num_elements) { - return static_cast(AllocateAligned(sizeof(T) * num_elements)); + inline T* CreateInternalRawArray(size_t num_elements) { + return static_cast( + AllocateAligned(RTTI_TYPE_ID(T), sizeof(T) * num_elements)); } template GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal( bool skip_explicit_ownership) { - T* t = new (AllocateAligned(sizeof(T))) T(); + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(); if (!skip_explicit_ownership) { AddListNode(t, &internal::arena_destruct_object); } @@ -436,7 +597,7 @@ class LIBPROTOBUF_EXPORT Arena { template GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal( bool skip_explicit_ownership, const Arg& arg) { - T* t = new (AllocateAligned(sizeof(T))) T(arg); + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg); if (!skip_explicit_ownership) { AddListNode(t, &internal::arena_destruct_object); } @@ -446,7 +607,7 @@ class LIBPROTOBUF_EXPORT Arena { template GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal( bool skip_explicit_ownership, const Arg1& arg1, const Arg2& arg2) { - T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2); + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) T(arg1, arg2); if (!skip_explicit_ownership) { AddListNode(t, &internal::arena_destruct_object); } @@ -458,7 +619,8 @@ class LIBPROTOBUF_EXPORT Arena { const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) { - T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3); + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) + T(arg1, arg2, arg3); if (!skip_explicit_ownership) { AddListNode(t, &internal::arena_destruct_object); } @@ -472,7 +634,79 @@ class LIBPROTOBUF_EXPORT Arena { const Arg2& arg2, const Arg3& arg3, const Arg4& arg4) { - T* t = new (AllocateAligned(sizeof(T))) T(arg1, arg2, arg3, arg4); + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) + T(arg1, arg2, arg3, arg4); + if (!skip_explicit_ownership) { + AddListNode(t, &internal::arena_destruct_object); + } + return t; + } + + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4, + const Arg5& arg5) { + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) + T(arg1, arg2, arg3, arg4, arg5); + if (!skip_explicit_ownership) { + AddListNode(t, &internal::arena_destruct_object); + } + return t; + } + + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4, + const Arg5& arg5, + const Arg6& arg6) { + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) + T(arg1, arg2, arg3, arg4, arg5, arg6); + if (!skip_explicit_ownership) { + AddListNode(t, &internal::arena_destruct_object); + } + return t; + } + + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4, + const Arg5& arg5, + const Arg6& arg6, + const Arg7& arg7) { + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) + T(arg1, arg2, arg3, arg4, arg5, arg6, arg7); + if (!skip_explicit_ownership) { + AddListNode(t, &internal::arena_destruct_object); + } + return t; + } + + template + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline T* CreateInternal(bool skip_explicit_ownership, + const Arg1& arg1, + const Arg2& arg2, + const Arg3& arg3, + const Arg4& arg4, + const Arg5& arg5, + const Arg6& arg6, + const Arg7& arg7, + const Arg8& arg8) { + T* t = new (AllocateAligned(RTTI_TYPE_ID(T), sizeof(T))) + T(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); if (!skip_explicit_ownership) { AddListNode(t, &internal::arena_destruct_object); } @@ -485,6 +719,20 @@ class LIBPROTOBUF_EXPORT Arena { this); } + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE + inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*, + const Arg& arg) { + return CreateInternal(SkipDeleteList(static_cast(0)), + this, arg); + } + + template GOOGLE_ATTRIBUTE_ALWAYS_INLINE + inline T* CreateMessageInternal(typename T::InternalArenaConstructable_*, + const Arg1& arg1, const Arg2& arg2) { + return CreateInternal(SkipDeleteList(static_cast(0)), + this, arg1, arg2); + } + // CreateInArenaStorage is used to implement map field. Without it, // google::protobuf::Map need to call generated message's protected arena constructor, // which needs to declare google::protobuf::Map as friend of generated message. @@ -536,8 +784,15 @@ class LIBPROTOBUF_EXPORT Arena { return NULL; } + // Allocate and also optionally call on_arena_allocation callback with the + // allocated type info when the hooks are in place in ArenaOptions and + // the cookie is not null. + void* AllocateAligned(const std::type_info* allocated, size_t n); - void* AllocateAligned(size_t size); + // Allocate an internal allocation, avoiding optional typed monitoring. + GOOGLE_ATTRIBUTE_ALWAYS_INLINE inline void* AllocateAligned(size_t n) { + return AllocateAligned(NULL, n); + } void Init(); @@ -596,6 +851,9 @@ class LIBPROTOBUF_EXPORT Arena { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Arena); }; +// Defined above for supporting environments without RTTI. +#undef RTTI_TYPE_ID + template const typename Arena::is_arena_constructable::type Arena::is_arena_constructable::value = diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py index f390df36..87a69b2a 100644 --- a/src/google/protobuf/arena_nc_test.py +++ b/src/google/protobuf/arena_nc_test.py @@ -35,6 +35,7 @@ import unittest from google3.testing.pybase import fake_target_util +import unittest class ArenaNcTest(unittest.TestCase): diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h index 7db7a90e..690cc706 100644 --- a/src/google/protobuf/arena_test_util.h +++ b/src/google/protobuf/arena_test_util.h @@ -31,6 +31,7 @@ #ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__ #define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__ + namespace google { namespace protobuf { namespace internal { diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index d9b198e0..873e85ae 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -39,6 +39,7 @@ #include #endif #include +#include #include #include @@ -47,11 +48,14 @@ #include #include #include +#include +#include #include #include #include #include #include +#include #include #include @@ -125,6 +129,29 @@ class MustBeConstructedWithOneThroughFour { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour); }; +// A class that takes eight different types as constructor arguments. +class MustBeConstructedWithOneThroughEight { + public: + MustBeConstructedWithOneThroughEight( + int one, const char* two, const string& three, + const PleaseDontCopyMe* four, int five, const char* six, + const string& seven, const string& eight) + : one_(one), two_(two), three_(three), four_(four), five_(five), + six_(six), seven_(seven), eight_(eight) {} + + int one_; + const char* const two_; + string three_; + const PleaseDontCopyMe* four_; + int five_; + const char* const six_; + string seven_; + string eight_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughEight); +}; + } // namespace TEST(ArenaTest, ArenaConstructable) { @@ -156,7 +183,7 @@ TEST(ArenaTest, BasicCreate) { EXPECT_EQ(2, notifier.GetCount()); } -TEST(ArenaTest, CreateWithManyConstructorArguments) { +TEST(ArenaTest, CreateWithFourConstructorArguments) { Arena arena; const string three("3"); const PleaseDontCopyMe four(4); @@ -170,6 +197,26 @@ TEST(ArenaTest, CreateWithManyConstructorArguments) { ASSERT_EQ(4, new_object->four_->value()); } +TEST(ArenaTest, CreateWithEightConstructorArguments) { + Arena arena; + const string three("3"); + const PleaseDontCopyMe four(4); + const string seven("7"); + const string eight("8"); + const MustBeConstructedWithOneThroughEight* new_object = + Arena::Create( + &arena, 1, "2", three, &four, 5, "6", seven, eight); + EXPECT_TRUE(new_object != NULL); + ASSERT_EQ(1, new_object->one_); + ASSERT_STREQ("2", new_object->two_); + ASSERT_EQ("3", new_object->three_); + ASSERT_EQ(4, new_object->four_->value()); + ASSERT_EQ(5, new_object->five_); + ASSERT_STREQ("6", new_object->six_); + ASSERT_EQ("7", new_object->seven_); + ASSERT_EQ("8", new_object->eight_); +} + TEST(ArenaTest, InitialBlockTooSmall) { // Construct a small (64 byte) initial block of memory to be used by the // arena allocator; then, allocate an object which will not fit in the @@ -1113,6 +1160,19 @@ TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) { EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message)); } +TEST(ArenaTest, UnsafeSetAllocatedOnArena) { + ::google::protobuf::Arena arena; + TestAllTypes* message = Arena::CreateMessage(&arena); + EXPECT_FALSE(message->has_optional_string()); + + string owned_string = "test with long enough content to heap-allocate"; + message->unsafe_arena_set_allocated_optional_string(&owned_string); + EXPECT_TRUE(message->has_optional_string()); + + message->unsafe_arena_set_allocated_optional_string(NULL); + EXPECT_FALSE(message->has_optional_string()); +} + // A helper utility class to only contain static hook functions, some // counters to be used to verify the counters have been called and a cookie // value to be verified. @@ -1124,6 +1184,13 @@ class ArenaHooksTestUtil { return static_cast(cookie); } + static void on_allocation(const std::type_info* /*unused*/, uint64 alloc_size, + void* cookie) { + ++num_allocations; + int cookie_value = *static_cast(cookie); + EXPECT_EQ(kCookieValue, cookie_value); + } + static void on_reset(::google::protobuf::Arena* arena, void* cookie, uint64 space_used) { ++num_reset; @@ -1141,10 +1208,12 @@ class ArenaHooksTestUtil { static const int kCookieValue = 999; static uint32 num_init; + static uint32 num_allocations; static uint32 num_reset; static uint32 num_destruct; }; uint32 ArenaHooksTestUtil::num_init = 0; +uint32 ArenaHooksTestUtil::num_allocations = 0; uint32 ArenaHooksTestUtil::num_reset = 0; uint32 ArenaHooksTestUtil::num_destruct = 0; const int ArenaHooksTestUtil::kCookieValue; @@ -1153,6 +1222,7 @@ const int ArenaHooksTestUtil::kCookieValue; TEST(ArenaTest, ArenaHooksSanity) { ::google::protobuf::ArenaOptions options; options.on_arena_init = ArenaHooksTestUtil::on_init; + options.on_arena_allocation = ArenaHooksTestUtil::on_allocation; options.on_arena_reset = ArenaHooksTestUtil::on_reset; options.on_arena_destruction = ArenaHooksTestUtil::on_destruction; @@ -1160,6 +1230,9 @@ TEST(ArenaTest, ArenaHooksSanity) { { ::google::protobuf::Arena arena(options); EXPECT_EQ(1, ArenaHooksTestUtil::num_init); + EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations); + ::google::protobuf::Arena::Create(&arena); + EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations); arena.Reset(); arena.Reset(); diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index 321a8ccd..b989f151 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -79,6 +79,37 @@ class LIBPROTOC_EXPORT CodeGenerator { GeneratorContext* generator_context, string* error) const = 0; + // Generates code for all given proto files, generating one or more files in + // the given output directory. + // + // This method should be called instead of |Generate()| when + // |HasGenerateAll()| returns |true|. It is used to emulate legacy semantics + // when more than one `.proto` file is specified on one compiler invocation. + // + // WARNING: Please do not use unless legacy semantics force the code generator + // to produce a single output file for all input files, or otherwise require + // an examination of all input files first. The canonical code generator + // design produces one output file per input .proto file, and we do not wish + // to encourage alternate designs. + // + // A parameter is given as passed on the command line, as in |Generate()| + // above. + // + // Returns true if successful. Otherwise, sets *error to a description of + // the problem (e.g. "invalid parameter") and returns false. + virtual bool GenerateAll(const vector& files, + const string& parameter, + GeneratorContext* generator_context, + string* error) const { + *error = "Unimplemented GenerateAll() method."; + return false; + } + + // Returns true if the code generator expects to receive all FileDescriptors + // at once (via |GenerateAll()|), rather than one at a time (via + // |Generate()|). This is required to implement legacy semantics. + virtual bool HasGenerateAll() const { return false; } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator); }; diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 567238ae..291fb054 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -898,12 +898,14 @@ CommandLineInterface::ParseArguments(int argc, const char* const argv[]) { return PARSE_ARGUMENT_FAIL; } if (mode_ != MODE_COMPILE && !dependency_out_name_.empty()) { - cerr << "Can only use --dependency_out=FILE when generating code." << endl; + std::cerr << "Can only use --dependency_out=FILE when generating code." + << std::endl; return PARSE_ARGUMENT_FAIL; } if (!dependency_out_name_.empty() && input_files_.size() > 1) { - cerr << "Can only process one input file when using --dependency_out=FILE." - << endl; + std::cerr + << "Can only process one input file when using --dependency_out=FILE." + << std::endl; return PARSE_ARGUMENT_FAIL; } if (imports_in_descriptor_set_ && descriptor_set_name_.empty()) { @@ -1054,11 +1056,11 @@ CommandLineInterface::InterpretArgument(const string& name, } else if (name == "--dependency_out") { if (!dependency_out_name_.empty()) { - cerr << name << " may only be passed once." << endl; + std::cerr << name << " may only be passed once." << std::endl; return PARSE_ARGUMENT_FAIL; } if (value.empty()) { - cerr << name << " requires a non-empty value." << endl; + std::cerr << name << " requires a non-empty value." << std::endl; return PARSE_ARGUMENT_FAIL; } dependency_out_name_ = value; @@ -1272,7 +1274,8 @@ void CommandLineInterface::PrintHelpText() { " defined in the given proto files. Groups share\n" " the same field number space with the parent \n" " message. Extension ranges are counted as \n" -" occupied fields numbers." << std::endl; +" occupied fields numbers." + << std::endl; if (!plugin_prefix_.empty()) { std::cerr << " --plugin=EXECUTABLE Specifies a plugin executable to use.\n" @@ -1327,13 +1330,23 @@ bool CommandLineInterface::GenerateOutput( } parameters.append(generator_parameters_[output_directive.name]); } - for (int i = 0; i < parsed_files.size(); i++) { - if (!output_directive.generator->Generate(parsed_files[i], parameters, - generator_context, &error)) { - // Generator returned an error. - std::cerr << output_directive.name << ": " << parsed_files[i]->name() - << ": " << error << std::endl; - return false; + if (output_directive.generator->HasGenerateAll()) { + if (!output_directive.generator->GenerateAll( + parsed_files, parameters, generator_context, &error)) { + // Generator returned an error. + std::cerr << output_directive.name << ": " + << ": " << error << std::endl; + return false; + } + } else { + for (int i = 0; i < parsed_files.size(); i++) { + if (!output_directive.generator->Generate(parsed_files[i], parameters, + generator_context, &error)) { + // Generator returned an error. + std::cerr << output_directive.name << ": " << parsed_files[i]->name() + << ": " << error << std::endl; + return false; + } } } } @@ -1403,7 +1416,8 @@ bool CommandLineInterface::GenerateDependencyManifestFile( printer.Print(" $disk_file$", "disk_file", disk_file); if (i < file_set.file_size() - 1) printer.Print("\\\n"); } else { - cerr << "Unable to identify path for file " << virtual_file << endl; + std::cerr << "Unable to identify path for file " << virtual_file + << std::endl; return false; } } @@ -1673,6 +1687,10 @@ void GatherOccupiedFieldRanges(const Descriptor* descriptor, ranges->insert(FieldRange(descriptor->extension_range(i)->start, descriptor->extension_range(i)->end)); } + for (int i = 0; i < descriptor->reserved_range_count(); ++i) { + ranges->insert(FieldRange(descriptor->reserved_range(i)->start, + descriptor->reserved_range(i)->end)); + } // Handle the nested messages/groups in declaration order to make it // post-order strict. for (int i = 0; i < descriptor->nested_type_count(); ++i) { diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index e284c791..23d67e2b 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -115,10 +115,15 @@ class CommandLineInterfaceTest : public testing::Test { // Create a subdirectory within temp_directory_. void CreateTempDir(const string& name); +#ifdef PROTOBUF_OPENSOURCE // Change working directory to temp directory. void SwitchToTempDirectory() { File::ChangeWorkingDirectory(temp_directory_); } +#else // !PROTOBUF_OPENSOURCE + // TODO(teboring): Figure out how to change and get working directory in + // google3. +#endif // !PROTOBUF_OPENSOURCE void SetInputsAreProtoPathRelative(bool enable) { cli_.SetInputsAreProtoPathRelative(enable); @@ -986,6 +991,7 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { "Can only process one input file when using --dependency_out=FILE.\n"); } +#ifdef PROTOBUF_OPENSOURCE TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" @@ -1011,6 +1017,10 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFile) { File::ChangeWorkingDirectory(current_working_directory); } +#else // !PROTOBUF_OPENSOURCE +// TODO(teboring): Figure out how to change and get working directory in +// google3. +#endif // !PROTOBUF_OPENSOURCE TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { CreateTempFile("foo.proto", diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 3eb20ab1..70d3a600 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -70,12 +70,23 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, EnumGenerator::~EnumGenerator() {} +void EnumGenerator::GenerateForwardDeclaration(io::Printer* printer) { + if (!options_.proto_h) { + return; + } + map vars; + vars["classname"] = classname_; + printer->Print(vars, "enum $classname$ : int;\n"); + printer->Print(vars, "bool $classname$_IsValid(int value);\n"); +} + void EnumGenerator::GenerateDefinition(io::Printer* printer) { map vars; vars["classname"] = classname_; vars["short_name"] = descriptor_->name(); + vars["enumbase"] = classname_ + (options_.proto_h ? " : int" : ""); - printer->Print(vars, "enum $classname$ {\n"); + printer->Print(vars, "enum $enumbase$ {\n"); printer->Indent(); const EnumValueDescriptor* min_value = descriptor_->value(0); @@ -90,7 +101,6 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { vars["prefix"] = (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; - if (i > 0) printer->Print(",\n"); printer->Print(vars, "$prefix$$name$ = $number$"); diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 1ebd7cf7..3e930856 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -60,6 +60,12 @@ class EnumGenerator { // Header stuff. + // Generate header code to forward-declare the enum. This is for use when + // generating other .proto.h files. This code should be placed within the + // enum's package namespace, but NOT within any class, even for nested + // enums. + void GenerateForwardDeclaration(io::Printer* printer); + // Generate header code defining the enum. This code should be placed // within the enum's package namespace, but NOT within any class, even for // nested enums. diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 74989703..965327b1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -242,7 +242,7 @@ void RepeatedEnumFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField $name$_;\n"); - if (descriptor_->options().packed() + if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); @@ -352,7 +352,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { - if (!descriptor_->options().packed()) { + if (!descriptor_->is_packed()) { // This path is rarely executed, so we use a non-inlined implementation. if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { printer->Print(variables_, @@ -419,7 +419,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" @@ -432,7 +432,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { } printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n"); - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, " ::google::protobuf::internal::WireFormatLite::WriteEnumNoTag(\n" " this->$name$(i), output);\n"); @@ -446,7 +446,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { void RepeatedEnumFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" @@ -460,7 +460,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { } printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n"); - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, " target = ::google::protobuf::internal::WireFormatLite::WriteEnumNoTagToArray(\n" " this->$name$(i), target);\n"); @@ -484,7 +484,7 @@ GenerateByteSize(io::Printer* printer) const { " this->$name$(i));\n" "}\n"); - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, "if (data_size > 0) {\n" " total_size += $tag_size$ +\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index cd2b6b75..1d7f8233 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -82,12 +82,38 @@ class FieldGenerator { // implementation is empty. virtual void GenerateStaticMembers(io::Printer* /*printer*/) const {} + // Generate prototypes for accessors that will manipulate imported + // messages inline. These are for .proto.h headers. + // + // In .proto.h mode, the headers of imports are not #included. However, + // functions that manipulate the imported message types need access to + // the class definition of the imported message, meaning that the headers + // must be #included. To get around this, functions that manipulate + // imported message objects are defined as dependent functions in a base + // template class. By making them dependent template functions, the + // function templates will not be instantiated until they are called, so + // we can defer to those translation units to #include the necessary + // generated headers. + // + // See: + // http://en.cppreference.com/w/cpp/language/class_template#Implicit_instantiation + // + // Most field types don't need this, so the default implementation is empty. + virtual void GenerateDependentAccessorDeclarations( + io::Printer* printer) const {} + // Generate prototypes for all of the accessor functions related to this // field. These are placed inside the class definition. virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0; + // Generate inline definitions of depenent accessor functions for this field. + // These are placed inside the header after all class definitions. + virtual void GenerateDependentInlineAccessorDefinitions( + io::Printer* printer) const {} + // Generate inline definitions of accessor functions for this field. // These are placed inside the header after all class definitions. + // In non-.proto.h mode, this generates dependent accessor functions as well. virtual void GenerateInlineAccessorDefinitions( io::Printer* printer, bool is_inline) const = 0; diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index a98c7d92..b997a51a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -94,113 +94,10 @@ FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) FileGenerator::~FileGenerator() {} void FileGenerator::GenerateHeader(io::Printer* printer) { - string filename_identifier = FilenameIdentifier(file_->name()); - - // Generate top of header. - printer->Print( - "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" - "// source: $filename$\n" - "\n" - "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n" - "#define PROTOBUF_$filename_identifier$__INCLUDED\n" - "\n" - "#include \n" - "\n", - "filename", file_->name(), - "filename_identifier", filename_identifier); - - - printer->Print( - "#include \n" - "\n"); - - // Verify the protobuf library header version is compatible with the protoc - // version before going any further. - printer->Print( - "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n" - "#error This file was generated by a newer version of protoc which is\n" - "#error incompatible with your Protocol Buffer headers. Please update\n" - "#error your headers.\n" - "#endif\n" - "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n" - "#error This file was generated by an older version of protoc which is\n" - "#error incompatible with your Protocol Buffer headers. Please\n" - "#error regenerate this file with a newer version of protoc.\n" - "#endif\n" - "\n", - "min_header_version", - SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc), - "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION)); - - // OK, it's now safe to #include other files. - printer->Print( - "#include \n" - "#include \n" - "#include \n"); - if (UseUnknownFieldSet(file_)) { - printer->Print( - "#include \n"); - } - if (file_->message_type_count() > 0) { - if (HasDescriptorMethods(file_)) { - printer->Print( - "#include \n"); - } else { - printer->Print( - "#include \n"); - } - } - printer->Print( - "#include \n" - "#include \n"); - if (HasMapFields(file_)) { - printer->Print( - "#include \n"); - if (HasDescriptorMethods(file_)) { - printer->Print( - "#include \n"); - } else { - printer->Print( - "#include \n"); - } - } - - if (HasEnumDefinitions(file_)) { - if (HasDescriptorMethods(file_)) { - printer->Print( - "#include \n"); - } else { - printer->Print( - "#include \n"); - } - } - - if (HasGenericServices(file_)) { - printer->Print( - "#include \n"); - } - - if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { - printer->Print( - "#include \n"); - } - - - set public_import_names; - for (int i = 0; i < file_->public_dependency_count(); i++) { - public_import_names.insert(file_->public_dependency(i)->name()); - } - - for (int i = 0; i < file_->dependency_count(); i++) { - const string& name = file_->dependency(i)->name(); - bool public_import = (public_import_names.count(name) != 0); + GenerateTopHeaderGuard(printer); - - printer->Print( - "#include \"$dependency$.pb.h\"$iwyu$\n", - "dependency", StripProto(name), - "iwyu", (public_import) ? " // IWYU pragma: export" : ""); - } + GenerateLibraryIncludes(printer); + GenerateDependencyIncludes(printer); printer->Print( "// @@protoc_insertion_point(includes)\n"); @@ -210,132 +107,44 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { // Open namespace. GenerateNamespaceOpeners(printer); - // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile - // functions, so that we can declare them to be friends of each class. - printer->Print( - "\n" - "// Internal implementation detail -- do not call these.\n" - "void $dllexport_decl$$adddescriptorsname$();\n", - "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), - "dllexport_decl", - options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " "); - - printer->Print( - // Note that we don't put dllexport_decl on these because they are only - // called by the .pb.cc file in which they are defined. - "void $assigndescriptorsname$();\n" - "void $shutdownfilename$();\n" - "\n", - "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()), - "shutdownfilename", GlobalShutdownFileName(file_->name())); - - // Generate forward declarations of classes. - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateForwardDeclaration(printer); - } + GenerateGlobalStateFunctionDeclarations(printer); + GenerateMessageForwardDeclarations(printer); printer->Print("\n"); - // Generate enum definitions. - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateEnumDefinitions(printer); - } - for (int i = 0; i < file_->enum_type_count(); i++) { - enum_generators_[i]->GenerateDefinition(printer); - } + GenerateEnumDefinitions(printer); printer->Print(kThickSeparator); printer->Print("\n"); - // Generate class definitions. - for (int i = 0; i < file_->message_type_count(); i++) { - if (i > 0) { - printer->Print("\n"); - printer->Print(kThinSeparator); - printer->Print("\n"); - } - message_generators_[i]->GenerateClassDefinition(printer); - } + GenerateMessageDefinitions(printer); printer->Print("\n"); printer->Print(kThickSeparator); printer->Print("\n"); - if (HasGenericServices(file_)) { - // Generate service definitions. - for (int i = 0; i < file_->service_count(); i++) { - if (i > 0) { - printer->Print("\n"); - printer->Print(kThinSeparator); - printer->Print("\n"); - } - service_generators_[i]->GenerateDeclarations(printer); - } - - printer->Print("\n"); - printer->Print(kThickSeparator); - printer->Print("\n"); - } + GenerateServiceDefinitions(printer); - // Declare extension identifiers. - for (int i = 0; i < file_->extension_count(); i++) { - extension_generators_[i]->GenerateDeclaration(printer); - } + GenerateExtensionIdentifiers(printer); printer->Print("\n"); printer->Print(kThickSeparator); printer->Print("\n"); - printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); - // Generate class inline methods. - for (int i = 0; i < file_->message_type_count(); i++) { - if (i > 0) { - printer->Print(kThinSeparator); - printer->Print("\n"); - } - message_generators_[i]->GenerateInlineMethods(printer, - /* is_inline = */ true); - } - printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); - - printer->Print( - "\n" - "// @@protoc_insertion_point(namespace_scope)\n"); + GenerateInlineFunctionDefinitions(printer); // Close up namespace. GenerateNamespaceClosers(printer); - // Emit GetEnumDescriptor specializations into google::protobuf namespace: - if (HasEnumDefinitions(file_)) { - // The SWIG conditional is to avoid a null-pointer dereference - // (bug 1984964) in swig-1.3.21 resulting from the following syntax: - // namespace X { void Y(); } - // which appears in GetEnumDescriptor() specializations. - printer->Print( - "\n" - "#ifndef SWIG\n" - "namespace google {\nnamespace protobuf {\n" - "\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); - } - for (int i = 0; i < file_->enum_type_count(); i++) { - enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); - } - printer->Print( - "\n" - "} // namespace protobuf\n} // namespace google\n" - "#endif // SWIG\n"); - } + // We need to specialize some templates in the ::google::protobuf namespace: + GenerateProto2NamespaceEnumSpecializations(printer); printer->Print( "\n" "// @@protoc_insertion_point(global_scope)\n" "\n"); - printer->Print( - "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", - "filename_identifier", filename_identifier); + GenerateBottomHeaderGuard(printer); } void FileGenerator::GenerateSource(io::Printer* printer) { @@ -707,6 +516,294 @@ void FileGenerator::GenerateNamespaceClosers(io::Printer* printer) { } } +void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer) { + string filename_identifier = FilenameIdentifier(file_->name()); + // Generate top of header. + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n" + "#ifndef PROTOBUF_$filename_identifier$__INCLUDED\n" + "#define PROTOBUF_$filename_identifier$__INCLUDED\n" + "\n" + "#include \n" + "\n", + "filename", file_->name(), + "filename_identifier", filename_identifier); +} + +void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer) { + string filename_identifier = FilenameIdentifier(file_->name()); + printer->Print( + "#endif // PROTOBUF_$filename_identifier$__INCLUDED\n", + "filename_identifier", filename_identifier); +} + +void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) { + + printer->Print( + "#include \n" + "\n"); + + // Verify the protobuf library header version is compatible with the protoc + // version before going any further. + printer->Print( + "#if GOOGLE_PROTOBUF_VERSION < $min_header_version$\n" + "#error This file was generated by a newer version of protoc which is\n" + "#error incompatible with your Protocol Buffer headers. Please update\n" + "#error your headers.\n" + "#endif\n" + "#if $protoc_version$ < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION\n" + "#error This file was generated by an older version of protoc which is\n" + "#error incompatible with your Protocol Buffer headers. Please\n" + "#error regenerate this file with a newer version of protoc.\n" + "#endif\n" + "\n", + "min_header_version", + SimpleItoa(protobuf::internal::kMinHeaderVersionForProtoc), + "protoc_version", SimpleItoa(GOOGLE_PROTOBUF_VERSION)); + + // OK, it's now safe to #include other files. + printer->Print( + "#include \n" + "#include \n" + "#include \n"); + if (UseUnknownFieldSet(file_)) { + printer->Print( + "#include \n"); + } + if (file_->message_type_count() > 0) { + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n"); + } else { + printer->Print( + "#include \n"); + } + } + printer->Print( + "#include \n" + "#include \n"); + if (HasMapFields(file_)) { + printer->Print( + "#include \n"); + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n"); + } else { + printer->Print( + "#include \n"); + } + } + + if (HasEnumDefinitions(file_)) { + if (HasDescriptorMethods(file_)) { + printer->Print( + "#include \n"); + } else { + printer->Print( + "#include \n"); + } + } + + if (HasGenericServices(file_)) { + printer->Print( + "#include \n"); + } + + if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { + printer->Print( + "#include \n"); + } + + + if (IsAnyMessage(file_)) { + printer->Print( + "#include \"google/protobuf/any.h\"\n"); + } +} + +void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) { + set public_import_names; + for (int i = 0; i < file_->public_dependency_count(); i++) { + public_import_names.insert(file_->public_dependency(i)->name()); + } + + for (int i = 0; i < file_->dependency_count(); i++) { + const string& name = file_->dependency(i)->name(); + bool public_import = (public_import_names.count(name) != 0); + + + printer->Print( + "#include \"$dependency$.pb.h\"$iwyu$\n", + "dependency", StripProto(name), + "iwyu", (public_import) ? " // IWYU pragma: export" : ""); + } +} + +void FileGenerator::GenerateGlobalStateFunctionDeclarations( + io::Printer* printer) { + // Forward-declare the AddDescriptors, AssignDescriptors, and ShutdownFile + // functions, so that we can declare them to be friends of each class. + printer->Print( + "\n" + "// Internal implementation detail -- do not call these.\n" + "void $dllexport_decl$$adddescriptorsname$();\n", + "adddescriptorsname", GlobalAddDescriptorsName(file_->name()), + "dllexport_decl", + options_.dllexport_decl.empty() ? "" : options_.dllexport_decl + " "); + + printer->Print( + // Note that we don't put dllexport_decl on these because they are only + // called by the .pb.cc file in which they are defined. + "void $assigndescriptorsname$();\n" + "void $shutdownfilename$();\n" + "\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name()), + "shutdownfilename", GlobalShutdownFileName(file_->name())); +} + +void FileGenerator::GenerateMessageForwardDeclarations(io::Printer* printer) { + // Generate forward declarations of classes. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateMessageForwardDeclaration(printer); + } +} + +void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) { + // Generate class definitions. + for (int i = 0; i < file_->message_type_count(); i++) { + if (i > 0) { + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + message_generators_[i]->GenerateClassDefinition(printer); + } +} + +void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) { + // Generate enum definitions. + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateEnumDefinitions(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateDefinition(printer); + } +} + +void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) { + if (HasGenericServices(file_)) { + // Generate service definitions. + for (int i = 0; i < file_->service_count(); i++) { + if (i > 0) { + printer->Print("\n"); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + service_generators_[i]->GenerateDeclarations(printer); + } + + printer->Print("\n"); + printer->Print(kThickSeparator); + printer->Print("\n"); + } +} + +void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) { + // Declare extension identifiers. + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateDeclaration(printer); + } +} + +void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) { + // An aside about inline functions in .proto.h mode: + // + // The PROTOBUF_INLINE_NOT_IN_HEADERS symbol controls conditionally + // moving much of the inline functions to the .pb.cc file, which can be a + // significant performance benefit for compilation time, at the expense + // of non-inline function calls. + // + // However, in .proto.h mode, the definition of the internal dependent + // base class must remain in the header, and can never be out-lined. The + // dependent base class also needs access to has-bit manipuation + // functions, so the has-bit functions must be unconditionally inlined in + // proto_h mode. + // + // This gives us three flavors of functions: + // + // 1. Functions on the message not used by the internal dependent base + // class: in .proto.h mode, only some functions are defined on the + // message class; others are defined on the dependent base class. + // These are guarded and can be out-lined. These are generated by + // GenerateInlineMethods, and include has_* bit functions in + // non-proto_h mode. + // + // 2. Functions on the internal dependent base class: these functions + // are dependent on a template parameter, so they always need to + // remain in the header. + // + // 3. Functions on the message that are used by the dependent base: the + // dependent base class down casts itself to the message + // implementation class to access these functions (the has_* bit + // manipulation functions). Unlike #1, these functions must + // unconditionally remain in the header. These are emitted by + // GenerateDependentInlineMethods, even though they are not actually + // dependent. + + printer->Print("#if !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); + // Generate class inline methods. + for (int i = 0; i < file_->message_type_count(); i++) { + if (i > 0) { + printer->Print(kThinSeparator); + printer->Print("\n"); + } + message_generators_[i]->GenerateInlineMethods(printer, + /* is_inline = */ true); + } + printer->Print("#endif // !PROTOBUF_INLINE_NOT_IN_HEADERS\n"); + + for (int i = 0; i < file_->message_type_count(); i++) { + if (i > 0) { + printer->Print(kThinSeparator); + printer->Print("\n"); + } + // Methods of the dependent base class must always be inline in the header. + message_generators_[i]->GenerateDependentInlineMethods(printer); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(namespace_scope)\n"); +} + +void FileGenerator::GenerateProto2NamespaceEnumSpecializations( + io::Printer* printer) { + // Emit GetEnumDescriptor specializations into google::protobuf namespace: + if (HasEnumDefinitions(file_)) { + // The SWIG conditional is to avoid a null-pointer dereference + // (bug 1984964) in swig-1.3.21 resulting from the following syntax: + // namespace X { void Y(); } + // which appears in GetEnumDescriptor() specializations. + printer->Print( + "\n" + "#ifndef SWIG\n" + "namespace google {\nnamespace protobuf {\n" + "\n"); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + for (int i = 0; i < file_->enum_type_count(); i++) { + enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer); + } + printer->Print( + "\n" + "} // namespace protobuf\n} // namespace google\n" + "#endif // SWIG\n"); + } +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h index 0e06547d..e68f67bb 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.h +++ b/src/google/protobuf/compiler/cpp/cpp_file.h @@ -80,6 +80,35 @@ class FileGenerator { void GenerateNamespaceOpeners(io::Printer* printer); void GenerateNamespaceClosers(io::Printer* printer); + // Generates top or bottom of a header file. + void GenerateTopHeaderGuard(io::Printer* printer); + void GenerateBottomHeaderGuard(io::Printer* printer); + + // Generates #include directives. + void GenerateLibraryIncludes(io::Printer* printer); + void GenerateDependencyIncludes(io::Printer* printer); + + // Generates a couple of different pieces before definitions: + void GenerateGlobalStateFunctionDeclarations(io::Printer* printer); + + // Generates types for classes. + void GenerateMessageForwardDeclarations(io::Printer* printer); + void GenerateMessageDefinitions(io::Printer* printer); + + // Generates enum definitions. + void GenerateEnumDefinitions(io::Printer* printer); + + // Generates generic service definitions. + void GenerateServiceDefinitions(io::Printer* printer); + + // Generates extension identifiers. + void GenerateExtensionIdentifiers(io::Printer* printer); + + // Generates inline function defintions. + void GenerateInlineFunctionDefinitions(io::Printer* printer); + + void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer); + const FileDescriptor* file_; google::protobuf::scoped_array > message_generators_; diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index c999b93f..99416372 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -82,6 +82,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, // } // FOO_EXPORT is a macro which should expand to __declspec(dllexport) or // __declspec(dllimport) depending on what is being compiled. + // Options file_options; for (int i = 0; i < options.size(); i++) { diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 4e7155c3..0f3688d0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -51,6 +51,9 @@ namespace cpp { namespace { +static const char kAnyMessageName[] = "Any"; +static const char kAnyProtoFile[] = "google/protobuf/any.proto"; + string DotsToUnderscores(const string& name) { return StringReplace(name, ".", "_", true); } @@ -162,6 +165,10 @@ string ClassName(const EnumDescriptor* enum_descriptor, bool qualified) { } +string DependentBaseClassTemplateName(const Descriptor* descriptor) { + return ClassName(descriptor, false) + "_InternalBase"; +} + string SuperClassName(const Descriptor* descriptor) { return HasDescriptorMethods(descriptor->file()) ? "::google::protobuf::Message" : "::google::protobuf::MessageLite"; @@ -200,6 +207,47 @@ string FieldConstantName(const FieldDescriptor *field) { return result; } +bool IsFieldDependent(const FieldDescriptor* field) { + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return false; + } + if (field->containing_oneof() != NULL) { + // Oneof fields will always be dependent. + // + // This is a unique case for field codegen. Field generators are + // responsible for generating all the field-specific accessor + // functions, except for the clear_*() function; instead, field + // generators produce inline clearing code. + // + // For non-oneof fields, the Message class uses the inline clearing + // code to define the field's clear_*() function, as well as in the + // destructor. For oneof fields, the Message class generates a much + // more complicated clear_*() function, which clears only the oneof + // member that is set, in addition to clearing methods for each of the + // oneof members individually. + // + // Since oneofs do not have their own generator class, the Message code + // generation logic would be significantly complicated in order to + // split dependent and non-dependent manipulation logic based on + // whether the oneof truly needs to be dependent; so, for oneof fields, + // we just assume it (and its constituents) should be manipulated by a + // dependent base class function. + // + // This is less precise than how dependent message-typed fields are + // handled, but the cost is limited to only the generated code for the + // oneof field, which seems like an acceptable tradeoff. + return true; + } + if (field->file() == field->message_type()->file()) { + return false; + } + return true; +} + +string DependentTypeName(const FieldDescriptor* field) { + return "InternalBase_" + field->name() + "_T"; +} + string FieldMessageTypeName(const FieldDescriptor* field) { // Note: The Google-internal version of Protocol Buffers uses this function // as a hook point for hacks to support legacy code. @@ -360,7 +408,7 @@ string FilenameIdentifier(const string& filename) { } else { // Not alphanumeric. To avoid any possibility of name conflicts we // use the hex code for the character. - StrAppend(&result, "_", ToHex(static_cast(filename[i]))); + StrAppend(&result, "_", strings::Hex(static_cast(filename[i]))); } } return result; @@ -521,6 +569,15 @@ FieldOptions::CType EffectiveStringCType(const FieldDescriptor* field) { } +bool IsAnyMessage(const FileDescriptor* descriptor) { + return descriptor->name() == kAnyProtoFile; +} + +bool IsAnyMessage(const Descriptor* descriptor) { + return descriptor->name() == kAnyMessageName && + descriptor->file()->name() == kAnyProtoFile; +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 284fa2c1..4bbf8303 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -66,6 +66,10 @@ extern const char kThinSeparator[]; string ClassName(const Descriptor* descriptor, bool qualified); string ClassName(const EnumDescriptor* enum_descriptor, bool qualified); +// Name of the CRTP class template (for use with proto_h). +// This is a class name, like "ProtoName_InternalBase". +string DependentBaseClassTemplateName(const Descriptor* descriptor); + string SuperClassName(const Descriptor* descriptor); // Get the (unqualified) name that should be used for this field in C++ code. @@ -88,6 +92,20 @@ inline const Descriptor* FieldScope(const FieldDescriptor* field) { field->extension_scope() : field->containing_type(); } +// Returns true if the given 'field_descriptor' has a message type that is +// a dependency of the file where the field is defined (i.e., the field +// type is defined in a different file than the message holding the field). +// +// This only applies to Message-typed fields. Enum-typed fields may refer +// to an enum in a dependency; however, enums are specified and +// forward-declared with an enum-base, so the definition is not required to +// manipulate the field value. +bool IsFieldDependent(const FieldDescriptor* field_descriptor); + +// Returns the name that should be used for forcing dependent lookup from a +// dependent base class. +string DependentTypeName(const FieldDescriptor* field); + // Returns the fully-qualified type name field->message_type(). Usually this // is just ClassName(field->message_type(), true); string FieldMessageTypeName(const FieldDescriptor* field); @@ -242,6 +260,9 @@ inline bool SupportsArenas(const FieldDescriptor* field) { return SupportsArenas(field->file()); } +bool IsAnyMessage(const FileDescriptor* descriptor); +bool IsAnyMessage(const Descriptor* descriptor); + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index 8c38db2b..0ff0d27c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -244,7 +244,8 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + " it = this->$name$().begin();\n" + " it != this->$name$().end(); ++it) {\n"); // If entry is allocated by arena, its desctructor should be avoided. if (SupportsArenas(descriptor_)) { @@ -277,7 +278,8 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + " it = this->$name$().begin();\n" + " it != this->$name$().end(); ++it) {\n"); // If entry is allocated by arena, its desctructor should be avoided. if (SupportsArenas(descriptor_)) { @@ -312,7 +314,8 @@ GenerateByteSize(io::Printer* printer) const { "{\n" " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = $name$().begin(); it != $name$().end(); ++it) {\n"); + " it = this->$name$().begin();\n" + " it != this->$name$().end(); ++it) {\n"); // If entry is allocated by arena, its desctructor should be avoided. if (SupportsArenas(descriptor_)) { diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 98929b1e..212fe2e1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -64,10 +64,15 @@ using internal::WireFormatLite; namespace { -void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { - // Print the field's proto-syntax definition as a comment. We don't want to - // print group bodies so we cut off after the first line. - string def = field->DebugString(); +template +void PrintFieldComment(io::Printer* printer, const T* field) { + // Print the field's (or oneof's) proto-syntax definition as a comment. + // We don't want to print group bodies so we cut off after the first + // line. + DebugStringOptions options; + options.elide_group_body = true; + options.elide_oneof_body = true; + string def = field->DebugStringWithOptions(options); printer->Print("// $def$\n", "def", def.substr(0, def.find_first_of('\n'))); } @@ -280,6 +285,10 @@ void OptimizePadding(vector* fields) { } } +string MessageTypeProtoName(const FieldDescriptor* field) { + return field->message_type()->full_name(); +} + // Emits an if-statement with a condition that evaluates to true if |field| is // considered non-default (will be sent over the wire), for message types // without true field presence. Should only be called if @@ -379,7 +388,8 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, enum_generators_( new google::protobuf::scoped_ptr[descriptor->enum_type_count()]), extension_generators_(new google::protobuf::scoped_ptr< - ExtensionGenerator>[descriptor->extension_count()]) { + ExtensionGenerator>[descriptor->extension_count()]), + use_dependent_base_(false) { for (int i = 0; i < descriptor->nested_type_count(); i++) { nested_generators_[i].reset( @@ -401,13 +411,16 @@ MessageGenerator::MessageGenerator(const Descriptor* descriptor, if (descriptor->field(i)->is_required()) { ++num_required_fields_; } + if (options.proto_h && IsFieldDependent(descriptor->field(i))) { + use_dependent_base_ = true; + } } } MessageGenerator::~MessageGenerator() {} void MessageGenerator:: -GenerateForwardDeclaration(io::Printer* printer) { +GenerateMessageForwardDeclaration(io::Printer* printer) { printer->Print("class $classname$;\n", "classname", classname_); @@ -416,7 +429,17 @@ GenerateForwardDeclaration(io::Printer* printer) { // message cannot be a top level class, we just need to avoid calling // GenerateForwardDeclaration here. if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; - nested_generators_[i]->GenerateForwardDeclaration(printer); + nested_generators_[i]->GenerateMessageForwardDeclaration(printer); + } +} + +void MessageGenerator:: +GenerateEnumForwardDeclaration(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + nested_generators_[i]->GenerateEnumForwardDeclaration(printer); + } + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + enum_generators_[i]->GenerateForwardDeclaration(printer); } } @@ -441,6 +464,35 @@ GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { } } +void MessageGenerator:: +GenerateDependentFieldAccessorDeclarations(io::Printer* printer) { + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + PrintFieldComment(printer, field); + + map vars; + SetCommonFieldVariables(field, &vars, options_); + + if (use_dependent_base_ && IsFieldDependent(field)) { + // If the message is dependent, the inline clear_*() method will need + // to delete the message type, so it must be in the dependent base + // class. (See also GenerateFieldAccessorDeclarations.) + printer->Print(vars, "void clear_$name$()$deprecation$;\n"); + } + // Generate type-specific accessor declarations. + field_generators_.get(field).GenerateDependentAccessorDeclarations(printer); + printer->Print("\n"); + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + PrintFieldComment(printer, oneof); + printer->Print( + "void clear_$oneof_name$();\n", + "oneof_name", oneof->name()); + } +} + void MessageGenerator:: GenerateFieldAccessorDeclarations(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { @@ -452,6 +504,19 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { SetCommonFieldVariables(field, &vars, options_); vars["constant_name"] = FieldConstantName(field); + bool dependent_field = use_dependent_base_ && IsFieldDependent(field); + if (dependent_field) { + // If this field is dependent, the dependent base class determines + // the message type from the derived class (which is a template + // parameter). This typedef is for that: + printer->Print( + "private:\n" + "typedef $field_type$ $dependent_type$;\n" + "public:\n", + "field_type", FieldMessageTypeName(field), + "dependent_type", DependentTypeName(field)); + } + if (field->is_repeated()) { printer->Print(vars, "int $name$_size() const$deprecation$;\n"); } else if (HasHasMethod(field)) { @@ -463,7 +528,11 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { "public:\n"); } - printer->Print(vars, "void clear_$name$()$deprecation$;\n"); + if (!dependent_field) { + // If this field is dependent, then its clear_() method is in the + // depenent base class. (See also GenerateDependentAccessorDeclarations.) + printer->Print(vars, "void clear_$name$()$deprecation$;\n"); + } printer->Print(vars, "static const int $constant_name$ = $number$;\n"); // Generate type-specific accessor declarations. @@ -489,6 +558,188 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { } } +void MessageGenerator:: +GenerateDependentFieldAccessorDefinitions(io::Printer* printer) { + if (!use_dependent_base_) return; + + printer->Print("// $classname$\n\n", "classname", + DependentBaseClassTemplateName(descriptor_)); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + + PrintFieldComment(printer, field); + + // These functions are not really dependent: they are part of the + // (non-dependent) derived class. However, they need to live outside + // any #ifdef guards, so we treat them as if they were dependent. + // + // See the comment in FileGenerator::GenerateInlineFunctionDefinitions + // for a more complete explanation. + if (use_dependent_base_ && IsFieldDependent(field)) { + map vars; + SetCommonFieldVariables(field, &vars, options_); + vars["inline"] = "inline "; + if (field->containing_oneof()) { + vars["field_name"] = UnderscoresToCamelCase(field->name(), true); + vars["oneof_name"] = field->containing_oneof()->name(); + vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); + GenerateOneofMemberHasBits(field, vars, printer); + } else if (!field->is_repeated()) { + // There will be no header guard, so this always has to be inline. + GenerateSingularFieldHasBits(field, vars, printer); + } + // vars needed for clear_(), which is in the dependent base: + // (See also GenerateDependentFieldAccessorDeclarations.) + vars["tmpl"] = "template\n"; + vars["dependent_classname"] = + DependentBaseClassTemplateName(descriptor_) + ""; + vars["this_message"] = "reinterpret_cast(this)->"; + vars["this_const_message"] = "reinterpret_cast(this)->"; + GenerateFieldClear(field, vars, printer); + } + + // Generate type-specific accessors. + field_generators_.get(field) + .GenerateDependentInlineAccessorDefinitions(printer); + + printer->Print("\n"); + } + + // Generate has_$name$() and clear_has_$name$() functions for oneofs + // Similar to other has-bits, these must always be in the header if we + // are using a dependent base class. + GenerateOneofHasBits(printer, true /* is_inline */); +} + +void MessageGenerator:: +GenerateSingularFieldHasBits(const FieldDescriptor* field, + map vars, + io::Printer* printer) { + if (HasFieldPresence(descriptor_->file())) { + // N.B.: without field presence, we do not use has-bits or generate + // has_$name$() methods. + vars["has_array_index"] = SimpleItoa(field->index() / 32); + vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32), + strings::Hex::ZERO_PAD_8)); + printer->Print(vars, + "$inline$" + "bool $classname$::has_$name$() const {\n" + " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" + "}\n" + "$inline$" + "void $classname$::set_has_$name$() {\n" + " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" + "}\n" + "$inline$" + "void $classname$::clear_has_$name$() {\n" + " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" + "}\n"); + } else { + // Message fields have a has_$name$() method. + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + bool is_lazy = false; + if (is_lazy) { + printer->Print(vars, + "$inline$" + "bool $classname$::has_$name$() const {\n" + " return !$name$_.IsCleared();\n" + "}\n"); + } else { + printer->Print(vars, + "$inline$" + "bool $classname$::has_$name$() const {\n" + " return !_is_default_instance_ && $name$_ != NULL;\n" + "}\n"); + } + } + } +} + +void MessageGenerator:: +GenerateOneofHasBits(io::Printer* printer, bool is_inline) { + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + map vars; + vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["cap_oneof_name"] = + ToUpper(descriptor_->oneof_decl(i)->name()); + vars["classname"] = classname_; + vars["inline"] = (is_inline ? "inline " : ""); + printer->Print( + vars, + "$inline$" + "bool $classname$::has_$oneof_name$() const {\n" + " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" + "}\n" + "$inline$" + "void $classname$::clear_has_$oneof_name$() {\n" + " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" + "}\n"); + } +} + +void MessageGenerator:: +GenerateOneofMemberHasBits(const FieldDescriptor* field, + const map& vars, + io::Printer* printer) { + // Singular field in a oneof + // N.B.: Without field presence, we do not use has-bits or generate + // has_$name$() methods, but oneofs still have set_has_$name$(). + // Oneofs also have has_$name$() but only as a private helper + // method, so that generated code is slightly cleaner (vs. comparing + // _oneof_case_[index] against a constant everywhere). + printer->Print(vars, + "$inline$" + "bool $classname$::has_$name$() const {\n" + " return $oneof_name$_case() == k$field_name$;\n" + "}\n"); + printer->Print(vars, + "$inline$" + "void $classname$::set_has_$name$() {\n" + " _oneof_case_[$oneof_index$] = k$field_name$;\n" + "}\n"); +} + +void MessageGenerator:: +GenerateFieldClear(const FieldDescriptor* field, + const map& vars, + io::Printer* printer) { + // Generate clear_$name$() (See GenerateFieldAccessorDeclarations and + // GenerateDependentFieldAccessorDeclarations, $dependent_classname$ is + // set by the Generate*Definitions functions.) + printer->Print(vars, + "$tmpl$" + "$inline$" + "void $dependent_classname$::clear_$name$() {\n"); + + printer->Indent(); + + if (field->containing_oneof()) { + // Clear this field only if it is the active field in this oneof, + // otherwise ignore + printer->Print(vars, + "if ($this_message$has_$name$()) {\n"); + printer->Indent(); + field_generators_.get(field).GenerateClearingCode(printer); + printer->Print(vars, + "$this_message$clear_has_$oneof_name$();\n"); + printer->Outdent(); + printer->Print("}\n"); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + if (HasFieldPresence(descriptor_->file())) { + if (!field->is_repeated()) { + printer->Print(vars, + "$this_message$clear_has_$name$();\n"); + } + } + } + + printer->Outdent(); + printer->Print("}\n"); +} + void MessageGenerator:: GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { printer->Print("// $classname$\n\n", "classname", classname_); @@ -500,101 +751,37 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { map vars; SetCommonFieldVariables(field, &vars, options_); - vars["inline"] = is_inline ? "inline" : ""; + vars["inline"] = is_inline ? "inline " : ""; // Generate has_$name$() or $name$_size(). if (field->is_repeated()) { printer->Print(vars, - "$inline$ int $classname$::$name$_size() const {\n" + "$inline$" + "int $classname$::$name$_size() const {\n" " return $name$_.size();\n" "}\n"); } else if (field->containing_oneof()) { - // Singular field in a oneof - // N.B.: Without field presence, we do not use has-bits or generate - // has_$name$() methods, but oneofs still have set_has_$name$(). - // Oneofs also have has_$name$() but only as a private helper - // method, so that generated code is slightly cleaner (vs. comparing - // _oneof_case_[index] against a constant everywhere). vars["field_name"] = UnderscoresToCamelCase(field->name(), true); vars["oneof_name"] = field->containing_oneof()->name(); vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); - printer->Print(vars, - "$inline$ bool $classname$::has_$name$() const {\n" - " return $oneof_name$_case() == k$field_name$;\n" - "}\n"); - printer->Print(vars, - "$inline$ void $classname$::set_has_$name$() {\n" - " _oneof_case_[$oneof_index$] = k$field_name$;\n" - "}\n"); + if (!use_dependent_base_ || !IsFieldDependent(field)) { + GenerateOneofMemberHasBits(field, vars, printer); + } } else { // Singular field. - if (HasFieldPresence(descriptor_->file())) { - // N.B.: without field presence, we do not use has-bits or generate - // has_$name$() methods. - char buffer[kFastToBufferSize]; - vars["has_array_index"] = SimpleItoa(field->index() / 32); - vars["has_mask"] = FastHex32ToBuffer(1u << (field->index() % 32), - buffer); - printer->Print(vars, - "$inline$ bool $classname$::has_$name$() const {\n" - " return (_has_bits_[$has_array_index$] & 0x$has_mask$u) != 0;\n" - "}\n" - "$inline$ void $classname$::set_has_$name$() {\n" - " _has_bits_[$has_array_index$] |= 0x$has_mask$u;\n" - "}\n" - "$inline$ void $classname$::clear_has_$name$() {\n" - " _has_bits_[$has_array_index$] &= ~0x$has_mask$u;\n" - "}\n" - ); - } else { - // Message fields have a has_$name$() method. - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - bool is_lazy = false; - if (is_lazy) { - printer->Print(vars, - "$inline$ bool $classname$::has_$name$() const {\n" - " return !$name$_.IsCleared();\n" - "}\n"); - } else { - printer->Print(vars, - "$inline$ bool $classname$::has_$name$() const {\n" - " return !_is_default_instance_ && $name$_ != NULL;\n" - "}\n"); - } - } + if (!use_dependent_base_ || !IsFieldDependent(field)) { + GenerateSingularFieldHasBits(field, vars, printer); } } - // Generate clear_$name$() - printer->Print(vars, - "$inline$ void $classname$::clear_$name$() {\n"); - - printer->Indent(); - - if (field->containing_oneof()) { - // Clear this field only if it is the active field in this oneof, - // otherwise ignore - printer->Print(vars, - "if (has_$name$()) {\n"); - printer->Indent(); - field_generators_.get(field).GenerateClearingCode(printer); - printer->Print(vars, - "clear_has_$oneof_name$();\n"); - printer->Outdent(); - printer->Print("}\n"); - } else { - field_generators_.get(field).GenerateClearingCode(printer); - if (HasFieldPresence(descriptor_->file())) { - if (!field->is_repeated()) { - printer->Print(vars, - "clear_has_$name$();\n"); - } - } + if (!use_dependent_base_ || !IsFieldDependent(field)) { + vars["tmpl"] = ""; + vars["dependent_classname"] = vars["classname"]; + vars["this_message"] = ""; + vars["this_const_message"] = ""; + GenerateFieldClear(field, vars, printer); } - printer->Outdent(); - printer->Print("}\n"); - // Generate type-specific accessors. field_generators_.get(field).GenerateInlineAccessorDefinitions(printer, is_inline); @@ -602,23 +789,11 @@ GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline) { printer->Print("\n"); } - // Generate has_$name$() and clear_has_$name$() functions for oneofs - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - map vars; - vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - vars["cap_oneof_name"] = - ToUpper(descriptor_->oneof_decl(i)->name()); - vars["classname"] = classname_; - vars["inline"] = is_inline ? "inline" : ""; - printer->Print( - vars, - "$inline$ bool $classname$::has_$oneof_name$() const {\n" - " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" - "}\n" - "$inline$ void $classname$::clear_has_$oneof_name$() {\n" - " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" - "}\n"); + if (!use_dependent_base_) { + // Generate has_$name$() and clear_has_$name$() functions for oneofs + // If we aren't using a dependent base, they can be with the other functions + // that are #ifdef-guarded. + GenerateOneofHasBits(printer, is_inline); } } @@ -647,6 +822,34 @@ static bool CanClearByZeroing(const FieldDescriptor* field) { } } +void MessageGenerator:: +GenerateDependentBaseClassDefinition(io::Printer* printer) { + if (!use_dependent_base_) { + return; + } + + map vars; + vars["classname"] = DependentBaseClassTemplateName(descriptor_); + vars["superclass"] = SuperClassName(descriptor_); + + printer->Print(vars, + "template \n" + "class $classname$ : public $superclass$ {\n" + " public:\n"); + printer->Indent(); + + printer->Print(vars, + "$classname$() {}\n" + "virtual ~$classname$() {}\n" + "\n"); + + // Generate dependent accessor methods for all fields. + GenerateDependentFieldAccessorDeclarations(printer); + + printer->Outdent(); + printer->Print("};\n"); +} + void MessageGenerator:: GenerateClassDefinition(io::Printer* printer) { for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -660,6 +863,11 @@ GenerateClassDefinition(io::Printer* printer) { printer->Print("\n"); } + if (use_dependent_base_) { + GenerateDependentBaseClassDefinition(printer); + printer->Print("\n"); + } + map vars; vars["classname"] = classname_; vars["field_count"] = SimpleItoa(descriptor_->field_count()); @@ -669,11 +877,18 @@ GenerateClassDefinition(io::Printer* printer) { } else { vars["dllexport"] = options_.dllexport_decl + " "; } - vars["superclass"] = SuperClassName(descriptor_); - + if (use_dependent_base_) { + vars["superclass"] = + DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; + } else { + vars["superclass"] = SuperClassName(descriptor_); + } printer->Print(vars, - "class $dllexport$$classname$ : public $superclass$ {\n" - " public:\n"); + "class $dllexport$$classname$ : public $superclass$ {\n"); + if (use_dependent_base_) { + printer->Print(vars, " friend class $superclass$;\n"); + } + printer->Print(" public:\n"); printer->Indent(); printer->Print(vars, @@ -782,6 +997,19 @@ GenerateClassDefinition(io::Printer* printer) { printer->Print(vars, "void UnsafeArenaSwap($classname$* other);\n"); } + + if (IsAnyMessage(descriptor_)) { + printer->Print(vars, + "// implements Any -----------------------------------------------\n" + "\n" + "void PackFrom(const ::google::protobuf::Message& message);\n" + "bool UnpackTo(::google::protobuf::Message* message) const;\n" + "template bool Is() const {\n" + " return _any_metadata_.Is();\n" + "}\n" + "\n"); + } + printer->Print(vars, "void Swap($classname$* other);\n" "\n" @@ -973,11 +1201,18 @@ GenerateClassDefinition(io::Printer* printer) { // Generate oneof function declarations for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "inline bool has_$oneof_name$() const;\n" - "void clear_$oneof_name$();\n" - "inline void clear_has_$oneof_name$();\n\n", - "oneof_name", descriptor_->oneof_decl(i)->name()); + if (use_dependent_base_) { + printer->Print( + "inline bool has_$oneof_name$() const;\n" + "inline void clear_has_$oneof_name$();\n\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } else { + printer->Print( + "inline bool has_$oneof_name$() const;\n" + "void clear_$oneof_name$();\n" + "inline void clear_has_$oneof_name$();\n\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } } if (HasGeneratedMethods(descriptor_->file()) && @@ -1139,6 +1374,12 @@ GenerateClassDefinition(io::Printer* printer) { "\n"); } + // Generate _any_metadata_ for the Any type. + if (IsAnyMessage(descriptor_)) { + printer->Print(vars, + "::google::protobuf::internal::AnyMetadata _any_metadata_;\n"); + } + // Declare AddDescriptors(), BuildDescriptors(), and ShutdownFile() as // friends so that they can access private static variables like // default_instance_ and reflection_. @@ -1171,6 +1412,21 @@ GenerateClassDefinition(io::Printer* printer) { GOOGLE_DCHECK(!need_to_emit_cached_size); } +void MessageGenerator:: +GenerateDependentInlineMethods(io::Printer* printer) { + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // map entry message doesn't need inline methods. Since map entry message + // cannot be a top level class, we just need to avoid calling + // GenerateInlineMethods here. + if (IsMapEntryMessage(descriptor_->nested_type(i))) continue; + nested_generators_[i]->GenerateDependentInlineMethods(printer); + printer->Print(kThinSeparator); + printer->Print("\n"); + } + + GenerateDependentFieldAccessorDefinitions(printer); +} + void MessageGenerator:: GenerateInlineMethods(io::Printer* printer, bool is_inline) { for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -1196,7 +1452,8 @@ GenerateInlineMethods(io::Printer* printer, bool is_inline) { vars["inline"] = is_inline ? "inline " : ""; printer->Print( vars, - "$inline$$class_name$::$camel_oneof_name$Case $class_name$::" + "$inline$" + "$class_name$::$camel_oneof_name$Case $class_name$::" "$oneof_name$_case() const {\n" " return $class_name$::$camel_oneof_name$Case(" "_oneof_case_[$oneof_index$]);\n" @@ -1494,6 +1751,19 @@ GenerateShutdownCode(io::Printer* printer) { void MessageGenerator:: GenerateClassMethods(io::Printer* printer) { + if (IsAnyMessage(descriptor_)) { + printer->Print( + "void $classname$::PackFrom(const ::google::protobuf::Message& message) {\n" + " _any_metadata_.PackFrom(message);\n" + "}\n" + "\n" + "bool $classname$::UnpackTo(::google::protobuf::Message* message) const {\n" + " return _any_metadata_.UnpackTo(message);\n" + "}\n" + "\n", + "classname", classname_); + } + for (int i = 0; i < descriptor_->enum_type_count(); i++) { enum_generators_[i]->GenerateMethods(printer); } @@ -1767,7 +2037,7 @@ GenerateArenaDestructorCode(io::Printer* printer) { if (need_registration) { printer->Print( "inline void $classname$::RegisterArenaDtor(::google::protobuf::Arena* arena) {\n" - " if (arena != NULL) {" + " if (arena != NULL) {\n" " arena->OwnCustomDestructor(this, &$classname$::ArenaDtor);\n" " }\n" "}\n", @@ -1782,18 +2052,23 @@ GenerateArenaDestructorCode(io::Printer* printer) { void MessageGenerator:: GenerateStructors(io::Printer* printer) { - string superclass = SuperClassName(descriptor_); - string initializer_with_arena; - if (UseUnknownFieldSet(descriptor_->file())) { - initializer_with_arena = "_internal_metadata_(arena)"; + string superclass; + if (use_dependent_base_) { + superclass = + DependentBaseClassTemplateName(descriptor_) + "<" + classname_ + ">"; } else { - initializer_with_arena = "_arena_ptr_(arena)"; + superclass = SuperClassName(descriptor_); } + string initializer_with_arena = superclass + "()"; + if (descriptor_->extension_range_count() > 0) { - initializer_with_arena = string("\n _extensions_(arena)") + - (!initializer_with_arena.empty() ? ", " : "") + initializer_with_arena; + initializer_with_arena += ",\n _extensions_(arena)"; + } + + if (UseUnknownFieldSet(descriptor_->file())) { + initializer_with_arena += ",\n _internal_metadata_(arena)"; } else { - initializer_with_arena = "\n " + initializer_with_arena; + initializer_with_arena += ",\n _arena_ptr_(arena)"; } // Initialize member variables with arena constructor. @@ -1804,16 +2079,21 @@ GenerateStructors(io::Printer* printer) { FieldName(descriptor_->field(i)) + string("_(arena)"); } } - initializer_with_arena = superclass + "()" + - (!initializer_with_arena.empty() ? "," : " ") + initializer_with_arena; + + if (IsAnyMessage(descriptor_)) { + initializer_with_arena += ",\n _any_metadata_(&type_url, &value_)"; + } string initializer_null; initializer_null = (UseUnknownFieldSet(descriptor_->file()) ? - ", _internal_metadata_(NULL) " : ", _arena_ptr_(NULL)"); + ", _internal_metadata_(NULL)" : ", _arena_ptr_(NULL)"); + if (IsAnyMessage(descriptor_)) { + initializer_null += ", _any_metadata_(&type_url_, &value_)"; + } printer->Print( "$classname$::$classname$()\n" - " : $superclass$() $initializer$ {\n" + " : $superclass$()$initializer$ {\n" " SharedCtor();\n" " // @@protoc_insertion_point(constructor:$full_name$)\n" "}\n", @@ -1894,10 +2174,14 @@ GenerateStructors(io::Printer* printer) { "full_name", descriptor_->full_name()); if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( - ",\n _internal_metadata_(NULL) {\n"); + ",\n _internal_metadata_(NULL)"); } else if (!UseUnknownFieldSet(descriptor_->file())) { - printer->Print(",\n _arena_ptr_(NULL) {\n"); + printer->Print(",\n _arena_ptr_(NULL)"); } + if (IsAnyMessage(descriptor_)) { + printer->Print(",\n _any_metadata_(&type_url_, &value_)"); + } + printer->Print(" {\n"); printer->Print( " SharedCtor();\n" " MergeFrom(from);\n" @@ -2124,7 +2408,11 @@ GenerateClear(io::Printer* printer) { have_enclosing_if = true; } - field_generators_.get(field).GenerateClearingCode(printer); + if (use_dependent_base_ && IsFieldDependent(field)) { + printer->Print("clear_$name$();\n", "name", fieldname); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + } if (have_enclosing_if) { printer->Outdent(); @@ -2147,7 +2435,11 @@ GenerateClear(io::Printer* printer) { const FieldDescriptor* field = descriptor_->field(i); if (field->is_repeated()) { - field_generators_.get(field).GenerateClearingCode(printer); + if (use_dependent_base_ && IsFieldDependent(field)) { + printer->Print("clear_$name$();\n", "name", FieldName(field)); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + } } } @@ -2184,19 +2476,38 @@ void MessageGenerator:: GenerateOneofClear(io::Printer* printer) { // Generated function clears the active field and union case (e.g. foo_case_). for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "void $classname$::clear_$oneofname$() {\n", - "classname", classname_, - "oneofname", descriptor_->oneof_decl(i)->name()); + map oneof_vars; + oneof_vars["classname"] = classname_; + oneof_vars["oneofname"] = descriptor_->oneof_decl(i)->name(); + string message_class; + + if (use_dependent_base_) { + oneof_vars["tmpl"] = "template\n"; + oneof_vars["inline"] = "inline "; + oneof_vars["dependent_classname"] = + DependentBaseClassTemplateName(descriptor_) + ""; + oneof_vars["this_message"] = "reinterpret_cast(this)->"; + message_class = "T::"; + } else { + oneof_vars["tmpl"] = ""; + oneof_vars["inline"] = ""; + oneof_vars["dependent_classname"] = classname_; + oneof_vars["this_message"] = ""; + } + + printer->Print(oneof_vars, + "$tmpl$" + "$inline$" + "void $dependent_classname$::clear_$oneofname$() {\n"); printer->Indent(); - printer->Print( - "switch($oneofname$_case()) {\n", - "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Print(oneof_vars, + "switch($this_message$$oneofname$_case()) {\n"); printer->Indent(); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); printer->Print( - "case k$field_name$: {\n", + "case $message_class$k$field_name$: {\n", + "message_class", message_class, "field_name", UnderscoresToCamelCase(field->name(), true)); printer->Indent(); // We clear only allocated objects in oneofs @@ -2213,16 +2524,20 @@ GenerateOneofClear(io::Printer* printer) { "}\n"); } printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" + "case $message_class$$cap_oneof_name$_NOT_SET: {\n" " break;\n" "}\n", + "message_class", message_class, "cap_oneof_name", ToUpper(descriptor_->oneof_decl(i)->name())); printer->Outdent(); printer->Print( "}\n" - "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n", + "$this_message$_oneof_case_[$oneof_index$] = " + "$message_class$$cap_oneof_name$_NOT_SET;\n", + "this_message", oneof_vars["this_message"], "oneof_index", SimpleItoa(i), + "message_class", message_class, "cap_oneof_name", ToUpper(descriptor_->oneof_decl(i)->name())); printer->Outdent(); @@ -2333,9 +2648,9 @@ GenerateMergeFrom(io::Printer* printer) { // system, as the GOOGLE_CHECK above ensured that we have the same descriptor // for each message. printer->Print( - "const $classname$* source =\n" - " ::google::protobuf::internal::dynamic_cast_if_available(\n" - " &from);\n" + "const $classname$* source = \n" + " ::google::protobuf::internal::DynamicCastToGenerated(\n" + " &from);\n" "if (source == NULL) {\n" " ::google::protobuf::internal::ReflectionOps::Merge(from, this);\n" "} else {\n" @@ -2585,8 +2900,24 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Indent(); + // Find repeated messages and groups now, to simplify what follows. + hash_set fields_with_parse_loop; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = ordered_fields[i]; + if (field->is_repeated() && + (field->type() == FieldDescriptor::TYPE_MESSAGE || + field->type() == FieldDescriptor::TYPE_GROUP)) { + fields_with_parse_loop.insert(i); + } + } + + // need_label is true if we generated "goto parse_$name$" while handling the + // previous field. + bool need_label = false; for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = ordered_fields[i]; + const bool loops = fields_with_parse_loop.count(i) > 0; + const bool next_field_loops = fields_with_parse_loop.count(i + 1) > 0; PrintFieldComment(printer, field); @@ -2600,9 +2931,16 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print("if (tag == $commontag$) {\n", "commontag", SimpleItoa(WireFormat::MakeTag(field))); - if (i > 0 || (field->is_repeated() && !field->options().packed())) { + if (need_label || + (field->is_repeated() && !field->options().packed() && !loops)) { + printer->Print( + " parse_$name$:\n", + "name", field->name()); + } + if (loops) { printer->Print( - " parse_$name$:\n", + " DO_(input->IncrementRecursionDepth());\n" + " parse_loop_$name$:\n", "name", field->name()); } @@ -2644,26 +2982,53 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // switch() is slow since it can't be predicted well. Insert some if()s // here that attempt to predict the next tag. - if (field->is_repeated() && !field->options().packed()) { - // Expect repeats of this field. + // For non-packed repeated fields, expect the same tag again. + if (loops) { + printer->Print( + "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n", + "tag", SimpleItoa(WireFormat::MakeTag(field)), + "name", field->name()); + } else if (field->is_repeated() && !field->options().packed()) { printer->Print( "if (input->ExpectTag($tag$)) goto parse_$name$;\n", "tag", SimpleItoa(WireFormat::MakeTag(field)), "name", field->name()); } - if (i + 1 < descriptor_->field_count()) { - // Expect the next field in order. - const FieldDescriptor* next_field = ordered_fields[i + 1]; - printer->Print( - "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n", - "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)), - "next_name", next_field->name()); - } else { - // Expect EOF. - // TODO(kenton): Expect group end-tag? + // Have we emitted "if (input->ExpectTag($next_tag$)) ..." yet? + bool emitted_goto_next_tag = false; + + // For repeated messages/groups, we need to decrement recursion depth, + // unless the next tag is also for a repeated message/group. + if (loops) { + if (next_field_loops) { + const FieldDescriptor* next_field = ordered_fields[i + 1]; + printer->Print( + "if (input->ExpectTag($next_tag$)) goto parse_loop_$next_name$;\n", + "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)), + "next_name", next_field->name()); + emitted_goto_next_tag = true; + } printer->Print( - "if (input->ExpectAtEnd()) goto success;\n"); + "input->UnsafeDecrementRecursionDepth();\n"); + } + + // If there are more fields, expect the next one. + need_label = false; + if (!emitted_goto_next_tag) { + if (i + 1 == descriptor_->field_count()) { + // Expect EOF. + // TODO(kenton): Expect group end-tag? + printer->Print( + "if (input->ExpectAtEnd()) goto success;\n"); + } else { + const FieldDescriptor* next_field = ordered_fields[i + 1]; + printer->Print( + "if (input->ExpectTag($next_tag$)) goto parse_$next_name$;\n", + "next_tag", SimpleItoa(WireFormat::MakeTag(next_field)), + "next_name", next_field->name()); + need_label = true; + } } printer->Print( @@ -2999,9 +3364,7 @@ static string ConditionalToCheckBitmasks(const vector& masks) { vector parts; for (int i = 0; i < masks.size(); i++) { if (masks[i] == 0) continue; - char buffer[kFastToBufferSize]; - FastHex32ToBuffer(masks[i], buffer); - string m = StrCat("0x", buffer); + string m = StrCat("0x", strings::Hex(masks[i], strings::Hex::ZERO_PAD_8)); // Each xor evaluates to 0 if the expected bits are present. parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); } @@ -3293,11 +3656,10 @@ GenerateIsInitialized(io::Printer* printer) { } if (mask != 0) { - char buffer[kFastToBufferSize]; printer->Print( "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", "i", SimpleItoa(i), - "mask", FastHex32ToBuffer(mask, buffer)); + "mask", StrCat(strings::Hex(mask, strings::Hex::ZERO_PAD_8))); } } } diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index ea96581d..23dad10c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -67,7 +67,8 @@ class MessageGenerator { // Header stuff. // Generate foward declarations for this class and all its nested types. - void GenerateForwardDeclaration(io::Printer* printer); + void GenerateMessageForwardDeclaration(io::Printer* printer); + void GenerateEnumForwardDeclaration(io::Printer* printer); // Generate definitions of all nested enums (must come before class // definitions because those classes use the enums definitions). @@ -84,6 +85,9 @@ class MessageGenerator { // file). void GenerateInlineMethods(io::Printer* printer, bool is_inline); + // Dependent methods are always inline. + void GenerateDependentInlineMethods(io::Printer* printer); + // Source file stuff. // Generate code which declares all the global descriptor pointers which @@ -115,7 +119,10 @@ class MessageGenerator { private: // Generate declarations and definitions of accessors for fields. + void GenerateDependentBaseClassDefinition(io::Printer* printer); + void GenerateDependentFieldAccessorDeclarations(io::Printer* printer); void GenerateFieldAccessorDeclarations(io::Printer* printer); + void GenerateDependentFieldAccessorDefinitions(io::Printer* printer); void GenerateFieldAccessorDefinitions(io::Printer* printer, bool is_inline); // Generate the field offsets array. @@ -158,6 +165,21 @@ class MessageGenerator { bool unbounded); + // Generates has_foo() functions and variables for singular field has-bits. + void GenerateSingularFieldHasBits(const FieldDescriptor* field, + map vars, + io::Printer* printer); + // Generates has_foo() functions and variables for oneof field has-bits. + void GenerateOneofHasBits(io::Printer* printer, bool is_inline); + // Generates has_foo_bar() functions for oneof members. + void GenerateOneofMemberHasBits(const FieldDescriptor* field, + const map& vars, + io::Printer* printer); + // Generates the clear_foo() method for a field. + void GenerateFieldClear(const FieldDescriptor* field, + const map& vars, + io::Printer* printer); + const Descriptor* descriptor_; string classname_; Options options_; @@ -168,6 +190,7 @@ class MessageGenerator { google::protobuf::scoped_array > extension_generators_; int num_required_fields_; bool uses_string_; + bool use_dependent_base_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index 467b6bf6..ba318d10 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -72,7 +72,8 @@ void SetMessageVariables(const FieldDescriptor* descriptor, MessageFieldGenerator:: MessageFieldGenerator(const FieldDescriptor* descriptor, const Options& options) - : descriptor_(descriptor) { + : descriptor_(descriptor), + dependent_field_(options.proto_h && IsFieldDependent(descriptor)) { SetMessageVariables(descriptor, &variables_, options); } @@ -83,6 +84,10 @@ GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "$type$* $name$_;\n"); } +void MessageFieldGenerator:: +GenerateDependentAccessorDeclarations(io::Printer* printer) const { +} + void MessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { if (SupportsArenas(descriptor_)) { @@ -144,6 +149,8 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( " return temp;\n" "}\n"); if (SupportsArenas(descriptor_->message_type())) { + // NOTE: the same logic is mirrored in weak_message_field.cc. Any + // arena-related semantics changes should be made in both places. printer->Print(variables_, "void $classname$::_slow_set_allocated_$name$(\n" " ::google::protobuf::Arena* message_arena, $type$** $name$) {\n" @@ -180,6 +187,10 @@ void MessageFieldGenerator::GenerateNonInlineAccessorDefinitions( } } +void MessageFieldGenerator:: +GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { +} + void MessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { @@ -294,7 +305,7 @@ GenerateClearingCode(io::Printer* printer) const { // If we don't have has-bits, message presence is indicated only by ptr != // NULL. Thus on clear, we need to delete the object. printer->Print(variables_, - "if ($name$_ != NULL) delete $name$_;\n" + "if (GetArenaNoVirtual() == NULL && $name$_ != NULL) delete $name$_;\n" "$name$_ = NULL;\n"); } else { printer->Print(variables_, @@ -365,6 +376,10 @@ MessageOneofFieldGenerator(const FieldDescriptor* descriptor, MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} +void MessageOneofFieldGenerator:: +GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { +} + void MessageOneofFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { @@ -559,6 +574,10 @@ GeneratePrivateMembers(io::Printer* printer) const { "::google::protobuf::RepeatedPtrField< $type$ > $name$_;\n"); } +void RepeatedMessageFieldGenerator:: +GenerateDependentAccessorDeclarations(io::Printer* printer) const { +} + void RepeatedMessageFieldGenerator:: GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, @@ -572,6 +591,10 @@ GenerateAccessorDeclarations(io::Printer* printer) const { " mutable_$name$()$deprecation$;\n"); } +void RepeatedMessageFieldGenerator:: +GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const { +} + void RepeatedMessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const { @@ -627,11 +650,13 @@ void RepeatedMessageFieldGenerator:: GenerateMergeFromCodedStream(io::Printer* printer) const { if (descriptor_->type() == FieldDescriptor::TYPE_MESSAGE) { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(\n" + "DO_(::google::protobuf::internal::WireFormatLite::" + "ReadMessageNoVirtualNoRecursionDepth(\n" " input, add_$name$()));\n"); } else { printer->Print(variables_, - "DO_(::google::protobuf::internal::WireFormatLite::ReadGroupNoVirtual(\n" + "DO_(::google::protobuf::internal::WireFormatLite::" + "ReadGroupNoVirtualNoRecursionDepth(\n" " $number$, input, add_$name$()));\n"); } } diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index c1704fc1..9ddf9643 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -52,7 +52,9 @@ class MessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateDependentAccessorDeclarations(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; @@ -67,6 +69,7 @@ class MessageFieldGenerator : public FieldGenerator { protected: const FieldDescriptor* descriptor_; + const bool dependent_field_; map variables_; private: @@ -80,6 +83,7 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { ~MessageOneofFieldGenerator(); // implements FieldGenerator --------------------------------------- + void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const {} @@ -99,7 +103,9 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateDependentAccessorDeclarations(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; + void GenerateDependentInlineAccessorDefinitions(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer, bool is_inline) const; void GenerateClearingCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/cpp/cpp_options.h b/src/google/protobuf/compiler/cpp/cpp_options.h index 0c99cff1..4463f200 100644 --- a/src/google/protobuf/compiler/cpp/cpp_options.h +++ b/src/google/protobuf/compiler/cpp/cpp_options.h @@ -41,12 +41,13 @@ namespace protobuf { namespace compiler { namespace cpp { -// Generator options: +// Generator options (see generator.cc for a description of each): struct Options { - Options() : safe_boundary_check(false) { + Options() : safe_boundary_check(false), proto_h(false) { } string dllexport_decl; bool safe_boundary_check; + bool proto_h; }; } // namespace cpp diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 329eae32..9f929d37 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -262,7 +262,7 @@ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, : descriptor_(descriptor) { SetPrimitiveVariables(descriptor, &variables_, options); - if (descriptor->options().packed()) { + if (descriptor->is_packed()) { variables_["packed_reader"] = "ReadPackedPrimitive"; variables_["repeated_reader"] = "ReadRepeatedPrimitiveNoInline"; } else { @@ -277,7 +277,7 @@ void RepeatedPrimitiveFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField< $type$ > $name$_;\n"); - if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { + if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -364,7 +364,7 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateSerializeWithCachedSizes(io::Printer* printer) const { - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" @@ -377,7 +377,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { } printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n"); - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, " ::google::protobuf::internal::WireFormatLite::Write$declared_type$NoTag(\n" " this->$name$(i), output);\n"); @@ -391,7 +391,7 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { void RepeatedPrimitiveFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { // Write the tag and the size. printer->Print(variables_, "if (this->$name$_size() > 0) {\n" @@ -405,7 +405,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { } printer->Print(variables_, "for (int i = 0; i < this->$name$_size(); i++) {\n"); - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, " target = ::google::protobuf::internal::WireFormatLite::\n" " Write$declared_type$NoTagToArray(this->$name$(i), target);\n"); @@ -435,7 +435,7 @@ GenerateByteSize(io::Printer* printer) const { "data_size = $fixed_size$ * this->$name$_size();\n"); } - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, "if (data_size > 0) {\n" " total_size += $tag_size$ +\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 1a1bcd3d..1a3896a1 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -226,7 +226,6 @@ GenerateInlineAccessorDefinitions(io::Printer* printer, " } else {\n" " $clear_hasbit$\n" " }\n" - " $set_hasbit$\n" " $name$_.UnsafeArenaSetAllocated($default_variable$,\n" " $name$, GetArenaNoVirtual());\n" " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto index 9f63155b..4e25b2ea 100644 --- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -131,23 +131,23 @@ message TestConflictingSymbolNamesExtension { // NO_PROTO3 } // NO_PROTO3 } // NO_PROTO3 -message TestConflictingEnumNames { - enum NestedConflictingEnum { - and = 1; - class = 2; - int = 3; - typedef = 4; - XOR = 5; - } - - optional NestedConflictingEnum conflicting_enum = 1; -} - -enum ConflictingEnum { - NOT_EQ = 1; - volatile = 2; - return = 3; -} +message TestConflictingEnumNames { // NO_PROTO3 + enum NestedConflictingEnum { // NO_PROTO3 + and = 1; // NO_PROTO3 + class = 2; // NO_PROTO3 + int = 3; // NO_PROTO3 + typedef = 4; // NO_PROTO3 + XOR = 5; // NO_PROTO3 + } // NO_PROTO3 + + optional NestedConflictingEnum conflicting_enum = 1; // NO_PROTO3 +} // NO_PROTO3 + +enum ConflictingEnum { // NO_PROTO3 + NOT_EQ = 1; // NO_PROTO3 + volatile = 2; // NO_PROTO3 + return = 3; // NO_PROTO3 +} // NO_PROTO3 message DummyMessage {} diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 9d14a924..b11fb21a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -941,6 +941,22 @@ TEST(GeneratedMessageTest, ExtensionConstantValues) { EXPECT_EQ(unittest::kRepeatedNestedEnumExtensionFieldNumber, 51); } +TEST(GeneratedMessageTest, ParseFromTruncated) { + const string long_string = string(128, 'q'); + FileDescriptorProto p; + p.add_extension()->set_name(long_string); + const string msg = p.SerializeAsString(); + int successful_count = 0; + for (int i = 0; i <= msg.size(); i++) { + if (p.ParseFromArray(msg.c_str(), i)) { + ++successful_count; + } + } + // We don't really care about how often we succeeded. + // As long as we didn't crash, we're happy. + EXPECT_GE(successful_count, 1); +} + // =================================================================== TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) { diff --git a/src/google/protobuf/compiler/cpp/test_large_enum_value.proto b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto new file mode 100644 index 00000000..cb6ca1b1 --- /dev/null +++ b/src/google/protobuf/compiler/cpp/test_large_enum_value.proto @@ -0,0 +1,43 @@ +// 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. + +// Test that proto2 compiler can generate valid code when the enum value +// is INT_MAX. Note that this is a compile-only test and this proto is not +// referenced in any C++ code. +syntax = "proto2"; + +package protobuf_unittest; + +message TestLargeEnumValue { + enum EnumWithLargeValue { + VALUE_1 = 1; + VALUE_MAX = 0x7fffffff; + } +} diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index 71a2ba4b..39318a19 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -67,7 +67,13 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); (*variables)["default_number"] = SimpleItoa( descriptor->default_value_enum()->number()); - (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + if (descriptor->is_packed()) { + (*variables)["tag"] = SimpleItoa(internal::WireFormatLite::MakeTag( + descriptor->number(), + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); + } else { + (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + } (*variables)["tag_size"] = SimpleItoa( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported @@ -641,7 +647,7 @@ GenerateMembers(io::Printer* printer) const { "}\n"); } - if (descriptor_->options().packed() && + if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->containing_type())) { printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); @@ -884,7 +890,7 @@ GenerateParsingDoneCode(io::Printer* printer) const { void RepeatedImmutableEnumFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, "if (get$capitalized_name$List().size() > 0) {\n" " output.writeRawVarint32($tag$);\n" @@ -915,7 +921,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}\n"); printer->Print( "size += dataSize;\n"); - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, "if (!get$capitalized_name$List().isEmpty()) {" " size += $tag_size$;\n" @@ -928,7 +934,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } // cache the data size for packed fields. - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); } diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.cc b/src/google/protobuf/compiler/java/java_enum_field_lite.cc new file mode 100644 index 00000000..697a07a7 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.cc @@ -0,0 +1,967 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { + +void SetEnumVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, + map* variables) { + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["type"] = + name_resolver->GetImmutableClassName(descriptor->enum_type()); + (*variables)["mutable_type"] = + name_resolver->GetMutableClassName(descriptor->enum_type()); + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default_number"] = SimpleItoa( + descriptor->default_value_enum()->number()); + (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["clear_has_field_bit_message"] = + GenerateClearBit(messageBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["clear_has_field_bit_message"] = ""; + + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != " + + (*variables)["default"] + ".getNumber()"; + } + + // For repeated builders, the underlying list tracks mutability state. + (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); + + if (SupportUnknownEnumValue(descriptor->file())) { + (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED"; + } else { + (*variables)["unknown"] = (*variables)["default"]; + } +} + +} // namespace + +// =================================================================== + +ImmutableEnumFieldLiteGenerator:: +ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {} + +int ImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const { + return 1; +} + +int ImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Value();\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private int $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Value() {\n" + " return $name$_;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " $type$ result = $type$.valueOf($name$_);\n" + " return result == null ? $unknown$ : result;\n" + "}\n"); + + // Generate private setters for the builder to proxy into. + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$Value(int value) {\n" + " $set_has_field_bit_message$" + " $name$_ = value;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $set_has_field_bit_message$\n" + " $name$_ = value.getNumber();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $clear_has_field_bit_message$\n" + " $name$_ = $default_number$;\n" + "}\n"); +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + } + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Value() {\n" + " return instance.get$capitalized_name$Value();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Value(int value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Value(int value);\n" + " return this;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for enums +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default_number$;\n"); +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } else if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print(variables_, + "if (other.$name$_ != $default_number$) {\n" + " set$capitalized_name$Value(other.get$capitalized_name$Value());\n" + "}\n"); + } else { + GOOGLE_LOG(FATAL) << "Can't reach here."; + } +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + // noop for scalars +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$set_has_field_bit_message$\n" + "$name$_ = rawValue;\n"); + } else { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (PreserveUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + " unknownFields.mergeVarintField($number$, rawValue);\n"); + } + printer->Print(variables_, + "} else {\n" + " $set_has_field_bit_message$\n" + " $name$_ = rawValue;\n" + "}\n"); + } +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for enums +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " output.writeEnum($number$, $name$_);\n" + "}\n"); +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSize($number$, $name$_);\n" + "}\n"); +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && $name$_ == other.$name$_;\n"); +} + +void ImmutableEnumFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + $name$_;\n"); +} + +string ImmutableEnumFieldLiteGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); +} + +// =================================================================== + +ImmutableEnumOneofFieldLiteGenerator:: +ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableEnumFieldLiteGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutableEnumOneofFieldLiteGenerator:: +~ImmutableEnumOneofFieldLiteGenerator() {} + +void ImmutableEnumOneofFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Value() {\n" + " if ($has_oneof_case_message$) {\n" + " return (java.lang.Integer) $oneof_name$_;\n" + " }\n" + " return $default_number$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $type$ result = $type$.valueOf((java.lang.Integer) $oneof_name$_);\n" + " return result == null ? $unknown$ : result;\n" + " }\n" + " return $default$;\n" + "}\n"); + + // Generate private setters for the builder to proxy into. + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$Value(int value) {\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value.getNumber();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); +} + +void ImmutableEnumOneofFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + } + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Value() {\n" + " return instance.get$capitalized_name$Value();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Value(int value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Value(value);\n" + " return this;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + +void ImmutableEnumOneofFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print(variables_, + "set$capitalized_name$Value(other.get$capitalized_name$Value());\n"); + } else { + printer->Print(variables_, + "set$capitalized_name$(other.get$capitalized_name$());\n"); + } +} + +void ImmutableEnumOneofFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = rawValue;\n"); + } else { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (PreserveUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + " unknownFields.mergeVarintField($number$, rawValue);\n"); + } + printer->Print(variables_, + "} else {\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = rawValue;\n" + "}\n"); + } +} + +void ImmutableEnumOneofFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeEnum($number$, ((java.lang.Integer) $oneof_name$_));\n" + "}\n"); +} + +void ImmutableEnumOneofFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSize($number$, ((java.lang.Integer) $oneof_name$_));\n" + "}\n"); +} + +void ImmutableEnumOneofFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print(variables_, + "result = result && get$capitalized_name$Value()\n" + " == other.get$capitalized_name$Value();\n"); + } else { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); + } +} + +void ImmutableEnumOneofFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + get$capitalized_name$Value();\n"); + } else { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + get$capitalized_name$().getNumber();\n"); + } +} + +// =================================================================== + +RepeatedImmutableEnumFieldLiteGenerator:: +RepeatedImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +RepeatedImmutableEnumFieldLiteGenerator:: +~RepeatedImmutableEnumFieldLiteGenerator() {} + +int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedImmutableEnumFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List\n" + "get$capitalized_name$ValueList();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Value(int index);\n"); + } +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + // TODO(dweis): Switch to IntList? + "private com.google.protobuf.Internal.ProtobufList<\n" + " java.lang.Integer> $name$_;\n" + "private static final com.google.protobuf.Internal.ListAdapter.Converter<\n" + " java.lang.Integer, $type$> $name$_converter_ =\n" + " new com.google.protobuf.Internal.ListAdapter.Converter<\n" + " java.lang.Integer, $type$>() {\n" + " public $type$ convert(java.lang.Integer from) {\n" + " $type$ result = $type$.valueOf(from);\n" + " return result == null ? $unknown$ : result;\n" + " }\n" + " };\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return new com.google.protobuf.Internal.ListAdapter<\n" + " java.lang.Integer, $type$>($name$_, $name$_converter_);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_converter_.convert($name$_.get(index));\n" + "}\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List\n" + "get$capitalized_name$ValueList() {\n" + " return $name$_;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Value(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + } + + if (descriptor_->options().packed() && + HasGeneratedMethods(descriptor_->containing_type())) { + printer->Print(variables_, + "private int $name$MemoizedSerializedSize;\n"); + } + + // Generate private setters for the builder to proxy into. + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$is_mutable$) {\n" + " $name$_ = newProtobufList($name$_);\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value.getNumber());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value.getNumber());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " for ($type$ value : values) {\n" + " $name$_.add(value.getNumber());\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_ = emptyProtobufList();\n" + "}\n"); + + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$Value(\n" + " int index, int value) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$Value(int value) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void addAll$capitalized_name$Value(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " for (int value : values) {\n" + " $name$_.add(value);\n" + " }\n" + "}\n"); + } +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return instance.get$capitalized_name$List();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return instance.get$capitalized_name$Count();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); + + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List\n" + "get$capitalized_name$ValueList() {\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$ValueList());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Value(int index) {\n" + " return instance.get$capitalized_name$Value(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Value(\n" + " int index, int value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Value(index, value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$Value(int value) {\n" + " instance.add$capitalized_name$Value(value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$Value(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$Value(values);\n" + " return this;\n" + "}\n"); + } +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for enums +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = emptyProtobufList();\n"); +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_.makeImmutable();\n"); +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + // Read and store the enum + if (SupportUnknownEnumValue(descriptor_->file())) { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "if (!$is_mutable$) {\n" + " $name$_ = newProtobufList();\n" + "}\n" + "$name$_.add(rawValue);\n"); + } else { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (PreserveUnknownFields(descriptor_->containing_type())) { + printer->Print(variables_, + " unknownFields.mergeVarintField($number$, rawValue);\n"); + } + printer->Print(variables_, + "} else {\n" + " if (!$is_mutable$) {\n" + " $name$_ = newProtobufList();\n" + " }\n" + " $name$_.add(rawValue);\n" + "}\n"); + } +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + // Wrap GenerateParsingCode's contents with a while loop. + + printer->Print(variables_, + "int length = input.readRawVarint32();\n" + "int oldLimit = input.pushLimit(length);\n" + "while(input.getBytesUntilLimit() > 0) {\n"); + printer->Indent(); + + GenerateParsingCode(printer); + + printer->Outdent(); + printer->Print(variables_, + "}\n" + "input.popLimit(oldLimit);\n"); +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_mutable$) {\n" + " $name$_.makeImmutable();\n" + "}\n"); +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeRawVarint32($tag$);\n" + " output.writeRawVarint32($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnumNoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeEnum($number$, $name$_.get(i));\n" + "}\n"); + } +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int dataSize = 0;\n"); + printer->Indent(); + + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSizeNoTag($name$_.get(i));\n" + "}\n"); + printer->Print( + "size += dataSize;\n"); + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (!get$capitalized_name$List().isEmpty()) {" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeRawVarint32Size(dataSize);\n" + "}"); + } else { + printer->Print(variables_, + "size += $tag_size$ * $name$_.size();\n"); + } + + // cache the data size for packed fields. + if (descriptor_->options().packed()) { + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && $name$_.equals(other.$name$_);\n"); +} + +void RepeatedImmutableEnumFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + $name$_.hashCode();\n" + "}\n"); +} + +string RepeatedImmutableEnumFieldLiteGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_enum_field_lite.h b/src/google/protobuf/compiler/java/java_enum_field_lite.h new file mode 100644 index 00000000..2c41c3e4 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_enum_field_lite.h @@ -0,0 +1,159 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableEnumFieldLiteGenerator : public ImmutableFieldLiteGenerator { + public: + explicit ImmutableEnumFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableEnumFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + protected: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldLiteGenerator); +}; + +class ImmutableEnumOneofFieldLiteGenerator + : public ImmutableEnumFieldLiteGenerator { + public: + ImmutableEnumOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableEnumOneofFieldLiteGenerator(); + + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator); +}; + +class RepeatedImmutableEnumFieldLiteGenerator + : public ImmutableFieldLiteGenerator { + public: + explicit RepeatedImmutableEnumFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableEnumFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldLiteGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc index af9978e2..3f0fa11f 100644 --- a/src/google/protobuf/compiler/java/java_field.cc +++ b/src/google/protobuf/compiler/java/java_field.cc @@ -42,12 +42,18 @@ #include #include #include +#include #include #include +#include #include +#include #include +#include #include +#include #include +#include #include #include #include @@ -133,6 +139,79 @@ ImmutableFieldGenerator* MakeImmutableGenerator( } } +ImmutableFieldLiteGenerator* MakeImmutableLiteGenerator( + const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, + Context* context) { + if (field->is_repeated()) { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + if (IsMapEntry(field->message_type())) { + return new ImmutableMapFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + if (IsLazy(field)) { + return new RepeatedImmutableLazyMessageFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new RepeatedImmutableMessageFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } + } + case JAVATYPE_ENUM: + return new RepeatedImmutableEnumFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new RepeatedImmutableStringFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + default: + return new RepeatedImmutablePrimitiveFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } + } else { + if (field->containing_oneof()) { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + if (IsLazy(field)) { + return new ImmutableLazyMessageOneofFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new ImmutableMessageOneofFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } + case JAVATYPE_ENUM: + return new ImmutableEnumOneofFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new ImmutableStringOneofFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + default: + return new ImmutablePrimitiveOneofFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } + } else { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + if (IsLazy(field)) { + return new ImmutableLazyMessageFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new ImmutableMessageFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } + case JAVATYPE_ENUM: + return new ImmutableEnumFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new ImmutableStringFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + default: + return new ImmutablePrimitiveFieldLiteGenerator( + field, messageBitIndex, builderBitIndex, context); + } + } + } +} + static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { // Reaching here indicates a bug. Cases are: @@ -153,6 +232,13 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { ReportUnexpectedPackedFieldsCall(printer); } +ImmutableFieldLiteGenerator::~ImmutableFieldLiteGenerator() {} + +void ImmutableFieldLiteGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + ReportUnexpectedPackedFieldsCall(printer); +} + // =================================================================== template <> @@ -178,6 +264,28 @@ FieldGeneratorMap::FieldGeneratorMap( template<> FieldGeneratorMap::~FieldGeneratorMap() {} +template <> +FieldGeneratorMap::FieldGeneratorMap( + const Descriptor* descriptor, Context* context) + : descriptor_(descriptor), + field_generators_(new google::protobuf::scoped_ptr< + ImmutableFieldLiteGenerator>[descriptor->field_count()]) { + // Construct all the FieldGenerators and assign them bit indices for their + // bit fields. + int messageBitIndex = 0; + int builderBitIndex = 0; + for (int i = 0; i < descriptor->field_count(); i++) { + ImmutableFieldLiteGenerator* generator = MakeImmutableLiteGenerator( + descriptor->field(i), messageBitIndex, builderBitIndex, context); + field_generators_[i].reset(generator); + messageBitIndex += generator->GetNumBitsForMessage(); + builderBitIndex += generator->GetNumBitsForBuilder(); + } +} + +template<> +FieldGeneratorMap::~FieldGeneratorMap() {} + void SetCommonFieldVariables(const FieldDescriptor* descriptor, const FieldGeneratorInfo* info, diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index 1cf360c1..00f3c601 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -83,7 +83,6 @@ class ImmutableFieldGenerator { virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) const = 0; - virtual void GenerateStaticInitializationCode(io::Printer* printer) const {} virtual void GenerateEqualsCode(io::Printer* printer) const = 0; virtual void GenerateHashCode(io::Printer* printer) const = 0; @@ -94,6 +93,37 @@ class ImmutableFieldGenerator { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator); }; +class ImmutableFieldLiteGenerator { + public: + ImmutableFieldLiteGenerator() {} + virtual ~ImmutableFieldLiteGenerator(); + + virtual int GetNumBitsForMessage() const = 0; + virtual int GetNumBitsForBuilder() const = 0; + virtual void GenerateInterfaceMembers(io::Printer* printer) const = 0; + virtual void GenerateMembers(io::Printer* printer) const = 0; + virtual void GenerateBuilderMembers(io::Printer* printer) const = 0; + virtual void GenerateInitializationCode(io::Printer* printer) const = 0; + virtual void GenerateMergingCode(io::Printer* printer) const = 0; + virtual void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) + const = 0; + virtual void GenerateParsingCode(io::Printer* printer) const = 0; + virtual void GenerateParsingCodeFromPacked(io::Printer* printer) const; + virtual void GenerateParsingDoneCode(io::Printer* printer) const = 0; + virtual void GenerateSerializationCode(io::Printer* printer) const = 0; + virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0; + virtual void GenerateFieldBuilderInitializationCode(io::Printer* printer) + const = 0; + + virtual void GenerateEqualsCode(io::Printer* printer) const = 0; + virtual void GenerateHashCode(io::Printer* printer) const = 0; + + virtual string GetBoxedType() const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator); +}; + // Convenience class which constructs FieldGenerators for a Descriptor. template diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index 4a1f4529..68b47ee1 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -35,10 +35,10 @@ #include #include -#include #ifndef _SHARED_PTR_H #include #endif +#include #include #include @@ -153,6 +153,12 @@ void CollectExtensions(const FileDescriptorProto& file_proto, } } +// Compare two field descriptors, returning true if the first should come +// before the second. +bool CompareFieldsByName(const FieldDescriptor *a, const FieldDescriptor *b) { + return a->full_name() < b->full_name(); +} + // Our static initialization methods can become very, very large. // So large that if we aren't careful we end up blowing the JVM's // 64K bytes of bytecode/method. Fortunately, since these static @@ -166,7 +172,6 @@ void MaybeRestartJavaMethod(io::Printer* printer, int *method_num, const char *chain_statement, const char *method_decl) { - // The goal here is to stay under 64K bytes of jvm bytecode/method, // since otherwise we hit a hardcoded limit in the jvm and javac will // then fail with the error "code too large". This limit lets our @@ -184,6 +189,7 @@ void MaybeRestartJavaMethod(io::Printer* printer, } } + } // namespace FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api) diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc index 2d1437f0..92ef851b 100644 --- a/src/google/protobuf/compiler/java/java_generator_factory.cc +++ b/src/google/protobuf/compiler/java/java_generator_factory.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include namespace google { @@ -57,7 +58,12 @@ ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {} MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator( const Descriptor* descriptor) const { - return new ImmutableMessageGenerator(descriptor, context_); + if (descriptor->file()->options().optimize_for() == + FileOptions::LITE_RUNTIME) { + return new ImmutableMessageLiteGenerator(descriptor, context_); + } else { + return new ImmutableMessageGenerator(descriptor, context_); + } } ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator( diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index 62efbefa..96d2545f 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -196,12 +196,6 @@ inline bool HasDescriptorMethods(const FileDescriptor* descriptor) { FileOptions::LITE_RUNTIME; } -inline bool HasNestedBuilders(const Descriptor* descriptor) { - // The proto-lite version doesn't support nested builders. - return descriptor->file()->options().optimize_for() != - FileOptions::LITE_RUNTIME; -} - // Should we generate generic services for this file? inline bool HasGenericServices(const FileDescriptor *file) { return file->service_count() > 0 && @@ -330,6 +324,10 @@ inline bool IsMapEntry(const Descriptor* descriptor) { return descriptor->options().map_entry(); } +inline bool IsMapField(const FieldDescriptor* descriptor) { + return descriptor->is_map(); +} + inline bool PreserveUnknownFields(const Descriptor* descriptor) { return descriptor->file()->syntax() != FileDescriptor::SYNTAX_PROTO3; } diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc index 6e29a40b..0de8cbe5 100644 --- a/src/google/protobuf/compiler/java/java_lazy_message_field.cc +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc @@ -72,14 +72,12 @@ GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "$deprecation$public $type$ get$capitalized_name$() {\n" " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" - "}\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " return $name$_;\n" - "}\n"); - } + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " return $name$_;\n" + "}\n"); } void ImmutableLazyMessageFieldGenerator:: @@ -92,14 +90,12 @@ GenerateBuilderMembers(io::Printer* printer) const { "private com.google.protobuf.LazyFieldLite $name$_ =\n" " new com.google.protobuf.LazyFieldLite();\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); - } + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); // The comments above the methods below are based on a hypothetical // field of type "Field" called "Field". @@ -179,39 +175,37 @@ GenerateBuilderMembers(io::Printer* printer) const { "$clear_has_field_bit_builder$;\n" "return this;\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " $set_has_field_bit_builder$;\n" - " $on_changed$\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " return $name$_;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " $set_has_field_bit_builder$;\n" + " $on_changed$\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " return $name$_;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); } @@ -538,14 +532,12 @@ GenerateBuilderMembers(io::Printer* printer) const { "}\n" "\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" - "\n"); - } + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" + "\n"); // The comments above the methods below are based on a hypothetical // repeated field of type "Field" called "RepeatedField". @@ -723,70 +715,68 @@ GenerateBuilderMembers(io::Printer* printer) const { "return this;\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" - "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " if ($name$Builder_ == null) {\n" - " return $name$_.get(index);" - " } else {\n" - " return $name$Builder_.getMessageOrBuilder(index);\n" - " }\n" - "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " if ($name$Builder_ == null) {\n" + " return $name$_.get(index);" + " } else {\n" + " return $name$Builder_.getMessageOrBuilder(index);\n" + " }\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List \n" - " get$capitalized_name$OrBuilderList() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilderList();\n" - " } else {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - " }\n" - "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilderList();\n" + " } else {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + " }\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " index, $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$.Builder> \n" - " get$capitalized_name$BuilderList() {\n" - " return get$capitalized_name$FieldBuilder().getBuilderList();\n" - "}\n" - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " $get_mutable_bit_builder$,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " index, $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$.Builder> \n" + " get$capitalized_name$BuilderList() {\n" + " return get$capitalized_name$FieldBuilder().getBuilderList();\n" + "}\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " $get_mutable_bit_builder$,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); } void RepeatedImmutableLazyMessageFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc new file mode 100644 index 00000000..283ba1d3 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.cc @@ -0,0 +1,708 @@ +// 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. + +// Author: niwasaki@google.com (Naoki Iwasaki) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +ImmutableLazyMessageFieldLiteGenerator:: +ImmutableLazyMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableMessageFieldLiteGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { +} + +ImmutableLazyMessageFieldLiteGenerator:: +~ImmutableLazyMessageFieldLiteGenerator() {} + +void ImmutableLazyMessageFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.LazyFieldLite $name$_ =\n" + " new com.google.protobuf.LazyFieldLite();\n"); + + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $name$_.setValue(value);\n" + " $set_has_field_bit_message$;\n" + "}\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " $name$_.setValue(builderForValue.build());\n" + " $set_has_field_bit_message$;\n" + "}\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void merge$capitalized_name$($type$ value) {\n" + " if ($get_has_field_bit_message$ &&\n" + " !$name$_.containsDefaultInstance()) {\n" + " $name$_.setValue(\n" + " $type$.newBuilder(\n" + " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" + " } else {\n" + " $name$_.setValue(value);\n" + " }\n" + " $set_has_field_bit_message$;\n" + "}\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_.clear();\n" + " $clear_has_field_bit_message$;\n" + "}\n"); +} + +void ImmutableLazyMessageFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(builderForValue);\n" + " return this;\n" + "}\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.merge$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + + +void ImmutableLazyMessageFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.clear();\n"); +} + +void ImmutableLazyMessageFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " $name$_.merge(other.$name$_);\n" + " $set_has_field_bit_message$;\n" + "}\n"); +} + +void ImmutableLazyMessageFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_.setByteString(input.readBytes(), extensionRegistry);\n"); + printer->Print(variables_, + "$set_has_field_bit_message$;\n"); +} + +void ImmutableLazyMessageFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + // Do not de-serialize lazy fields. + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " output.writeBytes($number$, $name$_.toByteString());\n" + "}\n"); +} + +void ImmutableLazyMessageFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, $name$_);\n" + "}\n"); +} + +// =================================================================== + +ImmutableLazyMessageOneofFieldLiteGenerator:: +ImmutableLazyMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableLazyMessageFieldLiteGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); + variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite"; +} + +ImmutableLazyMessageOneofFieldLiteGenerator:: +~ImmutableLazyMessageOneofFieldLiteGenerator() {} + +void ImmutableLazyMessageOneofFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" + " $type$.getDefaultInstance());\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + " }\n" + " (($lazy_type$) $oneof_name$_).setValue(value);\n" + "}\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + " }\n" + " (($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n" + "}\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void merge$capitalized_name$($type$ value) {\n" + " if ($has_oneof_case_message$ &&\n" + " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n" + " (($lazy_type$) $oneof_name$_).setValue(\n" + " $type$.newBuilder(\n" + " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" + " } else {\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + " }\n" + " (($lazy_type$) $oneof_name$_).setValue(value);\n" + " }\n" + "}\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); +} + +void ImmutableLazyMessageOneofFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(builderForValue);\n" + " return this;\n" + "}\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.merge$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + +void ImmutableLazyMessageOneofFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + "}\n" + "(($lazy_type$) $oneof_name$_).merge(\n" + " ($lazy_type$) other.$oneof_name$_);\n" + "$set_oneof_case_message$;\n"); +} + +void ImmutableLazyMessageOneofFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + "}\n" + "(($lazy_type$) $oneof_name$_).setByteString(\n" + " input.readBytes(), extensionRegistry);\n" + "$set_oneof_case_message$;\n"); +} + +void ImmutableLazyMessageOneofFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + // Do not de-serialize lazy fields. + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeBytes(\n" + " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n" + "}\n"); +} + +void ImmutableLazyMessageOneofFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutableLazyMessageFieldLiteGenerator:: +RepeatedImmutableLazyMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : RepeatedImmutableMessageFieldLiteGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { +} + + +RepeatedImmutableLazyMessageFieldLiteGenerator:: +~RepeatedImmutableLazyMessageFieldLiteGenerator() {} + +void RepeatedImmutableLazyMessageFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.Internal.ProtobufList<\n" + " com.google.protobuf.LazyFieldLite> $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$>\n" + " get$capitalized_name$List() {\n" + " java.util.List<$type$> list =\n" + " new java.util.ArrayList<$type$>($name$_.size());\n" + " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" + " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" + " }\n" + // TODO(dweis): Make this list immutable? + " return list;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List\n" + " get$capitalized_name$OrBuilderList() {\n" + " return get$capitalized_name$List();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return ($type$)\n" + " $name$_.get(index).getValue($type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " return ($type$OrBuilder)\n" + " $name$_.get(index).getValue($type$.getDefaultInstance());\n" + "}\n"); + + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$is_mutable$) {\n" + " $name$_ = newProtobufList($name$_);\n" + " }\n" + "}\n" + "\n"); + + // Builder setRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(\n" + " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" + "}\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "}\n"); + + // Builder addRepeatedField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n" + "}\n"); + + // Builder addRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$(\n" + " int index, $type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(\n" + " index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" + "}\n"); + + // Builder addRepeatedField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "}\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "}\n"); + + // Builder addAllRepeatedField(Iterable values) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " for (com.google.protobuf.MessageLite v : values) {\n" + " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n" + " }\n" + "}\n"); + + // Builder clearAllRepeatedField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_ = emptyProtobufList();\n" + "}\n"); + + // Builder removeRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void remove$capitalized_name$(int index) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.remove(index);\n" + "}\n"); +} + +void RepeatedImmutableLazyMessageFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // List getRepeatedFieldList() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$List());\n" + "}\n"); + + // int getRepeatedFieldCount() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return instance.get$capitalized_name$Count();\n" + "}\n"); + + // Field getRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); + + // Builder setRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, builderForValue);\n" + " return this;\n" + "}\n"); + + // Builder addRepeatedField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Builder addRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); + + // Builder addRepeatedField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(builderForValue);\n" + " return this;\n" + "}\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(index, builderForValue);\n" + " return this;\n" + "}\n"); + + // Builder addAllRepeatedField(Iterable values) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);\n" + " return this;\n" + "}\n"); + + // Builder clearAllRepeatedField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); + + // Builder removeRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder remove$capitalized_name$(int index) {\n" + " copyOnWrite();\n" + " instance.remove$capitalized_name$(index);\n" + " return this;\n" + "}\n"); +} + +void RepeatedImmutableLazyMessageFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!$is_mutable$) {\n" + " $name$_ = newProtobufList();\n" + "}\n" + "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" + " extensionRegistry, input.readBytes()));\n"); +} + +void RepeatedImmutableLazyMessageFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeBytes($number$, $name$_.get(i).toByteString());\n" + "}\n"); +} + +void RepeatedImmutableLazyMessageFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, $name$_.get(i));\n" + "}\n"); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h new file mode 100644 index 00000000..e85ec0f3 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_lazy_message_field_lite.h @@ -0,0 +1,118 @@ +// 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. + +// Author: niwasaki@google.com (Naoki Iwasaki) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ + +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableLazyMessageFieldLiteGenerator + : public ImmutableMessageFieldLiteGenerator { + public: + explicit ImmutableLazyMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableLazyMessageFieldLiteGenerator(); + + // overroads ImmutableMessageFieldLiteGenerator ------------------------------ + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldLiteGenerator); +}; + +class ImmutableLazyMessageOneofFieldLiteGenerator + : public ImmutableLazyMessageFieldLiteGenerator { + public: + ImmutableLazyMessageOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableLazyMessageOneofFieldLiteGenerator(); + + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldLiteGenerator); +}; + +class RepeatedImmutableLazyMessageFieldLiteGenerator + : public RepeatedImmutableMessageFieldLiteGenerator { + public: + explicit RepeatedImmutableLazyMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableLazyMessageFieldLiteGenerator(); + + // overroads RepeatedImmutableMessageFieldLiteGenerator ---------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldLiteGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_map_field.cc b/src/google/protobuf/compiler/java/java_map_field.cc index cf1ef589..f25970e5 100644 --- a/src/google/protobuf/compiler/java/java_map_field.cc +++ b/src/google/protobuf/compiler/java/java_map_field.cc @@ -133,9 +133,11 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["set_mutable_bit_parser"] = GenerateSetBitMutableLocal(builderBitIndex); + (*variables)["default_entry"] = (*variables)["capitalized_name"] + + "DefaultEntryHolder.defaultEntry"; if (HasDescriptorMethods(descriptor->file())) { (*variables)["lite"] = ""; - (*variables)["map_field_parameter"] = (*variables)["name"] + "DefaultEntry"; + (*variables)["map_field_parameter"] = (*variables)["default_entry"]; (*variables)["descriptor"] = name_resolver->GetImmutableClassName(descriptor->file()) + ".internal_" + UniqueFileScopeIdentifier(descriptor->message_type()) + @@ -197,27 +199,21 @@ GenerateInterfaceMembers(io::Printer* printer) const { } } -void ImmutableMapFieldGenerator:: -GenerateStaticInitializationCode(io::Printer* printer) const { - printer->Print( - variables_, - "$name$DefaultEntry =\n" - " com.google.protobuf.MapEntry$lite$\n" - " .<$type_parameters$>newDefaultInstance(\n" - " $descriptor$\n" - " $key_wire_type$,\n" - " $key_default_value$,\n" - " $value_wire_type$,\n" - " $value_default_value$);\n" - "\n"); -} - void ImmutableMapFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print( variables_, - "private static final com.google.protobuf.MapEntry$lite$<\n" - " $type_parameters$> $name$DefaultEntry;\n"); + "private static final class $capitalized_name$DefaultEntryHolder {\n" + " static final com.google.protobuf.MapEntry$lite$<\n" + " $type_parameters$> defaultEntry =\n" + " com.google.protobuf.MapEntry$lite$\n" + " .<$type_parameters$>newDefaultInstance(\n" + " $descriptor$\n" + " $key_wire_type$,\n" + " $key_default_value$,\n" + " $value_wire_type$,\n" + " $value_default_value$);\n" + "}\n"); printer->Print( variables_, "private com.google.protobuf.MapField$lite$<\n" @@ -291,7 +287,10 @@ GenerateBuilderMembers(io::Printer* printer) const { " if ($name$_ == null) {\n" " $name$_ = com.google.protobuf.MapField$lite$.newMapField(\n" " $map_field_parameter$);\n" - " }\n" + " }\n" + " if (!$name$_.isMutable()) {\n" + " $name$_ = $name$_.copy();\n" + " }\n" " return $name$_;\n" "}\n"); if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { @@ -381,10 +380,8 @@ void ImmutableMapFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { printer->Print( variables_, - // We do a copy of the map field to ensure that the built result is - // immutable. Implementation of this copy() method can do copy-on-write - // to defer this copy until further modifications are made on the field. - "result.$name$_ = internalGet$capitalized_name$().copy();\n"); + "result.$name$_ = internalGet$capitalized_name$();\n" + "result.$name$_.makeImmutable();\n"); } void ImmutableMapFieldGenerator:: @@ -402,7 +399,7 @@ GenerateParsingCode(io::Printer* printer) const { variables_, "com.google.protobuf.ByteString bytes = input.readBytes();\n" "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" - "$name$ = $name$DefaultEntry.getParserForType().parseFrom(bytes);\n"); + "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n"); printer->Print( variables_, "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n" @@ -415,7 +412,7 @@ GenerateParsingCode(io::Printer* printer) const { variables_, "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" "$name$ = input.readMessage(\n" - " $name$DefaultEntry.getParserForType(), extensionRegistry);\n" + " $default_entry$.getParserForType(), extensionRegistry);\n" "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"); } } @@ -432,7 +429,7 @@ GenerateSerializationCode(io::Printer* printer) const { "for (java.util.Map.Entry<$type_parameters$> entry\n" " : internalGet$capitalized_name$().getMap().entrySet()) {\n" " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" - " $name$ = $name$DefaultEntry.newBuilderForType()\n" + " $name$ = $default_entry$.newBuilderForType()\n" " .setKey(entry.getKey())\n" " .setValue(entry.getValue())\n" " .build();\n" @@ -447,7 +444,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "for (java.util.Map.Entry<$type_parameters$> entry\n" " : internalGet$capitalized_name$().getMap().entrySet()) {\n" " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" - " $name$ = $name$DefaultEntry.newBuilderForType()\n" + " $name$ = $default_entry$.newBuilderForType()\n" " .setKey(entry.getKey())\n" " .setValue(entry.getValue())\n" " .build();\n" diff --git a/src/google/protobuf/compiler/java/java_map_field.h b/src/google/protobuf/compiler/java/java_map_field.h index 3e6dd973..80a94f45 100644 --- a/src/google/protobuf/compiler/java/java_map_field.h +++ b/src/google/protobuf/compiler/java/java_map_field.h @@ -60,7 +60,6 @@ class ImmutableMapFieldGenerator : public ImmutableFieldGenerator { void GenerateSerializationCode(io::Printer* printer) const; void GenerateSerializedSizeCode(io::Printer* printer) const; void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; - void GenerateStaticInitializationCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.cc b/src/google/protobuf/compiler/java/java_map_field_lite.cc new file mode 100644 index 00000000..ccc1b32e --- /dev/null +++ b/src/google/protobuf/compiler/java/java_map_field_lite.cc @@ -0,0 +1,461 @@ +// 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 + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { + +const FieldDescriptor* KeyField(const FieldDescriptor* descriptor) { + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + const Descriptor* message = descriptor->message_type(); + GOOGLE_CHECK(message->options().map_entry()); + return message->FindFieldByName("key"); +} + +const FieldDescriptor* ValueField(const FieldDescriptor* descriptor) { + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, descriptor->type()); + const Descriptor* message = descriptor->message_type(); + GOOGLE_CHECK(message->options().map_entry()); + return message->FindFieldByName("value"); +} + +string TypeName(const FieldDescriptor* field, + ClassNameResolver* name_resolver, + bool boxed) { + if (GetJavaType(field) == JAVATYPE_MESSAGE) { + return name_resolver->GetImmutableClassName(field->message_type()); + } else if (GetJavaType(field) == JAVATYPE_ENUM) { + return name_resolver->GetImmutableClassName(field->enum_type()); + } else { + return boxed ? BoxedPrimitiveTypeName(GetJavaType(field)) + : PrimitiveTypeName(GetJavaType(field)); + } +} + +string WireType(const FieldDescriptor* field) { + return "com.google.protobuf.WireFormat.FieldType." + + string(FieldTypeName(field->type())); +} + +void SetMessageVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, + map* variables) { + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["type"] = + name_resolver->GetImmutableClassName(descriptor->message_type()); + const FieldDescriptor* key = KeyField(descriptor); + const FieldDescriptor* value = ValueField(descriptor); + (*variables)["key_type"] = TypeName(key, name_resolver, false); + (*variables)["boxed_key_type"] = TypeName(key, name_resolver, true); + (*variables)["key_wire_type"] = WireType(key); + (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver); + if (GetJavaType(value) == JAVATYPE_ENUM) { + // We store enums as Integers internally. + (*variables)["value_type"] = "int"; + (*variables)["boxed_value_type"] = "java.lang.Integer"; + (*variables)["value_wire_type"] = WireType(value); + (*variables)["value_default_value"] = + DefaultValue(value, true, name_resolver) + ".getNumber()"; + + (*variables)["value_enum_type"] = TypeName(value, name_resolver, false); + + if (SupportUnknownEnumValue(descriptor->file())) { + // Map unknown values to a special UNRECOGNIZED value if supported. + (*variables)["unrecognized_value"] = + (*variables)["value_enum_type"] + ".UNRECOGNIZED"; + } else { + // Map unknown values to the default value if we don't have UNRECOGNIZED. + (*variables)["unrecognized_value"] = + DefaultValue(value, true, name_resolver); + } + } else { + (*variables)["value_type"] = TypeName(value, name_resolver, false); + (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true); + (*variables)["value_wire_type"] = WireType(value); + (*variables)["value_default_value"] = + DefaultValue(value, true, name_resolver); + } + (*variables)["type_parameters"] = + (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"]; + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + (*variables)["default_entry"] = (*variables)["capitalized_name"] + + "DefaultEntryHolder.defaultEntry"; + (*variables)["lite"] = "Lite"; + (*variables)["descriptor"] = ""; +} + +} // namespace + +ImmutableMapFieldLiteGenerator:: +ImmutableMapFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +ImmutableMapFieldLiteGenerator:: +~ImmutableMapFieldLiteGenerator() {} + +int ImmutableMapFieldLiteGenerator::GetNumBitsForMessage() const { + return 0; +} + +int ImmutableMapFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +void ImmutableMapFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "get$capitalized_name$();\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$java.util.Map<$type_parameters$>\n" + "get$capitalized_name$Value();\n"); + } + } else { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$java.util.Map<$type_parameters$>\n" + "get$capitalized_name$();\n"); + } +} + +void ImmutableMapFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print( + variables_, + "private static final class $capitalized_name$DefaultEntryHolder {\n" + " static final com.google.protobuf.MapEntry$lite$<\n" + " $type_parameters$> defaultEntry =\n" + " com.google.protobuf.MapEntry$lite$\n" + " .<$type_parameters$>newDefaultInstance(\n" + " $descriptor$\n" + " $key_wire_type$,\n" + " $key_default_value$,\n" + " $value_wire_type$,\n" + " $value_default_value$);\n" + "}\n"); + printer->Print( + variables_, + "private com.google.protobuf.MapField$lite$<\n" + " $type_parameters$> $name$_ =\n" + " com.google.protobuf.MapField$lite$.emptyMapField();\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGet$capitalized_name$() {\n" + " return $name$_;\n" + "}\n" + "private com.google.protobuf.MapField$lite$<$type_parameters$>\n" + "internalGetMutable$capitalized_name$() {\n" + " if (!$name$_.isMutable()) {\n" + " $name$_ = $name$_.copy();\n" + " }\n" + " return $name$_;\n" + "}\n"); + if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { + printer->Print( + variables_, + "private static final\n" + "com.google.protobuf.Internal.MapAdapter.Converter<\n" + " java.lang.Integer, $value_enum_type$> $name$ValueConverter =\n" + " com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n" + " $value_enum_type$.internalGetValueMap(),\n" + " $unrecognized_value$);\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$\n" + "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" + "get$capitalized_name$Value() {\n" + " return internalGet$capitalized_name$().getMap();\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "get$capitalized_name$() {\n" + " return new com.google.protobuf.Internal.MapAdapter<\n" + " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" + " internalGet$capitalized_name$().getMap(),\n" + " $name$ValueConverter);\n" + "}\n"); + } else { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$\n" + "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n" + " return internalGet$capitalized_name$().getMap();\n" + "}\n"); + } + + // Generate private setters for the builder to proxy into. + if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "private java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "getMutable$capitalized_name$() {\n" + " return new com.google.protobuf.Internal.MapAdapter<\n" + " $boxed_key_type$, $value_enum_type$, java.lang.Integer>(\n" + " internalGetMutable$capitalized_name$().getMutableMap(),\n" + " $name$ValueConverter);\n" + "}\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "private java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" + "getMutable$capitalized_name$Value() {\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" + "}\n"); + } + } else { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "private java.util.Map<$type_parameters$>\n" + "getMutable$capitalized_name$() {\n" + " return internalGetMutable$capitalized_name$().getMutableMap();\n" + "}\n"); + } +} + +void ImmutableMapFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$\n" + "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n" + "getMutable$capitalized_name$() {\n" + " copyOnWrite();\n" + " return instance.getMutable$capitalized_name$();\n" + "}\n"); + if (SupportUnknownEnumValue(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$\n" + "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" + "get$capitalized_name$Value() {\n" + " return instance.get$capitalized_name$Value();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "$deprecation$\n" + "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n" + "getMutable$capitalized_name$Value() {\n" + " copyOnWrite();\n" + " return instance.getMutable$capitalized_name$Value();\n" + "}\n"); + } + } else { + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "public java.util.Map<$type_parameters$> get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print( + variables_, + "public java.util.Map<$type_parameters$>\n" + "getMutable$capitalized_name$() {\n" + " copyOnWrite();\n" + " return instance.getMutable$capitalized_name$();\n" + "}\n"); + } +} + +void ImmutableMapFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // Nothing to initialize. +} + +void ImmutableMapFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + // Nothing to initialize. +} + +void ImmutableMapFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print( + variables_, + "internalGetMutable$capitalized_name$().mergeFrom(\n" + " other.internalGet$capitalized_name$());\n"); +} + +void ImmutableMapFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_.makeImmutable();\n"); +} + +void ImmutableMapFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print( + variables_, + "if (!$name$_.isMutable()) {\n" + " $name$_ = $name$_.copy();\n" + "}\n"); + if (!SupportUnknownEnumValue(descriptor_->file()) && + GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) { + printer->Print( + variables_, + "com.google.protobuf.ByteString bytes = input.readBytes();\n" + "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" + "$name$ = $default_entry$.getParserForType().parseFrom(bytes);\n"); + printer->Print( + variables_, + "if ($value_enum_type$.valueOf($name$.getValue()) == null) {\n" + " unknownFields.mergeLengthDelimitedField($number$, bytes);\n" + "} else {\n" + " $name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n" + "}\n"); + } else { + printer->Print( + variables_, + "com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" + "$name$ = input.readMessage(\n" + " $default_entry$.getParserForType(), extensionRegistry);\n" + "$name$_.getMutableMap().put($name$.getKey(), $name$.getValue());\n"); + } +} + +void ImmutableMapFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // Nothing to do here. +} + +void ImmutableMapFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print( + variables_, + "for (java.util.Map.Entry<$type_parameters$> entry\n" + " : internalGet$capitalized_name$().getMap().entrySet()) {\n" + " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" + " $name$ = $default_entry$.newBuilderForType()\n" + " .setKey(entry.getKey())\n" + " .setValue(entry.getValue())\n" + " .build();\n" + " output.writeMessage($number$, $name$);\n" + "}\n"); +} + +void ImmutableMapFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print( + variables_, + "for (java.util.Map.Entry<$type_parameters$> entry\n" + " : internalGet$capitalized_name$().getMap().entrySet()) {\n" + " com.google.protobuf.MapEntry$lite$<$type_parameters$>\n" + " $name$ = $default_entry$.newBuilderForType()\n" + " .setKey(entry.getKey())\n" + " .setValue(entry.getValue())\n" + " .build();\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeMessageSize($number$, $name$);\n" + "}\n"); +} + +void ImmutableMapFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print( + variables_, + "result = result && internalGet$capitalized_name$().equals(\n" + " other.internalGet$capitalized_name$());\n"); +} + +void ImmutableMapFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print( + variables_, + "if (!internalGet$capitalized_name$().getMap().isEmpty()) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + internalGet$capitalized_name$().hashCode();\n" + "}\n"); +} + +string ImmutableMapFieldLiteGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->message_type()); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_map_field_lite.h b/src/google/protobuf/compiler/java/java_map_field_lite.h new file mode 100644 index 00000000..82472602 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_map_field_lite.h @@ -0,0 +1,81 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__ + +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableMapFieldLiteGenerator : public ImmutableFieldLiteGenerator { + public: + explicit ImmutableMapFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableMapFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MAP_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 63df10b4..09b0fd94 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include #include #include @@ -93,43 +95,46 @@ ImmutableMessageGenerator::ImmutableMessageGenerator( : MessageGenerator(descriptor), context_(context), name_resolver_(context->GetNameResolver()), field_generators_(descriptor, context_) { + GOOGLE_CHECK_NE( + FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for()); } ImmutableMessageGenerator::~ImmutableMessageGenerator() {} void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { - if (HasDescriptorMethods(descriptor_)) { - // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is - // used in the construction of descriptors, we have a tricky bootstrapping - // problem. To help control static initialization order, we make sure all - // descriptors and other static data that depends on them are members of - // the outermost class in the file. This way, they will be initialized in - // a deterministic order. - - map vars; - vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); - if (descriptor_->containing_type() != NULL) { - vars["parent"] = UniqueFileScopeIdentifier( - descriptor_->containing_type()); - } - if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { - // We can only make these package-private since the classes that use them - // are in separate files. - vars["private"] = ""; - } else { - vars["private"] = "private "; - } - - // The descriptor for this type. - printer->Print(vars, - "$private$static com.google.protobuf.Descriptors.Descriptor\n" - " internal_$identifier$_descriptor;\n"); + // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is + // used in the construction of descriptors, we have a tricky bootstrapping + // problem. To help control static initialization order, we make sure all + // descriptors and other static data that depends on them are members of + // the outermost class in the file. This way, they will be initialized in + // a deterministic order. - // And the FieldAccessorTable. - GenerateFieldAccessorTable(printer); + map vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = UniqueFileScopeIdentifier( + descriptor_->containing_type()); } + if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { + // We can only make these package-private since the classes that use them + // are in separate files. + vars["private"] = ""; + } else { + vars["private"] = "private "; + } + + // The descriptor for this type. + printer->Print(vars, + // TODO(teboring): final needs to be added back. The way to fix it is to + // generate methods that can construct the types, and then still declare the + // types, and then init them in clinit with the new method calls. + "$private$static com.google.protobuf.Descriptors.Descriptor\n" + " internal_$identifier$_descriptor;\n"); + + // And the FieldAccessorTable. + GenerateFieldAccessorTable(printer); // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { @@ -142,38 +147,37 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { int ImmutableMessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { int bytecode_estimate = 0; - if (HasDescriptorMethods(descriptor_)) { - map vars; - vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); - vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); - if (descriptor_->containing_type() != NULL) { - vars["parent"] = UniqueFileScopeIdentifier( - descriptor_->containing_type()); - } - - // The descriptor for this type. - if (descriptor_->containing_type() == NULL) { - printer->Print(vars, - "internal_$identifier$_descriptor =\n" - " getDescriptor().getMessageTypes().get($index$);\n"); - bytecode_estimate += 30; - } else { - printer->Print(vars, - "internal_$identifier$_descriptor =\n" - " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); - bytecode_estimate += 30; - } + map vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = UniqueFileScopeIdentifier( + descriptor_->containing_type()); + } - // And the FieldAccessorTable. - bytecode_estimate += GenerateFieldAccessorTableInitializer(printer); + // The descriptor for this type. + if (descriptor_->containing_type() == NULL) { + printer->Print(vars, + "internal_$identifier$_descriptor =\n" + " getDescriptor().getMessageTypes().get($index$);\n"); + bytecode_estimate += 30; + } else { + printer->Print(vars, + "internal_$identifier$_descriptor =\n" + " internal_$parent$_descriptor.getNestedTypes().get($index$);\n"); + bytecode_estimate += 30; } + // And the FieldAccessorTable. + bytecode_estimate += GenerateFieldAccessorTableInitializer(printer); + // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - bytecode_estimate += ImmutableMessageGenerator(descriptor_->nested_type(i), context_) - .GenerateStaticVariableInitializers(printer); + bytecode_estimate += + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) + .GenerateStaticVariableInitializers(printer); } return bytecode_estimate; } @@ -229,40 +233,20 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) { void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public interface $classname$OrBuilder extends\n" - " $extra_interfaces$\n" - " com.google.protobuf.GeneratedMessage.\n" - " ExtendableMessageOrBuilder<$classname$> {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); - } else { - printer->Print( - "public interface $classname$OrBuilder extends \n" - " $extra_interfaces$\n" - " com.google.protobuf.GeneratedMessageLite.\n" - " ExtendableMessageOrBuilder<\n" - " $classname$, $classname$.Builder> {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); - } + printer->Print( + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.GeneratedMessage.\n" + " ExtendableMessageOrBuilder<$classname$> {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), + "classname", descriptor_->name()); } else { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public interface $classname$OrBuilder extends\n" - " $extra_interfaces$\n" - " com.google.protobuf.MessageOrBuilder {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); - } else { - printer->Print( - "public interface $classname$OrBuilder extends\n" - " $extra_interfaces$\n" - " com.google.protobuf.MessageLiteOrBuilder {\n", - "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), - "classname", descriptor_->name()); - } + printer->Print( + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageOrBuilder {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), + "classname", descriptor_->name()); } printer->Indent(); @@ -287,98 +271,71 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { variables["static"] = is_own_file ? " " : " static "; variables["classname"] = descriptor_->name(); variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); - variables["lite"] = HasDescriptorMethods(descriptor_) ? "" : "Lite"; WriteMessageDocComment(printer, descriptor_); // The builder_type stores the super type name of the nested Builder class. string builder_type; if (descriptor_->extension_range_count() > 0) { - if (HasDescriptorMethods(descriptor_)) { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" - " $classname$> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); - } else { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" - " $classname$, $classname$.Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); - } + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", - name_resolver_->GetImmutableClassName(descriptor_), - variables["lite"]); + "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_)); } else { - if (HasDescriptorMethods(descriptor_)) { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); - } else { - printer->Print(variables, - "public $static$final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite<\n" - " $classname$, $classname$.Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n"); - } + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); - builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessage$0.Builder", - variables["lite"]); + builder_type = "com.google.protobuf.GeneratedMessage.Builder"; } printer->Indent(); - if (HasDescriptorMethods(descriptor_)) { - // Using builder_type, instead of Builder, prevents the Builder class from - // being loaded into PermGen space when the default instance is created. - // This optimizes the PermGen space usage for clients that do not modify - // messages. - printer->Print( - "// Use $classname$.newBuilder() to construct.\n" - "private $classname$($buildertype$ builder) {\n" - " super(builder);\n" - "}\n", - "classname", descriptor_->name(), - "buildertype", builder_type); - printer->Print( - "private $classname$() {\n", - "classname", descriptor_->name()); - printer->Indent(); - GenerateInitializers(printer); - printer->Outdent(); - printer->Print( - "}\n" - "\n"); - } + // Using builder_type, instead of Builder, prevents the Builder class from + // being loaded into PermGen space when the default instance is created. + // This optimizes the PermGen space usage for clients that do not modify + // messages. + printer->Print( + "// Use $classname$.newBuilder() to construct.\n" + "private $classname$($buildertype$ builder) {\n" + " super(builder);\n" + "}\n", + "classname", descriptor_->name(), + "buildertype", builder_type); + printer->Print( + "private $classname$() {\n", + "classname", descriptor_->name()); + printer->Indent(); + GenerateInitializers(printer); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); - if (HasDescriptorMethods(descriptor_)) { + printer->Print( + "@java.lang.Override\n" + "public final com.google.protobuf.UnknownFieldSet\n" + "getUnknownFields() {\n"); + if (PreserveUnknownFields(descriptor_)) { printer->Print( - "@java.lang.Override\n" - "public final com.google.protobuf.UnknownFieldSet\n" - "getUnknownFields() {\n"); - if (PreserveUnknownFields(descriptor_)) { - printer->Print( - " return this.unknownFields;\n"); - } else { - printer->Print( - " return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n"); - } + " return this.unknownFields;\n"); + } else { printer->Print( - "}\n"); + " return com.google.protobuf.UnknownFieldSet.getDefaultInstance();\n"); } + printer->Print( + "}\n"); if (HasGeneratedMethods(descriptor_)) { GenerateParsingConstructor(printer); } - GenerateDescriptorMethods(printer, false); - GenerateParser(printer); + GenerateDescriptorMethods(printer); // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { @@ -488,7 +445,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { } if (HasGeneratedMethods(descriptor_)) { - GenerateIsInitialized(printer, MEMOIZE); + GenerateIsInitialized(printer); GenerateMessageSerializationMethods(printer); } @@ -509,78 +466,39 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { // Carefully initialize the default instance in such a way that it doesn't // conflict with other initialization. printer->Print( - "private static final $classname$ defaultInstance;\n", + "private static final $classname$ DEFAULT_INSTANCE;\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "static {\n" - " defaultInstance = new $classname$();\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } else { - // LITE_RUNTIME only has one constructor. - printer->Print( - "static {\n" - " defaultInstance = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - "}\n" - "\n", - "classname", descriptor_->name()); - } + printer->Print( + "static {\n" + " DEFAULT_INSTANCE = new $classname$();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + printer->Print( "public static $classname$ getDefaultInstance() {\n" - " return defaultInstance;\n" + " return DEFAULT_INSTANCE;\n" "}\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); - if (HasDescriptorMethods(descriptor_)) { - // LITE_RUNTIME implements this at the GeneratedMessageLite level. - printer->Print( - "public $classname$ getDefaultInstanceForType() {\n" - " return defaultInstance;\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } else { - // LITE_RUNTIME uses this to implement the *ForType methods at the - // GeneratedMessageLite level. - printer->Print( - "static {" - " com.google.protobuf.GeneratedMessageLite.onLoad(\n" - " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n" - " .PrototypeHolder<$classname$, Builder>(\n" - " defaultInstance, PARSER));" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } + GenerateParser(printer); - // Extensions must be declared after the defaultInstance is initialized - // because the defaultInstance is used by the extension to lazily retrieve + printer->Print( + "public $classname$ getDefaultInstanceForType() {\n" + " return DEFAULT_INSTANCE;\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + // Extensions must be declared after the DEFAULT_INSTANCE is initialized + // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve // the outer class's FileDescriptor. for (int i = 0; i < descriptor_->extension_count(); i++) { ImmutableExtensionGenerator(descriptor_->extension(i), context_) .Generate(printer); } - // Some fields also have static members that must be initialized after we - // have the default instance available. - printer->Print( - "static {\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateStaticInitializationCode(printer); - } - printer->Outdent(); - printer->Print( - "}\n"); - printer->Outdent(); printer->Print("}\n\n"); } @@ -617,35 +535,17 @@ GenerateMessageSerializationMethods(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "com.google.protobuf.GeneratedMessage\n" - " .ExtendableMessage<$classname$>.ExtensionWriter\n" - " extensionWriter = newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } else { - printer->Print( - "com.google.protobuf.GeneratedMessageLite\n" - " .ExtendableMessage<$classname$, $classname$.Builder>\n" - " .ExtensionWriter extensionWriter =\n" - " newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } + printer->Print( + "com.google.protobuf.GeneratedMessage\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "com.google.protobuf.GeneratedMessage\n" - " .ExtendableMessage<$classname$>.ExtensionWriter\n" - " extensionWriter = newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } else { - printer->Print( - "com.google.protobuf.GeneratedMessageLite\n" - " .ExtendableMessage<$classname$, $classname$.Builder>\n" - " .ExtensionWriter extensionWriter =\n" - " newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } + printer->Print( + "com.google.protobuf.GeneratedMessage\n" + " .ExtendableMessage<$classname$>.ExtensionWriter\n" + " extensionWriter = newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } } @@ -665,8 +565,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } if (PreserveUnknownFields(descriptor_)) { - if (descriptor_->options().message_set_wire_format() - && HasDescriptorMethods(descriptor_)) { + if (descriptor_->options().message_set_wire_format()) { printer->Print( "unknownFields.writeAsMessageSetTo(output);\n"); } else { @@ -702,8 +601,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } if (PreserveUnknownFields(descriptor_)) { - if (descriptor_->options().message_set_wire_format() - && HasDescriptorMethods(descriptor_)) { + if (descriptor_->options().message_set_wire_format()) { printer->Print( "size += unknownFields.getSerializedSizeAsMessageSet();\n"); } else { @@ -800,609 +698,115 @@ void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( // =================================================================== void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { - if (HasDescriptorMethods(descriptor_)) { - // LITE_RUNTIME implements this at the GeneratedMessageLite level. - printer->Print( - "public Builder newBuilderForType() { return newBuilder(); }\n"); - } + // LITE_RUNTIME implements this at the GeneratedMessageLite level. + printer->Print( + "public Builder newBuilderForType() { return newBuilder(); }\n"); printer->Print( "public static Builder newBuilder() {\n" - " return defaultInstance.toBuilder();\n" + " return DEFAULT_INSTANCE.toBuilder();\n" "}\n" "public static Builder newBuilder($classname$ prototype) {\n" - " return defaultInstance.toBuilder().mergeFrom(prototype);\n" + " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n" "}\n" "public Builder toBuilder() {\n" - " return this == defaultInstance\n" + " return this == DEFAULT_INSTANCE\n" " ? new Builder() : new Builder().mergeFrom(this);\n" "}\n" "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); - if (HasNestedBuilders(descriptor_)) { - printer->Print( - "@java.lang.Override\n" - "protected Builder newBuilderForType(\n" - " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" - " Builder builder = new Builder(parent);\n" - " return builder;\n" - "}\n"); - } - - WriteMessageDocComment(printer, descriptor_); - - if (descriptor_->extension_range_count() > 0) { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" - " $classname$, Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); - } else { - printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" - " $classname$, Builder> implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); - } - } else { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); - } else { - printer->Print( - "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessageLite.Builder<\n" - " $classname$, Builder>\n" - " implements\n" - " $extra_interfaces$\n" - " $classname$OrBuilder {\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); - } - } - printer->Indent(); - - GenerateDescriptorMethods(printer, true); - GenerateCommonBuilderMethods(printer); - - if (HasGeneratedMethods(descriptor_)) { - GenerateIsInitialized(printer, DONT_MEMOIZE); - GenerateBuilderParsingMethods(printer); - } - - // oneof - map vars; - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - vars["oneof_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name; - vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name; - vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); - // oneofCase_ and oneof_ - printer->Print(vars, - "private int $oneof_name$Case_ = 0;\n" - "private java.lang.Object $oneof_name$_;\n"); - // oneofCase() and clearOneof() - printer->Print(vars, - "public $oneof_capitalized_name$Case\n" - " get$oneof_capitalized_name$Case() {\n" - " return $oneof_capitalized_name$Case.valueOf(\n" - " $oneof_name$Case_);\n" - "}\n" - "\n" - "public Builder clear$oneof_capitalized_name$() {\n" - " $oneof_name$Case_ = 0;\n" - " $oneof_name$_ = null;\n"); - if (HasDescriptorMethods(descriptor_)) { - printer->Print(" onChanged();\n"); - } - printer->Print( - " return this;\n" - "}\n" - "\n"); - } - - if (GenerateHasBits(descriptor_)) { - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForBuilder(); - } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\n"); - field_generators_.get(descriptor_->field(i)) - .GenerateBuilderMembers(printer); - } - - if (!PreserveUnknownFields(descriptor_)) { - printer->Print( - "public final Builder setUnknownFields(\n" - " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" - " return this;\n" - "}\n" - "\n" - "public final Builder mergeUnknownFields(\n" - " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" - " return this;\n" - "}\n" - "\n"); - } - printer->Print( - "\n" - "// @@protoc_insertion_point(builder_scope:$full_name$)\n", - "full_name", descriptor_->full_name()); - - printer->Outdent(); - printer->Print("}\n"); + "@java.lang.Override\n" + "protected Builder newBuilderForType(\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " Builder builder = new Builder(parent);\n" + " return builder;\n" + "}\n"); + + MessageBuilderGenerator builderGenerator(descriptor_, context_); + builderGenerator.Generate(printer); } void ImmutableMessageGenerator:: -GenerateDescriptorMethods(io::Printer* printer, bool is_builder) { - if (HasDescriptorMethods(descriptor_)) { - if (!descriptor_->options().no_standard_descriptor_accessor()) { - printer->Print( - "public static final com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptor() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n", - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); - } - vector map_fields; - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (GetJavaType(field) == JAVATYPE_MESSAGE && - IsMapEntry(field->message_type())) { - map_fields.push_back(field); - } - } - if (!map_fields.empty()) { - printer->Print( - "@SuppressWarnings({\"rawtypes\"})\n" - "protected com.google.protobuf.MapField internalGetMapField(\n" - " int number) {\n" - " switch (number) {\n"); - printer->Indent(); - printer->Indent(); - for (int i = 0; i < map_fields.size(); ++i) { - const FieldDescriptor* field = map_fields[i]; - const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); - printer->Print( - "case $number$:\n" - " return internalGet$capitalized_name$();\n", - "number", SimpleItoa(field->number()), - "capitalized_name", info->capitalized_name); - } - printer->Print( - "default:\n" - " throw new RuntimeException(\n" - " \"Invalid map field number: \" + number);\n"); - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" - "}\n"); - if (is_builder) { - printer->Print( - "@SuppressWarnings({\"rawtypes\"})\n" - "protected com.google.protobuf.MapField internalGetMutableMapField(\n" - " int number) {\n" - " switch (number) {\n"); - printer->Indent(); - printer->Indent(); - for (int i = 0; i < map_fields.size(); ++i) { - const FieldDescriptor* field = map_fields[i]; - const FieldGeneratorInfo* info = - context_->GetFieldGeneratorInfo(field); - printer->Print( - "case $number$:\n" - " return internalGetMutable$capitalized_name$();\n", - "number", SimpleItoa(field->number()), - "capitalized_name", info->capitalized_name); - } - printer->Print( - "default:\n" - " throw new RuntimeException(\n" - " \"Invalid map field number: \" + number);\n"); - printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\n" - "}\n"); - } - } +GenerateDescriptorMethods(io::Printer* printer) { + if (!descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internalGetFieldAccessorTable() {\n" - " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" - " .ensureFieldAccessorsInitialized(\n" - " $classname$.class, $classname$.Builder.class);\n" + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_), "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), "identifier", UniqueFileScopeIdentifier(descriptor_)); } -} - -// =================================================================== - -void ImmutableMessageGenerator:: -GenerateCommonBuilderMethods(io::Printer* printer) { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "// Construct using $classname$.newBuilder()\n" - "private Builder() {\n" - " maybeForceBuilderInitialization();\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - printer->Print( - "private Builder(\n" - " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" - " super(parent);\n" - " maybeForceBuilderInitialization();\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } else { - // LITE runtime passes along the default instance to implement - // getDefaultInstanceForType() at the GeneratedMessageLite level. - printer->Print( - "// Construct using $classname$.newBuilder()\n" - "private Builder() {\n" - " super(defaultInstance);\n" - " maybeForceBuilderInitialization();\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + vector map_fields; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (GetJavaType(field) == JAVATYPE_MESSAGE && + IsMapEntry(field->message_type())) { + map_fields.push_back(field); + } } - - - if (HasNestedBuilders(descriptor_)) { + if (!map_fields.empty()) { printer->Print( - "private void maybeForceBuilderInitialization() {\n" - " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n"); - + "@SuppressWarnings({\"rawtypes\"})\n" + "protected com.google.protobuf.MapField internalGetMapField(\n" + " int number) {\n" + " switch (number) {\n"); printer->Indent(); printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get(descriptor_->field(i)) - .GenerateFieldBuilderInitializationCode(printer); - } + for (int i = 0; i < map_fields.size(); ++i) { + const FieldDescriptor* field = map_fields[i]; + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + printer->Print( + "case $number$:\n" + " return internalGet$capitalized_name$();\n", + "number", SimpleItoa(field->number()), + "capitalized_name", info->capitalized_name); } + printer->Print( + "default:\n" + " throw new RuntimeException(\n" + " \"Invalid map field number: \" + number);\n"); printer->Outdent(); printer->Outdent(); - - printer->Print( - " }\n" - "}\n"); - } else { - printer->Print( - "private void maybeForceBuilderInitialization() {\n" - "}\n"); - } - - printer->Print( - "public Builder clear() {\n" - " super.clear();\n"); - - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get(descriptor_->field(i)) - .GenerateBuilderClearCode(printer); - } - } - - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print( - "$oneof_name$Case_ = 0;\n" - "$oneof_name$_ = null;\n", - "oneof_name", context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); - } - - printer->Outdent(); - - printer->Print( - " return this;\n" - "}\n" - "\n"); - - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public com.google.protobuf.Descriptors.Descriptor\n" - " getDescriptorForType() {\n" - " return $fileclass$.internal_$identifier$_descriptor;\n" - "}\n" - "\n", - "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); - - // LITE runtime implements this in GeneratedMessageLite. - printer->Print( - "public $classname$ getDefaultInstanceForType() {\n" - " return $classname$.getDefaultInstance();\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } - - // ----------------------------------------------------------------- - - if (HasDescriptorMethods(descriptor_)) { - // LITE implements build in GeneratedMessageLite to save methods. printer->Print( - "public $classname$ build() {\n" - " $classname$ result = buildPartial();\n" - " if (!result.isInitialized()) {\n" - " throw newUninitializedMessageException(result);\n" - " }\n" - " return result;\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } - - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public $classname$ buildPartial() {\n" - " $classname$ result = new $classname$(this);\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } else { - // LITE_RUNTIME only provides a single message constructor. - printer->Print( - "public $classname$ buildPartial() {\n" - " $classname$ result = new $classname$(\n" - " com.google.protobuf.Internal\n" - " .EMPTY_CODED_INPUT_STREAM,\n" - " com.google.protobuf.ExtensionRegistryLite\n" - " .getEmptyRegistry());\n" - " result.unknownFields = this.unknownFields;\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - if (descriptor_->extension_range_count() > 0) { - printer->Print( - " result.extensions = this.buildExtensions();\n"); - } - } - - printer->Indent(); - - int totalBuilderBits = 0; - int totalMessageBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - const ImmutableFieldGenerator& field = - field_generators_.get(descriptor_->field(i)); - totalBuilderBits += field.GetNumBitsForBuilder(); - totalMessageBits += field.GetNumBitsForMessage(); - } - int totalBuilderInts = (totalBuilderBits + 31) / 32; - int totalMessageInts = (totalMessageBits + 31) / 32; - - if (GenerateHasBits(descriptor_)) { - // Local vars for from and to bit fields to avoid accessing the builder and - // message over and over for these fields. Seems to provide a slight - // perforamance improvement in micro benchmark and this is also what proto1 - // code does. - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("int to_$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - - // Output generation code for each field. - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); - } - - if (GenerateHasBits(descriptor_)) { - // Copy the bit field results to the generated message - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - } - - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", - "oneof_name", context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name); - } - - printer->Outdent(); - - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - " onBuilt();\n"); + " }\n" + "}\n"); } - printer->Print( - " return result;\n" + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" + " .ensureFieldAccessorsInitialized(\n" + " $classname$.class, $classname$.Builder.class);\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - - // ----------------------------------------------------------------- - - if (HasGeneratedMethods(descriptor_)) { - // MergeFrom(Message other) requires the ability to distinguish the other - // messages type by its descriptor. - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "public Builder mergeFrom(com.google.protobuf.Message other) {\n" - " if (other instanceof $classname$) {\n" - " return mergeFrom(($classname$)other);\n" - " } else {\n" - " super.mergeFrom(other);\n" - " return this;\n" - " }\n" - "}\n" - "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } - - printer->Print( - "public Builder mergeFrom($classname$ other) {\n" - // Optimization: If other is the default instance, we know none of its - // fields are set so we can skip the merge. - " if (other == $classname$.getDefaultInstance()) return this;\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - printer->Indent(); - - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - field_generators_.get( - descriptor_->field(i)).GenerateMergingCode(printer); - } - } - - // Merge oneof fields. - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - printer->Print( - "switch (other.get$oneof_capitalized_name$Case()) {\n", - "oneof_capitalized_name", - context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->capitalized_name); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - printer->Print( - "case $field_name$: {\n", - "field_name", - ToUpper(field->name())); - printer->Indent(); - field_generators_.get(field).GenerateMergingCode(printer); - printer->Print( - "break;\n"); - printer->Outdent(); - printer->Print( - "}\n"); - } - printer->Print( - "case $cap_oneof_name$_NOT_SET: {\n" - " break;\n" - "}\n", - "cap_oneof_name", - ToUpper(context_->GetOneofGeneratorInfo( - descriptor_->oneof_decl(i))->name)); - printer->Outdent(); - printer->Print( - "}\n"); - } - - printer->Outdent(); - - // if message type has extensions - if (descriptor_->extension_range_count() > 0) { - printer->Print( - " this.mergeExtensionFields(other);\n"); - } - - if (PreserveUnknownFields(descriptor_)) { - printer->Print( - " this.mergeUnknownFields(other.unknownFields);\n"); - } - - if (HasDescriptorMethods(descriptor_)) { - printer->Print(" onChanged();\n"); - } - - printer->Print( - " return this;\n" - "}\n" - "\n"); - } -} - -// =================================================================== - -void ImmutableMessageGenerator:: -GenerateBuilderParsingMethods(io::Printer* printer) { - if (HasDescriptorMethods(descriptor_)) { - // LITE_RUNTIME implements this at the GeneratedMessageLite level. - printer->Print( - "public Builder mergeFrom(\n" - " com.google.protobuf.CodedInputStream input,\n" - " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" - " throws java.io.IOException {\n" - " $classname$ parsedMessage = null;\n" - " try {\n" - " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" - " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" - " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" - " throw e;\n" - " } finally {\n" - " if (parsedMessage != null) {\n" - " mergeFrom(parsedMessage);\n" - " }\n" - " }\n" - " return this;\n" - "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); } // =================================================================== void ImmutableMessageGenerator::GenerateIsInitialized( - io::Printer* printer, UseMemoization useMemoization) { - // LITE_RUNTIME avoids generating isInitialized if it's not needed. - if (!HasDescriptorMethods(descriptor_) - && !HasRequiredFields(descriptor_)) { - return; - } - - bool memoization = useMemoization == MEMOIZE; - if (memoization) { - // Memoizes whether the protocol buffer is fully initialized (has all - // required fields). -1 means not yet computed. 0 means false and 1 means - // true. - printer->Print( - "private byte memoizedIsInitialized = -1;\n"); - } + io::Printer* printer) { + // Memoizes whether the protocol buffer is fully initialized (has all + // required fields). -1 means not yet computed. 0 means false and 1 means + // true. + printer->Print( + "private byte memoizedIsInitialized = -1;\n"); printer->Print( "public final boolean isInitialized() {\n"); printer->Indent(); - if (memoization) { - // Don't directly compare to -1 to avoid an Android x86 JIT bug. - printer->Print( - "byte isInitialized = memoizedIsInitialized;\n" - "if (isInitialized == 1) return true;\n" - "if (isInitialized == 0) return false;\n" - "\n"); - } + // Don't directly compare to -1 to avoid an Android x86 JIT bug. + printer->Print( + "byte isInitialized = memoizedIsInitialized;\n" + "if (isInitialized == 1) return true;\n" + "if (isInitialized == 0) return false;\n" + "\n"); // Check that all required fields in this message are set. // TODO(kenton): We can optimize this when we switch to putting all the @@ -1414,11 +818,10 @@ void ImmutableMessageGenerator::GenerateIsInitialized( if (field->is_required()) { printer->Print( "if (!has$name$()) {\n" - " $memoize$\n" + " memoizedIsInitialized = 0;\n" " return false;\n" "}\n", - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + "name", info->capitalized_name); } } @@ -1432,13 +835,12 @@ void ImmutableMessageGenerator::GenerateIsInitialized( case FieldDescriptor::LABEL_REQUIRED: printer->Print( "if (!get$name$().isInitialized()) {\n" - " $memoize$\n" + " memoizedIsInitialized = 0;\n" " return false;\n" "}\n", "type", name_resolver_->GetImmutableClassName( field->message_type()), - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + "name", info->capitalized_name); break; case FieldDescriptor::LABEL_OPTIONAL: if (!SupportFieldPresence(descriptor_->file()) && @@ -1457,38 +859,35 @@ void ImmutableMessageGenerator::GenerateIsInitialized( } printer->Print( " if (!get$name$().isInitialized()) {\n" - " $memoize$\n" + " memoizedIsInitialized = 0;\n" " return false;\n" " }\n" "}\n", - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + "name", info->capitalized_name); break; case FieldDescriptor::LABEL_REPEATED: if (IsMapEntry(field->message_type())) { printer->Print( "for ($type$ item : get$name$().values()) {\n" " if (!item.isInitialized()) {\n" - " $memoize$\n" + " memoizedIsInitialized = 0;\n" " return false;\n" " }\n" "}\n", "type", MapValueImmutableClassdName(field->message_type(), name_resolver_), - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + "name", info->capitalized_name); } else { printer->Print( "for (int i = 0; i < get$name$Count(); i++) {\n" " if (!get$name$(i).isInitialized()) {\n" - " $memoize$\n" + " memoizedIsInitialized = 0;\n" " return false;\n" " }\n" "}\n", "type", name_resolver_->GetImmutableClassName( field->message_type()), - "name", info->capitalized_name, - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + "name", info->capitalized_name); } break; } @@ -1498,18 +897,15 @@ void ImmutableMessageGenerator::GenerateIsInitialized( if (descriptor_->extension_range_count() > 0) { printer->Print( "if (!extensionsAreInitialized()) {\n" - " $memoize$\n" + " memoizedIsInitialized = 0;\n" " return false;\n" - "}\n", - "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); + "}\n"); } printer->Outdent(); - if (memoization) { - printer->Print( - " memoizedIsInitialized = 1;\n"); - } + printer->Print( + " memoizedIsInitialized = 1;\n"); printer->Print( " return true;\n" @@ -1575,12 +971,10 @@ GenerateEqualsAndHashCode(io::Printer* printer) { printer->Print( "result = result && unknownFields.equals(other.unknownFields);\n"); } - if (HasDescriptorMethods(descriptor_)) { - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "result = result &&\n" - " getExtensionFields().equals(other.getExtensionFields());\n"); - } + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "result = result &&\n" + " getExtensionFields().equals(other.getExtensionFields());\n"); } printer->Print( "return result;\n"); @@ -1603,14 +997,7 @@ GenerateEqualsAndHashCode(io::Printer* printer) { "}\n" "int hash = 41;\n"); - if (HasDescriptorMethods(descriptor_)) { - printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n"); - } else { - // Include the hash of the class so that two objects with different types - // but the same field values will probably have different hashes. - printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); - } + printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); @@ -1628,11 +1015,9 @@ GenerateEqualsAndHashCode(io::Printer* printer) { printer->Print("}\n"); } } - if (HasDescriptorMethods(descriptor_)) { - if (descriptor_->extension_range_count() > 0) { - printer->Print( - "hash = hashFields(hash, getExtensionFields());\n"); - } + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "hash = hashFields(hash, getExtensionFields());\n"); } printer->Print( @@ -1675,13 +1060,8 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Indent(); // Initialize all fields to default. - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "this();\n"); - } else { - // LITE_RUNTIME only has one constructor. - GenerateInitializers(printer); - } + printer->Print( + "this();\n"); // Use builder bits to track mutable repeated fields. int totalBuilderBits = 0; @@ -1697,15 +1077,9 @@ GenerateParsingConstructor(io::Printer* printer) { } if (PreserveUnknownFields(descriptor_)) { - if (HasDescriptorMethods(descriptor_)) { - printer->Print( - "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" - " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); - } else { - printer->Print( - "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n" - " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n"); - } + printer->Print( + "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" + " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); } printer->Print( @@ -1728,29 +1102,14 @@ GenerateParsingConstructor(io::Printer* printer) { " break;\n"); if (PreserveUnknownFields(descriptor_)) { - if (!HasDescriptorMethods(descriptor_) - && descriptor_->extension_range_count() > 0) { - // Lite runtime directly invokes parseUnknownField to reduce method - // counts. - printer->Print( - "default: {\n" - " if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n" - " input, unknownFields,\n" - " extensionRegistry, tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } else { - printer->Print( - "default: {\n" - " if (!parseUnknownField(input, unknownFields,\n" - " extensionRegistry, tag)) {\n" - " done = true;\n" // it's an endgroup tag - " }\n" - " break;\n" - "}\n"); - } + printer->Print( + "default: {\n" + " if (!parseUnknownField(input, unknownFields,\n" + " extensionRegistry, tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); } else { printer->Print( "default: {\n" @@ -1825,18 +1184,9 @@ GenerateParsingConstructor(io::Printer* printer) { printer->Print("this.unknownFields = unknownFields.build();\n"); } - if (!HasDescriptorMethods(descriptor_)) { - // LITE runtime uses a static method to reduce method count. - if (descriptor_->extension_range_count() > 0) { - // Make extensions immutable. - printer->Print( - "makeExtensionsImmutable(extensions);\n"); - } - } else { - // Make extensions immutable. - printer->Print( - "makeExtensionsImmutable();\n"); - } + // Make extensions immutable. + printer->Print( + "makeExtensionsImmutable();\n"); printer->Outdent(); printer->Outdent(); @@ -1874,9 +1224,9 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { " }\n", "classname", descriptor_->name()); } else { - // When parsing constructor isn't generated, use builder to parse messages. - // Note, will fallback to use reflection based mergeFieldFrom() in - // AbstractMessage.Builder. + // When parsing constructor isn't generated, use builder to parse + // messages. Note, will fallback to use reflection based mergeFieldFrom() + // in AbstractMessage.Builder. printer->Indent(); printer->Print( "Builder builder = newBuilder();\n" @@ -1886,7 +1236,8 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { " throw e.setUnfinishedMessage(builder.buildPartial());\n" "} catch (java.io.IOException e) {\n" " throw new com.google.protobuf.InvalidProtocolBufferException(\n" - " e.getMessage()).setUnfinishedMessage(builder.buildPartial());\n" + " e.getMessage()).setUnfinishedMessage(\n" + " builder.buildPartial());\n" "}\n" "return builder.buildPartial();\n"); printer->Outdent(); @@ -1898,16 +1249,13 @@ void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { "};\n" "\n"); - if (HasDescriptorMethods(descriptor_)) { - // LITE_RUNTIME implements this at the GeneratedMessageLite level. - printer->Print( - "@java.lang.Override\n" - "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" - " return PARSER;\n" - "}\n" - "\n", - "classname", descriptor_->name()); - } + printer->Print( + "@java.lang.Override\n" + "public com.google.protobuf.Parser<$classname$> getParserForType() {\n" + " return PARSER;\n" + "}\n" + "\n", + "classname", descriptor_->name()); } // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index 58dd5f99..c3c37765 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -102,10 +102,6 @@ class ImmutableMessageGenerator : public MessageGenerator { virtual int GenerateStaticVariableInitializers(io::Printer* printer); private: - enum UseMemoization { - MEMOIZE, - DONT_MEMOIZE - }; void GenerateFieldAccessorTable(io::Printer* printer); @@ -120,11 +116,8 @@ class ImmutableMessageGenerator : public MessageGenerator { io::Printer* printer, const Descriptor::ExtensionRange* range); void GenerateBuilder(io::Printer* printer); - void GenerateCommonBuilderMethods(io::Printer* printer); - void GenerateDescriptorMethods(io::Printer* printer, bool is_builder); - void GenerateBuilderParsingMethods(io::Printer* printer); - void GenerateIsInitialized(io::Printer* printer, - UseMemoization useMemoization); + void GenerateIsInitialized(io::Printer* printer); + void GenerateDescriptorMethods(io::Printer* printer); void GenerateInitializers(io::Printer* printer); void GenerateEqualsAndHashCode(io::Printer* printer); void GenerateParser(io::Printer* printer); diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc new file mode 100644 index 00000000..72694119 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_message_builder.cc @@ -0,0 +1,661 @@ +// 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. + +// Author: dweis@google.com (Daniel Weis) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include + +#include +#include +#include +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { +bool GenerateHasBits(const Descriptor* descriptor) { + return SupportFieldPresence(descriptor->file()) || + HasRepeatedFields(descriptor); +} + +string MapValueImmutableClassdName(const Descriptor* descriptor, + ClassNameResolver* name_resolver) { + const FieldDescriptor* value_field = descriptor->FindFieldByName("value"); + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); + return name_resolver->GetImmutableClassName(value_field->message_type()); +} +} // namespace + +MessageBuilderGenerator::MessageBuilderGenerator( + const Descriptor* descriptor, Context* context) + : descriptor_(descriptor), context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { + GOOGLE_CHECK_NE( + FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for()); +} + +MessageBuilderGenerator::~MessageBuilderGenerator() {} + +void MessageBuilderGenerator:: +Generate(io::Printer* printer) { + WriteMessageDocComment(printer, descriptor_); + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); + } else { + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessage.Builder implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); + } + printer->Indent(); + + GenerateDescriptorMethods(printer); + GenerateCommonBuilderMethods(printer); + + if (HasGeneratedMethods(descriptor_)) { + GenerateIsInitialized(printer); + GenerateBuilderParsingMethods(printer); + } + + // oneof + map vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // oneofCase() and clearOneof() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + " get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.valueOf(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n" + "public Builder clear$oneof_capitalized_name$() {\n" + " $oneof_name$Case_ = 0;\n" + " $oneof_name$_ = null;\n"); + printer->Print(" onChanged();\n"); + printer->Print( + " return this;\n" + "}\n" + "\n"); + } + + if (GenerateHasBits(descriptor_)) { + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForBuilder(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderMembers(printer); + } + + if (!PreserveUnknownFields(descriptor_)) { + printer->Print( + "public final Builder setUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return this;\n" + "}\n" + "\n" + "public final Builder mergeUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return this;\n" + "}\n" + "\n"); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(builder_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print("}\n"); +} + +// =================================================================== + +void MessageBuilderGenerator:: +GenerateDescriptorMethods(io::Printer* printer) { + if (!descriptor_->options().no_standard_descriptor_accessor()) { + printer->Print( + "public static final com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptor() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n", + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + } + vector map_fields; + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + if (GetJavaType(field) == JAVATYPE_MESSAGE && + IsMapEntry(field->message_type())) { + map_fields.push_back(field); + } + } + if (!map_fields.empty()) { + printer->Print( + "@SuppressWarnings({\"rawtypes\"})\n" + "protected com.google.protobuf.MapField internalGetMapField(\n" + " int number) {\n" + " switch (number) {\n"); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < map_fields.size(); ++i) { + const FieldDescriptor* field = map_fields[i]; + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + printer->Print( + "case $number$:\n" + " return internalGet$capitalized_name$();\n", + "number", SimpleItoa(field->number()), + "capitalized_name", info->capitalized_name); + } + printer->Print( + "default:\n" + " throw new RuntimeException(\n" + " \"Invalid map field number: \" + number);\n"); + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" + "}\n"); + printer->Print( + "@SuppressWarnings({\"rawtypes\"})\n" + "protected com.google.protobuf.MapField internalGetMutableMapField(\n" + " int number) {\n" + " switch (number) {\n"); + printer->Indent(); + printer->Indent(); + for (int i = 0; i < map_fields.size(); ++i) { + const FieldDescriptor* field = map_fields[i]; + const FieldGeneratorInfo* info = + context_->GetFieldGeneratorInfo(field); + printer->Print( + "case $number$:\n" + " return internalGetMutable$capitalized_name$();\n", + "number", SimpleItoa(field->number()), + "capitalized_name", info->capitalized_name); + } + printer->Print( + "default:\n" + " throw new RuntimeException(\n" + " \"Invalid map field number: \" + number);\n"); + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" + "}\n"); + } + printer->Print( + "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internalGetFieldAccessorTable() {\n" + " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" + " .ensureFieldAccessorsInitialized(\n" + " $classname$.class, $classname$.Builder.class);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); +} + +// =================================================================== + +void MessageBuilderGenerator:: +GenerateCommonBuilderMethods(io::Printer* printer) { + printer->Print( + "// Construct using $classname$.newBuilder()\n" + "private Builder() {\n" + " maybeForceBuilderInitialization();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print( + "private Builder(\n" + " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " super(parent);\n" + " maybeForceBuilderInitialization();\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print( + "private void maybeForceBuilderInitialization() {\n" + " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n"); + + printer->Indent(); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateFieldBuilderInitializationCode(printer); + } + } + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + "}\n"); + + printer->Print( + "public Builder clear() {\n" + " super.clear();\n"); + + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderClearCode(printer); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "$oneof_name$Case_ = 0;\n" + "$oneof_name$_ = null;\n", + "oneof_name", context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); + } + + printer->Outdent(); + + printer->Print( + " return this;\n" + "}\n" + "\n"); + + printer->Print( + "public com.google.protobuf.Descriptors.Descriptor\n" + " getDescriptorForType() {\n" + " return $fileclass$.internal_$identifier$_descriptor;\n" + "}\n" + "\n", + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), + "identifier", UniqueFileScopeIdentifier(descriptor_)); + + // LITE runtime implements this in GeneratedMessageLite. + printer->Print( + "public $classname$ getDefaultInstanceForType() {\n" + " return $classname$.getDefaultInstance();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print( + "public $classname$ build() {\n" + " $classname$ result = buildPartial();\n" + " if (!result.isInitialized()) {\n" + " throw newUninitializedMessageException(result);\n" + " }\n" + " return result;\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print( + "public $classname$ buildPartial() {\n" + " $classname$ result = new $classname$(this);\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Indent(); + + int totalBuilderBits = 0; + int totalMessageBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const ImmutableFieldGenerator& field = + field_generators_.get(descriptor_->field(i)); + totalBuilderBits += field.GetNumBitsForBuilder(); + totalMessageBits += field.GetNumBitsForMessage(); + } + int totalBuilderInts = (totalBuilderBits + 31) / 32; + int totalMessageInts = (totalMessageBits + 31) / 32; + + if (GenerateHasBits(descriptor_)) { + // Local vars for from and to bit fields to avoid accessing the builder and + // message over and over for these fields. Seems to provide a slight + // perforamance improvement in micro benchmark and this is also what proto1 + // code does. + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("int to_$bit_field_name$ = 0;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + // Output generation code for each field. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); + } + + if (GenerateHasBits(descriptor_)) { + // Copy the bit field results to the generated message + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", + "oneof_name", context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); + } + + printer->Outdent(); + + printer->Print( + " onBuilt();\n"); + + printer->Print( + " return result;\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + // ----------------------------------------------------------------- + + if (HasGeneratedMethods(descriptor_)) { + printer->Print( + "public Builder mergeFrom(com.google.protobuf.Message other) {\n" + " if (other instanceof $classname$) {\n" + " return mergeFrom(($classname$)other);\n" + " } else {\n" + " super.mergeFrom(other);\n" + " return this;\n" + " }\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print( + "public Builder mergeFrom($classname$ other) {\n" + // Optimization: If other is the default instance, we know none of its + // fields are set so we can skip the merge. + " if (other == $classname$.getDefaultInstance()) return this;\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get( + descriptor_->field(i)).GenerateMergingCode(printer); + } + } + + // Merge oneof fields. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + printer->Print( + "switch (other.get$oneof_capitalized_name$Case()) {\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case $field_name$: {\n", + "field_name", + ToUpper(field->name())); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name)); + printer->Outdent(); + printer->Print( + "}\n"); + } + + printer->Outdent(); + + // if message type has extensions + if (descriptor_->extension_range_count() > 0) { + printer->Print( + " this.mergeExtensionFields(other);\n"); + } + + if (PreserveUnknownFields(descriptor_)) { + printer->Print( + " this.mergeUnknownFields(other.unknownFields);\n"); + } + + printer->Print( + " onChanged();\n"); + + printer->Print( + " return this;\n" + "}\n" + "\n"); + } +} + +// =================================================================== + +void MessageBuilderGenerator:: +GenerateBuilderParsingMethods(io::Printer* printer) { + printer->Print( + "public Builder mergeFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " $classname$ parsedMessage = null;\n" + " try {\n" + " parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);\n" + " } catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " parsedMessage = ($classname$) e.getUnfinishedMessage();\n" + " throw e;\n" + " } finally {\n" + " if (parsedMessage != null) {\n" + " mergeFrom(parsedMessage);\n" + " }\n" + " }\n" + " return this;\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); +} + +// =================================================================== + +void MessageBuilderGenerator::GenerateIsInitialized( + io::Printer* printer) { + printer->Print( + "public final boolean isInitialized() {\n"); + printer->Indent(); + + // Check that all required fields in this message are set. + // TODO(kenton): We can optimize this when we switch to putting all the + // "has" fields into a single bitfield. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + + if (field->is_required()) { + printer->Print( + "if (!has$name$()) {\n" + " return false;\n" + "}\n", + "name", info->capitalized_name); + } + } + + // Now check that all embedded messages are initialized. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + if (GetJavaType(field) == JAVATYPE_MESSAGE && + HasRequiredFields(field->message_type())) { + switch (field->label()) { + case FieldDescriptor::LABEL_REQUIRED: + printer->Print( + "if (!get$name$().isInitialized()) {\n" + " return false;\n" + "}\n", + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name); + break; + case FieldDescriptor::LABEL_OPTIONAL: + if (!SupportFieldPresence(descriptor_->file()) && + field->containing_oneof() != NULL) { + const OneofDescriptor* oneof = field->containing_oneof(); + const OneofGeneratorInfo* oneof_info = + context_->GetOneofGeneratorInfo(oneof); + printer->Print( + "if ($oneof_name$Case_ == $field_number$) {\n", + "oneof_name", oneof_info->name, + "field_number", SimpleItoa(field->number())); + } else { + printer->Print( + "if (has$name$()) {\n", + "name", info->capitalized_name); + } + printer->Print( + " if (!get$name$().isInitialized()) {\n" + " return false;\n" + " }\n" + "}\n", + "name", info->capitalized_name); + break; + case FieldDescriptor::LABEL_REPEATED: + if (IsMapEntry(field->message_type())) { + printer->Print( + "for ($type$ item : get$name$().values()) {\n" + " if (!item.isInitialized()) {\n" + " return false;\n" + " }\n" + "}\n", + "type", MapValueImmutableClassdName(field->message_type(), + name_resolver_), + "name", info->capitalized_name); + } else { + printer->Print( + "for (int i = 0; i < get$name$Count(); i++) {\n" + " if (!get$name$(i).isInitialized()) {\n" + " return false;\n" + " }\n" + "}\n", + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name); + } + break; + } + } + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "if (!extensionsAreInitialized()) {\n" + " return false;\n" + "}\n"); + } + + printer->Outdent(); + + printer->Print( + " return true;\n" + "}\n" + "\n"); +} + +// =================================================================== + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_message_builder.h b/src/google/protobuf/compiler/java/java_message_builder.h new file mode 100644 index 00000000..015ea062 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_message_builder.h @@ -0,0 +1,86 @@ +// 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. + +// Author: dweis@google.com (Daniel Weis) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class MessageBuilderGenerator { + public: + explicit MessageBuilderGenerator(const Descriptor* descriptor, + Context* context); + virtual ~MessageBuilderGenerator(); + + virtual void Generate(io::Printer* printer); + + private: + void GenerateCommonBuilderMethods(io::Printer* printer); + void GenerateDescriptorMethods(io::Printer* printer); + void GenerateBuilderParsingMethods(io::Printer* printer); + void GenerateIsInitialized(io::Printer* printer); + + const Descriptor* descriptor_; + Context* context_; + ClassNameResolver* name_resolver_; + FieldGeneratorMap field_generators_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__ diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.cc b/src/google/protobuf/compiler/java/java_message_builder_lite.cc new file mode 100644 index 00000000..8719d00d --- /dev/null +++ b/src/google/protobuf/compiler/java/java_message_builder_lite.cc @@ -0,0 +1,192 @@ +// 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. + +// Author: dweis@google.com (Daniel Weis) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include + +#include +#include +#include +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { +bool GenerateHasBits(const Descriptor* descriptor) { + return SupportFieldPresence(descriptor->file()) || + HasRepeatedFields(descriptor); +} + +string MapValueImmutableClassdName(const Descriptor* descriptor, + ClassNameResolver* name_resolver) { + const FieldDescriptor* value_field = descriptor->FindFieldByName("value"); + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); + return name_resolver->GetImmutableClassName(value_field->message_type()); +} +} // namespace + +MessageBuilderLiteGenerator::MessageBuilderLiteGenerator( + const Descriptor* descriptor, Context* context) + : descriptor_(descriptor), context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { + GOOGLE_CHECK_EQ( + FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for()); +} + +MessageBuilderLiteGenerator::~MessageBuilderLiteGenerator() {} + +void MessageBuilderLiteGenerator:: +Generate(io::Printer* printer) { + WriteMessageDocComment(printer, descriptor_); + printer->Print( + "public static final class Builder extends\n" + " com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n" + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_), + "extendible", + descriptor_->extension_range_count() > 0 ? "Extendable" : ""); + printer->Indent(); + + GenerateCommonBuilderMethods(printer); + + // oneof + map vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + + // oneofCase() and clearOneof() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + " get$oneof_capitalized_name$Case() {\n" + " return instance.get$oneof_capitalized_name$Case();\n" + "}\n" + "\n" + "public Builder clear$oneof_capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$oneof_capitalized_name$();\n" + " return this;\n" + "}\n" + "\n"); + } + + if (GenerateHasBits(descriptor_)) { + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForBuilder(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderMembers(printer); + } + + if (!PreserveUnknownFields(descriptor_)) { + printer->Print( + "public final Builder setUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return this;\n" + "}\n" + "\n" + "public final Builder mergeUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return this;\n" + "}\n" + "\n"); + } + + printer->Print( + "\n" + "// @@protoc_insertion_point(builder_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + printer->Outdent(); + printer->Print("}\n"); +} + +// =================================================================== + +void MessageBuilderLiteGenerator:: +GenerateCommonBuilderMethods(io::Printer* printer) { + printer->Print( + "// Construct using $classname$.newBuilder()\n" + "private Builder() {\n" + " super(DEFAULT_INSTANCE);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); +} + +// =================================================================== + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_message_builder_lite.h b/src/google/protobuf/compiler/java/java_message_builder_lite.h new file mode 100644 index 00000000..8597b2e6 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_message_builder_lite.h @@ -0,0 +1,83 @@ +// 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. + +// Author: dweis@google.com (Daniel Weis) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class MessageBuilderLiteGenerator { + public: + explicit MessageBuilderLiteGenerator(const Descriptor* descriptor, + Context* context); + virtual ~MessageBuilderLiteGenerator(); + + virtual void Generate(io::Printer* printer); + + private: + void GenerateCommonBuilderMethods(io::Printer* printer); + + const Descriptor* descriptor_; + Context* context_; + ClassNameResolver* name_resolver_; + FieldGeneratorMap field_generators_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index a2d12a38..b180b4a7 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -157,11 +157,9 @@ GenerateInterfaceMembers(io::Printer* printer) const { printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder();\n"); } void ImmutableMessageFieldGenerator:: @@ -182,14 +180,12 @@ GenerateMembers(io::Printer* printer) const { " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" "}\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "get$capitalized_name$OrBuilder() {\n" - " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" - "}\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder " + "get$capitalized_name$OrBuilder() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); } else { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -202,14 +198,12 @@ GenerateMembers(io::Printer* printer) const { " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" "}\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder " - "get$capitalized_name$OrBuilder() {\n" - " return get$capitalized_name$();\n" - "}\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder " + "get$capitalized_name$OrBuilder() {\n" + " return get$capitalized_name$();\n" + "}\n"); } } @@ -217,19 +211,15 @@ void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( io::Printer* printer, const char* regular_case, const char* nested_builder_case) const { - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, "if ($name$Builder_ == null) {\n"); - printer->Indent(); - printer->Print(variables_, regular_case); - printer->Outdent(); - printer->Print("} else {\n"); - printer->Indent(); - printer->Print(variables_, nested_builder_case); - printer->Outdent(); - printer->Print("}\n"); - } else { - printer->Print(variables_, regular_case); - } + printer->Print(variables_, "if ($name$Builder_ == null) {\n"); + printer->Indent(); + printer->Print(variables_, regular_case); + printer->Outdent(); + printer->Print("} else {\n"); + printer->Indent(); + printer->Print(variables_, nested_builder_case); + printer->Outdent(); + printer->Print("}\n"); } void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction( @@ -260,14 +250,12 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, "private $type$ $name$_ = null;\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, + printer->Print(variables_, // If this builder is non-null, it is used and the other fields are // ignored. "private com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" "\n"); - } // The comments above the methods below are based on a hypothetical // field of type "Field" called "Field". @@ -368,40 +356,38 @@ GenerateBuilderMembers(io::Printer* printer) const { "$clear_has_field_bit_builder$\n" "return this;\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " $set_has_field_bit_builder$\n" - " $on_changed$\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " return $name$_ == null ?\n" - " $type$.getDefaultInstance() : $name$_;\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " get$capitalized_name$(),\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " $set_has_field_bit_builder$\n" + " $on_changed$\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " return $name$_ == null ?\n" + " $type$.getDefaultInstance() : $name$_;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " get$capitalized_name$(),\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); } void ImmutableMessageFieldGenerator:: @@ -557,16 +543,14 @@ GenerateMembers(io::Printer* printer) const { " return $type$.getDefaultInstance();\n" "}\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" - "}\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); } void ImmutableMessageOneofFieldGenerator:: @@ -574,14 +558,12 @@ GenerateBuilderMembers(io::Printer* printer) const { // When using nested-builders, the code initially works just like the // non-nested builder case. It only creates a nested builder lazily on // demand and then forever delegates to it after creation. - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" - "\n"); - } + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); // The comments above the methods below are based on a hypothetical // field of type "Field" called "Field". @@ -683,45 +665,43 @@ GenerateBuilderMembers(io::Printer* printer) const { "return this;\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " return get$capitalized_name$FieldBuilder().getBuilder();\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" - " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n" - " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " if ($has_oneof_case_message$) {\n" - " return ($type$) $oneof_name$_;\n" - " }\n" - " return $type$.getDefaultInstance();\n" - " }\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "private com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " if (!($has_oneof_case_message$)) {\n" - " $oneof_name$_ = $type$.getDefaultInstance();\n" - " }\n" - " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " ($type$) $oneof_name$_,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $oneof_name$_ = null;\n" - " }\n" - " $set_oneof_case_message$;\n" - " $on_changed$;\n" - " return $name$Builder_;\n" - "}\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = $type$.getDefaultInstance();\n" + " }\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " ($type$) $oneof_name$_,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $oneof_name$_ = null;\n" + " }\n" + " $set_oneof_case_message$;\n" + " $on_changed$;\n" + " return $name$Builder_;\n" + "}\n"); } void ImmutableMessageOneofFieldGenerator:: @@ -831,16 +811,15 @@ GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$int get$capitalized_name$Count();\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$java.util.List \n" - " get$capitalized_name$OrBuilderList();\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index);\n"); - } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List \n" + " get$capitalized_name$OrBuilderList();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index);\n"); } void RepeatedImmutableMessageFieldGenerator:: @@ -882,19 +861,15 @@ void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition( io::Printer* printer, const char* regular_case, const char* nested_builder_case) const { - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, "if ($name$Builder_ == null) {\n"); - printer->Indent(); - printer->Print(variables_, regular_case); - printer->Outdent(); - printer->Print("} else {\n"); - printer->Indent(); - printer->Print(variables_, nested_builder_case); - printer->Outdent(); - printer->Print("}\n"); - } else { - printer->Print(variables_, regular_case); - } + printer->Print(variables_, "if ($name$Builder_ == null) {\n"); + printer->Indent(); + printer->Print(variables_, regular_case); + printer->Outdent(); + printer->Print("} else {\n"); + printer->Indent(); + printer->Print(variables_, nested_builder_case); + printer->Outdent(); + printer->Print("}\n"); } void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction( @@ -942,14 +917,12 @@ GenerateBuilderMembers(io::Printer* printer) const { "}\n" "\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - printer->Print(variables_, - // If this builder is non-null, it is used and the other fields are - // ignored. - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" - "\n"); - } + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" + "\n"); // The comments above the methods below are based on a hypothetical // repeated field of type "Field" called "RepeatedField". @@ -1116,70 +1089,68 @@ GenerateBuilderMembers(io::Printer* printer) const { "return this;\n"); - if (HasNestedBuilders(descriptor_->containing_type())) { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" - "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" - " int index) {\n" - " if ($name$Builder_ == null) {\n" - " return $name$_.get(index);" - " } else {\n" - " return $name$Builder_.getMessageOrBuilder(index);\n" - " }\n" - "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " if ($name$Builder_ == null) {\n" + " return $name$_.get(index);" + " } else {\n" + " return $name$Builder_.getMessageOrBuilder(index);\n" + " }\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List \n" - " get$capitalized_name$OrBuilderList() {\n" - " if ($name$Builder_ != null) {\n" - " return $name$Builder_.getMessageOrBuilderList();\n" - " } else {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" - " }\n" - "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilderList();\n" + " } else {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + " }\n" + "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" - " int index) {\n" - " return get$capitalized_name$FieldBuilder().addBuilder(\n" - " index, $type$.getDefaultInstance());\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public java.util.List<$type$.Builder> \n" - " get$capitalized_name$BuilderList() {\n" - " return get$capitalized_name$FieldBuilder().getBuilderList();\n" - "}\n" - "private com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder> \n" - " get$capitalized_name$FieldBuilder() {\n" - " if ($name$Builder_ == null) {\n" - " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" - " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" - " $get_mutable_bit_builder$,\n" - " getParentForChildren(),\n" - " isClean());\n" - " $name$_ = null;\n" - " }\n" - " return $name$Builder_;\n" - "}\n"); - } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " index, $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$.Builder> \n" + " get$capitalized_name$BuilderList() {\n" + " return get$capitalized_name$FieldBuilder().getBuilderList();\n" + "}\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " $get_mutable_bit_builder$,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); } void RepeatedImmutableMessageFieldGenerator:: diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.cc b/src/google/protobuf/compiler/java/java_message_field_lite.cc new file mode 100644 index 00000000..8332202c --- /dev/null +++ b/src/google/protobuf/compiler/java/java_message_field_lite.cc @@ -0,0 +1,944 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { + +void SetMessageVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, + map* variables) { + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["type"] = + name_resolver->GetImmutableClassName(descriptor->message_type()); + (*variables)["mutable_type"] = + name_resolver->GetMutableClassName(descriptor->message_type()); + (*variables)["group_or_message"] = + (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? + "Group" : "Message"; + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["clear_has_field_bit_message"] = + GenerateClearBit(messageBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["clear_has_field_bit_message"] = ""; + + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != null"; + } + + // For repeated builders, the underlying list tracks mutability state. + (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +} // namespace + +// =================================================================== + +ImmutableMessageFieldLiteGenerator:: +ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {} + +int ImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const { + return 1; +} + +int ImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + // TODO(jonp): In the future, consider having a method specific to the + // interface so that builders can choose dynamically to either return a + // message or a nested builder, so that asking for the interface doesn't + // cause a message to ever be built. + if (SupportFieldPresence(descriptor_->file()) || + descriptor_->containing_oneof() == NULL) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $type$ $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); + } else { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $name$_ != null;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); + } + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $name$_ = value;\n" + " $set_has_field_bit_message$\n" + " }\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " $name$_ = builderForValue.build();\n" + " $set_has_field_bit_message$\n" + "}\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void merge$capitalized_name$($type$ value) {\n" + " if ($name$_ != null &&\n" + " $name$_ != $type$.getDefaultInstance()) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + " } else {\n" + " $name$_ = value;\n" + " }\n" + " $set_has_field_bit_message$\n" + "}\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {" + " $name$_ = null;\n" + " $clear_has_field_bit_message$\n" + "}\n"); +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + + // Field getField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + " }\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(builderForValue);\n" + " return this;\n" + "}\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.merge$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); + } +} + + +void ImmutableMessageFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const {} + +void ImmutableMessageFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " merge$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + // noop for scalars +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$type$.Builder subBuilder = null;\n" + "if ($is_field_present_message$) {\n" + " subBuilder = $name$_.toBuilder();\n" + "}\n"); + + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "$name$_ = input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry);\n"); + } else { + printer->Print(variables_, + "$name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + } + + printer->Print(variables_, + "if (subBuilder != null) {\n" + " subBuilder.mergeFrom($name$_);\n" + " $name$_ = subBuilder.buildPartial();\n" + "}\n" + "$set_has_field_bit_message$\n"); +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for messages. +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " output.write$group_or_message$($number$, get$capitalized_name$());\n" + "}\n"); +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, get$capitalized_name$());\n" + "}\n"); +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); +} + +void ImmutableMessageFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n" + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); +} + +string ImmutableMessageFieldLiteGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->message_type()); +} + +// =================================================================== + +ImmutableMessageOneofFieldLiteGenerator:: +ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableMessageFieldLiteGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutableMessageOneofFieldLiteGenerator:: +~ImmutableMessageOneofFieldLiteGenerator() {} + +void ImmutableMessageOneofFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $oneof_name$_ = value;\n" + " $set_oneof_case_message$;\n" + "}\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " $oneof_name$_ = builderForValue.build();\n" + " $set_oneof_case_message$;\n" + "}\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void merge$capitalized_name$($type$ value) {\n" + " if ($has_oneof_case_message$ &&\n" + " $oneof_name$_ != $type$.getDefaultInstance()) {\n" + " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" + " .mergeFrom(value).buildPartial();\n" + " } else {\n" + " $oneof_name$_ = value;\n" + " }\n" + " $set_oneof_case_message$;\n" + "}\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); +} + +void ImmutableMessageOneofFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + if (SupportFieldPresence(descriptor_->file())) { + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + } + + // Field getField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(builderForValue);\n" + " return this;\n" + "}\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder merge$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.merge$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + +void ImmutableMessageOneofFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "merge$capitalized_name$(other.get$capitalized_name$());\n"); +} + +void ImmutableMessageOneofFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$type$.Builder subBuilder = null;\n" + "if ($has_oneof_case_message$) {\n" + " subBuilder = (($type$) $oneof_name$_).toBuilder();\n" + "}\n"); + + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry);\n"); + } else { + printer->Print(variables_, + "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + } + + printer->Print(variables_, + "if (subBuilder != null) {\n" + " subBuilder.mergeFrom(($type$) $oneof_name$_);\n" + " $oneof_name$_ = subBuilder.buildPartial();\n" + "}\n"); + printer->Print(variables_, + "$set_oneof_case_message$;\n"); +} + +void ImmutableMessageOneofFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n" + "}\n"); +} + +void ImmutableMessageOneofFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutableMessageFieldLiteGenerator:: +RepeatedImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +RepeatedImmutableMessageFieldLiteGenerator:: +~RepeatedImmutableMessageFieldLiteGenerator() {} + +int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedImmutableMessageFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + // TODO(jonp): In the future, consider having methods specific to the + // interface so that builders can choose dynamically to either return a + // message or a nested builder, so that asking for the interface doesn't + // cause a message to ever be built. + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$type$> \n" + " get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " return $name$_;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$is_mutable$) {\n" + " $name$_ = newProtobufList($name$_);\n" + " }\n" + "}\n" + "\n"); + + // Builder setRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + "}\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, builderForValue.build());\n" + "}\n"); + + // Builder addRepeatedField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + "}\n"); + + // Builder addRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$(\n" + " int index, $type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(index, value);\n" + "}\n"); + // Builder addRepeatedField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(builderForValue.build());\n" + "}\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(index, builderForValue.build());\n" + "}\n"); + + // Builder addAllRepeatedField(Iterable values) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.addAll(\n" + " values, $name$_);\n" + "}\n"); + + // Builder clearAllRepeatedField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_ = emptyProtobufList();\n" + "}\n"); + + // Builder removeRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void remove$capitalized_name$(int index) {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.remove(index);\n" + "}\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // The comments above the methods below are based on a hypothetical + // repeated field of type "Field" called "RepeatedField". + + // List getRepeatedFieldList() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$List());\n" + "}\n"); + + // int getRepeatedFieldCount() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return instance.get$capitalized_name$Count();\n" + "}"); + + // Field getRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); + + // Builder setRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, builderForValue);\n" + " return this;\n" + "}\n"); + + // Builder addRepeatedField(Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + // Builder addRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); + // Builder addRepeatedField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(builderForValue);\n" + " return this;\n" + "}\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(index, builderForValue);\n" + " return this;\n" + "}\n"); + + // Builder addAllRepeatedField(Iterable values) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);\n" + " return this;\n" + "}\n"); + + // Builder clearAllRepeatedField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); + + // Builder removeRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder remove$capitalized_name$(int index) {\n" + " copyOnWrite();\n" + " instance.remove$capitalized_name$(index);\n" + " return this;\n" + "}\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = emptyProtobufList();\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations (non-nested builder case): + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_.makeImmutable();\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!$is_mutable$) {\n" + " $name$_ = newProtobufList();\n" + "}\n"); + + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "$name$_.add(input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry));\n"); + } else { + printer->Print(variables_, + "$name$_.add(input.readMessage($type$.PARSER, extensionRegistry));\n"); + } +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_mutable$) {\n" + " $name$_.makeImmutable();\n" + "}\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$group_or_message$($number$, $name$_.get(i));\n" + "}\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, $name$_.get(i));\n" + "}\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedImmutableMessageFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedImmutableMessageFieldLiteGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->message_type()); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_message_field_lite.h b/src/google/protobuf/compiler/java/java_message_field_lite.h new file mode 100644 index 00000000..ae26c06a --- /dev/null +++ b/src/google/protobuf/compiler/java/java_message_field_lite.h @@ -0,0 +1,157 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableMessageFieldLiteGenerator : public ImmutableFieldLiteGenerator { + public: + explicit ImmutableMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableMessageFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + protected: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldLiteGenerator); +}; + +class ImmutableMessageOneofFieldLiteGenerator + : public ImmutableMessageFieldLiteGenerator { + public: + ImmutableMessageOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableMessageOneofFieldLiteGenerator(); + + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator); +}; + +class RepeatedImmutableMessageFieldLiteGenerator + : public ImmutableFieldLiteGenerator { + public: + explicit RepeatedImmutableMessageFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableMessageFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + protected: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldLiteGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_message_lite.cc b/src/google/protobuf/compiler/java/java_message_lite.cc new file mode 100644 index 00000000..3accee92 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_message_lite.cc @@ -0,0 +1,1174 @@ +// 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. + +// Author: dweis@google.com (Daniel Weis) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include + +#include +#include +#include +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { +bool GenerateHasBits(const Descriptor* descriptor) { + return SupportFieldPresence(descriptor->file()) || + HasRepeatedFields(descriptor); +} + +string MapValueImmutableClassdName(const Descriptor* descriptor, + ClassNameResolver* name_resolver) { + const FieldDescriptor* value_field = descriptor->FindFieldByName("value"); + GOOGLE_CHECK_EQ(FieldDescriptor::TYPE_MESSAGE, value_field->type()); + return name_resolver->GetImmutableClassName(value_field->message_type()); +} +} // namespace + +// =================================================================== +ImmutableMessageLiteGenerator::ImmutableMessageLiteGenerator( + const Descriptor* descriptor, Context* context) + : MessageGenerator(descriptor), context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { + GOOGLE_CHECK_EQ( + FileOptions::LITE_RUNTIME, descriptor->file()->options().optimize_for()); +} + +ImmutableMessageLiteGenerator::~ImmutableMessageLiteGenerator() {} + +void ImmutableMessageLiteGenerator::GenerateStaticVariables( + io::Printer* printer) { + // Generate static members for all nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) + .GenerateStaticVariables(printer); + } +} + +int ImmutableMessageLiteGenerator::GenerateStaticVariableInitializers( + io::Printer* printer) { + int bytecode_estimate = 0; + // Generate static member initializers for all nested types. + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // TODO(kenton): Reuse MessageGenerator objects? + bytecode_estimate += + ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) + .GenerateStaticVariableInitializers(printer); + } + return bytecode_estimate; +} + +// =================================================================== + +void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) { + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "public interface $classname$OrBuilder extends \n" + " $extra_interfaces$\n" + " com.google.protobuf.GeneratedMessageLite.\n" + " ExtendableMessageOrBuilder<\n" + " $classname$, $classname$.Builder> {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), + "classname", descriptor_->name()); + } else { + printer->Print( + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageLiteOrBuilder {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), + "classname", descriptor_->name()); + } + + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\n"); + field_generators_.get(descriptor_->field(i)) + .GenerateInterfaceMembers(printer); + } + printer->Outdent(); + + printer->Print("}\n"); +} + +// =================================================================== + +void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) { + bool is_own_file = + descriptor_->containing_type() == NULL && + MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); + + map variables; + variables["static"] = is_own_file ? " " : " static "; + variables["classname"] = descriptor_->name(); + variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); + + WriteMessageDocComment(printer, descriptor_); + + // The builder_type stores the super type name of the nested Builder class. + string builder_type; + if (descriptor_->extension_range_count() > 0) { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + builder_type = strings::Substitute( + "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print(variables, + "public $static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite<\n" + " $classname$, $classname$.Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n"); + + builder_type = "com.google.protobuf.GeneratedMessageLite.Builder"; + } + printer->Indent(); + + GenerateParsingConstructor(printer); + + // Nested types + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + EnumGenerator(descriptor_->enum_type(i), true, context_) + .Generate(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + // Don't generate Java classes for map entry messages. + if (IsMapEntry(descriptor_->nested_type(i))) continue; + ImmutableMessageLiteGenerator messageGenerator( + descriptor_->nested_type(i), context_); + messageGenerator.GenerateInterface(printer); + messageGenerator.Generate(printer); + } + + if (GenerateHasBits(descriptor_)) { + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForMessage(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + // oneof + map vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // OneofCase enum + printer->Print(vars, + "public enum $oneof_capitalized_name$Case\n" + " implements com.google.protobuf.Internal.EnumLite {\n"); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "$field_name$($field_number$),\n", + "field_name", + ToUpper(field->name()), + "field_number", + SimpleItoa(field->number())); + } + printer->Print( + "$cap_oneof_name$_NOT_SET(0);\n", + "cap_oneof_name", + ToUpper(vars["oneof_name"])); + printer->Print(vars, + "private int value = 0;\n" + "private $oneof_capitalized_name$Case(int value) {\n" + " this.value = value;\n" + "}\n"); + printer->Print(vars, + "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " switch (value) {\n"); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + " case $field_number$: return $field_name$;\n", + "field_number", + SimpleItoa(field->number()), + "field_name", + ToUpper(field->name())); + } + printer->Print( + " case 0: return $cap_oneof_name$_NOT_SET;\n" + " default: throw new java.lang.IllegalArgumentException(\n" + " \"Value is undefined for this oneof enum.\");\n" + " }\n" + "}\n" + "public int getNumber() {\n" + " return this.value;\n" + "}\n", + "cap_oneof_name", ToUpper(vars["oneof_name"])); + printer->Outdent(); + printer->Print("};\n\n"); + // oneofCase() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + "get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.valueOf(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n" + "private void clear$oneof_capitalized_name$() {\n" + " $oneof_name$Case_ = 0;\n" + " $oneof_name$_ = null;\n" + "}\n" + "\n"); + } + + // Fields + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("public static final int $constant_name$ = $number$;\n", + "constant_name", FieldConstantName(descriptor_->field(i)), + "number", SimpleItoa(descriptor_->field(i)->number())); + field_generators_.get(descriptor_->field(i)).GenerateMembers(printer); + printer->Print("\n"); + } + + GenerateMessageSerializationMethods(printer); + + if (HasEqualsAndHashCode(descriptor_)) { + GenerateEqualsAndHashCode(printer); + } + + + GenerateParseFromMethods(printer); + GenerateBuilder(printer); + + if (HasRequiredFields(descriptor_)) { + // Memoizes whether the protocol buffer is fully initialized (has all + // required fields). -1 means not yet computed. 0 means false and 1 means + // true. + printer->Print( + "private byte memoizedIsInitialized = -1;\n"); + } + + printer->Print( + "protected final Object dynamicMethod(\n" + " com.google.protobuf.GeneratedMessageLite.MethodToInvoke method,\n" + " Object... args) {\n" + " switch (method) {\n" + " case PARSE_PARTIAL_FROM: {\n" + " return new $classname$(" + " (com.google.protobuf.CodedInputStream) args[0],\n" + " (com.google.protobuf.ExtensionRegistryLite) args[1]);\n" + " }\n" + " case NEW_INSTANCE: {\n" + " return new $classname$(\n" + " com.google.protobuf.Internal.EMPTY_CODED_INPUT_STREAM,\n" + " com.google.protobuf.ExtensionRegistryLite\n" + " .getEmptyRegistry());\n" + " }\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Indent(); + printer->Indent(); + + printer->Print( + "case IS_INITIALIZED: {\n"); + printer->Indent(); + GenerateDynamicMethodIsInitialized(printer); + printer->Outdent(); + + printer->Print( + "}\n" + "case MAKE_IMMUTABLE: {\n"); + + printer->Indent(); + GenerateDynamicMethodMakeImmutable(printer); + printer->Outdent(); + + printer->Print( + "}\n" + "case NEW_BUILDER: {\n"); + + printer->Indent(); + GenerateDynamicMethodNewBuilder(printer); + printer->Outdent(); + + printer->Print( + "}\n" + "case MERGE_FROM: {\n"); + + printer->Indent(); + GenerateDynamicMethodMergeFrom(printer); + printer->Outdent(); + + printer->Print( + "}\n"); + + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + " throw new UnsupportedOperationException();\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print( + "\n" + "// @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", descriptor_->full_name()); + + + // Carefully initialize the default instance in such a way that it doesn't + // conflict with other initialization. + printer->Print( + "private static final $classname$ DEFAULT_INSTANCE;\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print( + "static {\n" + " DEFAULT_INSTANCE = new $classname$(\n" + " com.google.protobuf.Internal\n" + " .EMPTY_CODED_INPUT_STREAM,\n" + " com.google.protobuf.ExtensionRegistryLite\n" + " .getEmptyRegistry());\n" + "}\n" + "\n", + "classname", descriptor_->name()); + printer->Print( + "public static $classname$ getDefaultInstance() {\n" + " return DEFAULT_INSTANCE;\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + GenerateParser(printer); + + // LITE_RUNTIME uses this to implement the *ForType methods at the + // GeneratedMessageLite level. + printer->Print( + "static {\n" + " com.google.protobuf.GeneratedMessageLite.onLoad(\n" + " $classname$.class, new com.google.protobuf.GeneratedMessageLite\n" + " .PrototypeHolder<$classname$, Builder>(\n" + " DEFAULT_INSTANCE, PARSER));" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + // Extensions must be declared after the DEFAULT_INSTANCE is initialized + // because the DEFAULT_INSTANCE is used by the extension to lazily retrieve + // the outer class's FileDescriptor. + for (int i = 0; i < descriptor_->extension_count(); i++) { + ImmutableExtensionGenerator(descriptor_->extension(i), context_) + .Generate(printer); + } + + printer->Outdent(); + printer->Print("}\n\n"); +} + +// =================================================================== + +void ImmutableMessageLiteGenerator:: +GenerateMessageSerializationMethods(io::Printer* printer) { + google::protobuf::scoped_array sorted_fields( + SortFieldsByNumber(descriptor_)); + + vector sorted_extensions; + 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()); + + printer->Print( + "public void writeTo(com.google.protobuf.CodedOutputStream output)\n" + " throws java.io.IOException {\n"); + printer->Indent(); + if (HasPackedFields(descriptor_)) { + // writeTo(CodedOutputStream output) might be invoked without + // getSerializedSize() ever being called, but we need the memoized + // sizes in case this message has packed fields. Rather than emit checks for + // each packed field, just call getSerializedSize() up front. + // In most cases, getSerializedSize() will have already been called anyway + // by one of the wrapper writeTo() methods, making this call cheap. + printer->Print( + "getSerializedSize();\n"); + } + + if (descriptor_->extension_range_count() > 0) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newMessageSetExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } else { + printer->Print( + "com.google.protobuf.GeneratedMessageLite\n" + " .ExtendableMessage<$classname$, $classname$.Builder>\n" + " .ExtensionWriter extensionWriter =\n" + " newExtensionWriter();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } + } + + // Merge the fields and the extension ranges, both sorted by field number. + for (int i = 0, j = 0; + i < descriptor_->field_count() || j < sorted_extensions.size(); + ) { + if (i == descriptor_->field_count()) { + GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); + } else if (j == sorted_extensions.size()) { + GenerateSerializeOneField(printer, sorted_fields[i++]); + } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) { + GenerateSerializeOneField(printer, sorted_fields[i++]); + } else { + GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]); + } + } + + if (PreserveUnknownFields(descriptor_)) { + printer->Print( + "unknownFields.writeTo(output);\n"); + } + + printer->Outdent(); + printer->Print( + "}\n" + "\n" + "public int getSerializedSize() {\n" + " int size = memoizedSerializedSize;\n" + " if (size != -1) return size;\n" + "\n" + " size = 0;\n"); + printer->Indent(); + + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]).GenerateSerializedSizeCode(printer); + } + + if (descriptor_->extension_range_count() > 0) { + if (descriptor_->options().message_set_wire_format()) { + printer->Print( + "size += extensionsSerializedSizeAsMessageSet();\n"); + } else { + printer->Print( + "size += extensionsSerializedSize();\n"); + } + } + + if (PreserveUnknownFields(descriptor_)) { + printer->Print( + "size += unknownFields.getSerializedSize();\n"); + } + + printer->Outdent(); + printer->Print( + " memoizedSerializedSize = size;\n" + " return size;\n" + "}\n" + "\n"); + + printer->Print( + "private static final long serialVersionUID = 0L;\n"); +} + +void ImmutableMessageLiteGenerator:: +GenerateParseFromMethods(io::Printer* printer) { + // Note: These are separate from GenerateMessageSerializationMethods() + // because they need to be generated even for messages that are optimized + // for code size. + printer->Print( + "public static $classname$ parseFrom(\n" + " com.google.protobuf.ByteString data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.ByteString data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(byte[] data)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " byte[] data,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws com.google.protobuf.InvalidProtocolBufferException {\n" + " return PARSER.parseFrom(data, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(java.io.InputStream input)\n" + " throws java.io.IOException {\n" + " return PARSER.parseFrom(input);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " java.io.InputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return PARSER.parseFrom(input, extensionRegistry);\n" + "}\n" + "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" + " throws java.io.IOException {\n" + " return PARSER.parseDelimitedFrom(input);\n" + "}\n" + "public static $classname$ parseDelimitedFrom(\n" + " java.io.InputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return PARSER.parseDelimitedFrom(input, extensionRegistry);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.CodedInputStream input)\n" + " throws java.io.IOException {\n" + " return PARSER.parseFrom(input);\n" + "}\n" + "public static $classname$ parseFrom(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry)\n" + " throws java.io.IOException {\n" + " return PARSER.parseFrom(input, extensionRegistry);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); +} + +void ImmutableMessageLiteGenerator::GenerateSerializeOneField( + io::Printer* printer, const FieldDescriptor* field) { + field_generators_.get(field).GenerateSerializationCode(printer); +} + +void ImmutableMessageLiteGenerator::GenerateSerializeOneExtensionRange( + io::Printer* printer, const Descriptor::ExtensionRange* range) { + printer->Print( + "extensionWriter.writeUntil($end$, output);\n", + "end", SimpleItoa(range->end)); +} + +// =================================================================== + +void ImmutableMessageLiteGenerator::GenerateBuilder(io::Printer* printer) { + printer->Print( + "public static Builder newBuilder() {\n" + " return DEFAULT_INSTANCE.toBuilder();\n" + "}\n" + "public static Builder newBuilder($classname$ prototype) {\n" + " return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);\n" + "}\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + MessageBuilderLiteGenerator builderGenerator(descriptor_, context_); + builderGenerator.Generate(printer); +} + +// =================================================================== + +void ImmutableMessageLiteGenerator::GenerateDynamicMethodIsInitialized( + io::Printer* printer) { + // Returns null for false, DEFAULT_INSTANCE for true. + if (!HasRequiredFields(descriptor_)) { + printer->Print("return DEFAULT_INSTANCE;\n"); + return; + } + + // Don't directly compare to -1 to avoid an Android x86 JIT bug. + printer->Print( + "byte isInitialized = memoizedIsInitialized;\n" + "if (isInitialized == 1) return DEFAULT_INSTANCE;\n" + "if (isInitialized == 0) return null;\n" + "\n" + "boolean shouldMemoize = ((Boolean) args[0]).booleanValue();\n"); + + // Check that all required fields in this message are set. + // TODO(kenton): We can optimize this when we switch to putting all the + // "has" fields into a single bitfield. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + + if (field->is_required()) { + printer->Print( + "if (!has$name$()) {\n" + " if (shouldMemoize) {\n" + " memoizedIsInitialized = 0;\n" + " }\n" + " return null;\n" + "}\n", + "name", info->capitalized_name); + } + } + + // Now check that all embedded messages are initialized. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + if (GetJavaType(field) == JAVATYPE_MESSAGE && + HasRequiredFields(field->message_type())) { + switch (field->label()) { + case FieldDescriptor::LABEL_REQUIRED: + printer->Print( + "if (!get$name$().isInitialized()) {\n" + " if (shouldMemoize) {\n" + " memoizedIsInitialized = 0;\n" + " }\n" + " return null;\n" + "}\n", + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name); + break; + case FieldDescriptor::LABEL_OPTIONAL: + if (!SupportFieldPresence(descriptor_->file()) && + field->containing_oneof() != NULL) { + const OneofDescriptor* oneof = field->containing_oneof(); + const OneofGeneratorInfo* oneof_info = + context_->GetOneofGeneratorInfo(oneof); + printer->Print( + "if ($oneof_name$Case_ == $field_number$) {\n", + "oneof_name", oneof_info->name, + "field_number", SimpleItoa(field->number())); + } else { + printer->Print( + "if (has$name$()) {\n", + "name", info->capitalized_name); + } + printer->Print( + " if (!get$name$().isInitialized()) {\n" + " if (shouldMemoize) {\n" + " memoizedIsInitialized = 0;\n" + " }\n" + " return null;\n" + " }\n" + "}\n", + "name", info->capitalized_name); + break; + case FieldDescriptor::LABEL_REPEATED: + if (IsMapEntry(field->message_type())) { + printer->Print( + "for ($type$ item : get$name$().values()) {\n" + " if (!item.isInitialized()) {\n" + " if (shouldMemoize) {\n" + " memoizedIsInitialized = 0;\n" + " }\n" + " return null;\n" + " }\n" + "}\n", + "type", MapValueImmutableClassdName(field->message_type(), + name_resolver_), + "name", info->capitalized_name); + } else { + printer->Print( + "for (int i = 0; i < get$name$Count(); i++) {\n" + " if (!get$name$(i).isInitialized()) {\n" + " if (shouldMemoize) {\n" + " memoizedIsInitialized = 0;\n" + " }\n" + " return null;\n" + " }\n" + "}\n", + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name); + } + break; + } + } + } + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "if (!extensionsAreInitialized()) {\n" + " if (shouldMemoize) {\n" + " memoizedIsInitialized = 0;\n" + " }\n" + " return null;\n" + "}\n"); + } + + printer->Print( + "if (shouldMemoize) memoizedIsInitialized = 1;\n"); + + printer->Print( + "return DEFAULT_INSTANCE;\n" + "\n"); +} + +// =================================================================== + +void ImmutableMessageLiteGenerator::GenerateDynamicMethodMakeImmutable( + io::Printer* printer) { + // Output generation code for each field. + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateDynamicMethodMakeImmutableCode(printer); + } + printer->Print( + "return null;"); +} + +// =================================================================== + +void ImmutableMessageLiteGenerator::GenerateDynamicMethodNewBuilder( + io::Printer* printer) { + printer->Print( + "return new Builder();"); +} + +// =================================================================== + +void ImmutableMessageLiteGenerator::GenerateDynamicMethodMergeFrom( + io::Printer* printer) { + printer->Print( + // Optimization: If other is the default instance, we know none of its + // fields are set so we can skip the merge. + "Object arg = args[0];\n" + "if (arg == $classname$.getDefaultInstance()) return this;\n" + "$classname$ other = ($classname$) arg;\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get( + descriptor_->field(i)).GenerateMergingCode(printer); + } + } + + // Merge oneof fields. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + printer->Print( + "switch (other.get$oneof_capitalized_name$Case()) {\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case $field_name$: {\n", + "field_name", + ToUpper(field->name())); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name)); + printer->Outdent(); + printer->Print( + "}\n"); + } + + // if message type has extensions + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "this.mergeExtensionFields(other);\n"); + } + + if (PreserveUnknownFields(descriptor_)) { + printer->Print( + "this.mergeUnknownFields(other.unknownFields);\n"); + } + + printer->Print( + "return this;\n"); +} + +// =================================================================== + +namespace { +bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { + if (field->is_repeated()) { + return false; + } + if (SupportFieldPresence(field->file())) { + return true; + } + return GetJavaType(field) == JAVATYPE_MESSAGE && + field->containing_oneof() == NULL; +} +} // namespace + +void ImmutableMessageLiteGenerator:: +GenerateEqualsAndHashCode(io::Printer* printer) { + printer->Print( + "@java.lang.Override\n" + "public boolean equals(final java.lang.Object obj) {\n"); + printer->Indent(); + printer->Print( + "if (obj == this) {\n" + " return true;\n" + "}\n" + "if (!(obj instanceof $classname$)) {\n" + " return super.equals(obj);\n" + "}\n" + "$classname$ other = ($classname$) obj;\n" + "\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + printer->Print("boolean result = true;\n"); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); + if (check_has_bits) { + printer->Print( + "result = result && (has$name$() == other.has$name$());\n" + "if (has$name$()) {\n", + "name", info->capitalized_name); + printer->Indent(); + } + field_generators_.get(field).GenerateEqualsCode(printer); + if (check_has_bits) { + printer->Outdent(); + printer->Print( + "}\n"); + } + } + if (PreserveUnknownFields(descriptor_)) { + // Always consider unknown fields for equality. This will sometimes return + // false for non-canonical ordering when running in LITE_RUNTIME but it's + // the best we can do. + printer->Print( + "result = result && unknownFields.equals(other.unknownFields);\n"); + } + printer->Print( + "return result;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + + printer->Print( + "@java.lang.Override\n" + "public int hashCode() {\n"); + printer->Indent(); + printer->Print( + "if (memoizedHashCode != 0) {\n"); + printer->Indent(); + printer->Print( + "return memoizedHashCode;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "int hash = 41;\n"); + + // Include the hash of the class so that two objects with different types + // but the same field values will probably have different hashes. + printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); + if (check_has_bits) { + printer->Print( + "if (has$name$()) {\n", + "name", info->capitalized_name); + printer->Indent(); + } + field_generators_.get(field).GenerateHashCode(printer); + if (check_has_bits) { + printer->Outdent(); + printer->Print("}\n"); + } + } + + printer->Print( + "hash = (29 * hash) + unknownFields.hashCode();\n"); + printer->Print( + "memoizedHashCode = hash;\n" + "return hash;\n"); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); +} + +// =================================================================== + +void ImmutableMessageLiteGenerator:: +GenerateExtensionRegistrationCode(io::Printer* printer) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + ImmutableExtensionGenerator(descriptor_->extension(i), context_) + .GenerateRegistrationCode(printer); + } + + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + ImmutableMessageLiteGenerator(descriptor_->nested_type(i), context_) + .GenerateExtensionRegistrationCode(printer); + } +} + +// =================================================================== +void ImmutableMessageLiteGenerator:: +GenerateParsingConstructor(io::Printer* printer) { + google::protobuf::scoped_array sorted_fields( + SortFieldsByNumber(descriptor_)); + + printer->Print( + "private $classname$(\n" + " com.google.protobuf.CodedInputStream input,\n" + " com.google.protobuf.ExtensionRegistryLite extensionRegistry) {\n", + "classname", descriptor_->name()); + printer->Indent(); + + // Initialize all fields to default. + GenerateInitializers(printer); + + // Use builder bits to track mutable repeated fields. + int totalBuilderBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + const ImmutableFieldLiteGenerator& field = + field_generators_.get(descriptor_->field(i)); + totalBuilderBits += field.GetNumBitsForBuilder(); + } + int totalBuilderInts = (totalBuilderBits + 31) / 32; + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("int mutable_$bit_field_name$ = 0;\n", + "bit_field_name", GetBitFieldName(i)); + } + + if (PreserveUnknownFields(descriptor_)) { + printer->Print( + "com.google.protobuf.UnknownFieldSetLite.Builder unknownFields =\n" + " com.google.protobuf.UnknownFieldSetLite.newBuilder();\n"); + } + + printer->Print( + "try {\n"); + printer->Indent(); + + printer->Print( + "boolean done = false;\n" + "while (!done) {\n"); + printer->Indent(); + + printer->Print( + "int tag = input.readTag();\n" + "switch (tag) {\n"); + printer->Indent(); + + printer->Print( + "case 0:\n" // zero signals EOF / limit reached + " done = true;\n" + " break;\n"); + + if (PreserveUnknownFields(descriptor_)) { + if (descriptor_->extension_range_count() > 0) { + // Lite runtime directly invokes parseUnknownField to reduce method + // counts. + printer->Print( + "default: {\n" + " if (!parseUnknownField(extensions, getDefaultInstanceForType(),\n" + " input, unknownFields,\n" + " extensionRegistry, tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } else { + printer->Print( + "default: {\n" + " if (!parseUnknownField(input, unknownFields,\n" + " extensionRegistry, tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } + } else { + printer->Print( + "default: {\n" + " if (!input.skipField(tag)) {\n" + " done = true;\n" // it's an endgroup tag + " }\n" + " break;\n" + "}\n"); + } + + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = sorted_fields[i]; + uint32 tag = WireFormatLite::MakeTag(field->number(), + WireFormat::WireTypeForFieldType(field->type())); + + printer->Print( + "case $tag$: {\n", + "tag", SimpleItoa(tag)); + printer->Indent(); + + field_generators_.get(field).GenerateParsingCode(printer); + + printer->Outdent(); + printer->Print( + " break;\n" + "}\n"); + + if (field->is_packable()) { + // To make packed = true wire compatible, we generate parsing code from a + // packed version of this field regardless of field->options().packed(). + uint32 packed_tag = WireFormatLite::MakeTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + printer->Print( + "case $tag$: {\n", + "tag", SimpleItoa(packed_tag)); + printer->Indent(); + + field_generators_.get(field).GenerateParsingCodeFromPacked(printer); + + printer->Outdent(); + printer->Print( + " break;\n" + "}\n"); + } + } + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" // switch (tag) + "}\n"); // while (!done) + + printer->Outdent(); + printer->Print( + "} catch (com.google.protobuf.InvalidProtocolBufferException e) {\n" + " throw new RuntimeException(e.setUnfinishedMessage(this));\n" + "} catch (java.io.IOException e) {\n" + " throw new RuntimeException(\n" + " new com.google.protobuf.InvalidProtocolBufferException(\n" + " e.getMessage()).setUnfinishedMessage(this));\n" + "} finally {\n"); + printer->Indent(); + + // Make repeated field list immutable. + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = sorted_fields[i]; + field_generators_.get(field).GenerateParsingDoneCode(printer); + } + + if (PreserveUnknownFields(descriptor_)) { + // Make unknown fields immutable. + printer->Print("this.unknownFields = unknownFields.build();\n"); + } + + if (descriptor_->extension_range_count() > 0) { + // Make extensions immutable. + printer->Print( + "makeExtensionsImmutable(extensions);\n"); + } + + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" // finally + "}\n"); +} + +// =================================================================== +void ImmutableMessageLiteGenerator::GenerateParser(io::Printer* printer) { + printer->Print( + "public static final com.google.protobuf.Parser<$classname$> PARSER =\n" + " new DefaultInstanceBasedParser(DEFAULT_INSTANCE);\n" + "\n", + "classname", descriptor_->name()); +} + +// =================================================================== +void ImmutableMessageLiteGenerator::GenerateInitializers(io::Printer* printer) { + for (int i = 0; i < descriptor_->field_count(); i++) { + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateInitializationCode(printer); + } + } +} + + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_message_lite.h b/src/google/protobuf/compiler/java/java_message_lite.h new file mode 100644 index 00000000..2bd3cdd4 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_message_lite.h @@ -0,0 +1,91 @@ +// 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. + +// Author: dweis@google.com (Daniel Weis) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableMessageLiteGenerator : public MessageGenerator { + public: + explicit ImmutableMessageLiteGenerator(const Descriptor* descriptor, + Context* context); + virtual ~ImmutableMessageLiteGenerator(); + + virtual void Generate(io::Printer* printer); + virtual void GenerateInterface(io::Printer* printer); + virtual void GenerateExtensionRegistrationCode(io::Printer* printer); + virtual void GenerateStaticVariables(io::Printer* printer); + virtual int GenerateStaticVariableInitializers(io::Printer* printer); + + private: + + void GenerateMessageSerializationMethods(io::Printer* printer); + void GenerateParseFromMethods(io::Printer* printer); + void GenerateSerializeOneField(io::Printer* printer, + const FieldDescriptor* field); + void GenerateSerializeOneExtensionRange( + io::Printer* printer, const Descriptor::ExtensionRange* range); + + void GenerateBuilder(io::Printer* printer); + void GenerateDynamicMethodIsInitialized(io::Printer* printer); + void GenerateDynamicMethodMakeImmutable(io::Printer* printer); + void GenerateDynamicMethodMergeFrom(io::Printer* printer); + void GenerateDynamicMethodNewBuilder(io::Printer* printer); + void GenerateInitializers(io::Printer* printer); + void GenerateEqualsAndHashCode(io::Printer* printer); + void GenerateParser(io::Printer* printer); + void GenerateParsingConstructor(io::Printer* printer); + + Context* context_; + ClassNameResolver* name_resolver_; + FieldGeneratorMap field_generators_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageLiteGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index 48757c60..7bebe12a 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -74,7 +74,12 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); (*variables)["capitalized_type"] = GetCapitalizedType(descriptor, /* immutable = */ true); - (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); + if (descriptor->is_packed()) { + (*variables)["tag"] = SimpleItoa(WireFormatLite::MakeTag( + descriptor->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); + } else { + (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); + } (*variables)["tag_size"] = SimpleItoa( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); if (IsReferenceType(GetJavaType(descriptor))) { @@ -599,7 +604,7 @@ GenerateMembers(io::Printer* printer) const { " return $name$_.get(index);\n" "}\n"); - if (descriptor_->options().packed() && + if (descriptor_->is_packed() && HasGeneratedMethods(descriptor_->containing_type())) { printer->Print(variables_, "private int $name$MemoizedSerializedSize = -1;\n"); @@ -771,7 +776,7 @@ GenerateParsingDoneCode(io::Printer* printer) const { void RepeatedImmutablePrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { // We invoke getSerializedSize in writeTo for messages that have packed // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods. // That makes it safe to rely on the memoized size here. @@ -812,7 +817,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print( "size += dataSize;\n"); - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, "if (!get$capitalized_name$List().isEmpty()) {\n" " size += $tag_size$;\n" @@ -825,7 +830,7 @@ GenerateSerializedSizeCode(io::Printer* printer) const { } // cache the data size for packed fields. - if (descriptor_->options().packed()) { + if (descriptor_->is_packed()) { printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.cc b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc new file mode 100644 index 00000000..217ff9b6 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.cc @@ -0,0 +1,892 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, + map* variables) { + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); + (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); + (*variables)["field_type"] = (*variables)["type"]; + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? + "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); + (*variables)["capitalized_type"] = + GetCapitalizedType(descriptor, /* immutable = */ true); + (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + + string capitalized_type = UnderscoresToCamelCase(PrimitiveTypeName( + GetJavaType(descriptor)), true /* cap_next_letter */); + switch (GetJavaType(descriptor)) { + case JAVATYPE_INT: + case JAVATYPE_LONG: + case JAVATYPE_FLOAT: + case JAVATYPE_DOUBLE: + case JAVATYPE_BOOLEAN: + (*variables)["field_list_type"] = + "com.google.protobuf.Internal." + capitalized_type + "List"; + (*variables)["new_list"] = "new" + capitalized_type + "List"; + (*variables)["empty_list"] = "empty" + capitalized_type + "List()"; + (*variables)["make_name_unmodifiable"] = + (*variables)["name"] + "_.makeImmutable()"; + (*variables)["repeated_index_get"] = + (*variables)["name"] + "_.get" + capitalized_type + "(index)"; + (*variables)["repeated_add"] = + (*variables)["name"] + "_.add" + capitalized_type; + (*variables)["repeated_set"] = + (*variables)["name"] + "_.set" + capitalized_type; + break; + default: + (*variables)["field_list_type"] = + "com.google.protobuf.Internal.ProtobufList<" + + (*variables)["boxed_type"] + ">"; + (*variables)["new_list"] = "newProtobufList"; + (*variables)["empty_list"] = "emptyProtobufList()"; + (*variables)["make_name_unmodifiable"] = + (*variables)["name"] + "_.makeImmutable()"; + (*variables)["repeated_index_get"] = + (*variables)["name"] + "_.get(index)"; + (*variables)["repeated_add"] = (*variables)["name"] + "_.add"; + (*variables)["repeated_set"] = (*variables)["name"] + "_.set"; + } + + if (IsReferenceType(GetJavaType(descriptor))) { + (*variables)["null_check"] = + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n"; + } else { + (*variables)["null_check"] = ""; + } + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + int fixed_size = FixedSize(GetType(descriptor)); + if (fixed_size != -1) { + (*variables)["fixed_size"] = SimpleItoa(fixed_size); + } + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["clear_has_field_bit_message"] = + GenerateClearBit(messageBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["clear_has_field_bit_message"] = ""; + + if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { + (*variables)["is_field_present_message"] = + "!" + (*variables)["name"] + "_.isEmpty()"; + } else { + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != " + (*variables)["default"]; + } + } + + // For repeated builders, the underlying list tracks mutability state. + (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +} // namespace + +// =================================================================== + +ImmutablePrimitiveFieldLiteGenerator:: +ImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {} + +int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const { + return 1; +} + +int ImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$();\n"); +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $field_type$ $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + "$null_check$" + " $set_has_field_bit_message$\n" + " $name$_ = value;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $clear_has_field_bit_message$\n"); + JavaType type = GetJavaType(descriptor_); + if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) { + // The default value is not a simple literal so we want to avoid executing + // it multiple times. Instead, get the default out of the default instance. + printer->Print(variables_, + " $name$_ = getDefaultInstance().get$capitalized_name$();\n"); + } else { + printer->Print(variables_, + " $name$_ = $default$;\n"); + } + printer->Print(variables_, + "}\n"); +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + // noop for primitives +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } else { + printer->Print(variables_, + "if (other.get$capitalized_name$() != $default$) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + // noop for primitives +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + // noop for scalars +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$set_has_field_bit_message$\n" + "$name$_ = input.read$capitalized_type$();\n"); +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for primitives. +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " output.write$capitalized_type$($number$, $name$_);\n" + "}\n"); +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$Size($number$, $name$_);\n" + "}\n"); +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + switch (GetJavaType(descriptor_)) { + case JAVATYPE_INT: + case JAVATYPE_LONG: + case JAVATYPE_BOOLEAN: + printer->Print(variables_, + "result = result && (get$capitalized_name$()\n" + " == other.get$capitalized_name$());\n"); + break; + + case JAVATYPE_FLOAT: + printer->Print(variables_, + "result = result && (\n" + " java.lang.Float.floatToIntBits(get$capitalized_name$())\n" + " == java.lang.Float.floatToIntBits(\n" + " other.get$capitalized_name$()));\n"); + break; + + case JAVATYPE_DOUBLE: + printer->Print(variables_, + "result = result && (\n" + " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n" + " == java.lang.Double.doubleToLongBits(\n" + " other.get$capitalized_name$()));\n"); + break; + + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); + break; + + case JAVATYPE_ENUM: + case JAVATYPE_MESSAGE: + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } +} + +void ImmutablePrimitiveFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n"); + switch (GetJavaType(descriptor_)) { + case JAVATYPE_INT: + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$();\n"); + break; + + case JAVATYPE_LONG: + printer->Print(variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" + " get$capitalized_name$());\n"); + break; + + case JAVATYPE_BOOLEAN: + printer->Print(variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n" + " get$capitalized_name$());\n"); + break; + + case JAVATYPE_FLOAT: + printer->Print(variables_, + "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n" + " get$capitalized_name$());\n"); + break; + + case JAVATYPE_DOUBLE: + printer->Print(variables_, + "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" + " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n"); + break; + + case JAVATYPE_STRING: + case JAVATYPE_BYTES: + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); + break; + + case JAVATYPE_ENUM: + case JAVATYPE_MESSAGE: + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + break; + } +} + +string ImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { + return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); +} + +// =================================================================== + +ImmutablePrimitiveOneofFieldLiteGenerator:: +ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutablePrimitiveFieldLiteGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutablePrimitiveOneofFieldLiteGenerator:: +~ImmutablePrimitiveOneofFieldLiteGenerator() {} + +void ImmutablePrimitiveOneofFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$($type$ value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); +} + + +void ImmutablePrimitiveOneofFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + +void ImmutablePrimitiveOneofFieldLiteGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + // noop for primitives +} + +void ImmutablePrimitiveOneofFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "set$capitalized_name$(other.get$capitalized_name$());\n"); +} + +void ImmutablePrimitiveOneofFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$set_oneof_case_message$;\n" + "$oneof_name$_ = input.read$capitalized_type$();\n"); +} + +void ImmutablePrimitiveOneofFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.write$capitalized_type$(\n" + " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" + "}\n"); +} + +void ImmutablePrimitiveOneofFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$Size(\n" + " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutablePrimitiveFieldLiteGenerator:: +RepeatedImmutablePrimitiveFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +RepeatedImmutablePrimitiveFieldLiteGenerator:: +~RepeatedImmutablePrimitiveFieldLiteGenerator() {} + +int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedImmutablePrimitiveFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.util.List<$boxed_type$> get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$$type$ get$capitalized_name$(int index);\n"); +} + + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private $field_list_type$ $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$boxed_type$>\n" + " get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return $repeated_index_get$;\n" + "}\n"); + + if (descriptor_->options().packed() && + HasGeneratedMethods(descriptor_->containing_type())) { + printer->Print(variables_, + "private int $name$MemoizedSerializedSize = -1;\n"); + } + + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$is_mutable$) {\n" + " $name$_ = $new_list$($name$_);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, $type$ value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $repeated_set$(index, value);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$($type$ value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $repeated_add$(value);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.addAll(\n" + " values, $name$_);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + "}\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$boxed_type$>\n" + " get$capitalized_name$List() {\n" + " return java.util.Collections.unmodifiableList(\n" + " instance.get$capitalized_name$List());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return instance.get$capitalized_name$Count();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$($type$ value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for primitives +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $empty_list$;\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + // noop for primitives +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + // noop for primitives +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_.makeImmutable();\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!$is_mutable$) {\n" + " $name$_ = $new_list$();\n" + "}\n" + "$repeated_add$(input.read$capitalized_type$());\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + printer->Print(variables_, + "int length = input.readRawVarint32();\n" + "int limit = input.pushLimit(length);\n" + "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n" + " $name$_ = $new_list$();\n" + "}\n" + "while (input.getBytesUntilLimit() > 0) {\n" + " $repeated_add$(input.read$capitalized_type$());\n" + "}\n" + "input.popLimit(limit);\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_mutable$) {\n" + " $make_name_unmodifiable$;\n" + "}\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + if (descriptor_->options().packed()) { + // We invoke getSerializedSize in writeTo for messages that have packed + // fields in ImmutableMessageGenerator::GenerateMessageSerializationMethods. + // That makes it safe to rely on the memoized size here. + printer->Print(variables_, + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeRawVarint32($tag$);\n" + " output.writeRawVarint32($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$($number$, $name$_.get(i));\n" + "}\n"); + } +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int dataSize = 0;\n"); + printer->Indent(); + + if (FixedSize(GetType(descriptor_)) == -1) { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$SizeNoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "dataSize = $fixed_size$ * get$capitalized_name$List().size();\n"); + } + + printer->Print( + "size += dataSize;\n"); + + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (!get$capitalized_name$List().isEmpty()) {\n" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeInt32SizeNoTag(dataSize);\n" + "}\n"); + } else { + printer->Print(variables_, + "size += $tag_size$ * get$capitalized_name$List().size();\n"); + } + + // cache the data size for packed fields. + if (descriptor_->options().packed()) { + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedImmutablePrimitiveFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedImmutablePrimitiveFieldLiteGenerator::GetBoxedType() const { + return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_primitive_field_lite.h b/src/google/protobuf/compiler/java/java_primitive_field_lite.h new file mode 100644 index 00000000..ad603c2a --- /dev/null +++ b/src/google/protobuf/compiler/java/java_primitive_field_lite.h @@ -0,0 +1,163 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutablePrimitiveFieldLiteGenerator + : public ImmutableFieldLiteGenerator { + public: + explicit ImmutablePrimitiveFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutablePrimitiveFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + protected: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator); +}; + +class ImmutablePrimitiveOneofFieldLiteGenerator + : public ImmutablePrimitiveFieldLiteGenerator { + public: + ImmutablePrimitiveOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutablePrimitiveOneofFieldLiteGenerator(); + + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator); +}; + +class RepeatedImmutablePrimitiveFieldLiteGenerator + : public ImmutableFieldLiteGenerator { + public: + explicit RepeatedImmutablePrimitiveFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + virtual ~RepeatedImmutablePrimitiveFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldLiteGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 8aa5699c..68e863cc 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -208,7 +208,7 @@ GenerateInterfaceMembers(io::Printer* printer) const { void ImmutableStringFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, - "private java.lang.Object $name$_;\n"); + "private volatile java.lang.Object $name$_;\n"); PrintExtraFieldInfo(variables_, printer); if (SupportFieldPresence(descriptor_->file())) { diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.cc b/src/google/protobuf/compiler/java/java_string_field_lite.cc new file mode 100644 index 00000000..51bb245c --- /dev/null +++ b/src/google/protobuf/compiler/java/java_string_field_lite.cc @@ -0,0 +1,1013 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Author: jonp@google.com (Jon Perlow) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +using internal::WireFormat; +using internal::WireFormatLite; + +namespace { + +void SetPrimitiveVariables(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, + map* variables) { + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["empty_list"] = "emptyLazyStringArrayList()"; + + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default_init"] = + "= " + ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["capitalized_type"] = "String"; + (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); + (*variables)["tag_size"] = SimpleItoa( + WireFormat::TagSize(descriptor->number(), GetType(descriptor))); + (*variables)["null_check"] = + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n"; + + // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported + // by the proto compiler + (*variables)["deprecation"] = descriptor->options().deprecated() + ? "@java.lang.Deprecated " : ""; + (*variables)["on_changed"] = + HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; + + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["clear_has_field_bit_message"] = + GenerateClearBit(messageBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["clear_has_field_bit_message"] = ""; + + (*variables)["is_field_present_message"] = + "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()"; + } + + // For repeated builders, the underlying list tracks mutability state. + (*variables)["is_mutable"] = (*variables)["name"] + "_.isModifiable()"; + + (*variables)["get_has_field_bit_from_local"] = + GenerateGetBitFromLocal(builderBitIndex); + (*variables)["set_has_field_bit_to_local"] = + GenerateSetBitToLocal(messageBitIndex); +} + +bool CheckUtf8(const FieldDescriptor* descriptor) { + return descriptor->file()->options().java_string_check_utf8(); +} + +} // namespace + +// =================================================================== + +ImmutableStringFieldLiteGenerator:: +ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {} + +int ImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { + return 1; +} + +int ImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +// A note about how strings are handled. This code used to just store a String +// in the Message. This had two issues: +// +// 1. It wouldn't roundtrip byte arrays that were not vaid UTF-8 encoded +// strings, but rather fields that were raw bytes incorrectly marked +// as strings in the proto file. This is common because in the proto1 +// syntax, string was the way to indicate bytes and C++ engineers can +// easily make this mistake without affecting the C++ API. By converting to +// strings immediately, some java code might corrupt these byte arrays as +// it passes through a java server even if the field was never accessed by +// application code. +// +// 2. There's a performance hit to converting between bytes and strings and +// it many cases, the field is never even read by the application code. This +// avoids unnecessary conversions in the common use cases. +// +// So now, the field for String is maintained as an Object reference which can +// either store a String or a ByteString. The code uses an instanceof check +// to see which one it has and converts to the other one if needed. It remembers +// the last value requested (in a thread safe manner) as this is most likely +// the one needed next. The thread safety is such that if two threads both +// convert the field because the changes made by each thread were not visible to +// the other, they may cause a conversion to happen more times than would +// otherwise be necessary. This was deemed better than adding synchronization +// overhead. It will not cause any corruption issues or affect the behavior of +// the API. The instanceof check is also highly optimized in the JVM and we +// decided it was better to reduce the memory overhead by not having two +// separate fields but rather use dynamic type checking. +// +// For single fields, the logic for this is done inside the generated code. For +// repeated fields, the logic is done in LazyStringArrayList and +// UnmodifiableLazyStringList. +void ImmutableStringFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.lang.String get$capitalized_name$();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes();\n"); +} + +void ImmutableStringFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.lang.Object $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof java.lang.String) {\n" + " return (java.lang.String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " $name$_ = s;\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8()) {\n" + " $name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, + " return s;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref = $name$_;\n" + " if (ref instanceof java.lang.String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " $name$_ = b;\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_has_field_bit_message$\n" + " $name$_ = value;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $clear_has_field_bit_message$\n" + // The default value is not a simple literal so we want to avoid executing + // it multiple times. Instead, get the default out of the default instance. + " $name$_ = getDefaultInstance().get$capitalized_name$();\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, + " $set_has_field_bit_message$\n" + " $name$_ = value;\n" + "}\n"); +} + +void ImmutableStringFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " return instance.get$capitalized_name$Bytes();\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " java.lang.String value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Bytes(value);\n" + " return this;\n" + "}\n"); +} + +void ImmutableStringFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for strings +} + +void ImmutableStringFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $default$;\n"); +} + +void ImmutableStringFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + // Allow a slight breach of abstraction here in order to avoid forcing + // all string fields to Strings when copying fields from a Message. + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " $set_has_field_bit_message$\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); + } else { + printer->Print(variables_, + "if (!other.get$capitalized_name$().isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); + } +} + +void ImmutableStringFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + // noop for scalars +} + +void ImmutableStringFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n" + "$set_has_field_bit_message$\n" + "$name$_ = s;\n"); + } else if (!HasDescriptorMethods(descriptor_->file())) { + // Lite runtime should attempt to reduce allocations by attempting to + // construct the string directly from the input stream buffer. This avoids + // spurious intermediary ByteString allocations, cutting overall allocations + // in half. + printer->Print(variables_, + "String s = input.readString();\n" + "$set_has_field_bit_message$\n" + "$name$_ = s;\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "$set_has_field_bit_message$\n" + "$name$_ = bs;\n"); + } +} + +void ImmutableStringFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + // noop for strings +} + +void ImmutableStringFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void ImmutableStringFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_field_present_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void ImmutableStringFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$()\n" + " .equals(other.get$capitalized_name$());\n"); +} + +void ImmutableStringFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "hash = (37 * hash) + $constant_name$;\n"); + printer->Print(variables_, + "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); +} + +string ImmutableStringFieldLiteGenerator::GetBoxedType() const { + return "java.lang.String"; +} + +// =================================================================== + +ImmutableStringOneofFieldLiteGenerator:: +ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableStringFieldLiteGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutableStringOneofFieldLiteGenerator:: +~ImmutableStringOneofFieldLiteGenerator() {} + +void ImmutableStringOneofFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof java.lang.String) {\n" + " return (java.lang.String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = s;\n" + " }\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n" + " $oneof_name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, + " return s;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof java.lang.String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = b;\n" + " }\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + "}\n"); +} + +void ImmutableStringOneofFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return instance.has$capitalized_name$();\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " return instance.get$capitalized_name$();\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " return instance.get$capitalized_name$Bytes();\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " java.lang.String value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$Bytes(value);\n" + " return this;\n" + "}\n"); +} + +void ImmutableStringOneofFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // Allow a slight breach of abstraction here in order to avoid forcing + // all string fields to Strings when copying fields from a Message. + printer->Print(variables_, + "$set_oneof_case_message$;\n" + "$oneof_name$_ = other.$oneof_name$_;\n" + "$on_changed$\n"); +} + +void ImmutableStringOneofFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = s;\n"); + } else if (!HasDescriptorMethods(descriptor_->file())) { + // Lite runtime should attempt to reduce allocations by attempting to + // construct the string directly from the input stream buffer. This avoids + // spurious intermediary ByteString allocations, cutting overall allocations + // in half. + printer->Print(variables_, + "String s = input.readString();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = s;\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = bs;\n"); + } +} + +void ImmutableStringOneofFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void ImmutableStringOneofFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutableStringFieldLiteGenerator:: +RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : descriptor_(descriptor), messageBitIndex_(messageBitIndex), + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); +} + +RepeatedImmutableStringFieldLiteGenerator:: +~RepeatedImmutableStringFieldLiteGenerator() {} + +int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForMessage() const { + return 0; +} + +int RepeatedImmutableStringFieldLiteGenerator::GetNumBitsForBuilder() const { + return 0; +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateInterfaceMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$com.google.protobuf.ProtocolStringList\n" + " get$capitalized_name$List();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$int get$capitalized_name$Count();\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$java.lang.String get$capitalized_name$(int index);\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index);\n"); +} + + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.LazyStringArrayList $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ProtocolStringList\n" + " get$capitalized_name$List() {\n" + " return $name$_;\n" // note: unmodifiable list + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" + " return $name$_.get(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index) {\n" + " return $name$_.getByteString(index);\n" + "}\n"); + + if (descriptor_->options().packed() && + HasGeneratedMethods(descriptor_->containing_type())) { + printer->Print(variables_, + "private int $name$MemoizedSerializedSize = -1;\n"); + } + + printer->Print(variables_, + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$is_mutable$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList($name$_);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void set$capitalized_name$(\n" + " int index, java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.set(index, value);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " ensure$capitalized_name$IsMutable();\n" + " com.google.protobuf.AbstractMessageLite.addAll(\n" + " values, $name$_);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void clear$capitalized_name$() {\n" + " $name$_ = $empty_list$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private void add$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, + " ensure$capitalized_name$IsMutable();\n" + " $name$_.add(value);\n" + "}\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ProtocolStringList\n" + " get$capitalized_name$List() {\n" + " return ((com.google.protobuf.LazyStringList)\n" + " instance.get$capitalized_name$List()).getUnmodifiableView();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return instance.get$capitalized_name$Count();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$(int index) {\n" + " return instance.get$capitalized_name$(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes(int index) {\n" + " return instance.get$capitalized_name$Bytes(index);\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, java.lang.String value) {\n" + " copyOnWrite();\n" + " instance.set$capitalized_name$(index, value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$(\n" + " java.lang.String value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$(value);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values) {\n" + " copyOnWrite();\n" + " instance.addAll$capitalized_name$(values);\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " copyOnWrite();\n" + " instance.clear$capitalized_name$();\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder add$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + " copyOnWrite();\n" + " instance.add$capitalized_name$Bytes(value);\n" + " return this;\n" + "}\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateFieldBuilderInitializationCode(io::Printer* printer) const { + // noop for strings +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_ = $empty_list$;\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // The code below does two optimizations: + // 1. If the other list is empty, there's nothing to do. This ensures we + // don't allocate a new array if we already have an immutable one. + // 2. If the other list is non-empty and our current list is empty, we can + // reuse the other list which is guaranteed to be immutable. + printer->Print(variables_, + "if (!other.$name$_.isEmpty()) {\n" + " if ($name$_.isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " } else {\n" + " ensure$capitalized_name$IsMutable();\n" + " $name$_.addAll(other.$name$_);\n" + " }\n" + " $on_changed$\n" + "}\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_.makeImmutable();\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n"); + } else if (!HasDescriptorMethods(descriptor_->file())) { + // Lite runtime should attempt to reduce allocations by attempting to + // construct the string directly from the input stream buffer. This avoids + // spurious intermediary ByteString allocations, cutting overall allocations + // in half. + printer->Print(variables_, + "String s = input.readString();\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n"); + } + printer->Print(variables_, + "if (!$is_mutable$) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" + "}\n"); + if (CheckUtf8(descriptor_) || !HasDescriptorMethods(descriptor_->file())) { + printer->Print(variables_, + "$name$_.add(s);\n"); + } else { + printer->Print(variables_, + "$name$_.add(bs);\n"); + } +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + printer->Print(variables_, + "int length = input.readRawVarint32();\n" + "int limit = input.pushLimit(length);\n" + "if (!$is_mutable$ && input.getBytesUntilLimit() > 0) {\n" + " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" + "}\n" + "while (input.getBytesUntilLimit() > 0) {\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " String s = input.readStringRequireUtf8();\n"); + } else { + printer->Print(variables_, + " String s = input.readString();\n"); + } + printer->Print(variables_, + " $name$.add(s);\n"); + printer->Print(variables_, + "}\n" + "input.popLimit(limit);\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateParsingDoneCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($is_mutable$) {\n" + " $name$_.makeImmutable();\n" + "}\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (get$capitalized_name$List().size() > 0) {\n" + " output.writeRawVarint32($tag$);\n" + " output.writeRawVarint32($name$MemoizedSerializedSize);\n" + "}\n" + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.write$capitalized_type$NoTag($name$_.get(i));\n" + "}\n"); + } else { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeBytes($number$, $name$_.getByteString(i));\n" + "}\n"); + } +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "{\n" + " int dataSize = 0;\n"); + printer->Indent(); + + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " dataSize += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSizeNoTag($name$_.getByteString(i));\n" + "}\n"); + + printer->Print( + "size += dataSize;\n"); + + if (descriptor_->options().packed()) { + printer->Print(variables_, + "if (!get$capitalized_name$List().isEmpty()) {\n" + " size += $tag_size$;\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeInt32SizeNoTag(dataSize);\n" + "}\n"); + } else { + printer->Print(variables_, + "size += $tag_size$ * get$capitalized_name$List().size();\n"); + } + + // cache the data size for packed fields. + if (descriptor_->options().packed()) { + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); + } + + printer->Outdent(); + printer->Print("}\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateEqualsCode(io::Printer* printer) const { + printer->Print(variables_, + "result = result && get$capitalized_name$List()\n" + " .equals(other.get$capitalized_name$List());\n"); +} + +void RepeatedImmutableStringFieldLiteGenerator:: +GenerateHashCode(io::Printer* printer) const { + printer->Print(variables_, + "if (get$capitalized_name$Count() > 0) {\n" + " hash = (37 * hash) + $constant_name$;\n" + " hash = (53 * hash) + get$capitalized_name$List().hashCode();\n" + "}\n"); +} + +string RepeatedImmutableStringFieldLiteGenerator::GetBoxedType() const { + return "String"; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_string_field_lite.h b/src/google/protobuf/compiler/java/java_string_field_lite.h new file mode 100644 index 00000000..9d93b307 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_string_field_lite.h @@ -0,0 +1,158 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Author: jonp@google.com (Jon Perlow) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableStringFieldLiteGenerator : public ImmutableFieldLiteGenerator { + public: + explicit ImmutableStringFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableStringFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + protected: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldLiteGenerator); +}; + +class ImmutableStringOneofFieldLiteGenerator + : public ImmutableStringFieldLiteGenerator { + public: + ImmutableStringOneofFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableStringOneofFieldLiteGenerator(); + + private: + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator); +}; + +class RepeatedImmutableStringFieldLiteGenerator + : public ImmutableFieldLiteGenerator { + public: + explicit RepeatedImmutableStringFieldLiteGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableStringFieldLiteGenerator(); + + // implements ImmutableFieldLiteGenerator ------------------------------------ + int GetNumBitsForMessage() const; + int GetNumBitsForBuilder() const; + void GenerateInterfaceMembers(io::Printer* printer) const; + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateDynamicMethodMakeImmutableCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateParsingCodeFromPacked(io::Printer* printer) const; + void GenerateParsingDoneCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; + void GenerateEqualsCode(io::Printer* printer) const; + void GenerateHashCode(io::Printer* printer) const; + + string GetBoxedType() const; + + private: + const FieldDescriptor* descriptor_; + map variables_; + const int messageBitIndex_; + const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldLiteGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__ diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index c50cdf54..a2eeee2d 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -686,6 +686,8 @@ bool Parser::ParseMessageStatement(DescriptorProto* message, LocationRecorder location(message_location, DescriptorProto::kExtensionRangeFieldNumber); return ParseExtensions(message, location, containing_file); + } else if (LookingAt("reserved")) { + return ParseReserved(message, message_location); } else if (LookingAt("extend")) { LocationRecorder location(message_location, DescriptorProto::kExtensionFieldNumber); @@ -733,6 +735,13 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, FieldDescriptorProto::Label label; if (ParseLabel(&label, containing_file)) { field->set_label(label); + if (label == FieldDescriptorProto::LABEL_OPTIONAL && + syntax_identifier_ == "proto3") { + AddError( + "Explicit 'optional' labels are disallowed in the Proto3 syntax. " + "To define 'optional' fields in Proto3, simply remove the " + "'optional' label, as fields are 'optional' by default."); + } } } @@ -1353,6 +1362,77 @@ bool Parser::ParseExtensions(DescriptorProto* message, return true; } +// This is similar to extension range parsing, except that "max" is not +// supported, and accepts field name literals. +bool Parser::ParseReserved(DescriptorProto* message, + const LocationRecorder& message_location) { + // Parse the declaration. + DO(Consume("reserved")); + if (LookingAtType(io::Tokenizer::TYPE_STRING)) { + LocationRecorder location(message_location, + DescriptorProto::kReservedNameFieldNumber); + return ParseReservedNames(message, location); + } else { + LocationRecorder location(message_location, + DescriptorProto::kReservedRangeFieldNumber); + return ParseReservedNumbers(message, location); + } +} + + +bool Parser::ParseReservedNames(DescriptorProto* message, + const LocationRecorder& parent_location) { + do { + LocationRecorder location(parent_location, message->reserved_name_size()); + DO(ConsumeString(message->add_reserved_name(), "Expected field name.")); + } while (TryConsume(",")); + DO(ConsumeEndOfDeclaration(";", &parent_location)); + return true; +} + +bool Parser::ParseReservedNumbers(DescriptorProto* message, + const LocationRecorder& parent_location) { + bool first = true; + do { + LocationRecorder location(parent_location, message->reserved_range_size()); + + DescriptorProto::ReservedRange* range = message->add_reserved_range(); + int start, end; + io::Tokenizer::Token start_token; + { + LocationRecorder start_location( + location, DescriptorProto::ReservedRange::kStartFieldNumber); + start_token = input_->current(); + DO(ConsumeInteger(&start, (first ? + "Expected field name or number range." : + "Expected field number range."))); + } + + if (TryConsume("to")) { + LocationRecorder end_location( + location, DescriptorProto::ReservedRange::kEndFieldNumber); + DO(ConsumeInteger(&end, "Expected integer.")); + } else { + LocationRecorder end_location( + location, DescriptorProto::ReservedRange::kEndFieldNumber); + end_location.StartAt(start_token); + end_location.EndAt(start_token); + end = start; + } + + // Users like to specify inclusive ranges, but in code we like the end + // number to be exclusive. + ++end; + + range->set_start(start); + range->set_end(end); + first = false; + } while (TryConsume(",")); + + DO(ConsumeEndOfDeclaration(";", &parent_location)); + return true; +} + bool Parser::ParseExtend(RepeatedPtrField* extensions, RepeatedPtrField* messages, const LocationRecorder& parent_location, diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index 7cb1678a..16012e96 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -364,6 +364,14 @@ class LIBPROTOBUF_EXPORT Parser { const LocationRecorder& extensions_location, const FileDescriptorProto* containing_file); + // Parse an "reserved" declaration. + bool ParseReserved(DescriptorProto* message, + const LocationRecorder& message_location); + bool ParseReservedNames(DescriptorProto* message, + const LocationRecorder& parent_location); + bool ParseReservedNumbers(DescriptorProto* message, + const LocationRecorder& parent_location); + // Parse an "extend" declaration. (See also comments for // ParseMessageField().) bool ParseExtend(RepeatedPtrField* extensions, diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index 1684bebe..ddf34bfa 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -620,6 +620,36 @@ TEST_F(ParseMessageTest, NestedEnum) { "}"); } +TEST_F(ParseMessageTest, ReservedRange) { + ExpectParsesTo( + "message TestMessage {\n" + " required int32 foo = 1;\n" + " reserved 2, 15, 9 to 11, 3;\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"foo\" label:LABEL_REQUIRED type:TYPE_INT32 number:1 }" + " reserved_range { start:2 end:3 }" + " reserved_range { start:15 end:16 }" + " reserved_range { start:9 end:12 }" + " reserved_range { start:3 end:4 }" + "}"); +} + +TEST_F(ParseMessageTest, ReservedNames) { + ExpectParsesTo( + "message TestMessage {\n" + " reserved \"foo\", \"bar\";\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " reserved_name: \"foo\"" + " reserved_name: \"bar\"" + "}"); +} + TEST_F(ParseMessageTest, ExtensionRange) { ExpectParsesTo( "message TestMessage {\n" @@ -715,19 +745,17 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) { " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); } -TEST_F(ParseMessageTest, OptionalOptionalLabelProto3) { +TEST_F(ParseMessageTest, OptionalLabelProto3) { ExpectParsesTo( "syntax = \"proto3\";\n" "message TestMessage {\n" " int32 foo = 1;\n" - " optional int32 bar = 2;\n" "}\n", "syntax: \"proto3\" " "message_type {" " name: \"TestMessage\"" - " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 }" - " field { name:\"bar\" label:LABEL_OPTIONAL type:TYPE_INT32 number:2 } }"); + " field { name:\"foo\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 } }"); } // =================================================================== @@ -1230,6 +1258,18 @@ TEST_F(ParseErrorTest, EofInAggregateValue) { "1:0: Unexpected end of stream while parsing aggregate value.\n"); } +TEST_F(ParseErrorTest, ExplicitOptionalLabelProto3) { + ExpectHasErrors( + "syntax = 'proto3';\n" + "message TestMessage {\n" + " optional int32 foo = 1;\n" + "}\n", + "2:11: Explicit 'optional' labels are disallowed in the Proto3 syntax. " + "To define 'optional' fields in Proto3, simply remove the 'optional' " + "label, as fields are 'optional' by default.\n"); +} + + // ------------------------------------------------------------------- // Enum errors @@ -1247,6 +1287,33 @@ TEST_F(ParseErrorTest, EnumValueMissingNumber) { "1:5: Missing numeric value for enum constant.\n"); } +// ------------------------------------------------------------------- +// Reserved field number errors + +TEST_F(ParseErrorTest, ReservedMaxNotAllowed) { + ExpectHasErrors( + "message Foo {\n" + " reserved 10 to max;\n" + "}\n", + "1:17: Expected integer.\n"); +} + +TEST_F(ParseErrorTest, ReservedMixNameAndNumber) { + ExpectHasErrors( + "message Foo {\n" + " reserved 10, \"foo\";\n" + "}\n", + "1:15: Expected field number range.\n"); +} + +TEST_F(ParseErrorTest, ReservedMissingQuotes) { + ExpectHasErrors( + "message Foo {\n" + " reserved foo;\n" + "}\n", + "1:11: Expected field name or number range.\n"); +} + // ------------------------------------------------------------------- // Service errors diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc index ad501acf..cdcaffde 100644 --- a/src/google/protobuf/compiler/plugin.cc +++ b/src/google/protobuf/compiler/plugin.cc @@ -134,20 +134,34 @@ int PluginMain(int argc, char* argv[], const CodeGenerator* generator) { CodeGeneratorResponse response; GeneratorResponseContext context(&response, parsed_files); - for (int i = 0; i < parsed_files.size(); i++) { - const FileDescriptor* file = parsed_files[i]; - + if (generator->HasGenerateAll()) { string error; - bool succeeded = generator->Generate( - file, request.parameter(), &context, &error); + bool succeeded = generator->GenerateAll( + parsed_files, request.parameter(), &context, &error); if (!succeeded && error.empty()) { error = "Code generator returned false but provided no error " "description."; } if (!error.empty()) { - response.set_error(file->name() + ": " + error); - break; + response.set_error(error); + } + } else { + for (int i = 0; i < parsed_files.size(); i++) { + const FileDescriptor* file = parsed_files[i]; + + string error; + bool succeeded = generator->Generate( + file, request.parameter(), &context, &error); + + if (!succeeded && error.empty()) { + error = "Code generator returned false but provided no error " + "description."; + } + if (!error.empty()) { + response.set_error(file->name() + ": " + error); + break; + } } } diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index d78b715e..344ed450 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -179,7 +179,7 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber; #endif // !_MSC_VER CodeGeneratorRequest::CodeGeneratorRequest() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest) } @@ -300,12 +300,15 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( case 15: { if (tag == 122) { parse_proto_file: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_proto_file: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_proto_file())); } else { goto handle_unusual; } - if (input->ExpectTag(122)) goto parse_proto_file; + if (input->ExpectTag(122)) goto parse_loop_proto_file; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -445,9 +448,9 @@ int CodeGeneratorRequest::ByteSize() const { void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const CodeGeneratorRequest* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const CodeGeneratorRequest* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -513,10 +516,10 @@ void CodeGeneratorRequest::InternalSwap(CodeGeneratorRequest* other) { // CodeGeneratorRequest // repeated string file_to_generate = 1; - int CodeGeneratorRequest::file_to_generate_size() const { +int CodeGeneratorRequest::file_to_generate_size() const { return file_to_generate_.size(); } - void CodeGeneratorRequest::clear_file_to_generate() { +void CodeGeneratorRequest::clear_file_to_generate() { file_to_generate_.Clear(); } const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { @@ -567,16 +570,16 @@ CodeGeneratorRequest::mutable_file_to_generate() { } // optional string parameter = 2; - bool CodeGeneratorRequest::has_parameter() const { +bool CodeGeneratorRequest::has_parameter() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void CodeGeneratorRequest::set_has_parameter() { +void CodeGeneratorRequest::set_has_parameter() { _has_bits_[0] |= 0x00000002u; } - void CodeGeneratorRequest::clear_has_parameter() { +void CodeGeneratorRequest::clear_has_parameter() { _has_bits_[0] &= ~0x00000002u; } - void CodeGeneratorRequest::clear_parameter() { +void CodeGeneratorRequest::clear_parameter() { parameter_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_parameter(); } @@ -620,10 +623,10 @@ CodeGeneratorRequest::mutable_file_to_generate() { } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; - int CodeGeneratorRequest::proto_file_size() const { +int CodeGeneratorRequest::proto_file_size() const { return proto_file_.size(); } - void CodeGeneratorRequest::clear_proto_file() { +void CodeGeneratorRequest::clear_proto_file() { proto_file_.Clear(); } const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { @@ -660,7 +663,7 @@ const int CodeGeneratorResponse_File::kContentFieldNumber; #endif // !_MSC_VER CodeGeneratorResponse_File::CodeGeneratorResponse_File() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } @@ -946,9 +949,9 @@ int CodeGeneratorResponse_File::ByteSize() const { void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const CodeGeneratorResponse_File* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const CodeGeneratorResponse_File* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1024,7 +1027,7 @@ const int CodeGeneratorResponse::kFileFieldNumber; #endif // !_MSC_VER CodeGeneratorResponse::CodeGeneratorResponse() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse) } @@ -1124,12 +1127,15 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( case 15: { if (tag == 122) { parse_file: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_file: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_file())); } else { goto handle_unusual; } - if (input->ExpectTag(122)) goto parse_file; + if (input->ExpectTag(122)) goto parse_loop_file; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -1242,9 +1248,9 @@ int CodeGeneratorResponse::ByteSize() const { void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const CodeGeneratorResponse* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const CodeGeneratorResponse* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1307,16 +1313,16 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { // CodeGeneratorResponse_File // optional string name = 1; - bool CodeGeneratorResponse_File::has_name() const { +bool CodeGeneratorResponse_File::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void CodeGeneratorResponse_File::set_has_name() { +void CodeGeneratorResponse_File::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void CodeGeneratorResponse_File::clear_has_name() { +void CodeGeneratorResponse_File::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void CodeGeneratorResponse_File::clear_name() { +void CodeGeneratorResponse_File::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -1360,16 +1366,16 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { } // optional string insertion_point = 2; - bool CodeGeneratorResponse_File::has_insertion_point() const { +bool CodeGeneratorResponse_File::has_insertion_point() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void CodeGeneratorResponse_File::set_has_insertion_point() { +void CodeGeneratorResponse_File::set_has_insertion_point() { _has_bits_[0] |= 0x00000002u; } - void CodeGeneratorResponse_File::clear_has_insertion_point() { +void CodeGeneratorResponse_File::clear_has_insertion_point() { _has_bits_[0] &= ~0x00000002u; } - void CodeGeneratorResponse_File::clear_insertion_point() { +void CodeGeneratorResponse_File::clear_insertion_point() { insertion_point_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_insertion_point(); } @@ -1413,16 +1419,16 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { } // optional string content = 15; - bool CodeGeneratorResponse_File::has_content() const { +bool CodeGeneratorResponse_File::has_content() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void CodeGeneratorResponse_File::set_has_content() { +void CodeGeneratorResponse_File::set_has_content() { _has_bits_[0] |= 0x00000004u; } - void CodeGeneratorResponse_File::clear_has_content() { +void CodeGeneratorResponse_File::clear_has_content() { _has_bits_[0] &= ~0x00000004u; } - void CodeGeneratorResponse_File::clear_content() { +void CodeGeneratorResponse_File::clear_content() { content_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_content(); } @@ -1470,16 +1476,16 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { // CodeGeneratorResponse // optional string error = 1; - bool CodeGeneratorResponse::has_error() const { +bool CodeGeneratorResponse::has_error() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void CodeGeneratorResponse::set_has_error() { +void CodeGeneratorResponse::set_has_error() { _has_bits_[0] |= 0x00000001u; } - void CodeGeneratorResponse::clear_has_error() { +void CodeGeneratorResponse::clear_has_error() { _has_bits_[0] &= ~0x00000001u; } - void CodeGeneratorResponse::clear_error() { +void CodeGeneratorResponse::clear_error() { error_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_error(); } @@ -1523,10 +1529,10 @@ void CodeGeneratorResponse::InternalSwap(CodeGeneratorResponse* other) { } // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; - int CodeGeneratorResponse::file_size() const { +int CodeGeneratorResponse::file_size() const { return file_.size(); } - void CodeGeneratorResponse::clear_file() { +void CodeGeneratorResponse::clear_file() { file_.Clear(); } const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index ea48b8b5..6fcaea2e 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -796,6 +796,10 @@ CodeGeneratorResponse::mutable_file() { } #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index bfdacd95..2855c377 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -1518,6 +1518,18 @@ Descriptor::FindExtensionRangeContainingNumber(int number) const { return NULL; } +const Descriptor::ReservedRange* +Descriptor::FindReservedRangeContainingNumber(int number) const { + // TODO(chrisn): Consider a non-linear search. + for (int i = 0; i < reserved_range_count(); i++) { + if (number >= reserved_range(i)->start && + number < reserved_range(i)->end) { + return reserved_range(i); + } + } + return NULL; +} + // ------------------------------------------------------------------- bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const { @@ -1741,6 +1753,14 @@ void Descriptor::CopyTo(DescriptorProto* proto) const { for (int i = 0; i < extension_count(); i++) { extension(i)->CopyTo(proto->add_extension()); } + for (int i = 0; i < reserved_range_count(); i++) { + DescriptorProto::ReservedRange* range = proto->add_reserved_range(); + range->set_start(reserved_range(i)->start); + range->set_end(reserved_range(i)->end); + } + for (int i = 0; i < reserved_name_count(); i++) { + proto->add_reserved_name(reserved_name(i)); + } if (&options() != &MessageOptions::default_instance()) { proto->mutable_options()->CopyFrom(options()); @@ -2186,6 +2206,29 @@ void Descriptor::DebugString(int depth, string *contents, if (extension_count() > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix); + if (reserved_range_count() > 0) { + strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); + for (int i = 0; i < reserved_range_count(); i++) { + const Descriptor::ReservedRange* range = reserved_range(i); + if (range->end == range->start + 1) { + strings::SubstituteAndAppend(contents, "$0, ", range->start); + } else { + strings::SubstituteAndAppend(contents, "$0 to $1, ", + range->start, range->end - 1); + } + } + contents->replace(contents->size() - 2, 2, ";\n"); + } + + if (reserved_name_count() > 0) { + strings::SubstituteAndAppend(contents, "$0 reserved ", prefix); + for (int i = 0; i < reserved_name_count(); i++) { + strings::SubstituteAndAppend(contents, "\"$0\", ", + CEscape(reserved_name(i))); + } + contents->replace(contents->size() - 2, 2, ";\n"); + } + strings::SubstituteAndAppend(contents, "$0}\n", prefix); comment_printer.AddPostComment(contents); } @@ -2278,8 +2321,12 @@ void FieldDescriptor::DebugString(int depth, } if (type() == TYPE_GROUP) { - message_type()->DebugString(depth, contents, debug_string_options, - /* include_opening_clause */ false); + if (debug_string_options.elide_group_body) { + contents->append(" { ... };\n"); + } else { + message_type()->DebugString(depth, contents, debug_string_options, + /* include_opening_clause */ false); + } } else { contents->append(";\n"); } @@ -2308,12 +2355,16 @@ void OneofDescriptor::DebugString(int depth, string* contents, comment_printer(this, prefix, debug_string_options); comment_printer.AddPreComment(contents); strings::SubstituteAndAppend( - contents, "$0 oneof $1 {\n", prefix, name()); - for (int i = 0; i < field_count(); i++) { - field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents, - debug_string_options); + contents, "$0 oneof $1 {", prefix, name()); + if (debug_string_options.elide_oneof_body) { + contents->append(" ... }\n"); + } else { + for (int i = 0; i < field_count(); i++) { + field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents, + debug_string_options); + } + strings::SubstituteAndAppend(contents, "$0}\n", prefix); } - strings::SubstituteAndAppend(contents, "$0}\n", prefix); comment_printer.AddPostComment(contents); } @@ -2491,7 +2542,12 @@ bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const { } bool FieldDescriptor::is_packed() const { - return is_packable() && (options_ != NULL) && options_->packed(); + if (!is_packable()) return false; + if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) { + return (options_ != NULL) && options_->packed(); + } else { + return options_ == NULL || !options_->has_packed() || options_->packed(); + } } bool Descriptor::GetSourceLocation(SourceLocation* out_location) const { @@ -2604,7 +2660,7 @@ void MethodDescriptor::GetLocationPath(vector* output) const { namespace { // Represents an options message to interpret. Extension names in the option -// name are respolved relative to name_scope. element_name and orig_opt are +// name are resolved relative to name_scope. element_name and orig_opt are // used only for error reporting (since the parser records locations against // pointers in the original options, not the mutable copy). The Message must be // one of the Options messages in descriptor.proto. @@ -2830,6 +2886,9 @@ class DescriptorBuilder { void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto, const Descriptor* parent, Descriptor::ExtensionRange* result); + void BuildReservedRange(const DescriptorProto::ReservedRange& proto, + const Descriptor* parent, + Descriptor::ReservedRange* result); void BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent, OneofDescriptor* result); @@ -3920,6 +3979,17 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, BUILD_ARRAY(proto, result, enum_type , BuildEnum , result); BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result); BUILD_ARRAY(proto, result, extension , BuildExtension , result); + BUILD_ARRAY(proto, result, reserved_range , BuildReservedRange , result); + + // Copy reserved names. + int reserved_name_count = proto.reserved_name_size(); + result->reserved_name_count_ = reserved_name_count; + result->reserved_names_ = + tables_->AllocateArray(reserved_name_count); + for (int i = 0; i < reserved_name_count; ++i) { + result->reserved_names_[i] = + tables_->AllocateString(proto.reserved_name(i)); + } // Copy options. if (!proto.has_options()) { @@ -3931,7 +4001,34 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result)); - // Check that no fields have numbers in extension ranges. + for (int i = 0; i < proto.reserved_range_size(); i++) { + const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i); + for (int j = i + 1; j < proto.reserved_range_size(); j++) { + const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j); + if (range1.end() > range2.start() && range2.end() > range1.start()) { + AddError(result->full_name(), proto.reserved_range(i), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Reserved range $0 to $1 overlaps with " + "already-defined range $2 to $3.", + range2.start(), range2.end() - 1, + range1.start(), range1.end() - 1)); + } + } + } + + hash_set reserved_name_set; + for (int i = 0; i < proto.reserved_name_size(); i++) { + const string& name = proto.reserved_name(i); + if (reserved_name_set.find(name) == reserved_name_set.end()) { + reserved_name_set.insert(name); + } else { + AddError(name, proto, DescriptorPool::ErrorCollector::NAME, + strings::Substitute( + "Field name \"$0\" is reserved multiple times.", + name)); + } + } + for (int i = 0; i < result->field_count(); i++) { const FieldDescriptor* field = result->field(i); for (int j = 0; j < result->extension_range_count(); j++) { @@ -3945,11 +4042,39 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, field->name(), field->number())); } } + for (int j = 0; j < result->reserved_range_count(); j++) { + const Descriptor::ReservedRange* range = result->reserved_range(j); + if (range->start <= field->number() && field->number() < range->end) { + AddError(field->full_name(), proto.reserved_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute( + "Field \"$0\" uses reserved number $1.", + field->name(), field->number())); + } + } + if (reserved_name_set.find(field->name()) != reserved_name_set.end()) { + AddError(field->full_name(), proto.field(i), + DescriptorPool::ErrorCollector::NAME, + strings::Substitute( + "Field name \"$0\" is reserved.", field->name())); + } } - // Check that extension ranges don't overlap. + // Check that extension ranges don't overlap and don't include + // reserved field numbers. for (int i = 0; i < result->extension_range_count(); i++) { const Descriptor::ExtensionRange* range1 = result->extension_range(i); + for (int j = 0; j < result->reserved_range_count(); j++) { + const Descriptor::ReservedRange* range2 = result->reserved_range(j); + if (range1->end > range2->start && range2->end > range1->start) { + AddError(result->full_name(), proto.extension_range(j), + DescriptorPool::ErrorCollector::NUMBER, + strings::Substitute("Extension range $0 to $1 overlaps with " + "reserved range $2 to $3.", + range1->start, range1->end - 1, + range2->start, range2->end - 1)); + } + } for (int j = i + 1; j < result->extension_range_count(); j++) { const Descriptor::ExtensionRange* range2 = result->extension_range(j); if (range1->end > range2->start && range2->end > range1->start) { @@ -4262,6 +4387,19 @@ void DescriptorBuilder::BuildExtensionRange( } } +void DescriptorBuilder::BuildReservedRange( + const DescriptorProto::ReservedRange& proto, + const Descriptor* parent, + Descriptor::ReservedRange* result) { + result->start = proto.start(); + result->end = proto.end(); + if (result->start <= 0) { + AddError(parent->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, + "Reserved numbers must be positive integers."); + } +} + void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent, OneofDescriptor* result) { @@ -4503,6 +4641,23 @@ void DescriptorBuilder::CrossLinkMessage( for (int i = 0; i < message->field_count(); i++) { const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof(); if (oneof_decl != NULL) { + // Make sure fields belonging to the same oneof are defined consecutively. + // This enables optimizations in codegens and reflection libraries to + // skip fields in the oneof group, as only one of the field can be set. + // Note that field_count() returns how many fields in this oneof we have + // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is + // safe. + if (oneof_decl->field_count() > 0 && + message->field(i - 1)->containing_oneof() != oneof_decl) { + AddWarning( + message->full_name() + "." + message->field(i - 1)->name(), + proto.field(i - 1), DescriptorPool::ErrorCollector::OTHER, + strings::Substitute( + "Fields in the same oneof must be defined consecutively. " + "\"$0\" cannot be defined before the completion of the " + "\"$1\" oneof definition.", + message->field(i - 1)->name(), oneof_decl->name())); + } // Must go through oneof_decls_ array to get a non-const version of the // OneofDescriptor. ++message->oneof_decls_[oneof_decl->index()].field_count_; @@ -4933,6 +5088,12 @@ void DescriptorBuilder::ValidateProto3Field( field->containing_type()->full_name() + "\" which is a proto3 message type."); } + bool allow_groups = false; + if (field->type() == FieldDescriptor::TYPE_GROUP && !allow_groups) { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::TYPE, + "Groups are not supported in proto3 syntax."); + } } void DescriptorBuilder::ValidateProto3Enum( diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index c0a48cea..ca87d634 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -135,10 +135,14 @@ struct DebugStringOptions { // example, the C++ code generation for fields in the proto compiler) rely on // DebugString() output being unobstructed by user comments. bool include_comments; + // If true, elide the braced body in the debug string. + bool elide_group_body; + bool elide_oneof_body; DebugStringOptions() - : include_comments(false) - {} + : include_comments(false), + elide_group_body(false), + elide_oneof_body(false) {} }; // Describes a type of protocol message, or a particular group within a @@ -298,6 +302,36 @@ class LIBPROTOBUF_EXPORT Descriptor { // this message type's scope. const FieldDescriptor* FindExtensionByCamelcaseName(const string& name) const; + // Reserved fields ------------------------------------------------- + + // A range of reserved field numbers. + struct ReservedRange { + int start; // inclusive + int end; // exclusive + }; + + // The number of reserved ranges in this message type. + int reserved_range_count() const; + // Gets an reserved range by index, where 0 <= index < + // reserved_range_count(). These are returned in the order they were defined + // in the .proto file. + const ReservedRange* reserved_range(int index) const; + + // Returns true if the number is in one of the reserved ranges. + bool IsReservedNumber(int number) const; + + // Returns NULL if no reserved range contains the given number. + const ReservedRange* FindReservedRangeContainingNumber(int number) const; + + // The number of reserved field names in this message type. + int reserved_name_count() const; + + // Gets a reserved name by index, where 0 <= index < reserved_name_count(). + const string& reserved_name(int index) const; + + // Returns true if the field name is reserved. + bool IsReservedName(const string& name) const; + // Source Location --------------------------------------------------- // Updates |*out_location| to the source location of the complete @@ -343,6 +377,10 @@ class LIBPROTOBUF_EXPORT Descriptor { ExtensionRange* extension_ranges_; int extension_count_; FieldDescriptor* extensions_; + int reserved_range_count_; + ReservedRange* reserved_ranges_; + int reserved_name_count_; + const string** reserved_names_; // IMPORTANT: If you add a new field, make sure to search for all instances // of Allocate() and AllocateArray() in descriptor.cc // and update them to initialize the field. @@ -1567,6 +1605,12 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range, const Descriptor::ExtensionRange*) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension, const FieldDescriptor*) + +PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_range_count, int) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, reserved_range, + const Descriptor::ReservedRange*) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, reserved_name_count, int) + PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions); PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool) @@ -1667,6 +1711,25 @@ inline bool Descriptor::IsExtensionNumber(int number) const { return FindExtensionRangeContainingNumber(number) != NULL; } +inline bool Descriptor::IsReservedNumber(int number) const { + return FindReservedRangeContainingNumber(number) != NULL; +} + +inline bool Descriptor::IsReservedName(const string& name) const { + for (int i = 0; i < reserved_name_count(); i++) { + if (name == reserved_name(i)) { + return true; + } + } + return false; +} + +// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because reserved_names_ is actually +// an array of pointers rather than the usual array of objects. +inline const string& Descriptor::reserved_name(int index) const { + return *reserved_names_[index]; +} + inline bool FieldDescriptor::is_required() const { return label() == LABEL_REQUIRED; } diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 8968f362..755c2617 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -33,6 +33,9 @@ const ::google::protobuf::internal::GeneratedMessageReflection* const ::google::protobuf::Descriptor* DescriptorProto_ExtensionRange_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* DescriptorProto_ExtensionRange_reflection_ = NULL; +const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + DescriptorProto_ReservedRange_reflection_ = NULL; const ::google::protobuf::Descriptor* FieldDescriptorProto_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* FieldDescriptorProto_reflection_ = NULL; @@ -64,6 +67,7 @@ const ::google::protobuf::Descriptor* FieldOptions_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* FieldOptions_reflection_ = NULL; const ::google::protobuf::EnumDescriptor* FieldOptions_CType_descriptor_ = NULL; +const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor_ = NULL; const ::google::protobuf::Descriptor* EnumOptions_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* EnumOptions_reflection_ = NULL; @@ -140,7 +144,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileDescriptorProto, _internal_metadata_), -1); DescriptorProto_descriptor_ = file->message_type(2); - static const int DescriptorProto_offsets_[8] = { + static const int DescriptorProto_offsets_[10] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_), @@ -149,6 +153,8 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_range_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, oneof_decl_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, options_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_range_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, reserved_name_), }; DescriptorProto_reflection_ = ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( @@ -177,6 +183,22 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { sizeof(DescriptorProto_ExtensionRange), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ExtensionRange, _internal_metadata_), -1); + DescriptorProto_ReservedRange_descriptor_ = DescriptorProto_descriptor_->nested_type(1); + static const int DescriptorProto_ReservedRange_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, start_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, end_), + }; + DescriptorProto_ReservedRange_reflection_ = + ::google::protobuf::internal::GeneratedMessageReflection::NewGeneratedMessageReflection( + DescriptorProto_ReservedRange_descriptor_, + DescriptorProto_ReservedRange::default_instance_, + DescriptorProto_ReservedRange_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _has_bits_[0]), + -1, + -1, + sizeof(DescriptorProto_ReservedRange), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto_ReservedRange, _internal_metadata_), + -1); FieldDescriptorProto_descriptor_ = file->message_type(3); static const int FieldDescriptorProto_offsets_[9] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_), @@ -338,9 +360,10 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, _internal_metadata_), -1); FieldOptions_descriptor_ = file->message_type(11); - static const int FieldOptions_offsets_[6] = { + static const int FieldOptions_offsets_[7] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, jstype_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, lazy_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, weak_), @@ -358,6 +381,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, _internal_metadata_), -1); FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0); + FieldOptions_JSType_descriptor_ = FieldOptions_descriptor_->enum_type(1); EnumOptions_descriptor_ = file->message_type(12); static const int EnumOptions_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_), @@ -514,6 +538,8 @@ void protobuf_RegisterTypes(const ::std::string&) { DescriptorProto_descriptor_, &DescriptorProto::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( DescriptorProto_ExtensionRange_descriptor_, &DescriptorProto_ExtensionRange::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + DescriptorProto_ReservedRange_descriptor_, &DescriptorProto_ReservedRange::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( FieldDescriptorProto_descriptor_, &FieldDescriptorProto::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -561,6 +587,8 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() { delete DescriptorProto_reflection_; delete DescriptorProto_ExtensionRange::default_instance_; delete DescriptorProto_ExtensionRange_reflection_; + delete DescriptorProto_ReservedRange::default_instance_; + delete DescriptorProto_ReservedRange_reflection_; delete FieldDescriptorProto::default_instance_; delete FieldDescriptorProto_reflection_; delete OneofDescriptorProto::default_instance_; @@ -619,7 +647,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001" - "(\t\"\344\003\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005" + "(\t\"\360\004\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005" "field\030\002 \003(\0132%.google.protobuf.FieldDescr" "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p" "rotobuf.FieldDescriptorProto\0225\n\013nested_t" @@ -630,104 +658,111 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo" "gle.protobuf.OneofDescriptorProto\0220\n\007opt" "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti" - "ons\032,\n\016ExtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003" - "end\030\002 \001(\005\"\251\005\n\024FieldDescriptorProto\022\014\n\004na" - "me\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162" - "+.google.protobuf.FieldDescriptorProto.L" - "abel\0228\n\004type\030\005 \001(\0162*.google.protobuf.Fie" - "ldDescriptorProto.Type\022\021\n\ttype_name\030\006 \001(" - "\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_value\030\007 \001" - "(\t\022\023\n\013oneof_index\030\t \001(\005\022.\n\007options\030\010 \001(\013" - "2\035.google.protobuf.FieldOptions\"\266\002\n\004Type" - "\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYP" - "E_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32" - "\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r" - "\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_G" - "ROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014" - "\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE" - "_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_S" - "INT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016LAB" - "EL_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LAB" - "EL_REPEATED\020\003\"$\n\024OneofDescriptorProto\022\014\n" - "\004name\030\001 \001(\t\"\214\001\n\023EnumDescriptorProto\022\014\n\004n" - "ame\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).google.protob" - "uf.EnumValueDescriptorProto\022-\n\007options\030\003" - " \001(\0132\034.google.protobuf.EnumOptions\"l\n\030En" - "umValueDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006" - "number\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.google.p" - "rotobuf.EnumValueOptions\"\220\001\n\026ServiceDesc" - "riptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002 \003(" - "\0132&.google.protobuf.MethodDescriptorProt" - "o\0220\n\007options\030\003 \001(\0132\037.google.protobuf.Ser" - "viceOptions\"\301\001\n\025MethodDescriptorProto\022\014\n" - "\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013outpu" - "t_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.google.p" - "rotobuf.MethodOptions\022\037\n\020client_streamin" - "g\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 \001(\010" - ":\005false\"\201\005\n\013FileOptions\022\024\n\014java_package\030" - "\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023j" - "ava_multiple_files\030\n \001(\010:\005false\022,\n\035java_" - "generate_equals_and_hash\030\024 \001(\010:\005false\022%\n" - "\026java_string_check_utf8\030\033 \001(\010:\005false\022F\n\014" - "optimize_for\030\t \001(\0162).google.protobuf.Fil" - "eOptions.OptimizeMode:\005SPEED\022\022\n\ngo_packa" - "ge\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005f" - "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal" - "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031" - "\n\ndeprecated\030\027 \001(\010:\005false\022\037\n\020cc_enable_a" - "renas\030\037 \001(\010:\005false\022\031\n\021objc_class_prefix\030" - "$ \001(\t\022\030\n\020csharp_namespace\030% \001(\t\022C\n\024unint" - "erpreted_option\030\347\007 \003(\0132$.google.protobuf" - ".UninterpretedOption\":\n\014OptimizeMode\022\t\n\005" - "SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003" - "*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016MessageOptions\022&\n\027messag" - "e_set_wire_format\030\001 \001(\010:\005false\022.\n\037no_sta" - "ndard_descriptor_accessor\030\002 \001(\010:\005false\022\031" - "\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_entry\030\007" - " \001(\010\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.go" - "ogle.protobuf.UninterpretedOption*\t\010\350\007\020\200" - "\200\200\200\002\"\240\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.g" - "oogle.protobuf.FieldOptions.CType:\006STRIN" - "G\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022\031" - "\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:" - "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." - "google.protobuf.UninterpretedOption\"/\n\005C" - "Type\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIE" - "CE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013allow" - "_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005false\022" - "C\n\024uninterpreted_option\030\347\007 \003(\0132$.google." - "protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"" - "}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:" - "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." - "google.protobuf.UninterpretedOption*\t\010\350\007" - "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!" + "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro" + "tobuf.DescriptorProto.ReservedRange\022\025\n\rr" + "eserved_name\030\n \003(\t\032,\n\016ExtensionRange\022\r\n\005" + "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\032+\n\rReservedRang" + "e\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\251\005\n\024FieldD" + "escriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003" + " \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf.Fi" + "eldDescriptorProto.Label\0228\n\004type\030\005 \001(\0162*" + ".google.protobuf.FieldDescriptorProto.Ty" + "pe\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022" + "\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030\t " + "\001(\005\022.\n\007options\030\010 \001(\0132\035.google.protobuf.F" + "ieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020\001\022\016\n" + "\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYPE_UI" + "NT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED64\020\006" + "\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYP" + "E_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE_MESSA" + "GE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n" + "\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rTYPE_" + "SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_SINT" + "64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n\016LAB" + "EL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"$\n\024One" + "ofDescriptorProto\022\014\n\004name\030\001 \001(\t\"\214\001\n\023Enum" + "DescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002" + " \003(\0132).google.protobuf.EnumValueDescript" + "orProto\022-\n\007options\030\003 \001(\0132\034.google.protob" + "uf.EnumOptions\"l\n\030EnumValueDescriptorPro" + "to\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007opti" + "ons\030\003 \001(\0132!.google.protobuf.EnumValueOpt" + "ions\"\220\001\n\026ServiceDescriptorProto\022\014\n\004name\030" + "\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.protobuf." + "MethodDescriptorProto\0220\n\007options\030\003 \001(\0132\037" + ".google.protobuf.ServiceOptions\"\301\001\n\025Meth" + "odDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\ninput" + "_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007opti" + "ons\030\004 \001(\0132\036.google.protobuf.MethodOption" + "s\022\037\n\020client_streaming\030\005 \001(\010:\005false\022\037\n\020se" + "rver_streaming\030\006 \001(\010:\005false\"\201\005\n\013FileOpti" + "ons\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_outer_" + "classname\030\010 \001(\t\022\"\n\023java_multiple_files\030\n" + " \001(\010:\005false\022,\n\035java_generate_equals_and_" + "hash\030\024 \001(\010:\005false\022%\n\026java_string_check_u" + "tf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001(\0162)" + ".google.protobuf.FileOptions.OptimizeMod" + "e:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_gener" + "ic_services\030\020 \001(\010:\005false\022$\n\025java_generic" + "_services\030\021 \001(\010:\005false\022\"\n\023py_generic_ser" + "vices\030\022 \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005" + "false\022\037\n\020cc_enable_arenas\030\037 \001(\010:\005false\022\031" + "\n\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_name" + "space\030% \001(\t\022C\n\024uninterpreted_option\030\347\007 \003" + "(\0132$.google.protobuf.UninterpretedOption" + "\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE" + "\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\346\001\n\016Mess" + "ageOptions\022&\n\027message_set_wire_format\030\001 " + "\001(\010:\005false\022.\n\037no_standard_descriptor_acc" + "essor\030\002 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005" + "false\022\021\n\tmap_entry\030\007 \001(\010\022C\n\024uninterprete" + "d_option\030\347\007 \003(\0132$.google.protobuf.Uninte" + "rpretedOption*\t\010\350\007\020\200\200\200\200\002\"\230\003\n\014FieldOption" + "s\022:\n\005ctype\030\001 \001(\0162#.google.protobuf.Field" + "Options.CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\?\n" + "\006jstype\030\006 \001(\0162$.google.protobuf.FieldOpt" + "ions.JSType:\tJS_NORMAL\022\023\n\004lazy\030\005 \001(\010:\005fa" + "lse\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n" " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003" "(\0132$.google.protobuf.UninterpretedOption" - "*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprecat" - "ed\030! \001(\010:\005false\022C\n\024uninterpreted_option\030" - "\347\007 \003(\0132$.google.protobuf.UninterpretedOp" - "tion*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOption\022" - ";\n\004name\030\002 \003(\0132-.google.protobuf.Uninterp" - "retedOption.NamePart\022\030\n\020identifier_value" - "\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022ne" - "gative_int_value\030\005 \001(\003\022\024\n\014double_value\030\006" - " \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_" - "value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002" - "(\t\022\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeI" - "nfo\022:\n\010location\030\001 \003(\0132(.google.protobuf." - "SourceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004" - "path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lead" - "ing_comments\030\003 \001(\t\022\031\n\021trailing_comments\030" - "\004 \001(\t\022!\n\031leading_detached_comments\030\006 \003(\t" - "BY\n\023com.google.protobufB\020DescriptorProto" - "sH\001\242\002\003GPB\252\002\'Google.ProtocolBuffers.Descr" - "iptorProtos", 4691); + "\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRIN" + "G_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMAL\020\000\022\r\n\tJS" + "_STRING\020\001\022\r\n\tJS_NUMBER\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013" + "EnumOptions\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndepr" + "ecated\030\003 \001(\010:\005false\022C\n\024uninterpreted_opt" + "ion\030\347\007 \003(\0132$.google.protobuf.Uninterpret" + "edOption*\t\010\350\007\020\200\200\200\200\002\"}\n\020EnumValueOptions\022" + "\031\n\ndeprecated\030\001 \001(\010:\005false\022C\n\024uninterpre" + "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin" + "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"{\n\016ServiceOpt" + "ions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024unint" + "erpreted_option\030\347\007 \003(\0132$.google.protobuf" + ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"z\n\rMetho" + "dOptions\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024u" + "ninterpreted_option\030\347\007 \003(\0132$.google.prot" + "obuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023" + "UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goog" + "le.protobuf.UninterpretedOption.NamePart" + "\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_i" + "nt_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001" + "(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_value" + "\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NameP" + "art\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002" + " \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003(" + "\0132(.google.protobuf.SourceCodeInfo.Locat" + "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp" + "an\030\002 \003(\005B\002\020\001\022\030\n\020leading_comments\030\003 \001(\t\022\031" + "\n\021trailing_comments\030\004 \001(\t\022!\n\031leading_det" + "ached_comments\030\006 \003(\tBY\n\023com.google.proto" + "bufB\020DescriptorProtosH\001\242\002\003GPB\252\002\'Google.P" + "rotocolBuffers.DescriptorProtos", 4951); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); FileDescriptorProto::default_instance_ = new FileDescriptorProto(); DescriptorProto::default_instance_ = new DescriptorProto(); DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange(); + DescriptorProto_ReservedRange::default_instance_ = new DescriptorProto_ReservedRange(); FieldDescriptorProto::default_instance_ = new FieldDescriptorProto(); OneofDescriptorProto::default_instance_ = new OneofDescriptorProto(); EnumDescriptorProto::default_instance_ = new EnumDescriptorProto(); @@ -749,6 +784,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { FileDescriptorProto::default_instance_->InitAsDefaultInstance(); DescriptorProto::default_instance_->InitAsDefaultInstance(); DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance(); + DescriptorProto_ReservedRange::default_instance_->InitAsDefaultInstance(); FieldDescriptorProto::default_instance_->InitAsDefaultInstance(); OneofDescriptorProto::default_instance_->InitAsDefaultInstance(); EnumDescriptorProto::default_instance_->InitAsDefaultInstance(); @@ -793,7 +829,7 @@ const int FileDescriptorSet::kFileFieldNumber; #endif // !_MSC_VER FileDescriptorSet::FileDescriptorSet() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet) } @@ -870,13 +906,15 @@ bool FileDescriptorSet::MergePartialFromCodedStream( // repeated .google.protobuf.FileDescriptorProto file = 1; case 1: { if (tag == 10) { - parse_file: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_file: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_file())); } else { goto handle_unusual; } - if (input->ExpectTag(10)) goto parse_file; + if (input->ExpectTag(10)) goto parse_loop_file; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -961,9 +999,9 @@ int FileDescriptorSet::ByteSize() const { void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const FileDescriptorSet* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const FileDescriptorSet* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1020,10 +1058,10 @@ void FileDescriptorSet::InternalSwap(FileDescriptorSet* other) { // FileDescriptorSet // repeated .google.protobuf.FileDescriptorProto file = 1; - int FileDescriptorSet::file_size() const { +int FileDescriptorSet::file_size() const { return file_.size(); } - void FileDescriptorSet::clear_file() { +void FileDescriptorSet::clear_file() { file_.Clear(); } const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { @@ -1069,7 +1107,7 @@ const int FileDescriptorProto::kSyntaxFieldNumber; #endif // !_MSC_VER FileDescriptorProto::FileDescriptorProto() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto) } @@ -1237,54 +1275,63 @@ bool FileDescriptorProto::MergePartialFromCodedStream( case 4: { if (tag == 34) { parse_message_type: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_message_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_message_type())); } else { goto handle_unusual; } - if (input->ExpectTag(34)) goto parse_message_type; - if (input->ExpectTag(42)) goto parse_enum_type; + if (input->ExpectTag(34)) goto parse_loop_message_type; + if (input->ExpectTag(42)) goto parse_loop_enum_type; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; case 5: { if (tag == 42) { - parse_enum_type: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_enum_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_enum_type())); } else { goto handle_unusual; } - if (input->ExpectTag(42)) goto parse_enum_type; - if (input->ExpectTag(50)) goto parse_service; + if (input->ExpectTag(42)) goto parse_loop_enum_type; + if (input->ExpectTag(50)) goto parse_loop_service; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.ServiceDescriptorProto service = 6; case 6: { if (tag == 50) { - parse_service: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_service: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_service())); } else { goto handle_unusual; } - if (input->ExpectTag(50)) goto parse_service; - if (input->ExpectTag(58)) goto parse_extension; + if (input->ExpectTag(50)) goto parse_loop_service; + if (input->ExpectTag(58)) goto parse_loop_extension; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.FieldDescriptorProto extension = 7; case 7: { if (tag == 58) { - parse_extension: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_extension: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_extension())); } else { goto handle_unusual; } - if (input->ExpectTag(58)) goto parse_extension; + if (input->ExpectTag(58)) goto parse_loop_extension; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(66)) goto parse_options; break; } @@ -1712,9 +1759,9 @@ int FileDescriptorProto::ByteSize() const { void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const FileDescriptorProto* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const FileDescriptorProto* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1816,16 +1863,16 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { // FileDescriptorProto // optional string name = 1; - bool FileDescriptorProto::has_name() const { +bool FileDescriptorProto::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void FileDescriptorProto::set_has_name() { +void FileDescriptorProto::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void FileDescriptorProto::clear_has_name() { +void FileDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void FileDescriptorProto::clear_name() { +void FileDescriptorProto::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -1869,16 +1916,16 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { } // optional string package = 2; - bool FileDescriptorProto::has_package() const { +bool FileDescriptorProto::has_package() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void FileDescriptorProto::set_has_package() { +void FileDescriptorProto::set_has_package() { _has_bits_[0] |= 0x00000002u; } - void FileDescriptorProto::clear_has_package() { +void FileDescriptorProto::clear_has_package() { _has_bits_[0] &= ~0x00000002u; } - void FileDescriptorProto::clear_package() { +void FileDescriptorProto::clear_package() { package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_package(); } @@ -1922,10 +1969,10 @@ void FileDescriptorProto::InternalSwap(FileDescriptorProto* other) { } // repeated string dependency = 3; - int FileDescriptorProto::dependency_size() const { +int FileDescriptorProto::dependency_size() const { return dependency_.size(); } - void FileDescriptorProto::clear_dependency() { +void FileDescriptorProto::clear_dependency() { dependency_.Clear(); } const ::std::string& FileDescriptorProto::dependency(int index) const { @@ -1976,10 +2023,10 @@ FileDescriptorProto::mutable_dependency() { } // repeated int32 public_dependency = 10; - int FileDescriptorProto::public_dependency_size() const { +int FileDescriptorProto::public_dependency_size() const { return public_dependency_.size(); } - void FileDescriptorProto::clear_public_dependency() { +void FileDescriptorProto::clear_public_dependency() { public_dependency_.Clear(); } ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const { @@ -2006,10 +2053,10 @@ FileDescriptorProto::mutable_public_dependency() { } // repeated int32 weak_dependency = 11; - int FileDescriptorProto::weak_dependency_size() const { +int FileDescriptorProto::weak_dependency_size() const { return weak_dependency_.size(); } - void FileDescriptorProto::clear_weak_dependency() { +void FileDescriptorProto::clear_weak_dependency() { weak_dependency_.Clear(); } ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const { @@ -2036,10 +2083,10 @@ FileDescriptorProto::mutable_weak_dependency() { } // repeated .google.protobuf.DescriptorProto message_type = 4; - int FileDescriptorProto::message_type_size() const { +int FileDescriptorProto::message_type_size() const { return message_type_.size(); } - void FileDescriptorProto::clear_message_type() { +void FileDescriptorProto::clear_message_type() { message_type_.Clear(); } const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { @@ -2066,10 +2113,10 @@ FileDescriptorProto::mutable_message_type() { } // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; - int FileDescriptorProto::enum_type_size() const { +int FileDescriptorProto::enum_type_size() const { return enum_type_.size(); } - void FileDescriptorProto::clear_enum_type() { +void FileDescriptorProto::clear_enum_type() { enum_type_.Clear(); } const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { @@ -2096,10 +2143,10 @@ FileDescriptorProto::mutable_enum_type() { } // repeated .google.protobuf.ServiceDescriptorProto service = 6; - int FileDescriptorProto::service_size() const { +int FileDescriptorProto::service_size() const { return service_.size(); } - void FileDescriptorProto::clear_service() { +void FileDescriptorProto::clear_service() { service_.Clear(); } const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { @@ -2126,10 +2173,10 @@ FileDescriptorProto::mutable_service() { } // repeated .google.protobuf.FieldDescriptorProto extension = 7; - int FileDescriptorProto::extension_size() const { +int FileDescriptorProto::extension_size() const { return extension_.size(); } - void FileDescriptorProto::clear_extension() { +void FileDescriptorProto::clear_extension() { extension_.Clear(); } const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { @@ -2156,16 +2203,16 @@ FileDescriptorProto::mutable_extension() { } // optional .google.protobuf.FileOptions options = 8; - bool FileDescriptorProto::has_options() const { +bool FileDescriptorProto::has_options() const { return (_has_bits_[0] & 0x00000200u) != 0; } - void FileDescriptorProto::set_has_options() { +void FileDescriptorProto::set_has_options() { _has_bits_[0] |= 0x00000200u; } - void FileDescriptorProto::clear_has_options() { +void FileDescriptorProto::clear_has_options() { _has_bits_[0] &= ~0x00000200u; } - void FileDescriptorProto::clear_options() { +void FileDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); clear_has_options(); } @@ -2199,16 +2246,16 @@ FileDescriptorProto::mutable_extension() { } // optional .google.protobuf.SourceCodeInfo source_code_info = 9; - bool FileDescriptorProto::has_source_code_info() const { +bool FileDescriptorProto::has_source_code_info() const { return (_has_bits_[0] & 0x00000400u) != 0; } - void FileDescriptorProto::set_has_source_code_info() { +void FileDescriptorProto::set_has_source_code_info() { _has_bits_[0] |= 0x00000400u; } - void FileDescriptorProto::clear_has_source_code_info() { +void FileDescriptorProto::clear_has_source_code_info() { _has_bits_[0] &= ~0x00000400u; } - void FileDescriptorProto::clear_source_code_info() { +void FileDescriptorProto::clear_source_code_info() { if (source_code_info_ != NULL) source_code_info_->::google::protobuf::SourceCodeInfo::Clear(); clear_has_source_code_info(); } @@ -2242,16 +2289,16 @@ FileDescriptorProto::mutable_extension() { } // optional string syntax = 12; - bool FileDescriptorProto::has_syntax() const { +bool FileDescriptorProto::has_syntax() const { return (_has_bits_[0] & 0x00000800u) != 0; } - void FileDescriptorProto::set_has_syntax() { +void FileDescriptorProto::set_has_syntax() { _has_bits_[0] |= 0x00000800u; } - void FileDescriptorProto::clear_has_syntax() { +void FileDescriptorProto::clear_has_syntax() { _has_bits_[0] &= ~0x00000800u; } - void FileDescriptorProto::clear_syntax() { +void FileDescriptorProto::clear_syntax() { syntax_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_syntax(); } @@ -2304,7 +2351,7 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber; #endif // !_MSC_VER DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ExtensionRange) } @@ -2516,9 +2563,9 @@ int DescriptorProto_ExtensionRange::ByteSize() const { void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const DescriptorProto_ExtensionRange* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const DescriptorProto_ExtensionRange* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -2579,6 +2626,289 @@ void DescriptorProto_ExtensionRange::InternalSwap(DescriptorProto_ExtensionRange } +// ------------------------------------------------------------------- + +#ifndef _MSC_VER +const int DescriptorProto_ReservedRange::kStartFieldNumber; +const int DescriptorProto_ReservedRange::kEndFieldNumber; +#endif // !_MSC_VER + +DescriptorProto_ReservedRange::DescriptorProto_ReservedRange() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ReservedRange) +} + +void DescriptorProto_ReservedRange::InitAsDefaultInstance() { +} + +DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { + SharedCtor(); + MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ReservedRange) +} + +void DescriptorProto_ReservedRange::SharedCtor() { + _cached_size_ = 0; + start_ = 0; + end_ = 0; + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +DescriptorProto_ReservedRange::~DescriptorProto_ReservedRange() { + // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ReservedRange) + SharedDtor(); +} + +void DescriptorProto_ReservedRange::SharedDtor() { + if (this != default_instance_) { + } +} + +void DescriptorProto_ReservedRange::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* DescriptorProto_ReservedRange::descriptor() { + protobuf_AssignDescriptorsOnce(); + return DescriptorProto_ReservedRange_descriptor_; +} + +const DescriptorProto_ReservedRange& DescriptorProto_ReservedRange::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::default_instance_ = NULL; + +DescriptorProto_ReservedRange* DescriptorProto_ReservedRange::New(::google::protobuf::Arena* arena) const { + DescriptorProto_ReservedRange* n = new DescriptorProto_ReservedRange; + if (arena != NULL) { + arena->Own(n); + } + return n; +} + +void DescriptorProto_ReservedRange::Clear() { +#define ZR_HELPER_(f) reinterpret_cast(\ + &reinterpret_cast(16)->f) + +#define ZR_(first, last) do {\ + ::memset(&first, 0,\ + ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ +} while (0) + + ZR_(start_, end_); + +#undef ZR_HELPER_ +#undef ZR_ + + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + if (_internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->Clear(); + } +} + +bool DescriptorProto_ReservedRange::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ReservedRange) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional int32 start = 1; + case 1: { + if (tag == 8) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &start_))); + set_has_start(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(16)) goto parse_end; + break; + } + + // optional int32 end = 2; + case 2: { + if (tag == 16) { + parse_end: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &end_))); + set_has_end(); + } else { + goto handle_unusual; + } + if (input->ExpectAtEnd()) goto success; + break; + } + + default: { + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ReservedRange) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ReservedRange) + return false; +#undef DO_ +} + +void DescriptorProto_ReservedRange::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ReservedRange) + // optional int32 start = 1; + if (has_start()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output); + } + + // optional int32 end = 2; + if (has_end()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->end(), output); + } + + if (_internal_metadata_.have_unknown_fields()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ReservedRange) +} + +::google::protobuf::uint8* DescriptorProto_ReservedRange::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange) + // optional int32 start = 1; + if (has_start()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target); + } + + // optional int32 end = 2; + if (has_end()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->end(), target); + } + + if (_internal_metadata_.have_unknown_fields()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ReservedRange) + return target; +} + +int DescriptorProto_ReservedRange::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & 3) { + // optional int32 start = 1; + if (has_start()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->start()); + } + + // optional int32 end = 2; + if (has_end()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->end()); + } + + } + if (_internal_metadata_.have_unknown_fields()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) { + if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + const DescriptorProto_ReservedRange* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) { + if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_start()) { + set_start(from.start()); + } + if (from.has_end()) { + set_end(from.end()); + } + } + if (from._internal_metadata_.have_unknown_fields()) { + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); + } +} + +void DescriptorProto_ReservedRange::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void DescriptorProto_ReservedRange::CopyFrom(const DescriptorProto_ReservedRange& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool DescriptorProto_ReservedRange::IsInitialized() const { + + return true; +} + +void DescriptorProto_ReservedRange::Swap(DescriptorProto_ReservedRange* other) { + if (other == this) return; + InternalSwap(other); +} +void DescriptorProto_ReservedRange::InternalSwap(DescriptorProto_ReservedRange* other) { + std::swap(start_, other->start_); + std::swap(end_, other->end_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _internal_metadata_.Swap(&other->_internal_metadata_); + std::swap(_cached_size_, other->_cached_size_); +} + +::google::protobuf::Metadata DescriptorProto_ReservedRange::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = DescriptorProto_ReservedRange_descriptor_; + metadata.reflection = DescriptorProto_ReservedRange_reflection_; + return metadata; +} + + // ------------------------------------------------------------------- #ifndef _MSC_VER @@ -2590,10 +2920,12 @@ const int DescriptorProto::kEnumTypeFieldNumber; const int DescriptorProto::kExtensionRangeFieldNumber; const int DescriptorProto::kOneofDeclFieldNumber; const int DescriptorProto::kOptionsFieldNumber; +const int DescriptorProto::kReservedRangeFieldNumber; +const int DescriptorProto::kReservedNameFieldNumber; #endif // !_MSC_VER DescriptorProto::DescriptorProto() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto) } @@ -2670,6 +3002,8 @@ void DescriptorProto::Clear() { enum_type_.Clear(); extension_range_.Clear(); oneof_decl_.Clear(); + reserved_range_.Clear(); + reserved_name_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); if (_internal_metadata_.have_unknown_fields()) { mutable_unknown_fields()->Clear(); @@ -2706,68 +3040,79 @@ bool DescriptorProto::MergePartialFromCodedStream( case 2: { if (tag == 18) { parse_field: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_field: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_field())); } else { goto handle_unusual; } - if (input->ExpectTag(18)) goto parse_field; - if (input->ExpectTag(26)) goto parse_nested_type; + if (input->ExpectTag(18)) goto parse_loop_field; + if (input->ExpectTag(26)) goto parse_loop_nested_type; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.DescriptorProto nested_type = 3; case 3: { if (tag == 26) { - parse_nested_type: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_nested_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_nested_type())); } else { goto handle_unusual; } - if (input->ExpectTag(26)) goto parse_nested_type; - if (input->ExpectTag(34)) goto parse_enum_type; + if (input->ExpectTag(26)) goto parse_loop_nested_type; + if (input->ExpectTag(34)) goto parse_loop_enum_type; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; case 4: { if (tag == 34) { - parse_enum_type: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_enum_type: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_enum_type())); } else { goto handle_unusual; } - if (input->ExpectTag(34)) goto parse_enum_type; - if (input->ExpectTag(42)) goto parse_extension_range; + if (input->ExpectTag(34)) goto parse_loop_enum_type; + if (input->ExpectTag(42)) goto parse_loop_extension_range; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; case 5: { if (tag == 42) { - parse_extension_range: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_extension_range: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_extension_range())); } else { goto handle_unusual; } - if (input->ExpectTag(42)) goto parse_extension_range; - if (input->ExpectTag(50)) goto parse_extension; + if (input->ExpectTag(42)) goto parse_loop_extension_range; + if (input->ExpectTag(50)) goto parse_loop_extension; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.FieldDescriptorProto extension = 6; case 6: { if (tag == 50) { - parse_extension: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_extension: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_extension())); } else { goto handle_unusual; } - if (input->ExpectTag(50)) goto parse_extension; + if (input->ExpectTag(50)) goto parse_loop_extension; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(58)) goto parse_options; break; } @@ -2789,12 +3134,50 @@ bool DescriptorProto::MergePartialFromCodedStream( case 8: { if (tag == 66) { parse_oneof_decl: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_oneof_decl: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_oneof_decl())); } else { goto handle_unusual; } - if (input->ExpectTag(66)) goto parse_oneof_decl; + if (input->ExpectTag(66)) goto parse_loop_oneof_decl; + if (input->ExpectTag(74)) goto parse_loop_reserved_range; + input->UnsafeDecrementRecursionDepth(); + break; + } + + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + case 9: { + if (tag == 74) { + DO_(input->IncrementRecursionDepth()); + parse_loop_reserved_range: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( + input, add_reserved_range())); + } else { + goto handle_unusual; + } + if (input->ExpectTag(74)) goto parse_loop_reserved_range; + input->UnsafeDecrementRecursionDepth(); + if (input->ExpectTag(82)) goto parse_reserved_name; + break; + } + + // repeated string reserved_name = 10; + case 10: { + if (tag == 82) { + parse_reserved_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->add_reserved_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->reserved_name(this->reserved_name_size() - 1).data(), + this->reserved_name(this->reserved_name_size() - 1).length(), + ::google::protobuf::internal::WireFormat::PARSE, + "google.protobuf.DescriptorProto.reserved_name"); + } else { + goto handle_unusual; + } + if (input->ExpectTag(82)) goto parse_reserved_name; if (input->ExpectAtEnd()) goto success; break; } @@ -2876,6 +3259,22 @@ void DescriptorProto::SerializeWithCachedSizes( 8, this->oneof_decl(i), output); } + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 9, this->reserved_range(i), output); + } + + // repeated string reserved_name = 10; + for (int i = 0; i < this->reserved_name_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->reserved_name(i).data(), this->reserved_name(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.DescriptorProto.reserved_name"); + ::google::protobuf::internal::WireFormatLite::WriteString( + 10, this->reserved_name(i), output); + } + if (_internal_metadata_.have_unknown_fields()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); @@ -2946,6 +3345,23 @@ void DescriptorProto::SerializeWithCachedSizes( 8, this->oneof_decl(i), target); } + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + for (unsigned int i = 0, n = this->reserved_range_size(); i < n; i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 9, this->reserved_range(i), target); + } + + // repeated string reserved_name = 10; + for (int i = 0; i < this->reserved_name_size(); i++) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->reserved_name(i).data(), this->reserved_name(i).length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "google.protobuf.DescriptorProto.reserved_name"); + target = ::google::protobuf::internal::WireFormatLite:: + WriteStringToArray(10, this->reserved_name(i), target); + } + if (_internal_metadata_.have_unknown_fields()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); @@ -3021,6 +3437,21 @@ int DescriptorProto::ByteSize() const { this->oneof_decl(i)); } + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + total_size += 1 * this->reserved_range_size(); + for (int i = 0; i < this->reserved_range_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->reserved_range(i)); + } + + // repeated string reserved_name = 10; + total_size += 1 * this->reserved_name_size(); + for (int i = 0; i < this->reserved_name_size(); i++) { + total_size += ::google::protobuf::internal::WireFormatLite::StringSize( + this->reserved_name(i)); + } + if (_internal_metadata_.have_unknown_fields()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -3034,9 +3465,9 @@ int DescriptorProto::ByteSize() const { void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const DescriptorProto* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const DescriptorProto* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -3052,6 +3483,8 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) { enum_type_.MergeFrom(from.enum_type_); extension_range_.MergeFrom(from.extension_range_); oneof_decl_.MergeFrom(from.oneof_decl_); + reserved_range_.MergeFrom(from.reserved_range_); + reserved_name_.MergeFrom(from.reserved_name_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { set_has_name(); @@ -3103,6 +3536,8 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { extension_range_.UnsafeArenaSwap(&other->extension_range_); oneof_decl_.UnsafeArenaSwap(&other->oneof_decl_); std::swap(options_, other->options_); + reserved_range_.UnsafeArenaSwap(&other->reserved_range_); + reserved_name_.UnsafeArenaSwap(&other->reserved_name_); std::swap(_has_bits_[0], other->_has_bits_[0]); _internal_metadata_.Swap(&other->_internal_metadata_); std::swap(_cached_size_, other->_cached_size_); @@ -3120,16 +3555,16 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { // DescriptorProto_ExtensionRange // optional int32 start = 1; - bool DescriptorProto_ExtensionRange::has_start() const { +bool DescriptorProto_ExtensionRange::has_start() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void DescriptorProto_ExtensionRange::set_has_start() { +void DescriptorProto_ExtensionRange::set_has_start() { _has_bits_[0] |= 0x00000001u; } - void DescriptorProto_ExtensionRange::clear_has_start() { +void DescriptorProto_ExtensionRange::clear_has_start() { _has_bits_[0] &= ~0x00000001u; } - void DescriptorProto_ExtensionRange::clear_start() { +void DescriptorProto_ExtensionRange::clear_start() { start_ = 0; clear_has_start(); } @@ -3144,16 +3579,16 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { } // optional int32 end = 2; - bool DescriptorProto_ExtensionRange::has_end() const { +bool DescriptorProto_ExtensionRange::has_end() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void DescriptorProto_ExtensionRange::set_has_end() { +void DescriptorProto_ExtensionRange::set_has_end() { _has_bits_[0] |= 0x00000002u; } - void DescriptorProto_ExtensionRange::clear_has_end() { +void DescriptorProto_ExtensionRange::clear_has_end() { _has_bits_[0] &= ~0x00000002u; } - void DescriptorProto_ExtensionRange::clear_end() { +void DescriptorProto_ExtensionRange::clear_end() { end_ = 0; clear_has_end(); } @@ -3169,19 +3604,71 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { // ------------------------------------------------------------------- +// DescriptorProto_ReservedRange + +// optional int32 start = 1; +bool DescriptorProto_ReservedRange::has_start() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +void DescriptorProto_ReservedRange::set_has_start() { + _has_bits_[0] |= 0x00000001u; +} +void DescriptorProto_ReservedRange::clear_has_start() { + _has_bits_[0] &= ~0x00000001u; +} +void DescriptorProto_ReservedRange::clear_start() { + start_ = 0; + clear_has_start(); +} + ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start) + return start_; +} + void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) { + set_has_start(); + start_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start) +} + +// optional int32 end = 2; +bool DescriptorProto_ReservedRange::has_end() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +void DescriptorProto_ReservedRange::set_has_end() { + _has_bits_[0] |= 0x00000002u; +} +void DescriptorProto_ReservedRange::clear_has_end() { + _has_bits_[0] &= ~0x00000002u; +} +void DescriptorProto_ReservedRange::clear_end() { + end_ = 0; + clear_has_end(); +} + ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end) + return end_; +} + void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) { + set_has_end(); + end_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end) +} + +// ------------------------------------------------------------------- + // DescriptorProto // optional string name = 1; - bool DescriptorProto::has_name() const { +bool DescriptorProto::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void DescriptorProto::set_has_name() { +void DescriptorProto::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void DescriptorProto::clear_has_name() { +void DescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void DescriptorProto::clear_name() { +void DescriptorProto::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -3225,10 +3712,10 @@ void DescriptorProto::InternalSwap(DescriptorProto* other) { } // repeated .google.protobuf.FieldDescriptorProto field = 2; - int DescriptorProto::field_size() const { +int DescriptorProto::field_size() const { return field_.size(); } - void DescriptorProto::clear_field() { +void DescriptorProto::clear_field() { field_.Clear(); } const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { @@ -3255,10 +3742,10 @@ DescriptorProto::mutable_field() { } // repeated .google.protobuf.FieldDescriptorProto extension = 6; - int DescriptorProto::extension_size() const { +int DescriptorProto::extension_size() const { return extension_.size(); } - void DescriptorProto::clear_extension() { +void DescriptorProto::clear_extension() { extension_.Clear(); } const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { @@ -3285,10 +3772,10 @@ DescriptorProto::mutable_extension() { } // repeated .google.protobuf.DescriptorProto nested_type = 3; - int DescriptorProto::nested_type_size() const { +int DescriptorProto::nested_type_size() const { return nested_type_.size(); } - void DescriptorProto::clear_nested_type() { +void DescriptorProto::clear_nested_type() { nested_type_.Clear(); } const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { @@ -3315,10 +3802,10 @@ DescriptorProto::mutable_nested_type() { } // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; - int DescriptorProto::enum_type_size() const { +int DescriptorProto::enum_type_size() const { return enum_type_.size(); } - void DescriptorProto::clear_enum_type() { +void DescriptorProto::clear_enum_type() { enum_type_.Clear(); } const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { @@ -3345,10 +3832,10 @@ DescriptorProto::mutable_enum_type() { } // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; - int DescriptorProto::extension_range_size() const { +int DescriptorProto::extension_range_size() const { return extension_range_.size(); } - void DescriptorProto::clear_extension_range() { +void DescriptorProto::clear_extension_range() { extension_range_.Clear(); } const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { @@ -3375,10 +3862,10 @@ DescriptorProto::mutable_extension_range() { } // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; - int DescriptorProto::oneof_decl_size() const { +int DescriptorProto::oneof_decl_size() const { return oneof_decl_.size(); } - void DescriptorProto::clear_oneof_decl() { +void DescriptorProto::clear_oneof_decl() { oneof_decl_.Clear(); } const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { @@ -3405,16 +3892,16 @@ DescriptorProto::mutable_oneof_decl() { } // optional .google.protobuf.MessageOptions options = 7; - bool DescriptorProto::has_options() const { +bool DescriptorProto::has_options() const { return (_has_bits_[0] & 0x00000080u) != 0; } - void DescriptorProto::set_has_options() { +void DescriptorProto::set_has_options() { _has_bits_[0] |= 0x00000080u; } - void DescriptorProto::clear_has_options() { +void DescriptorProto::clear_has_options() { _has_bits_[0] &= ~0x00000080u; } - void DescriptorProto::clear_options() { +void DescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); clear_has_options(); } @@ -3447,6 +3934,90 @@ DescriptorProto::mutable_oneof_decl() { // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) } +// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; +int DescriptorProto::reserved_range_size() const { + return reserved_range_.size(); +} +void DescriptorProto::clear_reserved_range() { + reserved_range_.Clear(); +} + const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range) + return reserved_range_.Get(index); +} + ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range) + return reserved_range_.Mutable(index); +} + ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range) + return reserved_range_.Add(); +} + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >& +DescriptorProto::reserved_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range) + return reserved_range_; +} + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >* +DescriptorProto::mutable_reserved_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range) + return &reserved_range_; +} + +// repeated string reserved_name = 10; +int DescriptorProto::reserved_name_size() const { + return reserved_name_.size(); +} +void DescriptorProto::clear_reserved_name() { + reserved_name_.Clear(); +} + const ::std::string& DescriptorProto::reserved_name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name) + return reserved_name_.Get(index); +} + ::std::string* DescriptorProto::mutable_reserved_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name) + return reserved_name_.Mutable(index); +} + void DescriptorProto::set_reserved_name(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) + reserved_name_.Mutable(index)->assign(value); +} + void DescriptorProto::set_reserved_name(int index, const char* value) { + reserved_name_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name) +} + void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) { + reserved_name_.Mutable(index)->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name) +} + ::std::string* DescriptorProto::add_reserved_name() { + return reserved_name_.Add(); +} + void DescriptorProto::add_reserved_name(const ::std::string& value) { + reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) +} + void DescriptorProto::add_reserved_name(const char* value) { + reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name) +} + void DescriptorProto::add_reserved_name(const char* value, size_t size) { + reserved_name_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name) +} + const ::google::protobuf::RepeatedPtrField< ::std::string>& +DescriptorProto::reserved_name() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name) + return reserved_name_; +} + ::google::protobuf::RepeatedPtrField< ::std::string>* +DescriptorProto::mutable_reserved_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name) + return &reserved_name_; +} + #endif // PROTOBUF_INLINE_NOT_IN_HEADERS // =================================================================== @@ -3540,7 +4111,7 @@ const int FieldDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER FieldDescriptorProto::FieldDescriptorProto() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.FieldDescriptorProto) } @@ -4063,9 +4634,9 @@ int FieldDescriptorProto::ByteSize() const { void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const FieldDescriptorProto* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const FieldDescriptorProto* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -4166,16 +4737,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { // FieldDescriptorProto // optional string name = 1; - bool FieldDescriptorProto::has_name() const { +bool FieldDescriptorProto::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void FieldDescriptorProto::set_has_name() { +void FieldDescriptorProto::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void FieldDescriptorProto::clear_has_name() { +void FieldDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void FieldDescriptorProto::clear_name() { +void FieldDescriptorProto::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -4219,16 +4790,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { } // optional int32 number = 3; - bool FieldDescriptorProto::has_number() const { +bool FieldDescriptorProto::has_number() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void FieldDescriptorProto::set_has_number() { +void FieldDescriptorProto::set_has_number() { _has_bits_[0] |= 0x00000002u; } - void FieldDescriptorProto::clear_has_number() { +void FieldDescriptorProto::clear_has_number() { _has_bits_[0] &= ~0x00000002u; } - void FieldDescriptorProto::clear_number() { +void FieldDescriptorProto::clear_number() { number_ = 0; clear_has_number(); } @@ -4243,16 +4814,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; - bool FieldDescriptorProto::has_label() const { +bool FieldDescriptorProto::has_label() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void FieldDescriptorProto::set_has_label() { +void FieldDescriptorProto::set_has_label() { _has_bits_[0] |= 0x00000004u; } - void FieldDescriptorProto::clear_has_label() { +void FieldDescriptorProto::clear_has_label() { _has_bits_[0] &= ~0x00000004u; } - void FieldDescriptorProto::clear_label() { +void FieldDescriptorProto::clear_label() { label_ = 1; clear_has_label(); } @@ -4268,16 +4839,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; - bool FieldDescriptorProto::has_type() const { +bool FieldDescriptorProto::has_type() const { return (_has_bits_[0] & 0x00000008u) != 0; } - void FieldDescriptorProto::set_has_type() { +void FieldDescriptorProto::set_has_type() { _has_bits_[0] |= 0x00000008u; } - void FieldDescriptorProto::clear_has_type() { +void FieldDescriptorProto::clear_has_type() { _has_bits_[0] &= ~0x00000008u; } - void FieldDescriptorProto::clear_type() { +void FieldDescriptorProto::clear_type() { type_ = 1; clear_has_type(); } @@ -4293,16 +4864,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { } // optional string type_name = 6; - bool FieldDescriptorProto::has_type_name() const { +bool FieldDescriptorProto::has_type_name() const { return (_has_bits_[0] & 0x00000010u) != 0; } - void FieldDescriptorProto::set_has_type_name() { +void FieldDescriptorProto::set_has_type_name() { _has_bits_[0] |= 0x00000010u; } - void FieldDescriptorProto::clear_has_type_name() { +void FieldDescriptorProto::clear_has_type_name() { _has_bits_[0] &= ~0x00000010u; } - void FieldDescriptorProto::clear_type_name() { +void FieldDescriptorProto::clear_type_name() { type_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_type_name(); } @@ -4346,16 +4917,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { } // optional string extendee = 2; - bool FieldDescriptorProto::has_extendee() const { +bool FieldDescriptorProto::has_extendee() const { return (_has_bits_[0] & 0x00000020u) != 0; } - void FieldDescriptorProto::set_has_extendee() { +void FieldDescriptorProto::set_has_extendee() { _has_bits_[0] |= 0x00000020u; } - void FieldDescriptorProto::clear_has_extendee() { +void FieldDescriptorProto::clear_has_extendee() { _has_bits_[0] &= ~0x00000020u; } - void FieldDescriptorProto::clear_extendee() { +void FieldDescriptorProto::clear_extendee() { extendee_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_extendee(); } @@ -4399,16 +4970,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { } // optional string default_value = 7; - bool FieldDescriptorProto::has_default_value() const { +bool FieldDescriptorProto::has_default_value() const { return (_has_bits_[0] & 0x00000040u) != 0; } - void FieldDescriptorProto::set_has_default_value() { +void FieldDescriptorProto::set_has_default_value() { _has_bits_[0] |= 0x00000040u; } - void FieldDescriptorProto::clear_has_default_value() { +void FieldDescriptorProto::clear_has_default_value() { _has_bits_[0] &= ~0x00000040u; } - void FieldDescriptorProto::clear_default_value() { +void FieldDescriptorProto::clear_default_value() { default_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_default_value(); } @@ -4452,16 +5023,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { } // optional int32 oneof_index = 9; - bool FieldDescriptorProto::has_oneof_index() const { +bool FieldDescriptorProto::has_oneof_index() const { return (_has_bits_[0] & 0x00000080u) != 0; } - void FieldDescriptorProto::set_has_oneof_index() { +void FieldDescriptorProto::set_has_oneof_index() { _has_bits_[0] |= 0x00000080u; } - void FieldDescriptorProto::clear_has_oneof_index() { +void FieldDescriptorProto::clear_has_oneof_index() { _has_bits_[0] &= ~0x00000080u; } - void FieldDescriptorProto::clear_oneof_index() { +void FieldDescriptorProto::clear_oneof_index() { oneof_index_ = 0; clear_has_oneof_index(); } @@ -4476,16 +5047,16 @@ void FieldDescriptorProto::InternalSwap(FieldDescriptorProto* other) { } // optional .google.protobuf.FieldOptions options = 8; - bool FieldDescriptorProto::has_options() const { +bool FieldDescriptorProto::has_options() const { return (_has_bits_[0] & 0x00000100u) != 0; } - void FieldDescriptorProto::set_has_options() { +void FieldDescriptorProto::set_has_options() { _has_bits_[0] |= 0x00000100u; } - void FieldDescriptorProto::clear_has_options() { +void FieldDescriptorProto::clear_has_options() { _has_bits_[0] &= ~0x00000100u; } - void FieldDescriptorProto::clear_options() { +void FieldDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); clear_has_options(); } @@ -4527,7 +5098,7 @@ const int OneofDescriptorProto::kNameFieldNumber; #endif // !_MSC_VER OneofDescriptorProto::OneofDescriptorProto() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto) } @@ -4709,9 +5280,9 @@ int OneofDescriptorProto::ByteSize() const { void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const OneofDescriptorProto* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const OneofDescriptorProto* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -4772,16 +5343,16 @@ void OneofDescriptorProto::InternalSwap(OneofDescriptorProto* other) { // OneofDescriptorProto // optional string name = 1; - bool OneofDescriptorProto::has_name() const { +bool OneofDescriptorProto::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void OneofDescriptorProto::set_has_name() { +void OneofDescriptorProto::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void OneofDescriptorProto::clear_has_name() { +void OneofDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void OneofDescriptorProto::clear_name() { +void OneofDescriptorProto::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -4835,7 +5406,7 @@ const int EnumDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER EnumDescriptorProto::EnumDescriptorProto() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto) } @@ -4943,12 +5514,15 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( case 2: { if (tag == 18) { parse_value: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_value: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_value())); } else { goto handle_unusual; } - if (input->ExpectTag(18)) goto parse_value; + if (input->ExpectTag(18)) goto parse_loop_value; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(26)) goto parse_options; break; } @@ -5096,9 +5670,9 @@ int EnumDescriptorProto::ByteSize() const { void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const EnumDescriptorProto* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const EnumDescriptorProto* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -5169,16 +5743,16 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) { // EnumDescriptorProto // optional string name = 1; - bool EnumDescriptorProto::has_name() const { +bool EnumDescriptorProto::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void EnumDescriptorProto::set_has_name() { +void EnumDescriptorProto::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void EnumDescriptorProto::clear_has_name() { +void EnumDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void EnumDescriptorProto::clear_name() { +void EnumDescriptorProto::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -5222,10 +5796,10 @@ void EnumDescriptorProto::InternalSwap(EnumDescriptorProto* other) { } // repeated .google.protobuf.EnumValueDescriptorProto value = 2; - int EnumDescriptorProto::value_size() const { +int EnumDescriptorProto::value_size() const { return value_.size(); } - void EnumDescriptorProto::clear_value() { +void EnumDescriptorProto::clear_value() { value_.Clear(); } const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { @@ -5252,16 +5826,16 @@ EnumDescriptorProto::mutable_value() { } // optional .google.protobuf.EnumOptions options = 3; - bool EnumDescriptorProto::has_options() const { +bool EnumDescriptorProto::has_options() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void EnumDescriptorProto::set_has_options() { +void EnumDescriptorProto::set_has_options() { _has_bits_[0] |= 0x00000004u; } - void EnumDescriptorProto::clear_has_options() { +void EnumDescriptorProto::clear_has_options() { _has_bits_[0] &= ~0x00000004u; } - void EnumDescriptorProto::clear_options() { +void EnumDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::EnumOptions::Clear(); clear_has_options(); } @@ -5305,7 +5879,7 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER EnumValueDescriptorProto::EnumValueDescriptorProto() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto) } @@ -5564,9 +6138,9 @@ int EnumValueDescriptorProto::ByteSize() const { void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const EnumValueDescriptorProto* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const EnumValueDescriptorProto* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -5638,16 +6212,16 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) { // EnumValueDescriptorProto // optional string name = 1; - bool EnumValueDescriptorProto::has_name() const { +bool EnumValueDescriptorProto::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void EnumValueDescriptorProto::set_has_name() { +void EnumValueDescriptorProto::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void EnumValueDescriptorProto::clear_has_name() { +void EnumValueDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void EnumValueDescriptorProto::clear_name() { +void EnumValueDescriptorProto::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -5691,16 +6265,16 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) { } // optional int32 number = 2; - bool EnumValueDescriptorProto::has_number() const { +bool EnumValueDescriptorProto::has_number() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void EnumValueDescriptorProto::set_has_number() { +void EnumValueDescriptorProto::set_has_number() { _has_bits_[0] |= 0x00000002u; } - void EnumValueDescriptorProto::clear_has_number() { +void EnumValueDescriptorProto::clear_has_number() { _has_bits_[0] &= ~0x00000002u; } - void EnumValueDescriptorProto::clear_number() { +void EnumValueDescriptorProto::clear_number() { number_ = 0; clear_has_number(); } @@ -5715,16 +6289,16 @@ void EnumValueDescriptorProto::InternalSwap(EnumValueDescriptorProto* other) { } // optional .google.protobuf.EnumValueOptions options = 3; - bool EnumValueDescriptorProto::has_options() const { +bool EnumValueDescriptorProto::has_options() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void EnumValueDescriptorProto::set_has_options() { +void EnumValueDescriptorProto::set_has_options() { _has_bits_[0] |= 0x00000004u; } - void EnumValueDescriptorProto::clear_has_options() { +void EnumValueDescriptorProto::clear_has_options() { _has_bits_[0] &= ~0x00000004u; } - void EnumValueDescriptorProto::clear_options() { +void EnumValueDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::EnumValueOptions::Clear(); clear_has_options(); } @@ -5768,7 +6342,7 @@ const int ServiceDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER ServiceDescriptorProto::ServiceDescriptorProto() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto) } @@ -5876,12 +6450,15 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( case 2: { if (tag == 18) { parse_method: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_method: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_method())); } else { goto handle_unusual; } - if (input->ExpectTag(18)) goto parse_method; + if (input->ExpectTag(18)) goto parse_loop_method; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(26)) goto parse_options; break; } @@ -6029,9 +6606,9 @@ int ServiceDescriptorProto::ByteSize() const { void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const ServiceDescriptorProto* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const ServiceDescriptorProto* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -6102,16 +6679,16 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) { // ServiceDescriptorProto // optional string name = 1; - bool ServiceDescriptorProto::has_name() const { +bool ServiceDescriptorProto::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void ServiceDescriptorProto::set_has_name() { +void ServiceDescriptorProto::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void ServiceDescriptorProto::clear_has_name() { +void ServiceDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void ServiceDescriptorProto::clear_name() { +void ServiceDescriptorProto::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -6155,10 +6732,10 @@ void ServiceDescriptorProto::InternalSwap(ServiceDescriptorProto* other) { } // repeated .google.protobuf.MethodDescriptorProto method = 2; - int ServiceDescriptorProto::method_size() const { +int ServiceDescriptorProto::method_size() const { return method_.size(); } - void ServiceDescriptorProto::clear_method() { +void ServiceDescriptorProto::clear_method() { method_.Clear(); } const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { @@ -6185,16 +6762,16 @@ ServiceDescriptorProto::mutable_method() { } // optional .google.protobuf.ServiceOptions options = 3; - bool ServiceDescriptorProto::has_options() const { +bool ServiceDescriptorProto::has_options() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void ServiceDescriptorProto::set_has_options() { +void ServiceDescriptorProto::set_has_options() { _has_bits_[0] |= 0x00000004u; } - void ServiceDescriptorProto::clear_has_options() { +void ServiceDescriptorProto::clear_has_options() { _has_bits_[0] &= ~0x00000004u; } - void ServiceDescriptorProto::clear_options() { +void ServiceDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::ServiceOptions::Clear(); clear_has_options(); } @@ -6241,7 +6818,7 @@ const int MethodDescriptorProto::kServerStreamingFieldNumber; #endif // !_MSC_VER MethodDescriptorProto::MethodDescriptorProto() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto) } @@ -6641,9 +7218,9 @@ int MethodDescriptorProto::ByteSize() const { void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const MethodDescriptorProto* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const MethodDescriptorProto* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -6729,16 +7306,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { // MethodDescriptorProto // optional string name = 1; - bool MethodDescriptorProto::has_name() const { +bool MethodDescriptorProto::has_name() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void MethodDescriptorProto::set_has_name() { +void MethodDescriptorProto::set_has_name() { _has_bits_[0] |= 0x00000001u; } - void MethodDescriptorProto::clear_has_name() { +void MethodDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } - void MethodDescriptorProto::clear_name() { +void MethodDescriptorProto::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name(); } @@ -6782,16 +7359,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { } // optional string input_type = 2; - bool MethodDescriptorProto::has_input_type() const { +bool MethodDescriptorProto::has_input_type() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void MethodDescriptorProto::set_has_input_type() { +void MethodDescriptorProto::set_has_input_type() { _has_bits_[0] |= 0x00000002u; } - void MethodDescriptorProto::clear_has_input_type() { +void MethodDescriptorProto::clear_has_input_type() { _has_bits_[0] &= ~0x00000002u; } - void MethodDescriptorProto::clear_input_type() { +void MethodDescriptorProto::clear_input_type() { input_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_input_type(); } @@ -6835,16 +7412,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { } // optional string output_type = 3; - bool MethodDescriptorProto::has_output_type() const { +bool MethodDescriptorProto::has_output_type() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void MethodDescriptorProto::set_has_output_type() { +void MethodDescriptorProto::set_has_output_type() { _has_bits_[0] |= 0x00000004u; } - void MethodDescriptorProto::clear_has_output_type() { +void MethodDescriptorProto::clear_has_output_type() { _has_bits_[0] &= ~0x00000004u; } - void MethodDescriptorProto::clear_output_type() { +void MethodDescriptorProto::clear_output_type() { output_type_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_output_type(); } @@ -6888,16 +7465,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { } // optional .google.protobuf.MethodOptions options = 4; - bool MethodDescriptorProto::has_options() const { +bool MethodDescriptorProto::has_options() const { return (_has_bits_[0] & 0x00000008u) != 0; } - void MethodDescriptorProto::set_has_options() { +void MethodDescriptorProto::set_has_options() { _has_bits_[0] |= 0x00000008u; } - void MethodDescriptorProto::clear_has_options() { +void MethodDescriptorProto::clear_has_options() { _has_bits_[0] &= ~0x00000008u; } - void MethodDescriptorProto::clear_options() { +void MethodDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MethodOptions::Clear(); clear_has_options(); } @@ -6931,16 +7508,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { } // optional bool client_streaming = 5 [default = false]; - bool MethodDescriptorProto::has_client_streaming() const { +bool MethodDescriptorProto::has_client_streaming() const { return (_has_bits_[0] & 0x00000010u) != 0; } - void MethodDescriptorProto::set_has_client_streaming() { +void MethodDescriptorProto::set_has_client_streaming() { _has_bits_[0] |= 0x00000010u; } - void MethodDescriptorProto::clear_has_client_streaming() { +void MethodDescriptorProto::clear_has_client_streaming() { _has_bits_[0] &= ~0x00000010u; } - void MethodDescriptorProto::clear_client_streaming() { +void MethodDescriptorProto::clear_client_streaming() { client_streaming_ = false; clear_has_client_streaming(); } @@ -6955,16 +7532,16 @@ void MethodDescriptorProto::InternalSwap(MethodDescriptorProto* other) { } // optional bool server_streaming = 6 [default = false]; - bool MethodDescriptorProto::has_server_streaming() const { +bool MethodDescriptorProto::has_server_streaming() const { return (_has_bits_[0] & 0x00000020u) != 0; } - void MethodDescriptorProto::set_has_server_streaming() { +void MethodDescriptorProto::set_has_server_streaming() { _has_bits_[0] |= 0x00000020u; } - void MethodDescriptorProto::clear_has_server_streaming() { +void MethodDescriptorProto::clear_has_server_streaming() { _has_bits_[0] &= ~0x00000020u; } - void MethodDescriptorProto::clear_server_streaming() { +void MethodDescriptorProto::clear_server_streaming() { server_streaming_ = false; clear_has_server_streaming(); } @@ -7024,7 +7601,7 @@ const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER FileOptions::FileOptions() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.FileOptions) } @@ -7381,12 +7958,15 @@ bool FileOptions::MergePartialFromCodedStream( case 999: { if (tag == 7994) { parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_uninterpreted_option())); } else { goto handle_unusual; } - if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -7768,9 +8348,9 @@ int FileOptions::ByteSize() const { void FileOptions::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const FileOptions* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const FileOptions* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -7895,16 +8475,16 @@ void FileOptions::InternalSwap(FileOptions* other) { // FileOptions // optional string java_package = 1; - bool FileOptions::has_java_package() const { +bool FileOptions::has_java_package() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void FileOptions::set_has_java_package() { +void FileOptions::set_has_java_package() { _has_bits_[0] |= 0x00000001u; } - void FileOptions::clear_has_java_package() { +void FileOptions::clear_has_java_package() { _has_bits_[0] &= ~0x00000001u; } - void FileOptions::clear_java_package() { +void FileOptions::clear_java_package() { java_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_java_package(); } @@ -7948,16 +8528,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional string java_outer_classname = 8; - bool FileOptions::has_java_outer_classname() const { +bool FileOptions::has_java_outer_classname() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void FileOptions::set_has_java_outer_classname() { +void FileOptions::set_has_java_outer_classname() { _has_bits_[0] |= 0x00000002u; } - void FileOptions::clear_has_java_outer_classname() { +void FileOptions::clear_has_java_outer_classname() { _has_bits_[0] &= ~0x00000002u; } - void FileOptions::clear_java_outer_classname() { +void FileOptions::clear_java_outer_classname() { java_outer_classname_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_java_outer_classname(); } @@ -8001,16 +8581,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional bool java_multiple_files = 10 [default = false]; - bool FileOptions::has_java_multiple_files() const { +bool FileOptions::has_java_multiple_files() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void FileOptions::set_has_java_multiple_files() { +void FileOptions::set_has_java_multiple_files() { _has_bits_[0] |= 0x00000004u; } - void FileOptions::clear_has_java_multiple_files() { +void FileOptions::clear_has_java_multiple_files() { _has_bits_[0] &= ~0x00000004u; } - void FileOptions::clear_java_multiple_files() { +void FileOptions::clear_java_multiple_files() { java_multiple_files_ = false; clear_has_java_multiple_files(); } @@ -8025,16 +8605,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional bool java_generate_equals_and_hash = 20 [default = false]; - bool FileOptions::has_java_generate_equals_and_hash() const { +bool FileOptions::has_java_generate_equals_and_hash() const { return (_has_bits_[0] & 0x00000008u) != 0; } - void FileOptions::set_has_java_generate_equals_and_hash() { +void FileOptions::set_has_java_generate_equals_and_hash() { _has_bits_[0] |= 0x00000008u; } - void FileOptions::clear_has_java_generate_equals_and_hash() { +void FileOptions::clear_has_java_generate_equals_and_hash() { _has_bits_[0] &= ~0x00000008u; } - void FileOptions::clear_java_generate_equals_and_hash() { +void FileOptions::clear_java_generate_equals_and_hash() { java_generate_equals_and_hash_ = false; clear_has_java_generate_equals_and_hash(); } @@ -8049,16 +8629,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional bool java_string_check_utf8 = 27 [default = false]; - bool FileOptions::has_java_string_check_utf8() const { +bool FileOptions::has_java_string_check_utf8() const { return (_has_bits_[0] & 0x00000010u) != 0; } - void FileOptions::set_has_java_string_check_utf8() { +void FileOptions::set_has_java_string_check_utf8() { _has_bits_[0] |= 0x00000010u; } - void FileOptions::clear_has_java_string_check_utf8() { +void FileOptions::clear_has_java_string_check_utf8() { _has_bits_[0] &= ~0x00000010u; } - void FileOptions::clear_java_string_check_utf8() { +void FileOptions::clear_java_string_check_utf8() { java_string_check_utf8_ = false; clear_has_java_string_check_utf8(); } @@ -8073,16 +8653,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; - bool FileOptions::has_optimize_for() const { +bool FileOptions::has_optimize_for() const { return (_has_bits_[0] & 0x00000020u) != 0; } - void FileOptions::set_has_optimize_for() { +void FileOptions::set_has_optimize_for() { _has_bits_[0] |= 0x00000020u; } - void FileOptions::clear_has_optimize_for() { +void FileOptions::clear_has_optimize_for() { _has_bits_[0] &= ~0x00000020u; } - void FileOptions::clear_optimize_for() { +void FileOptions::clear_optimize_for() { optimize_for_ = 1; clear_has_optimize_for(); } @@ -8098,16 +8678,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional string go_package = 11; - bool FileOptions::has_go_package() const { +bool FileOptions::has_go_package() const { return (_has_bits_[0] & 0x00000040u) != 0; } - void FileOptions::set_has_go_package() { +void FileOptions::set_has_go_package() { _has_bits_[0] |= 0x00000040u; } - void FileOptions::clear_has_go_package() { +void FileOptions::clear_has_go_package() { _has_bits_[0] &= ~0x00000040u; } - void FileOptions::clear_go_package() { +void FileOptions::clear_go_package() { go_package_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_go_package(); } @@ -8151,16 +8731,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional bool cc_generic_services = 16 [default = false]; - bool FileOptions::has_cc_generic_services() const { +bool FileOptions::has_cc_generic_services() const { return (_has_bits_[0] & 0x00000080u) != 0; } - void FileOptions::set_has_cc_generic_services() { +void FileOptions::set_has_cc_generic_services() { _has_bits_[0] |= 0x00000080u; } - void FileOptions::clear_has_cc_generic_services() { +void FileOptions::clear_has_cc_generic_services() { _has_bits_[0] &= ~0x00000080u; } - void FileOptions::clear_cc_generic_services() { +void FileOptions::clear_cc_generic_services() { cc_generic_services_ = false; clear_has_cc_generic_services(); } @@ -8175,16 +8755,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional bool java_generic_services = 17 [default = false]; - bool FileOptions::has_java_generic_services() const { +bool FileOptions::has_java_generic_services() const { return (_has_bits_[0] & 0x00000100u) != 0; } - void FileOptions::set_has_java_generic_services() { +void FileOptions::set_has_java_generic_services() { _has_bits_[0] |= 0x00000100u; } - void FileOptions::clear_has_java_generic_services() { +void FileOptions::clear_has_java_generic_services() { _has_bits_[0] &= ~0x00000100u; } - void FileOptions::clear_java_generic_services() { +void FileOptions::clear_java_generic_services() { java_generic_services_ = false; clear_has_java_generic_services(); } @@ -8199,16 +8779,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional bool py_generic_services = 18 [default = false]; - bool FileOptions::has_py_generic_services() const { +bool FileOptions::has_py_generic_services() const { return (_has_bits_[0] & 0x00000200u) != 0; } - void FileOptions::set_has_py_generic_services() { +void FileOptions::set_has_py_generic_services() { _has_bits_[0] |= 0x00000200u; } - void FileOptions::clear_has_py_generic_services() { +void FileOptions::clear_has_py_generic_services() { _has_bits_[0] &= ~0x00000200u; } - void FileOptions::clear_py_generic_services() { +void FileOptions::clear_py_generic_services() { py_generic_services_ = false; clear_has_py_generic_services(); } @@ -8223,16 +8803,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional bool deprecated = 23 [default = false]; - bool FileOptions::has_deprecated() const { +bool FileOptions::has_deprecated() const { return (_has_bits_[0] & 0x00000400u) != 0; } - void FileOptions::set_has_deprecated() { +void FileOptions::set_has_deprecated() { _has_bits_[0] |= 0x00000400u; } - void FileOptions::clear_has_deprecated() { +void FileOptions::clear_has_deprecated() { _has_bits_[0] &= ~0x00000400u; } - void FileOptions::clear_deprecated() { +void FileOptions::clear_deprecated() { deprecated_ = false; clear_has_deprecated(); } @@ -8247,16 +8827,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional bool cc_enable_arenas = 31 [default = false]; - bool FileOptions::has_cc_enable_arenas() const { +bool FileOptions::has_cc_enable_arenas() const { return (_has_bits_[0] & 0x00000800u) != 0; } - void FileOptions::set_has_cc_enable_arenas() { +void FileOptions::set_has_cc_enable_arenas() { _has_bits_[0] |= 0x00000800u; } - void FileOptions::clear_has_cc_enable_arenas() { +void FileOptions::clear_has_cc_enable_arenas() { _has_bits_[0] &= ~0x00000800u; } - void FileOptions::clear_cc_enable_arenas() { +void FileOptions::clear_cc_enable_arenas() { cc_enable_arenas_ = false; clear_has_cc_enable_arenas(); } @@ -8271,16 +8851,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional string objc_class_prefix = 36; - bool FileOptions::has_objc_class_prefix() const { +bool FileOptions::has_objc_class_prefix() const { return (_has_bits_[0] & 0x00001000u) != 0; } - void FileOptions::set_has_objc_class_prefix() { +void FileOptions::set_has_objc_class_prefix() { _has_bits_[0] |= 0x00001000u; } - void FileOptions::clear_has_objc_class_prefix() { +void FileOptions::clear_has_objc_class_prefix() { _has_bits_[0] &= ~0x00001000u; } - void FileOptions::clear_objc_class_prefix() { +void FileOptions::clear_objc_class_prefix() { objc_class_prefix_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_objc_class_prefix(); } @@ -8324,16 +8904,16 @@ void FileOptions::InternalSwap(FileOptions* other) { } // optional string csharp_namespace = 37; - bool FileOptions::has_csharp_namespace() const { +bool FileOptions::has_csharp_namespace() const { return (_has_bits_[0] & 0x00002000u) != 0; } - void FileOptions::set_has_csharp_namespace() { +void FileOptions::set_has_csharp_namespace() { _has_bits_[0] |= 0x00002000u; } - void FileOptions::clear_has_csharp_namespace() { +void FileOptions::clear_has_csharp_namespace() { _has_bits_[0] &= ~0x00002000u; } - void FileOptions::clear_csharp_namespace() { +void FileOptions::clear_csharp_namespace() { csharp_namespace_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_csharp_namespace(); } @@ -8377,10 +8957,10 @@ void FileOptions::InternalSwap(FileOptions* other) { } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - int FileOptions::uninterpreted_option_size() const { +int FileOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); } - void FileOptions::clear_uninterpreted_option() { +void FileOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { @@ -8419,7 +8999,7 @@ const int MessageOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER MessageOptions::MessageOptions() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.MessageOptions) } @@ -8574,12 +9154,15 @@ bool MessageOptions::MergePartialFromCodedStream( case 999: { if (tag == 7994) { parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_uninterpreted_option())); } else { goto handle_unusual; } - if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -8741,9 +9324,9 @@ int MessageOptions::ByteSize() const { void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const MessageOptions* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const MessageOptions* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -8821,16 +9404,16 @@ void MessageOptions::InternalSwap(MessageOptions* other) { // MessageOptions // optional bool message_set_wire_format = 1 [default = false]; - bool MessageOptions::has_message_set_wire_format() const { +bool MessageOptions::has_message_set_wire_format() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void MessageOptions::set_has_message_set_wire_format() { +void MessageOptions::set_has_message_set_wire_format() { _has_bits_[0] |= 0x00000001u; } - void MessageOptions::clear_has_message_set_wire_format() { +void MessageOptions::clear_has_message_set_wire_format() { _has_bits_[0] &= ~0x00000001u; } - void MessageOptions::clear_message_set_wire_format() { +void MessageOptions::clear_message_set_wire_format() { message_set_wire_format_ = false; clear_has_message_set_wire_format(); } @@ -8845,16 +9428,16 @@ void MessageOptions::InternalSwap(MessageOptions* other) { } // optional bool no_standard_descriptor_accessor = 2 [default = false]; - bool MessageOptions::has_no_standard_descriptor_accessor() const { +bool MessageOptions::has_no_standard_descriptor_accessor() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void MessageOptions::set_has_no_standard_descriptor_accessor() { +void MessageOptions::set_has_no_standard_descriptor_accessor() { _has_bits_[0] |= 0x00000002u; } - void MessageOptions::clear_has_no_standard_descriptor_accessor() { +void MessageOptions::clear_has_no_standard_descriptor_accessor() { _has_bits_[0] &= ~0x00000002u; } - void MessageOptions::clear_no_standard_descriptor_accessor() { +void MessageOptions::clear_no_standard_descriptor_accessor() { no_standard_descriptor_accessor_ = false; clear_has_no_standard_descriptor_accessor(); } @@ -8869,16 +9452,16 @@ void MessageOptions::InternalSwap(MessageOptions* other) { } // optional bool deprecated = 3 [default = false]; - bool MessageOptions::has_deprecated() const { +bool MessageOptions::has_deprecated() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void MessageOptions::set_has_deprecated() { +void MessageOptions::set_has_deprecated() { _has_bits_[0] |= 0x00000004u; } - void MessageOptions::clear_has_deprecated() { +void MessageOptions::clear_has_deprecated() { _has_bits_[0] &= ~0x00000004u; } - void MessageOptions::clear_deprecated() { +void MessageOptions::clear_deprecated() { deprecated_ = false; clear_has_deprecated(); } @@ -8893,16 +9476,16 @@ void MessageOptions::InternalSwap(MessageOptions* other) { } // optional bool map_entry = 7; - bool MessageOptions::has_map_entry() const { +bool MessageOptions::has_map_entry() const { return (_has_bits_[0] & 0x00000008u) != 0; } - void MessageOptions::set_has_map_entry() { +void MessageOptions::set_has_map_entry() { _has_bits_[0] |= 0x00000008u; } - void MessageOptions::clear_has_map_entry() { +void MessageOptions::clear_has_map_entry() { _has_bits_[0] &= ~0x00000008u; } - void MessageOptions::clear_map_entry() { +void MessageOptions::clear_map_entry() { map_entry_ = false; clear_has_map_entry(); } @@ -8917,10 +9500,10 @@ void MessageOptions::InternalSwap(MessageOptions* other) { } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - int MessageOptions::uninterpreted_option_size() const { +int MessageOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); } - void MessageOptions::clear_uninterpreted_option() { +void MessageOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { @@ -8973,9 +9556,33 @@ const FieldOptions_CType FieldOptions::CType_MIN; const FieldOptions_CType FieldOptions::CType_MAX; const int FieldOptions::CType_ARRAYSIZE; #endif // _MSC_VER +const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor() { + protobuf_AssignDescriptorsOnce(); + return FieldOptions_JSType_descriptor_; +} +bool FieldOptions_JSType_IsValid(int value) { + switch(value) { + case 0: + case 1: + case 2: + return true; + default: + return false; + } +} + +#ifndef _MSC_VER +const FieldOptions_JSType FieldOptions::JS_NORMAL; +const FieldOptions_JSType FieldOptions::JS_STRING; +const FieldOptions_JSType FieldOptions::JS_NUMBER; +const FieldOptions_JSType FieldOptions::JSType_MIN; +const FieldOptions_JSType FieldOptions::JSType_MAX; +const int FieldOptions::JSType_ARRAYSIZE; +#endif // _MSC_VER #ifndef _MSC_VER const int FieldOptions::kCtypeFieldNumber; const int FieldOptions::kPackedFieldNumber; +const int FieldOptions::kJstypeFieldNumber; const int FieldOptions::kLazyFieldNumber; const int FieldOptions::kDeprecatedFieldNumber; const int FieldOptions::kWeakFieldNumber; @@ -8983,7 +9590,7 @@ const int FieldOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER FieldOptions::FieldOptions() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.FieldOptions) } @@ -9003,6 +9610,7 @@ void FieldOptions::SharedCtor() { _cached_size_ = 0; ctype_ = 0; packed_ = false; + jstype_ = 0; lazy_ = false; deprecated_ = false; weak_ = false; @@ -9054,8 +9662,9 @@ void FieldOptions::Clear() { ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) - if (_has_bits_[0 / 32] & 31u) { - ZR_(ctype_, weak_); + if (_has_bits_[0 / 32] & 63u) { + ZR_(ctype_, jstype_); + ZR_(packed_, weak_); } #undef ZR_HELPER_ @@ -9138,6 +9747,26 @@ bool FieldOptions::MergePartialFromCodedStream( } else { goto handle_unusual; } + if (input->ExpectTag(48)) goto parse_jstype; + break; + } + + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + case 6: { + if (tag == 48) { + parse_jstype: + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + if (::google::protobuf::FieldOptions_JSType_IsValid(value)) { + set_jstype(static_cast< ::google::protobuf::FieldOptions_JSType >(value)); + } else { + mutable_unknown_fields()->AddVarint(6, value); + } + } else { + goto handle_unusual; + } if (input->ExpectTag(80)) goto parse_weak; break; } @@ -9161,12 +9790,15 @@ bool FieldOptions::MergePartialFromCodedStream( case 999: { if (tag == 7994) { parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_uninterpreted_option())); } else { goto handle_unusual; } - if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -9222,6 +9854,12 @@ void FieldOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteBool(5, this->lazy(), output); } + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + if (has_jstype()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 6, this->jstype(), output); + } + // optional bool weak = 10 [default = false]; if (has_weak()) { ::google::protobuf::internal::WireFormatLite::WriteBool(10, this->weak(), output); @@ -9268,6 +9906,12 @@ void FieldOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(5, this->lazy(), target); } + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + if (has_jstype()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 6, this->jstype(), target); + } + // optional bool weak = 10 [default = false]; if (has_weak()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(10, this->weak(), target); @@ -9295,7 +9939,7 @@ void FieldOptions::SerializeWithCachedSizes( int FieldOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 31) { + if (_has_bits_[0 / 32] & 63) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (has_ctype()) { total_size += 1 + @@ -9307,6 +9951,12 @@ int FieldOptions::ByteSize() const { total_size += 1 + 1; } + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + if (has_jstype()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->jstype()); + } + // optional bool lazy = 5 [default = false]; if (has_lazy()) { total_size += 1 + 1; @@ -9346,9 +9996,9 @@ int FieldOptions::ByteSize() const { void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const FieldOptions* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const FieldOptions* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -9366,6 +10016,9 @@ void FieldOptions::MergeFrom(const FieldOptions& from) { if (from.has_packed()) { set_packed(from.packed()); } + if (from.has_jstype()) { + set_jstype(from.jstype()); + } if (from.has_lazy()) { set_lazy(from.lazy()); } @@ -9408,6 +10061,7 @@ void FieldOptions::Swap(FieldOptions* other) { void FieldOptions::InternalSwap(FieldOptions* other) { std::swap(ctype_, other->ctype_); std::swap(packed_, other->packed_); + std::swap(jstype_, other->jstype_); std::swap(lazy_, other->lazy_); std::swap(deprecated_, other->deprecated_); std::swap(weak_, other->weak_); @@ -9430,16 +10084,16 @@ void FieldOptions::InternalSwap(FieldOptions* other) { // FieldOptions // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; - bool FieldOptions::has_ctype() const { +bool FieldOptions::has_ctype() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void FieldOptions::set_has_ctype() { +void FieldOptions::set_has_ctype() { _has_bits_[0] |= 0x00000001u; } - void FieldOptions::clear_has_ctype() { +void FieldOptions::clear_has_ctype() { _has_bits_[0] &= ~0x00000001u; } - void FieldOptions::clear_ctype() { +void FieldOptions::clear_ctype() { ctype_ = 0; clear_has_ctype(); } @@ -9455,16 +10109,16 @@ void FieldOptions::InternalSwap(FieldOptions* other) { } // optional bool packed = 2; - bool FieldOptions::has_packed() const { +bool FieldOptions::has_packed() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void FieldOptions::set_has_packed() { +void FieldOptions::set_has_packed() { _has_bits_[0] |= 0x00000002u; } - void FieldOptions::clear_has_packed() { +void FieldOptions::clear_has_packed() { _has_bits_[0] &= ~0x00000002u; } - void FieldOptions::clear_packed() { +void FieldOptions::clear_packed() { packed_ = false; clear_has_packed(); } @@ -9478,17 +10132,42 @@ void FieldOptions::InternalSwap(FieldOptions* other) { // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) } -// optional bool lazy = 5 [default = false]; - bool FieldOptions::has_lazy() const { +// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; +bool FieldOptions::has_jstype() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void FieldOptions::set_has_lazy() { +void FieldOptions::set_has_jstype() { _has_bits_[0] |= 0x00000004u; } - void FieldOptions::clear_has_lazy() { +void FieldOptions::clear_has_jstype() { _has_bits_[0] &= ~0x00000004u; } - void FieldOptions::clear_lazy() { +void FieldOptions::clear_jstype() { + jstype_ = 0; + clear_has_jstype(); +} + ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype) + return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_); +} + void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) { + assert(::google::protobuf::FieldOptions_JSType_IsValid(value)); + set_has_jstype(); + jstype_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype) +} + +// optional bool lazy = 5 [default = false]; +bool FieldOptions::has_lazy() const { + return (_has_bits_[0] & 0x00000008u) != 0; +} +void FieldOptions::set_has_lazy() { + _has_bits_[0] |= 0x00000008u; +} +void FieldOptions::clear_has_lazy() { + _has_bits_[0] &= ~0x00000008u; +} +void FieldOptions::clear_lazy() { lazy_ = false; clear_has_lazy(); } @@ -9503,16 +10182,16 @@ void FieldOptions::InternalSwap(FieldOptions* other) { } // optional bool deprecated = 3 [default = false]; - bool FieldOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000008u) != 0; +bool FieldOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000010u) != 0; } - void FieldOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000008u; +void FieldOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000010u; } - void FieldOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000008u; +void FieldOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000010u; } - void FieldOptions::clear_deprecated() { +void FieldOptions::clear_deprecated() { deprecated_ = false; clear_has_deprecated(); } @@ -9527,16 +10206,16 @@ void FieldOptions::InternalSwap(FieldOptions* other) { } // optional bool weak = 10 [default = false]; - bool FieldOptions::has_weak() const { - return (_has_bits_[0] & 0x00000010u) != 0; +bool FieldOptions::has_weak() const { + return (_has_bits_[0] & 0x00000020u) != 0; } - void FieldOptions::set_has_weak() { - _has_bits_[0] |= 0x00000010u; +void FieldOptions::set_has_weak() { + _has_bits_[0] |= 0x00000020u; } - void FieldOptions::clear_has_weak() { - _has_bits_[0] &= ~0x00000010u; +void FieldOptions::clear_has_weak() { + _has_bits_[0] &= ~0x00000020u; } - void FieldOptions::clear_weak() { +void FieldOptions::clear_weak() { weak_ = false; clear_has_weak(); } @@ -9551,10 +10230,10 @@ void FieldOptions::InternalSwap(FieldOptions* other) { } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - int FieldOptions::uninterpreted_option_size() const { +int FieldOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); } - void FieldOptions::clear_uninterpreted_option() { +void FieldOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { @@ -9591,7 +10270,7 @@ const int EnumOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER EnumOptions::EnumOptions() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.EnumOptions) } @@ -9714,12 +10393,15 @@ bool EnumOptions::MergePartialFromCodedStream( case 999: { if (tag == 7994) { parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_uninterpreted_option())); } else { goto handle_unusual; } - if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -9851,9 +10533,9 @@ int EnumOptions::ByteSize() const { void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const EnumOptions* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const EnumOptions* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -9923,16 +10605,16 @@ void EnumOptions::InternalSwap(EnumOptions* other) { // EnumOptions // optional bool allow_alias = 2; - bool EnumOptions::has_allow_alias() const { +bool EnumOptions::has_allow_alias() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void EnumOptions::set_has_allow_alias() { +void EnumOptions::set_has_allow_alias() { _has_bits_[0] |= 0x00000001u; } - void EnumOptions::clear_has_allow_alias() { +void EnumOptions::clear_has_allow_alias() { _has_bits_[0] &= ~0x00000001u; } - void EnumOptions::clear_allow_alias() { +void EnumOptions::clear_allow_alias() { allow_alias_ = false; clear_has_allow_alias(); } @@ -9947,16 +10629,16 @@ void EnumOptions::InternalSwap(EnumOptions* other) { } // optional bool deprecated = 3 [default = false]; - bool EnumOptions::has_deprecated() const { +bool EnumOptions::has_deprecated() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void EnumOptions::set_has_deprecated() { +void EnumOptions::set_has_deprecated() { _has_bits_[0] |= 0x00000002u; } - void EnumOptions::clear_has_deprecated() { +void EnumOptions::clear_has_deprecated() { _has_bits_[0] &= ~0x00000002u; } - void EnumOptions::clear_deprecated() { +void EnumOptions::clear_deprecated() { deprecated_ = false; clear_has_deprecated(); } @@ -9971,10 +10653,10 @@ void EnumOptions::InternalSwap(EnumOptions* other) { } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - int EnumOptions::uninterpreted_option_size() const { +int EnumOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); } - void EnumOptions::clear_uninterpreted_option() { +void EnumOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { @@ -10010,7 +10692,7 @@ const int EnumValueOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER EnumValueOptions::EnumValueOptions() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.EnumValueOptions) } @@ -10105,12 +10787,15 @@ bool EnumValueOptions::MergePartialFromCodedStream( case 999: { if (tag == 7994) { parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_uninterpreted_option())); } else { goto handle_unusual; } - if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -10225,9 +10910,9 @@ int EnumValueOptions::ByteSize() const { void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const EnumValueOptions* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const EnumValueOptions* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -10293,16 +10978,16 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) { // EnumValueOptions // optional bool deprecated = 1 [default = false]; - bool EnumValueOptions::has_deprecated() const { +bool EnumValueOptions::has_deprecated() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void EnumValueOptions::set_has_deprecated() { +void EnumValueOptions::set_has_deprecated() { _has_bits_[0] |= 0x00000001u; } - void EnumValueOptions::clear_has_deprecated() { +void EnumValueOptions::clear_has_deprecated() { _has_bits_[0] &= ~0x00000001u; } - void EnumValueOptions::clear_deprecated() { +void EnumValueOptions::clear_deprecated() { deprecated_ = false; clear_has_deprecated(); } @@ -10317,10 +11002,10 @@ void EnumValueOptions::InternalSwap(EnumValueOptions* other) { } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - int EnumValueOptions::uninterpreted_option_size() const { +int EnumValueOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); } - void EnumValueOptions::clear_uninterpreted_option() { +void EnumValueOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { @@ -10356,7 +11041,7 @@ const int ServiceOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER ServiceOptions::ServiceOptions() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.ServiceOptions) } @@ -10451,12 +11136,15 @@ bool ServiceOptions::MergePartialFromCodedStream( case 999: { if (tag == 7994) { parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_uninterpreted_option())); } else { goto handle_unusual; } - if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -10571,9 +11259,9 @@ int ServiceOptions::ByteSize() const { void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const ServiceOptions* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const ServiceOptions* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -10639,16 +11327,16 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) { // ServiceOptions // optional bool deprecated = 33 [default = false]; - bool ServiceOptions::has_deprecated() const { +bool ServiceOptions::has_deprecated() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void ServiceOptions::set_has_deprecated() { +void ServiceOptions::set_has_deprecated() { _has_bits_[0] |= 0x00000001u; } - void ServiceOptions::clear_has_deprecated() { +void ServiceOptions::clear_has_deprecated() { _has_bits_[0] &= ~0x00000001u; } - void ServiceOptions::clear_deprecated() { +void ServiceOptions::clear_deprecated() { deprecated_ = false; clear_has_deprecated(); } @@ -10663,10 +11351,10 @@ void ServiceOptions::InternalSwap(ServiceOptions* other) { } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - int ServiceOptions::uninterpreted_option_size() const { +int ServiceOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); } - void ServiceOptions::clear_uninterpreted_option() { +void ServiceOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { @@ -10702,7 +11390,7 @@ const int MethodOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER MethodOptions::MethodOptions() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.MethodOptions) } @@ -10797,12 +11485,15 @@ bool MethodOptions::MergePartialFromCodedStream( case 999: { if (tag == 7994) { parse_uninterpreted_option: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_uninterpreted_option: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_uninterpreted_option())); } else { goto handle_unusual; } - if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + if (input->ExpectTag(7994)) goto parse_loop_uninterpreted_option; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -10917,9 +11608,9 @@ int MethodOptions::ByteSize() const { void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const MethodOptions* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const MethodOptions* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -10985,16 +11676,16 @@ void MethodOptions::InternalSwap(MethodOptions* other) { // MethodOptions // optional bool deprecated = 33 [default = false]; - bool MethodOptions::has_deprecated() const { +bool MethodOptions::has_deprecated() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void MethodOptions::set_has_deprecated() { +void MethodOptions::set_has_deprecated() { _has_bits_[0] |= 0x00000001u; } - void MethodOptions::clear_has_deprecated() { +void MethodOptions::clear_has_deprecated() { _has_bits_[0] &= ~0x00000001u; } - void MethodOptions::clear_deprecated() { +void MethodOptions::clear_deprecated() { deprecated_ = false; clear_has_deprecated(); } @@ -11009,10 +11700,10 @@ void MethodOptions::InternalSwap(MethodOptions* other) { } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; - int MethodOptions::uninterpreted_option_size() const { +int MethodOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); } - void MethodOptions::clear_uninterpreted_option() { +void MethodOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { @@ -11048,7 +11739,7 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber; #endif // !_MSC_VER UninterpretedOption_NamePart::UninterpretedOption_NamePart() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption.NamePart) } @@ -11281,9 +11972,9 @@ int UninterpretedOption_NamePart::ByteSize() const { void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const UninterpretedOption_NamePart* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const UninterpretedOption_NamePart* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -11359,7 +12050,7 @@ const int UninterpretedOption::kAggregateValueFieldNumber; #endif // !_MSC_VER UninterpretedOption::UninterpretedOption() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption) } @@ -11470,13 +12161,15 @@ bool UninterpretedOption::MergePartialFromCodedStream( // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; case 2: { if (tag == 18) { - parse_name: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_name: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_name())); } else { goto handle_unusual; } - if (input->ExpectTag(18)) goto parse_name; + if (input->ExpectTag(18)) goto parse_loop_name; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(26)) goto parse_identifier_value; break; } @@ -11780,9 +12473,9 @@ int UninterpretedOption::ByteSize() const { void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const UninterpretedOption* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const UninterpretedOption* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -11868,16 +12561,16 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) { // UninterpretedOption_NamePart // required string name_part = 1; - bool UninterpretedOption_NamePart::has_name_part() const { +bool UninterpretedOption_NamePart::has_name_part() const { return (_has_bits_[0] & 0x00000001u) != 0; } - void UninterpretedOption_NamePart::set_has_name_part() { +void UninterpretedOption_NamePart::set_has_name_part() { _has_bits_[0] |= 0x00000001u; } - void UninterpretedOption_NamePart::clear_has_name_part() { +void UninterpretedOption_NamePart::clear_has_name_part() { _has_bits_[0] &= ~0x00000001u; } - void UninterpretedOption_NamePart::clear_name_part() { +void UninterpretedOption_NamePart::clear_name_part() { name_part_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_name_part(); } @@ -11921,16 +12614,16 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) { } // required bool is_extension = 2; - bool UninterpretedOption_NamePart::has_is_extension() const { +bool UninterpretedOption_NamePart::has_is_extension() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void UninterpretedOption_NamePart::set_has_is_extension() { +void UninterpretedOption_NamePart::set_has_is_extension() { _has_bits_[0] |= 0x00000002u; } - void UninterpretedOption_NamePart::clear_has_is_extension() { +void UninterpretedOption_NamePart::clear_has_is_extension() { _has_bits_[0] &= ~0x00000002u; } - void UninterpretedOption_NamePart::clear_is_extension() { +void UninterpretedOption_NamePart::clear_is_extension() { is_extension_ = false; clear_has_is_extension(); } @@ -11949,10 +12642,10 @@ void UninterpretedOption::InternalSwap(UninterpretedOption* other) { // UninterpretedOption // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; - int UninterpretedOption::name_size() const { +int UninterpretedOption::name_size() const { return name_.size(); } - void UninterpretedOption::clear_name() { +void UninterpretedOption::clear_name() { name_.Clear(); } const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { @@ -11979,16 +12672,16 @@ UninterpretedOption::mutable_name() { } // optional string identifier_value = 3; - bool UninterpretedOption::has_identifier_value() const { +bool UninterpretedOption::has_identifier_value() const { return (_has_bits_[0] & 0x00000002u) != 0; } - void UninterpretedOption::set_has_identifier_value() { +void UninterpretedOption::set_has_identifier_value() { _has_bits_[0] |= 0x00000002u; } - void UninterpretedOption::clear_has_identifier_value() { +void UninterpretedOption::clear_has_identifier_value() { _has_bits_[0] &= ~0x00000002u; } - void UninterpretedOption::clear_identifier_value() { +void UninterpretedOption::clear_identifier_value() { identifier_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_identifier_value(); } @@ -12032,16 +12725,16 @@ UninterpretedOption::mutable_name() { } // optional uint64 positive_int_value = 4; - bool UninterpretedOption::has_positive_int_value() const { +bool UninterpretedOption::has_positive_int_value() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void UninterpretedOption::set_has_positive_int_value() { +void UninterpretedOption::set_has_positive_int_value() { _has_bits_[0] |= 0x00000004u; } - void UninterpretedOption::clear_has_positive_int_value() { +void UninterpretedOption::clear_has_positive_int_value() { _has_bits_[0] &= ~0x00000004u; } - void UninterpretedOption::clear_positive_int_value() { +void UninterpretedOption::clear_positive_int_value() { positive_int_value_ = GOOGLE_ULONGLONG(0); clear_has_positive_int_value(); } @@ -12056,16 +12749,16 @@ UninterpretedOption::mutable_name() { } // optional int64 negative_int_value = 5; - bool UninterpretedOption::has_negative_int_value() const { +bool UninterpretedOption::has_negative_int_value() const { return (_has_bits_[0] & 0x00000008u) != 0; } - void UninterpretedOption::set_has_negative_int_value() { +void UninterpretedOption::set_has_negative_int_value() { _has_bits_[0] |= 0x00000008u; } - void UninterpretedOption::clear_has_negative_int_value() { +void UninterpretedOption::clear_has_negative_int_value() { _has_bits_[0] &= ~0x00000008u; } - void UninterpretedOption::clear_negative_int_value() { +void UninterpretedOption::clear_negative_int_value() { negative_int_value_ = GOOGLE_LONGLONG(0); clear_has_negative_int_value(); } @@ -12080,16 +12773,16 @@ UninterpretedOption::mutable_name() { } // optional double double_value = 6; - bool UninterpretedOption::has_double_value() const { +bool UninterpretedOption::has_double_value() const { return (_has_bits_[0] & 0x00000010u) != 0; } - void UninterpretedOption::set_has_double_value() { +void UninterpretedOption::set_has_double_value() { _has_bits_[0] |= 0x00000010u; } - void UninterpretedOption::clear_has_double_value() { +void UninterpretedOption::clear_has_double_value() { _has_bits_[0] &= ~0x00000010u; } - void UninterpretedOption::clear_double_value() { +void UninterpretedOption::clear_double_value() { double_value_ = 0; clear_has_double_value(); } @@ -12104,16 +12797,16 @@ UninterpretedOption::mutable_name() { } // optional bytes string_value = 7; - bool UninterpretedOption::has_string_value() const { +bool UninterpretedOption::has_string_value() const { return (_has_bits_[0] & 0x00000020u) != 0; } - void UninterpretedOption::set_has_string_value() { +void UninterpretedOption::set_has_string_value() { _has_bits_[0] |= 0x00000020u; } - void UninterpretedOption::clear_has_string_value() { +void UninterpretedOption::clear_has_string_value() { _has_bits_[0] &= ~0x00000020u; } - void UninterpretedOption::clear_string_value() { +void UninterpretedOption::clear_string_value() { string_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_string_value(); } @@ -12157,16 +12850,16 @@ UninterpretedOption::mutable_name() { } // optional string aggregate_value = 8; - bool UninterpretedOption::has_aggregate_value() const { +bool UninterpretedOption::has_aggregate_value() const { return (_has_bits_[0] & 0x00000040u) != 0; } - void UninterpretedOption::set_has_aggregate_value() { +void UninterpretedOption::set_has_aggregate_value() { _has_bits_[0] |= 0x00000040u; } - void UninterpretedOption::clear_has_aggregate_value() { +void UninterpretedOption::clear_has_aggregate_value() { _has_bits_[0] &= ~0x00000040u; } - void UninterpretedOption::clear_aggregate_value() { +void UninterpretedOption::clear_aggregate_value() { aggregate_value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_aggregate_value(); } @@ -12222,7 +12915,7 @@ const int SourceCodeInfo_Location::kLeadingDetachedCommentsFieldNumber; #endif // !_MSC_VER SourceCodeInfo_Location::SourceCodeInfo_Location() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location) } @@ -12625,9 +13318,9 @@ int SourceCodeInfo_Location::ByteSize() const { void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const SourceCodeInfo_Location* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const SourceCodeInfo_Location* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -12703,7 +13396,7 @@ const int SourceCodeInfo::kLocationFieldNumber; #endif // !_MSC_VER SourceCodeInfo::SourceCodeInfo() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo) } @@ -12780,13 +13473,15 @@ bool SourceCodeInfo::MergePartialFromCodedStream( // repeated .google.protobuf.SourceCodeInfo.Location location = 1; case 1: { if (tag == 10) { - parse_location: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_location: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_location())); } else { goto handle_unusual; } - if (input->ExpectTag(10)) goto parse_location; + if (input->ExpectTag(10)) goto parse_loop_location; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -12871,9 +13566,9 @@ int SourceCodeInfo::ByteSize() const { void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const SourceCodeInfo* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const SourceCodeInfo* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -12929,10 +13624,10 @@ void SourceCodeInfo::InternalSwap(SourceCodeInfo* other) { // SourceCodeInfo_Location // repeated int32 path = 1 [packed = true]; - int SourceCodeInfo_Location::path_size() const { +int SourceCodeInfo_Location::path_size() const { return path_.size(); } - void SourceCodeInfo_Location::clear_path() { +void SourceCodeInfo_Location::clear_path() { path_.Clear(); } ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { @@ -12959,10 +13654,10 @@ SourceCodeInfo_Location::mutable_path() { } // repeated int32 span = 2 [packed = true]; - int SourceCodeInfo_Location::span_size() const { +int SourceCodeInfo_Location::span_size() const { return span_.size(); } - void SourceCodeInfo_Location::clear_span() { +void SourceCodeInfo_Location::clear_span() { span_.Clear(); } ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { @@ -12989,16 +13684,16 @@ SourceCodeInfo_Location::mutable_span() { } // optional string leading_comments = 3; - bool SourceCodeInfo_Location::has_leading_comments() const { +bool SourceCodeInfo_Location::has_leading_comments() const { return (_has_bits_[0] & 0x00000004u) != 0; } - void SourceCodeInfo_Location::set_has_leading_comments() { +void SourceCodeInfo_Location::set_has_leading_comments() { _has_bits_[0] |= 0x00000004u; } - void SourceCodeInfo_Location::clear_has_leading_comments() { +void SourceCodeInfo_Location::clear_has_leading_comments() { _has_bits_[0] &= ~0x00000004u; } - void SourceCodeInfo_Location::clear_leading_comments() { +void SourceCodeInfo_Location::clear_leading_comments() { leading_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_leading_comments(); } @@ -13042,16 +13737,16 @@ SourceCodeInfo_Location::mutable_span() { } // optional string trailing_comments = 4; - bool SourceCodeInfo_Location::has_trailing_comments() const { +bool SourceCodeInfo_Location::has_trailing_comments() const { return (_has_bits_[0] & 0x00000008u) != 0; } - void SourceCodeInfo_Location::set_has_trailing_comments() { +void SourceCodeInfo_Location::set_has_trailing_comments() { _has_bits_[0] |= 0x00000008u; } - void SourceCodeInfo_Location::clear_has_trailing_comments() { +void SourceCodeInfo_Location::clear_has_trailing_comments() { _has_bits_[0] &= ~0x00000008u; } - void SourceCodeInfo_Location::clear_trailing_comments() { +void SourceCodeInfo_Location::clear_trailing_comments() { trailing_comments_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_trailing_comments(); } @@ -13095,10 +13790,10 @@ SourceCodeInfo_Location::mutable_span() { } // repeated string leading_detached_comments = 6; - int SourceCodeInfo_Location::leading_detached_comments_size() const { +int SourceCodeInfo_Location::leading_detached_comments_size() const { return leading_detached_comments_.size(); } - void SourceCodeInfo_Location::clear_leading_detached_comments() { +void SourceCodeInfo_Location::clear_leading_detached_comments() { leading_detached_comments_.Clear(); } const ::std::string& SourceCodeInfo_Location::leading_detached_comments(int index) const { @@ -13153,10 +13848,10 @@ SourceCodeInfo_Location::mutable_leading_detached_comments() { // SourceCodeInfo // repeated .google.protobuf.SourceCodeInfo.Location location = 1; - int SourceCodeInfo::location_size() const { +int SourceCodeInfo::location_size() const { return location_.size(); } - void SourceCodeInfo::clear_location() { +void SourceCodeInfo::clear_location() { location_.Clear(); } const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index 5bebf4fd..b887b8cb 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -42,6 +42,7 @@ class FileDescriptorSet; class FileDescriptorProto; class DescriptorProto; class DescriptorProto_ExtensionRange; +class DescriptorProto_ReservedRange; class FieldDescriptorProto; class OneofDescriptorProto; class EnumDescriptorProto; @@ -155,6 +156,26 @@ inline bool FieldOptions_CType_Parse( return ::google::protobuf::internal::ParseNamedEnum( FieldOptions_CType_descriptor(), name, value); } +enum FieldOptions_JSType { + FieldOptions_JSType_JS_NORMAL = 0, + FieldOptions_JSType_JS_STRING = 1, + FieldOptions_JSType_JS_NUMBER = 2 +}; +LIBPROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value); +const FieldOptions_JSType FieldOptions_JSType_JSType_MIN = FieldOptions_JSType_JS_NORMAL; +const FieldOptions_JSType FieldOptions_JSType_JSType_MAX = FieldOptions_JSType_JS_NUMBER; +const int FieldOptions_JSType_JSType_ARRAYSIZE = FieldOptions_JSType_JSType_MAX + 1; + +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* FieldOptions_JSType_descriptor(); +inline const ::std::string& FieldOptions_JSType_Name(FieldOptions_JSType value) { + return ::google::protobuf::internal::NameOfEnum( + FieldOptions_JSType_descriptor(), value); +} +inline bool FieldOptions_JSType_Parse( + const ::std::string& name, FieldOptions_JSType* value) { + return ::google::protobuf::internal::ParseNamedEnum( + FieldOptions_JSType_descriptor(), name, value); +} // =================================================================== class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message { @@ -591,6 +612,105 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto }; // ------------------------------------------------------------------- +class LIBPROTOBUF_EXPORT DescriptorProto_ReservedRange : public ::google::protobuf::Message { + public: + DescriptorProto_ReservedRange(); + virtual ~DescriptorProto_ReservedRange(); + + DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from); + + inline DescriptorProto_ReservedRange& operator=(const DescriptorProto_ReservedRange& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _internal_metadata_.unknown_fields(); + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return _internal_metadata_.mutable_unknown_fields(); + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const DescriptorProto_ReservedRange& default_instance(); + + void Swap(DescriptorProto_ReservedRange* other); + + // implements Message ---------------------------------------------- + + inline DescriptorProto_ReservedRange* New() const { return New(NULL); } + + DescriptorProto_ReservedRange* New(::google::protobuf::Arena* arena) const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const DescriptorProto_ReservedRange& from); + void MergeFrom(const DescriptorProto_ReservedRange& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + void InternalSwap(DescriptorProto_ReservedRange* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } + public: + + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional int32 start = 1; + bool has_start() const; + void clear_start(); + static const int kStartFieldNumber = 1; + ::google::protobuf::int32 start() const; + void set_start(::google::protobuf::int32 value); + + // optional int32 end = 2; + bool has_end() const; + void clear_end(); + static const int kEndFieldNumber = 2; + ::google::protobuf::int32 end() const; + void set_end(::google::protobuf::int32 value); + + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange) + private: + inline void set_has_start(); + inline void clear_has_start(); + inline void set_has_end(); + inline void clear_has_end(); + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; + ::google::protobuf::int32 start_; + ::google::protobuf::int32 end_; + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); + + void InitAsDefaultInstance(); + static DescriptorProto_ReservedRange* default_instance_; +}; +// ------------------------------------------------------------------- + class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { public: DescriptorProto(); @@ -654,6 +774,7 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { // nested types ---------------------------------------------------- typedef DescriptorProto_ExtensionRange ExtensionRange; + typedef DescriptorProto_ReservedRange ReservedRange; // accessors ------------------------------------------------------- @@ -750,6 +871,34 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { ::google::protobuf::MessageOptions* release_options(); void set_allocated_options(::google::protobuf::MessageOptions* options); + // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; + int reserved_range_size() const; + void clear_reserved_range(); + static const int kReservedRangeFieldNumber = 9; + const ::google::protobuf::DescriptorProto_ReservedRange& reserved_range(int index) const; + ::google::protobuf::DescriptorProto_ReservedRange* mutable_reserved_range(int index); + ::google::protobuf::DescriptorProto_ReservedRange* add_reserved_range(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >& + reserved_range() const; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >* + mutable_reserved_range(); + + // repeated string reserved_name = 10; + int reserved_name_size() const; + void clear_reserved_name(); + static const int kReservedNameFieldNumber = 10; + const ::std::string& reserved_name(int index) const; + ::std::string* mutable_reserved_name(int index); + void set_reserved_name(int index, const ::std::string& value); + void set_reserved_name(int index, const char* value); + void set_reserved_name(int index, const char* value, size_t size); + ::std::string* add_reserved_name(); + void add_reserved_name(const ::std::string& value); + void add_reserved_name(const char* value); + void add_reserved_name(const char* value, size_t size); + const ::google::protobuf::RepeatedPtrField< ::std::string>& reserved_name() const; + ::google::protobuf::RepeatedPtrField< ::std::string>* mutable_reserved_name(); + // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto) private: inline void set_has_name(); @@ -768,6 +917,8 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto > oneof_decl_; ::google::protobuf::MessageOptions* options_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange > reserved_range_; + ::google::protobuf::RepeatedPtrField< ::std::string> reserved_name_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2144,6 +2295,31 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { return FieldOptions_CType_Parse(name, value); } + typedef FieldOptions_JSType JSType; + static const JSType JS_NORMAL = FieldOptions_JSType_JS_NORMAL; + static const JSType JS_STRING = FieldOptions_JSType_JS_STRING; + static const JSType JS_NUMBER = FieldOptions_JSType_JS_NUMBER; + static inline bool JSType_IsValid(int value) { + return FieldOptions_JSType_IsValid(value); + } + static const JSType JSType_MIN = + FieldOptions_JSType_JSType_MIN; + static const JSType JSType_MAX = + FieldOptions_JSType_JSType_MAX; + static const int JSType_ARRAYSIZE = + FieldOptions_JSType_JSType_ARRAYSIZE; + static inline const ::google::protobuf::EnumDescriptor* + JSType_descriptor() { + return FieldOptions_JSType_descriptor(); + } + static inline const ::std::string& JSType_Name(JSType value) { + return FieldOptions_JSType_Name(value); + } + static inline bool JSType_Parse(const ::std::string& name, + JSType* value) { + return FieldOptions_JSType_Parse(name, value); + } + // accessors ------------------------------------------------------- // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; @@ -2160,6 +2336,13 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { bool packed() const; void set_packed(bool value); + // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; + bool has_jstype() const; + void clear_jstype(); + static const int kJstypeFieldNumber = 6; + ::google::protobuf::FieldOptions_JSType jstype() const; + void set_jstype(::google::protobuf::FieldOptions_JSType value); + // optional bool lazy = 5 [default = false]; bool has_lazy() const; void clear_lazy(); @@ -2200,6 +2383,8 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { inline void clear_has_ctype(); inline void set_has_packed(); inline void clear_has_packed(); + inline void set_has_jstype(); + inline void clear_has_jstype(); inline void set_has_lazy(); inline void clear_has_lazy(); inline void set_has_deprecated(); @@ -2213,11 +2398,12 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; int ctype_; + int jstype_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool packed_; bool lazy_; bool deprecated_; bool weak_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -3754,6 +3940,58 @@ inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 va // ------------------------------------------------------------------- +// DescriptorProto_ReservedRange + +// optional int32 start = 1; +inline bool DescriptorProto_ReservedRange::has_start() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void DescriptorProto_ReservedRange::set_has_start() { + _has_bits_[0] |= 0x00000001u; +} +inline void DescriptorProto_ReservedRange::clear_has_start() { + _has_bits_[0] &= ~0x00000001u; +} +inline void DescriptorProto_ReservedRange::clear_start() { + start_ = 0; + clear_has_start(); +} +inline ::google::protobuf::int32 DescriptorProto_ReservedRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start) + return start_; +} +inline void DescriptorProto_ReservedRange::set_start(::google::protobuf::int32 value) { + set_has_start(); + start_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start) +} + +// optional int32 end = 2; +inline bool DescriptorProto_ReservedRange::has_end() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void DescriptorProto_ReservedRange::set_has_end() { + _has_bits_[0] |= 0x00000002u; +} +inline void DescriptorProto_ReservedRange::clear_has_end() { + _has_bits_[0] &= ~0x00000002u; +} +inline void DescriptorProto_ReservedRange::clear_end() { + end_ = 0; + clear_has_end(); +} +inline ::google::protobuf::int32 DescriptorProto_ReservedRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end) + return end_; +} +inline void DescriptorProto_ReservedRange::set_end(::google::protobuf::int32 value) { + set_has_end(); + end_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end) +} + +// ------------------------------------------------------------------- + // DescriptorProto // optional string name = 1; @@ -4032,6 +4270,90 @@ inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOp // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) } +// repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9; +inline int DescriptorProto::reserved_range_size() const { + return reserved_range_.size(); +} +inline void DescriptorProto::clear_reserved_range() { + reserved_range_.Clear(); +} +inline const ::google::protobuf::DescriptorProto_ReservedRange& DescriptorProto::reserved_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_range) + return reserved_range_.Get(index); +} +inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::mutable_reserved_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_range) + return reserved_range_.Mutable(index); +} +inline ::google::protobuf::DescriptorProto_ReservedRange* DescriptorProto::add_reserved_range() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_range) + return reserved_range_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >& +DescriptorProto::reserved_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_range) + return reserved_range_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ReservedRange >* +DescriptorProto::mutable_reserved_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_range) + return &reserved_range_; +} + +// repeated string reserved_name = 10; +inline int DescriptorProto::reserved_name_size() const { + return reserved_name_.size(); +} +inline void DescriptorProto::clear_reserved_name() { + reserved_name_.Clear(); +} +inline const ::std::string& DescriptorProto::reserved_name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.reserved_name) + return reserved_name_.Get(index); +} +inline ::std::string* DescriptorProto::mutable_reserved_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.reserved_name) + return reserved_name_.Mutable(index); +} +inline void DescriptorProto::set_reserved_name(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.reserved_name) + reserved_name_.Mutable(index)->assign(value); +} +inline void DescriptorProto::set_reserved_name(int index, const char* value) { + reserved_name_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) { + reserved_name_.Mutable(index)->assign( + reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name) +} +inline ::std::string* DescriptorProto::add_reserved_name() { + return reserved_name_.Add(); +} +inline void DescriptorProto::add_reserved_name(const ::std::string& value) { + reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::add_reserved_name(const char* value) { + reserved_name_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name) +} +inline void DescriptorProto::add_reserved_name(const char* value, size_t size) { + reserved_name_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name) +} +inline const ::google::protobuf::RepeatedPtrField< ::std::string>& +DescriptorProto::reserved_name() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.reserved_name) + return reserved_name_; +} +inline ::google::protobuf::RepeatedPtrField< ::std::string>* +DescriptorProto::mutable_reserved_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.reserved_name) + return &reserved_name_; +} + // ------------------------------------------------------------------- // FieldDescriptorProto @@ -5783,15 +6105,40 @@ inline void FieldOptions::set_packed(bool value) { // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) } +// optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL]; +inline bool FieldOptions::has_jstype() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void FieldOptions::set_has_jstype() { + _has_bits_[0] |= 0x00000004u; +} +inline void FieldOptions::clear_has_jstype() { + _has_bits_[0] &= ~0x00000004u; +} +inline void FieldOptions::clear_jstype() { + jstype_ = 0; + clear_has_jstype(); +} +inline ::google::protobuf::FieldOptions_JSType FieldOptions::jstype() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.jstype) + return static_cast< ::google::protobuf::FieldOptions_JSType >(jstype_); +} +inline void FieldOptions::set_jstype(::google::protobuf::FieldOptions_JSType value) { + assert(::google::protobuf::FieldOptions_JSType_IsValid(value)); + set_has_jstype(); + jstype_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.jstype) +} + // optional bool lazy = 5 [default = false]; inline bool FieldOptions::has_lazy() const { - return (_has_bits_[0] & 0x00000004u) != 0; + return (_has_bits_[0] & 0x00000008u) != 0; } inline void FieldOptions::set_has_lazy() { - _has_bits_[0] |= 0x00000004u; + _has_bits_[0] |= 0x00000008u; } inline void FieldOptions::clear_has_lazy() { - _has_bits_[0] &= ~0x00000004u; + _has_bits_[0] &= ~0x00000008u; } inline void FieldOptions::clear_lazy() { lazy_ = false; @@ -5809,13 +6156,13 @@ inline void FieldOptions::set_lazy(bool value) { // optional bool deprecated = 3 [default = false]; inline bool FieldOptions::has_deprecated() const { - return (_has_bits_[0] & 0x00000008u) != 0; + return (_has_bits_[0] & 0x00000010u) != 0; } inline void FieldOptions::set_has_deprecated() { - _has_bits_[0] |= 0x00000008u; + _has_bits_[0] |= 0x00000010u; } inline void FieldOptions::clear_has_deprecated() { - _has_bits_[0] &= ~0x00000008u; + _has_bits_[0] &= ~0x00000010u; } inline void FieldOptions::clear_deprecated() { deprecated_ = false; @@ -5833,13 +6180,13 @@ inline void FieldOptions::set_deprecated(bool value) { // optional bool weak = 10 [default = false]; inline bool FieldOptions::has_weak() const { - return (_has_bits_[0] & 0x00000010u) != 0; + return (_has_bits_[0] & 0x00000020u) != 0; } inline void FieldOptions::set_has_weak() { - _has_bits_[0] |= 0x00000010u; + _has_bits_[0] |= 0x00000020u; } inline void FieldOptions::clear_has_weak() { - _has_bits_[0] &= ~0x00000010u; + _has_bits_[0] &= ~0x00000020u; } inline void FieldOptions::clear_weak() { weak_ = false; @@ -6746,6 +7093,48 @@ SourceCodeInfo::mutable_location() { } #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) @@ -6776,6 +7165,11 @@ template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() { return ::google::protobuf::FieldOptions_CType_descriptor(); } +template <> struct is_proto_enum< ::google::protobuf::FieldOptions_JSType> : ::google::protobuf::internal::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_JSType>() { + return ::google::protobuf::FieldOptions_JSType_descriptor(); +} } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 7099135d..20a60080 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -106,6 +106,18 @@ message DescriptorProto { repeated OneofDescriptorProto oneof_decl = 8; optional MessageOptions options = 7; + + // Range of reserved tag numbers. Reserved tag numbers may not be used by + // fields or extension ranges in the same message. Reserved ranges may + // not overlap. + message ReservedRange { + optional int32 start = 1; // Inclusive. + optional int32 end = 2; // Exclusive. + } + repeated ReservedRange reserved_range = 9; + // Reserved field names, which may not be used by fields in the same message. + // A given name may only be reserved once. + repeated string reserved_name = 10; } // Describes a field within a message. @@ -251,11 +263,11 @@ message MethodDescriptorProto { // * For options which will be published and used publicly by multiple // independent entities, e-mail protobuf-global-extension-registry@google.com // to reserve extension numbers. Simply provide your project name (e.g. -// Object-C plugin) and your porject website (if available) -- there's no need -// to explain how you intend to use them. Usually you only need one extension -// number. You can declare multiple options with only one extension number by -// putting them in a sub-message. See the Custom Options section of the docs -// for examples: +// Objective-C plugin) and your project website (if available) -- there's no +// need to explain how you intend to use them. Usually you only need one +// extension number. You can declare multiple options with only one extension +// number by putting them in a sub-message. See the Custom Options section of +// the docs for examples: // https://developers.google.com/protocol-buffers/docs/proto#options // If this turns out to be popular, a web service will be set up // to automatically assign option numbers. @@ -442,10 +454,31 @@ message FieldOptions { // The packed option can be enabled for repeated primitive fields to enable // a more efficient representation on the wire. Rather than repeatedly // writing the tag and type for each element, the entire array is encoded as - // a single length-delimited blob. + // a single length-delimited blob. In proto3, only explicit setting it to + // false will avoid using packed encoding. optional bool packed = 2; + // The jstype option determines the JavaScript type used for values of the + // field. The option is permitted only for 64 bit integral and fixed types + // (int64, uint64, sint64, fixed64, sfixed64). By default these types are + // represented as JavaScript strings. This avoids loss of precision that can + // happen when a large value is converted to a floating point JavaScript + // numbers. Specifying JS_NUMBER for the jstype causes the generated + // JavaScript code to use the JavaScript "number" type instead of strings. + // This option is an enum to permit additional types to be added, + // e.g. goog.math.Integer. + optional JSType jstype = 6 [default = JS_NORMAL]; + enum JSType { + // Use the default type. + JS_NORMAL = 0; + + // Use JavaScript strings. + JS_STRING = 1; + + // Use JavaScript numbers. + JS_NUMBER = 2; + } // Should this field be parsed lazily? Lazy applies only to message-type // fields. It means that when the outer message is initially parsed, the diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h index 934e4022..86002d56 100644 --- a/src/google/protobuf/descriptor_database.h +++ b/src/google/protobuf/descriptor_database.h @@ -312,7 +312,7 @@ class LIBPROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase { // A DescriptorDatabase that fetches files from a given pool. class LIBPROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase { public: - DescriptorPoolDatabase(const DescriptorPool& pool); + explicit DescriptorPoolDatabase(const DescriptorPool& pool); ~DescriptorPoolDatabase(); // implements DescriptorDatabase ----------------------------------- @@ -341,7 +341,7 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { // Merge more than two databases. The sources remain property of the caller. // The vector may be deleted after the constructor returns but the // DescriptorDatabases need to stick around. - MergedDescriptorDatabase(const vector& sources); + explicit MergedDescriptorDatabase(const vector& sources); ~MergedDescriptorDatabase(); // implements DescriptorDatabase ----------------------------------- diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index fdce3d78..760df097 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -139,6 +139,14 @@ DescriptorProto::ExtensionRange* AddExtensionRange(DescriptorProto* parent, return result; } +DescriptorProto::ReservedRange* AddReservedRange(DescriptorProto* parent, + int start, int end) { + DescriptorProto::ReservedRange* result = parent->add_reserved_range(); + result->set_start(start); + result->set_end(end); + return result; +} + EnumValueDescriptorProto* AddEnumValue(EnumDescriptorProto* enum_proto, const string& name, int number) { EnumValueDescriptorProto* result = enum_proto->add_value(); @@ -1720,6 +1728,84 @@ TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) { // =================================================================== +// Test reserved fields. +class ReservedDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // message Foo { + // reserved 2, 9 to 11, 15; + // reserved "foo", "bar"; + // } + + FileDescriptorProto foo_file; + foo_file.set_name("foo.proto"); + + DescriptorProto* foo = AddMessage(&foo_file, "Foo"); + AddReservedRange(foo, 2, 3); + AddReservedRange(foo, 9, 12); + AddReservedRange(foo, 15, 16); + + foo->add_reserved_name("foo"); + foo->add_reserved_name("bar"); + + // Build the descriptors and get the pointers. + foo_file_ = pool_.BuildFile(foo_file); + ASSERT_TRUE(foo_file_ != NULL); + + ASSERT_EQ(1, foo_file_->message_type_count()); + foo_ = foo_file_->message_type(0); + } + + DescriptorPool pool_; + const FileDescriptor* foo_file_; + const Descriptor* foo_; +}; + +TEST_F(ReservedDescriptorTest, ReservedRanges) { + ASSERT_EQ(3, foo_->reserved_range_count()); + + EXPECT_EQ(2, foo_->reserved_range(0)->start); + EXPECT_EQ(3, foo_->reserved_range(0)->end); + + EXPECT_EQ(9, foo_->reserved_range(1)->start); + EXPECT_EQ(12, foo_->reserved_range(1)->end); + + EXPECT_EQ(15, foo_->reserved_range(2)->start); + EXPECT_EQ(16, foo_->reserved_range(2)->end); +}; + +TEST_F(ReservedDescriptorTest, IsReservedNumber) { + EXPECT_FALSE(foo_->IsReservedNumber(1)); + EXPECT_TRUE (foo_->IsReservedNumber(2)); + EXPECT_FALSE(foo_->IsReservedNumber(3)); + EXPECT_FALSE(foo_->IsReservedNumber(8)); + EXPECT_TRUE (foo_->IsReservedNumber(9)); + EXPECT_TRUE (foo_->IsReservedNumber(10)); + EXPECT_TRUE (foo_->IsReservedNumber(11)); + EXPECT_FALSE(foo_->IsReservedNumber(12)); + EXPECT_FALSE(foo_->IsReservedNumber(13)); + EXPECT_FALSE(foo_->IsReservedNumber(14)); + EXPECT_TRUE (foo_->IsReservedNumber(15)); + EXPECT_FALSE(foo_->IsReservedNumber(16)); +}; + +TEST_F(ReservedDescriptorTest, ReservedNames) { + ASSERT_EQ(2, foo_->reserved_name_count()); + + EXPECT_EQ("foo", foo_->reserved_name(0)); + EXPECT_EQ("bar", foo_->reserved_name(1)); +}; + +TEST_F(ReservedDescriptorTest, IsReservedName) { + EXPECT_TRUE (foo_->IsReservedName("foo")); + EXPECT_TRUE (foo_->IsReservedName("bar")); + EXPECT_FALSE(foo_->IsReservedName("baz")); +}; + +// =================================================================== + class MiscTest : public testing::Test { protected: // Function which makes a field descriptor of the given type. @@ -2997,10 +3083,10 @@ class ValidationErrorTest : public testing::Test { protected: // Parse file_text as a FileDescriptorProto in text format and add it // to the DescriptorPool. Expect no errors. - void BuildFile(const string& file_text) { + const FileDescriptor* BuildFile(const string& file_text) { FileDescriptorProto file_proto; - ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); - ASSERT_TRUE(pool_.BuildFile(file_proto) != NULL); + EXPECT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); + return GOOGLE_CHECK_NOTNULL(pool_.BuildFile(file_proto)); } // Parse file_text as a FileDescriptorProto in text format and add it @@ -3251,6 +3337,102 @@ TEST_F(ValidationErrorTest, OverlappingExtensionRanges) { "already-defined range 20 to 29.\n"); } +TEST_F(ValidationErrorTest, ReservedFieldError) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " reserved_range { start: 10 end: 20 }" + "}", + + "foo.proto: Foo.foo: NUMBER: Field \"foo\" uses reserved number 15.\n"); +} + +TEST_F(ValidationErrorTest, ReservedExtensionRangeError) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 20 }" + " reserved_range { start: 5 end: 15 }" + "}", + + "foo.proto: Foo: NUMBER: Extension range 10 to 19" + " overlaps with reserved range 5 to 14.\n"); +} + +TEST_F(ValidationErrorTest, ReservedExtensionRangeAdjacent) { + BuildFile( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " extension_range { start: 10 end: 20 }" + " reserved_range { start: 5 end: 10 }" + "}"); +} + +TEST_F(ValidationErrorTest, ReservedRangeOverlap) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " reserved_range { start: 10 end: 20 }" + " reserved_range { start: 5 end: 15 }" + "}", + + "foo.proto: Foo: NUMBER: Reserved range 5 to 14" + " overlaps with already-defined range 10 to 19.\n"); +} + +TEST_F(ValidationErrorTest, ReservedNameError) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name: \"foo\" number: 15 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name: \"bar\" number: 16 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name: \"baz\" number: 17 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " reserved_name: \"foo\"" + " reserved_name: \"bar\"" + "}", + + "foo.proto: Foo.foo: NAME: Field name \"foo\" is reserved.\n" + "foo.proto: Foo.bar: NAME: Field name \"bar\" is reserved.\n"); +} + +TEST_F(ValidationErrorTest, ReservedNameRedundant) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " reserved_name: \"foo\"" + " reserved_name: \"foo\"" + "}", + + "foo.proto: foo: NAME: Field name \"foo\" is reserved multiple times.\n"); +} + +TEST_F(ValidationErrorTest, ReservedFieldsDebugString) { + const FileDescriptor* file = BuildFile( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " reserved_name: \"foo\"" + " reserved_name: \"bar\"" + " reserved_range { start: 5 end: 6 }" + " reserved_range { start: 10 end: 20 }" + "}"); + + ASSERT_EQ( + "syntax = \"proto2\";\n\n" + "message Foo {\n" + " reserved 5, 10 to 19;\n" + " reserved \"foo\", \"bar\";\n" + "}\n\n", + file->DebugString()); +} + TEST_F(ValidationErrorTest, InvalidDefaults) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -3399,6 +3581,48 @@ TEST_F(ValidationErrorTest, FieldOneofIndexNegative) { "range for type \"Foo\".\n"); } +TEST_F(ValidationErrorTest, OneofFieldsConsecutiveDefinition) { + // Fields belonging to the same oneof must be defined consecutively. + BuildFileWithWarnings( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " field { name:\"bar\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 }" + " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " oneof_decl { name:\"foos\" }" + "}", + + "foo.proto: Foo.bar: OTHER: Fields in the same oneof must be defined " + "consecutively. \"bar\" cannot be defined before the completion of the " + "\"foos\" oneof definition.\n"); + + // Prevent interleaved fields, which belong to different oneofs. + BuildFileWithWarnings( + "name: \"foo2.proto\" " + "message_type {" + " name: \"Foo2\"" + " field { name:\"foo1\" number: 1 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " field { name:\"bar1\" number: 2 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 1 }" + " field { name:\"foo2\" number: 3 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " field { name:\"bar2\" number: 4 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 1 }" + " oneof_decl { name:\"foos\" }" + " oneof_decl { name:\"bars\" }" + "}", + "foo2.proto: Foo2.bar1: OTHER: Fields in the same oneof must be defined " + "consecutively. \"bar1\" cannot be defined before the completion of the " + "\"foos\" oneof definition.\n" + "foo2.proto: Foo2.foo2: OTHER: Fields in the same oneof must be defined " + "consecutively. \"foo2\" cannot be defined before the completion of the " + "\"bars\" oneof definition.\n"); +} + TEST_F(ValidationErrorTest, FieldNumberConflict) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -5293,6 +5517,22 @@ TEST_F(ValidationErrorTest, ValidateProto3LiteRuntime) { "in proto3.\n"); } +TEST_F(ValidationErrorTest, ValidateProto3Group) { + BuildFileWithErrors( + "name: 'foo.proto' " + "syntax: 'proto3' " + "message_type { " + " name: 'Foo' " + " nested_type { " + " name: 'FooGroup' " + " } " + " field { name:'foo_group' number: 1 label:LABEL_OPTIONAL " + " type: TYPE_GROUP type_name:'FooGroup' } " + "}", + "foo.proto: Foo.foo_group: TYPE: Groups are not supported in proto3 " + "syntax.\n"); +} + TEST_F(ValidationErrorTest, ValidateProto3EnumFromProto2) { // Define an enum in a proto2 file. diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index 4a11209e..f78fce21 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -117,7 +117,7 @@ const int Duration::kNanosFieldNumber; #endif // !_MSC_VER Duration::Duration() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Duration) } @@ -310,9 +310,9 @@ int Duration::ByteSize() const { void Duration::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Duration* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Duration* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -370,7 +370,7 @@ void Duration::InternalSwap(Duration* other) { // Duration // optional int64 seconds = 1; - void Duration::clear_seconds() { +void Duration::clear_seconds() { seconds_ = GOOGLE_LONGLONG(0); } ::google::protobuf::int64 Duration::seconds() const { @@ -384,7 +384,7 @@ void Duration::InternalSwap(Duration* other) { } // optional int32 nanos = 2; - void Duration::clear_nanos() { +void Duration::clear_nanos() { nanos_ = 0; } ::google::protobuf::int32 Duration::nanos() const { diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index f7ca5013..1a9a6661 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -111,7 +111,7 @@ static void MergeFromFail(int line) { #endif // !_MSC_VER Empty::Empty() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Empty) } @@ -221,9 +221,9 @@ int Empty::ByteSize() const { void Empty::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Empty* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Empty* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 03b38dd0..649ae184 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -314,7 +314,7 @@ void ExtensionSet::Add##CAMELCASE(int number, FieldType type, \ extension->is_repeated = true; \ extension->is_packed = packed; \ extension->repeated_##LOWERCASE##_value = \ - Arena::Create >(arena_, arena_); \ + Arena::CreateMessage >(arena_); \ } else { \ GOOGLE_DCHECK_TYPE(*extension, REPEATED, UPPERCASE); \ GOOGLE_DCHECK_EQ(extension->is_packed, packed); \ @@ -359,43 +359,43 @@ void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, static_cast(field_type))) { case WireFormatLite::CPPTYPE_INT32: extension->repeated_int32_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_INT64: extension->repeated_int64_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_UINT32: extension->repeated_uint32_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_UINT64: extension->repeated_uint64_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_DOUBLE: extension->repeated_double_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_FLOAT: extension->repeated_float_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_BOOL: extension->repeated_bool_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_ENUM: extension->repeated_enum_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_STRING: extension->repeated_string_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; case WireFormatLite::CPPTYPE_MESSAGE: extension->repeated_message_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); break; } } @@ -468,7 +468,7 @@ void ExtensionSet::AddEnum(int number, FieldType type, extension->is_repeated = true; extension->is_packed = packed; extension->repeated_enum_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); } else { GOOGLE_DCHECK_TYPE(*extension, REPEATED, ENUM); GOOGLE_DCHECK_EQ(extension->is_packed, packed); @@ -529,7 +529,7 @@ string* ExtensionSet::AddString(int number, FieldType type, extension->is_repeated = true; extension->is_packed = false; extension->repeated_string_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); } else { GOOGLE_DCHECK_TYPE(*extension, REPEATED, STRING); } @@ -632,6 +632,35 @@ void ExtensionSet::SetAllocatedMessage(int number, FieldType type, extension->is_cleared = false; } +void ExtensionSet::UnsafeArenaSetAllocatedMessage( + int number, FieldType type, const FieldDescriptor* descriptor, + MessageLite* message) { + if (message == NULL) { + ClearExtension(number); + return; + } + Extension* extension; + if (MaybeNewExtension(number, descriptor, &extension)) { + extension->type = type; + GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); + extension->is_repeated = false; + extension->is_lazy = false; + extension->message_value = message; + } else { + GOOGLE_DCHECK_TYPE(*extension, OPTIONAL, MESSAGE); + if (extension->is_lazy) { + extension->lazymessage_value->UnsafeArenaSetAllocatedMessage(message); + } else { + if (arena_ == NULL) { + delete extension->message_value; + } + extension->message_value = message; + } + } + extension->is_cleared = false; +} + + MessageLite* ExtensionSet::ReleaseMessage(int number, const MessageLite& prototype) { map::iterator iter = extensions_.find(number); @@ -712,7 +741,7 @@ MessageLite* ExtensionSet::AddMessage(int number, FieldType type, GOOGLE_DCHECK_EQ(cpp_type(extension->type), WireFormatLite::CPPTYPE_MESSAGE); extension->is_repeated = true; extension->repeated_message_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); } else { GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); } @@ -866,7 +895,7 @@ void ExtensionSet::InternalExtensionMergeFrom( case WireFormatLite::CPPTYPE_##UPPERCASE: \ if (is_new) { \ extension->repeated_##LOWERCASE##_value = \ - Arena::Create(arena_, arena_); \ + Arena::CreateMessage(arena_); \ } \ extension->repeated_##LOWERCASE##_value->MergeFrom( \ *other_extension.repeated_##LOWERCASE##_value); \ @@ -886,7 +915,7 @@ void ExtensionSet::InternalExtensionMergeFrom( case WireFormatLite::CPPTYPE_MESSAGE: if (is_new) { extension->repeated_message_value = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); } // We can't call RepeatedPtrField::MergeFrom() because // it would attempt to allocate new objects. diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index 6d6702b3..c371e011 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -194,7 +194,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // directly, unless you are doing low-level memory management. // // When calling any of these accessors, the extension number requested - // MUST exist in the DescriptorPool provided to the constructor. Otheriwse, + // MUST exist in the DescriptorPool provided to the constructor. Otherwise, // the method will fail an assert. Normally, though, you would not call // these directly; you would either call the generated accessors of your // message class (e.g. GetExtension()) or you would call the accessors @@ -262,6 +262,9 @@ class LIBPROTOBUF_EXPORT ExtensionSet { void SetAllocatedMessage(int number, FieldType type, const FieldDescriptor* descriptor, MessageLite* message); + void UnsafeArenaSetAllocatedMessage(int number, FieldType type, + const FieldDescriptor* descriptor, + MessageLite* message); MessageLite* ReleaseMessage(int number, const MessageLite& prototype); MessageLite* UnsafeArenaReleaseMessage( int number, const MessageLite& prototype); @@ -432,6 +435,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { const MessageLite& prototype) const = 0; virtual MessageLite* MutableMessage(const MessageLite& prototype) = 0; virtual void SetAllocatedMessage(MessageLite *message) = 0; + virtual void UnsafeArenaSetAllocatedMessage(MessageLite *message) = 0; virtual MessageLite* ReleaseMessage(const MessageLite& prototype) = 0; virtual MessageLite* UnsafeArenaReleaseMessage( const MessageLite& prototype) = 0; diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 796e7a5f..330bd828 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -221,7 +221,7 @@ MessageLite* ExtensionSet::AddMessage(const FieldDescriptor* descriptor, GOOGLE_DCHECK_EQ(cpp_type(extension->type), FieldDescriptor::CPPTYPE_MESSAGE); extension->is_repeated = true; extension->repeated_message_value = - ::google::protobuf::Arena::Create >(arena_, arena_); + ::google::protobuf::Arena::CreateMessage >(arena_); } else { GOOGLE_DCHECK_TYPE(*extension, REPEATED, MESSAGE); } diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index b00461d5..68314fd3 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -114,7 +114,7 @@ const int FieldMask::kPathsFieldNumber; #endif // !_MSC_VER FieldMask::FieldMask() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.FieldMask) } @@ -277,9 +277,9 @@ int FieldMask::ByteSize() const { void FieldMask::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const FieldMask* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const FieldMask* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -331,10 +331,10 @@ void FieldMask::InternalSwap(FieldMask* other) { // FieldMask // repeated string paths = 1; - int FieldMask::paths_size() const { +int FieldMask::paths_size() const { return paths_.size(); } - void FieldMask::clear_paths() { +void FieldMask::clear_paths() { paths_.Clear(); } const ::std::string& FieldMask::paths(int index) const { diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index 4dddf6c7..dc8abb98 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -40,6 +40,7 @@ #include #include +#include #include // TODO(jasonh): Remove this once the compiler change to directly include this // is released to components. @@ -597,6 +598,42 @@ inline To dynamic_cast_if_available(From from) { #endif } +// Tries to downcast this message to a generated message type. +// Returns NULL if this class is not an instance of T. +// +// This is like dynamic_cast_if_available, except it works even when +// dynamic_cast is not available by using Reflection. However it only works +// with Message objects. +// +// TODO(haberman): can we remove dynamic_cast_if_available in favor of this? +template +T* DynamicCastToGenerated(const Message* from) { + // Compile-time assert that T is a generated type that has a + // default_instance() accessor, but avoid actually calling it. + const T&(*get_default_instance)() = &T::default_instance; + (void)get_default_instance; + + // Compile-time assert that T is a subclass of google::protobuf::Message. + const Message* unused = static_cast(NULL); + (void)unused; + +#if defined(GOOGLE_PROTOBUF_NO_RTTI) || \ + (defined(_MSC_VER) && !defined(_CPPRTTI)) + bool ok = &T::default_instance() == + from->GetReflection()->GetMessageFactory()->GetPrototype( + from->GetDescriptor()); + return ok ? down_cast(from) : NULL; +#else + return dynamic_cast(from); +#endif +} + +template +T* DynamicCastToGenerated(Message* from) { + const Message* message_const = from; + return const_cast(DynamicCastToGenerated(message_const)); +} + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h index 678f92a7..6357e27d 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -47,6 +47,10 @@ namespace google { namespace protobuf { + +class Arena; +namespace io { class CodedInputStream; } + namespace internal { @@ -106,6 +110,15 @@ template bool AllAreInitialized(const Type& t) { return true; } +class ArenaString; + +// Read a length (varint32), followed by a string, from *input. Return a +// pointer to a copy of the string that resides in *arena. Requires both +// args to be non-NULL. If something goes wrong while reading the data +// then NULL is returned (e.g., input does not start with a valid varint). +ArenaString* ReadArenaString(::google::protobuf::io::CodedInputStream* input, + ::google::protobuf::Arena* arena); + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 93e1a22e..3b8650d6 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -156,6 +156,11 @@ CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) { return std::make_pair(PushLimit(byte_limit), --recursion_budget_); } +CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() { + uint32 length; + return PushLimit(ReadVarint32(&length) ? length : 0); +} + bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) { bool result = ConsumedEntireMessage(); PopLimit(limit); @@ -164,6 +169,12 @@ bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) { return result; } +bool CodedInputStream::CheckEntireMessageConsumedAndPopLimit(Limit limit) { + bool result = ConsumedEntireMessage(); + PopLimit(limit); + return result; +} + int CodedInputStream::BytesUntilLimit() const { if (current_limit_ == INT_MAX) return -1; int current_position = CurrentPosition(); @@ -245,20 +256,7 @@ bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) { } bool CodedInputStream::ReadRaw(void* buffer, int size) { - int current_buffer_size; - while ((current_buffer_size = BufferSize()) < size) { - // Reading past end of buffer. Copy what we have, then refresh. - memcpy(buffer, buffer_, current_buffer_size); - buffer = reinterpret_cast(buffer) + current_buffer_size; - size -= current_buffer_size; - Advance(current_buffer_size); - if (!Refresh()) return false; - } - - memcpy(buffer, buffer_, size); - Advance(size); - - return true; + return InternalReadRawInline(buffer, size); } bool CodedInputStream::ReadString(string* buffer, int size) { @@ -336,17 +334,23 @@ bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) { namespace { -inline const uint8* ReadVarint32FromArray( - const uint8* buffer, uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; -inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) { +// Read a varint from the given buffer, write it to *value, and return a pair. +// The first part of the pair is true iff the read was successful. The second +// part is buffer + (number of bytes read). This function is always inlined, +// so returning a pair is costless. +inline ::std::pair ReadVarint32FromArray( + uint32 first_byte, const uint8* buffer, + uint32* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; +inline ::std::pair ReadVarint32FromArray( + uint32 first_byte, const uint8* buffer, uint32* value) { // Fast path: We have enough bytes left in the buffer to guarantee that // this read won't cross the end, so we can skip the checks. + GOOGLE_DCHECK_EQ(*buffer, first_byte); + GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte; const uint8* ptr = buffer; uint32 b; - uint32 result; - - b = *(ptr++); result = b ; if (!(b & 0x80)) goto done; - result -= 0x80; + uint32 result = first_byte - 0x80; + ++ptr; // We just processed the first byte. Move on to the second. b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done; result -= 0x80 << 7; b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done; @@ -364,38 +368,42 @@ inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) { // We have overrun the maximum size of a varint (10 bytes). Assume // the data is corrupt. - return NULL; + return std::make_pair(false, ptr); done: *value = result; - return ptr; + return std::make_pair(true, ptr); } } // namespace bool CodedInputStream::ReadVarint32Slow(uint32* value) { - uint64 result; // Directly invoke ReadVarint64Fallback, since we already tried to optimize // for one-byte varints. - if (!ReadVarint64Fallback(&result)) return false; - *value = (uint32)result; - return true; + std::pair p = ReadVarint64Fallback(); + *value = static_cast(p.first); + return p.second; } -bool CodedInputStream::ReadVarint32Fallback(uint32* value) { +int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) { if (BufferSize() >= kMaxVarintBytes || // Optimization: We're also safe if the buffer is non-empty and it ends // with a byte that would terminate a varint. (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { - const uint8* end = ReadVarint32FromArray(buffer_, value); - if (end == NULL) return false; - buffer_ = end; - return true; + GOOGLE_DCHECK_NE(first_byte_or_zero, 0) + << "Caller should provide us with *buffer_ when buffer is non-empty"; + uint32 temp; + ::std::pair p = + ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp); + if (!p.first) return -1; + buffer_ = p.second; + return temp; } else { // Really slow case: we will incur the cost of an extra function call here, // but moving this out of line reduces the size of this function, which // improves the common case. In micro benchmarks, this is worth about 10-15% - return ReadVarint32Slow(value); + uint32 temp; + return ReadVarint32Slow(&temp) ? static_cast(temp) : -1; } } @@ -425,18 +433,24 @@ uint32 CodedInputStream::ReadTagSlow() { return static_cast(result); } -uint32 CodedInputStream::ReadTagFallback() { +uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) { const int buf_size = BufferSize(); if (buf_size >= kMaxVarintBytes || // Optimization: We're also safe if the buffer is non-empty and it ends // with a byte that would terminate a varint. (buf_size > 0 && !(buffer_end_[-1] & 0x80))) { + GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]); + if (first_byte_or_zero == 0) { + ++buffer_; + return 0; + } uint32 tag; - const uint8* end = ReadVarint32FromArray(buffer_, &tag); - if (end == NULL) { + ::std::pair p = + ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag); + if (!p.first) { return 0; } - buffer_ = end; + buffer_ = p.second; return tag; } else { // We are commonly at a limit when attempting to read tags. Try to quickly @@ -479,7 +493,7 @@ bool CodedInputStream::ReadVarint64Slow(uint64* value) { return true; } -bool CodedInputStream::ReadVarint64Fallback(uint64* value) { +std::pair CodedInputStream::ReadVarint64Fallback() { if (BufferSize() >= kMaxVarintBytes || // Optimization: We're also safe if the buffer is non-empty and it ends // with a byte that would terminate a varint. @@ -517,16 +531,18 @@ bool CodedInputStream::ReadVarint64Fallback(uint64* value) { // We have overrun the maximum size of a varint (10 bytes). The data // must be corrupt. - return false; + return std::make_pair(0, false); done: Advance(ptr - buffer_); - *value = (static_cast(part0) ) | - (static_cast(part1) << 28) | - (static_cast(part2) << 56); - return true; + return std::make_pair((static_cast(part0)) | + (static_cast(part1) << 28) | + (static_cast(part2) << 56), + true); } else { - return ReadVarint64Slow(value); + uint64 temp; + bool success = ReadVarint64Slow(&temp); + return std::make_pair(temp, success); } } diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index dea4b650..961c1a3f 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -197,6 +197,11 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Read raw bytes, copying them into the given buffer. bool ReadRaw(void* buffer, int size); + // Like the above, with inlined optimizations. This should only be used + // by the protobuf implementation. + inline bool InternalReadRawInline(void* buffer, + int size) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + // Like ReadRaw, but reads into a string. // // Implementation Note: ReadString() grows the string gradually as it @@ -387,9 +392,14 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // under the limit, false if it has gone over. bool IncrementRecursionDepth(); - // Decrements the recursion depth. + // Decrements the recursion depth if possible. void DecrementRecursionDepth(); + // Decrements the recursion depth blindly. This is faster than + // DecrementRecursionDepth(). It should be used only if all previous + // increments to recursion depth were successful. + void UnsafeDecrementRecursionDepth(); + // Shorthand for make_pair(PushLimit(byte_limit), --recursion_budget_). // Using this can reduce code size and complexity in some cases. The caller // is expected to check that the second part of the result is non-negative (to @@ -398,15 +408,25 @@ class LIBPROTOBUF_EXPORT CodedInputStream { std::pair IncrementRecursionDepthAndPushLimit( int byte_limit); + // Shorthand for PushLimit(ReadVarint32(&length) ? length : 0). + Limit ReadLengthAndPushLimit(); + // Helper that is equivalent to: { // bool result = ConsumedEntireMessage(); // PopLimit(limit); - // DecrementRecursionDepth(); + // UnsafeDecrementRecursionDepth(); // return result; } // Using this can reduce code size and complexity in some cases. // Do not use unless the current recursion depth is greater than zero. bool DecrementRecursionDepthAndPopLimit(Limit limit); + // Helper that is equivalent to: { + // bool result = ConsumedEntireMessage(); + // PopLimit(limit); + // return result; } + // Using this can reduce code size and complexity in some cases. + bool CheckEntireMessageConsumedAndPopLimit(Limit limit); + // Extension Registry ---------------------------------------------- // ADVANCED USAGE: 99.9% of people can ignore this section. // @@ -568,9 +588,13 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // optimization. The Slow method is yet another fallback when the buffer is // not large enough. Making the slow path out-of-line speeds up the common // case by 10-15%. The slow path is fairly uncommon: it only triggers when a - // message crosses multiple buffers. - bool ReadVarint32Fallback(uint32* value); - bool ReadVarint64Fallback(uint64* value); + // message crosses multiple buffers. Note: ReadVarint32Fallback() and + // ReadVarint64Fallback() are called frequently and generally not inlined, so + // they have been optimized to avoid "out" parameters. The former returns -1 + // if it fails and the uint32 it read otherwise. The latter has a bool + // indicating success or failure as part of its return type. + int64 ReadVarint32Fallback(uint32 first_byte_or_zero); + std::pair ReadVarint64Fallback(); bool ReadVarint32Slow(uint32* value); bool ReadVarint64Slow(uint64* value); bool ReadLittleEndian32Fallback(uint32* value); @@ -578,7 +602,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Fallback/slow methods for reading tags. These do not update last_tag_, // but will set legitimate_message_end_ if we are at the end of the input // stream. - uint32 ReadTagFallback(); + uint32 ReadTagFallback(uint32 first_byte_or_zero); uint32 ReadTagSlow(); bool ReadStringFallback(string* buffer, int size); @@ -818,13 +842,18 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // methods optimize for that case. inline bool CodedInputStream::ReadVarint32(uint32* value) { - if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && *buffer_ < 0x80) { - *value = *buffer_; - Advance(1); - return true; - } else { - return ReadVarint32Fallback(value); + uint32 v = 0; + if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { + v = *buffer_; + if (v < 0x80) { + *value = v; + Advance(1); + return true; + } } + int64 result = ReadVarint32Fallback(v); + *value = static_cast(result); + return result >= 0; } inline bool CodedInputStream::ReadVarint64(uint64* value) { @@ -832,9 +861,10 @@ inline bool CodedInputStream::ReadVarint64(uint64* value) { *value = *buffer_; Advance(1); return true; - } else { - return ReadVarint64Fallback(value); } + std::pair p = ReadVarint64Fallback(); + *value = p.first; + return p.second; } // static @@ -903,14 +933,17 @@ inline bool CodedInputStream::ReadLittleEndian64(uint64* value) { } inline uint32 CodedInputStream::ReadTag() { - if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_) && buffer_[0] < 0x80) { - last_tag_ = buffer_[0]; - Advance(1); - return last_tag_; - } else { - last_tag_ = ReadTagFallback(); - return last_tag_; + uint32 v = 0; + if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { + v = *buffer_; + if (v < 0x80) { + last_tag_ = v; + Advance(1); + return v; + } } + last_tag_ = ReadTagFallback(v); + return last_tag_; } inline std::pair CodedInputStream::ReadTagWithCutoff( @@ -918,10 +951,12 @@ inline std::pair CodedInputStream::ReadTagWithCutoff( // In performance-sensitive code we can expect cutoff to be a compile-time // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at // compile time. + uint32 first_byte_or_zero = 0; if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { // Hot case: buffer_ non_empty, buffer_[0] in [1, 128). // TODO(gpike): Is it worth rearranging this? E.g., if the number of fields // is large enough then is it better to check for the two-byte case first? + first_byte_or_zero = buffer_[0]; if (static_cast(buffer_[0]) > 0) { const uint32 kMax1ByteVarint = 0x7f; uint32 tag = last_tag_ = buffer_[0]; @@ -948,7 +983,7 @@ inline std::pair CodedInputStream::ReadTagWithCutoff( } } // Slow path - last_tag_ = ReadTagFallback(); + last_tag_ = ReadTagFallback(first_byte_or_zero); return std::make_pair(last_tag_, static_cast(last_tag_ - 1) < cutoff); } @@ -1177,6 +1212,11 @@ inline void CodedInputStream::DecrementRecursionDepth() { if (recursion_budget_ < recursion_limit_) ++recursion_budget_; } +inline void CodedInputStream::UnsafeDecrementRecursionDepth() { + assert(recursion_budget_ < recursion_limit_); + ++recursion_budget_; +} + inline void CodedInputStream::SetExtensionRegistry(const DescriptorPool* pool, MessageFactory* factory) { extension_pool_ = pool; diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h index cd8d1746..fa20f208 100644 --- a/src/google/protobuf/io/coded_stream_inl.h +++ b/src/google/protobuf/io/coded_stream_inl.h @@ -66,6 +66,23 @@ inline bool CodedInputStream::InternalReadStringInline(string* buffer, return ReadStringFallback(buffer, size); } +inline bool CodedInputStream::InternalReadRawInline(void* buffer, int size) { + int current_buffer_size; + while ((current_buffer_size = BufferSize()) < size) { + // Reading past end of buffer. Copy what we have, then refresh. + memcpy(buffer, buffer_, current_buffer_size); + buffer = reinterpret_cast(buffer) + current_buffer_size; + size -= current_buffer_size; + Advance(current_buffer_size); + if (!Refresh()) return false; + } + + memcpy(buffer, buffer_, size); + Advance(size); + + return true; +} + } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc index e621ba1d..3ae8c268 100644 --- a/src/google/protobuf/io/printer.cc +++ b/src/google/protobuf/io/printer.cc @@ -155,6 +155,78 @@ void Printer::Print(const char* text, Print(vars, text); } +void Printer::Print(const char* text, + const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3, + const char* variable4, const string& value4, + const char* variable5, const string& value5) { + map vars; + vars[variable1] = value1; + vars[variable2] = value2; + vars[variable3] = value3; + vars[variable4] = value4; + vars[variable5] = value5; + Print(vars, text); +} + +void Printer::Print(const char* text, + const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3, + const char* variable4, const string& value4, + const char* variable5, const string& value5, + const char* variable6, const string& value6) { + map vars; + vars[variable1] = value1; + vars[variable2] = value2; + vars[variable3] = value3; + vars[variable4] = value4; + vars[variable5] = value5; + vars[variable6] = value6; + Print(vars, text); +} + +void Printer::Print(const char* text, + const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3, + const char* variable4, const string& value4, + const char* variable5, const string& value5, + const char* variable6, const string& value6, + const char* variable7, const string& value7) { + map vars; + vars[variable1] = value1; + vars[variable2] = value2; + vars[variable3] = value3; + vars[variable4] = value4; + vars[variable5] = value5; + vars[variable6] = value6; + vars[variable7] = value7; + Print(vars, text); +} + +void Printer::Print(const char* text, + const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3, + const char* variable4, const string& value4, + const char* variable5, const string& value5, + const char* variable6, const string& value6, + const char* variable7, const string& value7, + const char* variable8, const string& value8) { + map vars; + vars[variable1] = value1; + vars[variable2] = value2; + vars[variable3] = value3; + vars[variable4] = value4; + vars[variable5] = value5; + vars[variable6] = value6; + vars[variable7] = value7; + vars[variable8] = value8; + Print(vars, text); +} + void Printer::Indent() { indent_ += " "; } diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h index 92ce3409..f1490bbe 100644 --- a/src/google/protobuf/io/printer.h +++ b/src/google/protobuf/io/printer.h @@ -91,8 +91,36 @@ class LIBPROTOBUF_EXPORT Printer { const char* variable2, const string& value2, const char* variable3, const string& value3, const char* variable4, const string& value4); - // TODO(kenton): Overloaded versions with more variables? Three seems - // to be enough. + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3, + const char* variable4, const string& value4, + const char* variable5, const string& value5); + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3, + const char* variable4, const string& value4, + const char* variable5, const string& value5, + const char* variable6, const string& value6); + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3, + const char* variable4, const string& value4, + const char* variable5, const string& value5, + const char* variable6, const string& value6, + const char* variable7, const string& value7); + // Like the first Print(), except the substitutions are given as parameters. + void Print(const char* text, const char* variable1, const string& value1, + const char* variable2, const string& value2, + const char* variable3, const string& value3, + const char* variable4, const string& value4, + const char* variable5, const string& value5, + const char* variable6, const string& value6, + const char* variable7, const string& value7, + const char* variable8, const string& value8); // Indent text by two spaces. After calling Indent(), two spaces will be // inserted at the beginning of each line of text. Indent() may be called diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index 4ea21007..1995cf08 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -34,12 +34,16 @@ #include #include +#include +#include +#include #include #include #include #include #include #include +#include using namespace std; @@ -84,6 +88,12 @@ void SetSomeTypesInEmptyMessageUnknownFields( } // namespace +#define EXPECT_TRUE GOOGLE_CHECK +#define ASSERT_TRUE GOOGLE_CHECK +#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND)) +#define EXPECT_EQ GOOGLE_CHECK_EQ +#define ASSERT_EQ GOOGLE_CHECK_EQ + int main(int argc, char* argv[]) { string data, data2, packed_data; @@ -345,6 +355,374 @@ int main(int argc, char* argv[]) { GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size()); } + // Tests for map lite ============================================= + + { + // Accessors + protobuf_unittest::TestMapLite message; + + google::protobuf::MapLiteTestUtil::SetMapFields(&message); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message); + + google::protobuf::MapLiteTestUtil::ModifyMapFields(&message); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message); + } + + { + // SetMapFieldsInitialized + protobuf_unittest::TestMapLite message; + + google::protobuf::MapLiteTestUtil::SetMapFieldsInitialized(&message); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSetInitialized(message); + } + + { + // Proto2SetMapFieldsInitialized + protobuf_unittest::TestEnumStartWithNonZeroMapLite message; + EXPECT_EQ(protobuf_unittest::PROTO2_NON_ZERO_MAP_ENUM_FOO_LITE, + (*message.mutable_map_field())[0]); + } + + { + // Clear + protobuf_unittest::TestMapLite message; + + google::protobuf::MapLiteTestUtil::SetMapFields(&message); + message.Clear(); + google::protobuf::MapLiteTestUtil::ExpectClear(message); + } + + { + // ClearMessageMap + protobuf_unittest::TestMessageMapLite message; + + // Creates a TestAllTypes with default value + google::protobuf::TestUtilLite::ExpectClear( + (*message.mutable_map_int32_message())[0]); + } + + { + // CopyFrom + protobuf_unittest::TestMapLite message1, message2; + + google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + message2.CopyFrom(message1); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + + // Copying from self should be a no-op. + message2.CopyFrom(message2); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + } + + { + // CopyFromMessageMap + protobuf_unittest::TestMessageMapLite message1, message2; + + (*message1.mutable_map_int32_message())[0].add_repeated_int32(100); + (*message2.mutable_map_int32_message())[0].add_repeated_int32(101); + + message1.CopyFrom(message2); + + // Checks repeated field is overwritten. + EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size()); + EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0)); + } + + { + // SwapWithEmpty + protobuf_unittest::TestMapLite message1, message2; + + google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1); + google::protobuf::MapLiteTestUtil::ExpectClear(message2); + + message1.Swap(&message2); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + google::protobuf::MapLiteTestUtil::ExpectClear(message1); + } + + { + // SwapWithSelf + protobuf_unittest::TestMapLite message; + + google::protobuf::MapLiteTestUtil::SetMapFields(&message); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message); + + message.Swap(&message); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message); + } + + { + // SwapWithOther + protobuf_unittest::TestMapLite message1, message2; + + google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + google::protobuf::MapLiteTestUtil::SetMapFields(&message2); + google::protobuf::MapLiteTestUtil::ModifyMapFields(&message2); + + message1.Swap(&message2); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsModified(message1); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + } + + { + // CopyConstructor + protobuf_unittest::TestMapLite message1; + google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + + protobuf_unittest::TestMapLite message2(message1); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + } + + { + // CopyAssignmentOperator + protobuf_unittest::TestMapLite message1; + google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + + protobuf_unittest::TestMapLite message2; + message2 = message1; + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + + // Make sure that self-assignment does something sane. + message2.operator=(message2); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + } + + { + // NonEmptyMergeFrom + protobuf_unittest::TestMapLite message1, message2; + + google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + + // This field will test merging into an empty spot. + (*message2.mutable_map_int32_int32())[1] = 1; + message1.mutable_map_int32_int32()->erase(1); + + // This tests overwriting. + (*message2.mutable_map_int32_double())[1] = 1; + (*message1.mutable_map_int32_double())[1] = 2; + + message1.MergeFrom(message2); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message1); + } + + { + // MergeFromMessageMap + protobuf_unittest::TestMessageMapLite message1, message2; + + (*message1.mutable_map_int32_message())[0].add_repeated_int32(100); + (*message2.mutable_map_int32_message())[0].add_repeated_int32(101); + + message1.MergeFrom(message2); + + // Checks repeated field is overwritten. + EXPECT_EQ(1, message1.map_int32_message().at(0).repeated_int32_size()); + EXPECT_EQ(101, message1.map_int32_message().at(0).repeated_int32(0)); + } + + { + // Test the generated SerializeWithCachedSizesToArray() + protobuf_unittest::TestMapLite message1, message2; + string data; + google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + int size = message1.ByteSize(); + data.resize(size); + ::google::protobuf::uint8* start = reinterpret_cast< ::google::protobuf::uint8*>(::google::protobuf::string_as_array(&data)); + ::google::protobuf::uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + } + + { + // Test the generated SerializeWithCachedSizes() + protobuf_unittest::TestMapLite message1, message2; + google::protobuf::MapLiteTestUtil::SetMapFields(&message1); + int size = message1.ByteSize(); + string data; + data.resize(size); + { + // Allow the output stream to buffer only one byte at a time. + google::protobuf::io::ArrayOutputStream array_stream( + ::google::protobuf::string_as_array(&data), size, 1); + google::protobuf::io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + EXPECT_TRUE(message2.ParseFromString(data)); + google::protobuf::MapLiteTestUtil::ExpectMapFieldsSet(message2); + } + + + { + // Proto2UnknownEnum + protobuf_unittest::TestEnumMapPlusExtraLite from; + (*from.mutable_known_map_field())[0] = + protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE; + (*from.mutable_unknown_map_field())[0] = + protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE; + string data; + from.SerializeToString(&data); + + protobuf_unittest::TestEnumMapLite to; + EXPECT_TRUE(to.ParseFromString(data)); + EXPECT_EQ(0, to.unknown_map_field().size()); + EXPECT_FALSE(to.mutable_unknown_fields()->empty()); + EXPECT_EQ(1, to.known_map_field().size()); + EXPECT_EQ(protobuf_unittest::PROTO2_MAP_ENUM_FOO_LITE, + to.known_map_field().at(0)); + + data.clear(); + from.Clear(); + to.SerializeToString(&data); + EXPECT_TRUE(from.ParseFromString(data)); + EXPECT_EQ(1, from.known_map_field().size()); + EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_FOO_LITE, + from.known_map_field().at(0)); + EXPECT_EQ(1, from.unknown_map_field().size()); + EXPECT_EQ(protobuf_unittest::E_PROTO2_MAP_ENUM_EXTRA_LITE, + from.unknown_map_field().at(0)); + } + + { + // StandardWireFormat + protobuf_unittest::TestMapLite message; + string data = "\x0A\x04\x08\x01\x10\x01"; + + EXPECT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(1, message.map_int32_int32().at(1)); + } + + { + // UnorderedWireFormat + protobuf_unittest::TestMapLite message; + + // put value before key in wire format + string data = "\x0A\x04\x10\x01\x08\x02"; + + EXPECT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(1, message.map_int32_int32().at(2)); + } + + { + // DuplicatedKeyWireFormat + protobuf_unittest::TestMapLite message; + + // Two key fields in wire format + string data = "\x0A\x06\x08\x01\x08\x02\x10\x01"; + + EXPECT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(1, message.map_int32_int32().at(2)); + } + + { + // DuplicatedValueWireFormat + protobuf_unittest::TestMapLite message; + + // Two value fields in wire format + string data = "\x0A\x06\x08\x01\x10\x01\x10\x02"; + + EXPECT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(2, message.map_int32_int32().at(1)); + } + + { + // MissedKeyWireFormat + protobuf_unittest::TestMapLite message; + + // No key field in wire format + string data = "\x0A\x02\x10\x01"; + + EXPECT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(1, message.map_int32_int32().at(0)); + } + + { + // MissedValueWireFormat + protobuf_unittest::TestMapLite message; + + // No value field in wire format + string data = "\x0A\x02\x08\x01"; + + EXPECT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(0, message.map_int32_int32().at(1)); + } + + { + // UnknownFieldWireFormat + protobuf_unittest::TestMapLite message; + + // Unknown field in wire format + string data = "\x0A\x06\x08\x02\x10\x03\x18\x01"; + + EXPECT_TRUE(message.ParseFromString(data)); + EXPECT_EQ(1, message.map_int32_int32().size()); + EXPECT_EQ(3, message.map_int32_int32().at(2)); + } + + { + // CorruptedWireFormat + protobuf_unittest::TestMapLite message; + + // corrupted data in wire format + string data = "\x0A\x06\x08\x02\x11\x03"; + + EXPECT_FALSE(message.ParseFromString(data)); + } + + { + // IsInitialized + protobuf_unittest::TestRequiredMessageMapLite map_message; + + // Add an uninitialized message. + (*map_message.mutable_map_field())[0]; + EXPECT_FALSE(map_message.IsInitialized()); + + // Initialize uninitialized message + (*map_message.mutable_map_field())[0].set_a(0); + (*map_message.mutable_map_field())[0].set_b(0); + (*map_message.mutable_map_field())[0].set_c(0); + EXPECT_TRUE(map_message.IsInitialized()); + } + + // arena support for map ========================================= + + { + // ParsingAndSerializingNoHeapAllocation + + // Allocate a large initial block to avoid mallocs during hooked test. + std::vector arena_block(128 * 1024); + google::protobuf::ArenaOptions options; + options.initial_block = arena_block.data(); + options.initial_block_size = arena_block.size(); + google::protobuf::Arena arena(options); + string data; + data.reserve(128 * 1024); + + { + google::protobuf::internal::NoHeapChecker no_heap; + + protobuf_unittest::TestArenaMapLite* from = + google::protobuf::Arena::CreateMessage( + &arena); + google::protobuf::MapLiteTestUtil::SetArenaMapFields(from); + from->SerializeToString(&data); + + protobuf_unittest::TestArenaMapLite* to = + google::protobuf::Arena::CreateMessage( + &arena); + to->ParseFromString(data); + google::protobuf::MapLiteTestUtil::ExpectArenaMapFieldsSet(*to); + } + } + std::cout << "PASS" << std::endl; return 0; } diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index e56af3fc..1858e2f9 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -422,6 +422,7 @@ class Map { int default_enum_value_; friend class ::google::protobuf::Arena; + typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; template >( - arena, key, value, arena); + arena, key, value); } // Like above, but for all the other types. This avoids value copy to create // MapEntryLite from google::protobuf::Map in serialization. static MapEntryLite* Wrap(const Key& key, const Value& value, Arena* arena) { - return Arena::Create >( - arena, key, value, arena); + return Arena::CreateMessage >( + arena, key, value); } protected: @@ -308,7 +309,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { typedef typename Base::ValCppType ValCppType; public: - MapEntryWrapper(const K& key, const V& value, Arena* arena) + MapEntryWrapper(Arena* arena, const K& key, const V& value) : MapEntryLite(arena), key_(key), value_(value) { @@ -323,6 +324,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { const Value& value_; friend class ::google::protobuf::Arena; + typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; }; @@ -341,7 +343,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { typedef typename Base::ValCppType ValCppType; public: - MapEnumEntryWrapper(const K& key, const V& value, Arena* arena) + MapEnumEntryWrapper(Arena* arena, const K& key, const V& value) : MapEntryLite(arena), key_(key), value_(value) { @@ -355,7 +357,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { const KeyCppType& key_; const ValCppType value_; - friend class ::google::protobuf::Arena; + friend class LIBPROTOBUF_EXPORT google::protobuf::Arena; typedef void DestructorSkippable_; }; diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc index fd40c0d8..6ff1936e 100644 --- a/src/google/protobuf/map_field.cc +++ b/src/google/protobuf/map_field.cc @@ -104,14 +104,18 @@ void MapFieldBase::SetRepeatedDirty() { state_ = STATE_MODIFIED_REPEATED; } void* MapFieldBase::MutableRepeatedPtrField() const { return repeated_field_; } void MapFieldBase::SyncRepeatedFieldWithMap() const { - Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_); + // "Acquire" insures the operation after SyncRepeatedFieldWithMap won't get + // executed before state_ is checked. + Atomic32 state = google::protobuf::internal::Acquire_Load(&state_); if (state == STATE_MODIFIED_MAP) { mutex_.Lock(); // Double check state, because another thread may have seen the same state // and done the synchronization before the current thread. if (state_ == STATE_MODIFIED_MAP) { SyncRepeatedFieldWithMapNoLock(); - google::protobuf::internal::NoBarrier_Store(&state_, CLEAN); + // "Release" insures state_ can only be changed "after" + // SyncRepeatedFieldWithMapNoLock is finished. + google::protobuf::internal::Release_Store(&state_, CLEAN); } mutex_.Unlock(); } @@ -119,19 +123,23 @@ void MapFieldBase::SyncRepeatedFieldWithMap() const { void MapFieldBase::SyncRepeatedFieldWithMapNoLock() const { if (repeated_field_ == NULL) { - repeated_field_ = Arena::Create >(arena_, arena_); + repeated_field_ = Arena::CreateMessage >(arena_); } } void MapFieldBase::SyncMapWithRepeatedField() const { - Atomic32 state = google::protobuf::internal::NoBarrier_Load(&state_); + // "Acquire" insures the operation after SyncMapWithRepeatedField won't get + // executed before state_ is checked. + Atomic32 state = google::protobuf::internal::Acquire_Load(&state_); if (state == STATE_MODIFIED_REPEATED) { mutex_.Lock(); // Double check state, because another thread may have seen the same state // and done the synchronization before the current thread. if (state_ == STATE_MODIFIED_REPEATED) { SyncMapWithRepeatedFieldNoLock(); - google::protobuf::internal::NoBarrier_Store(&state_, CLEAN); + // "Release" insures state_ can only be changed "after" + // SyncRepeatedFieldWithMapNoLock is finished. + google::protobuf::internal::Release_Store(&state_, CLEAN); } mutex_.Unlock(); } diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index 6d8b6ec8..f3504f1b 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -208,6 +208,7 @@ class LIBPROTOBUF_EXPORT MapField : public MapFieldBase, void SetAssignDescriptorCallback(void (*callback)()); private: + typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; // MapField needs MapEntry's default instance to create new MapEntry. diff --git a/src/google/protobuf/map_field_inl.h b/src/google/protobuf/map_field_inl.h index ae63c721..cbfc0c8f 100644 --- a/src/google/protobuf/map_field_inl.h +++ b/src/google/protobuf/map_field_inl.h @@ -216,7 +216,7 @@ MapField(); } else { repeated_field_ = - Arena::Create >(arena_, arena_); + Arena::CreateMessage >(arena_); } } const Map& map = GetInternalMap(); diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h index 549ecc08..40322851 100644 --- a/src/google/protobuf/map_field_lite.h +++ b/src/google/protobuf/map_field_lite.h @@ -109,7 +109,7 @@ template ::MapFieldLite(Arena* arena) : arena_(arena) { - map_ = Arena::Create >(arena, arena); + map_ = Arena::CreateMessage >(arena); SetDefaultEnumValue(); } diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index 61344cbb..f4681866 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -56,6 +56,7 @@ using unittest::TestAllTypes; class MapFieldBaseStub : public MapFieldBase { public: + typedef void InternalArenaConstructable_; typedef void DestructorSkippable_; MapFieldBaseStub() {} explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {} @@ -149,10 +150,12 @@ TEST_F(MapFieldBasePrimitiveTest, Arena) { Arena arena(options); { - NoHeapChecker no_heap; + // TODO(liujisi): Re-write the test to ensure the memory for the map and + // repeated fields are allocated from arenas. + // NoHeapChecker no_heap; MapFieldType* map_field = - Arena::Create(&arena, &arena, default_entry_); + Arena::CreateMessage(&arena, default_entry_); // Set content in map (*map_field->MutableMap())[100] = 101; @@ -162,10 +165,12 @@ TEST_F(MapFieldBasePrimitiveTest, Arena) { } { - NoHeapChecker no_heap; + // TODO(liujisi): Re-write the test to ensure the memory for the map and + // repeated fields are allocated from arenas. + // NoHeapChecker no_heap; MapFieldBaseStub* map_field = - Arena::Create(&arena, &arena); + Arena::CreateMessage(&arena); // Trigger conversion to repeated field. EXPECT_TRUE(map_field->MutableRepeatedField() != NULL); diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index 88cba1f2..447f52d9 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -2258,6 +2258,27 @@ TEST(TextFormatMapTest, SerializeAndParse) { MapTestUtil::ExpectMapFieldsSet(dest); } +TEST(TextFormatMapTest, Sorted) { + unittest::TestMap message; + MapTestUtil::MapReflectionTester tester(message.GetDescriptor()); + tester.SetMapFieldsViaReflection(&message); + + string expected_text; + GOOGLE_CHECK_OK(File::GetContents( + TestSourceDir() + + "/google/protobuf/" + "testdata/map_test_data.txt", + &expected_text, true)); + + EXPECT_EQ(message.DebugString(), expected_text); + + // Test again on the reverse order. + unittest::TestMap message2; + tester.SetMapFieldsViaReflection(&message2); + tester.SwapMapsViaReflection(&message2); + EXPECT_EQ(message2.DebugString(), expected_text); +} + // arena support ================================================= TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) { diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index 278b78ae..ffdb6dfb 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -129,11 +129,11 @@ class MapCppTypeHandler : public MapCommonTypeHandler { // Return bytes used by value in Map. static int SpaceUsedInMap(const Type& value) { return value.SpaceUsed(); } static inline void Clear(Type** value) { - if (*value != NULL) (*value)->Type::Clear(); + if (*value != NULL) (*value)->Clear(); } static inline void ClearMaybeByDefaultEnum(Type** value, int default_enum_value) { - if (*value != NULL) (*value)->Type::Clear(); + if (*value != NULL) (*value)->Clear(); } static inline void Merge(const Type& from, Type** to) { (*to)->MergeFrom(from); diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto index b6a988b3..cbf747d9 100644 --- a/src/google/protobuf/map_unittest.proto +++ b/src/google/protobuf/map_unittest.proto @@ -62,7 +62,7 @@ message TestMap { } message TestMapSubmessage { - optional TestMap test_map = 1; + TestMap test_map = 1; } message TestMessageMap { @@ -104,3 +104,17 @@ message TestArenaMap { map map_int32_enum = 14; map map_int32_foreign_message = 15; } + +// Previously, message containing enum called Type cannot be used as value of +// map field. +message MessageContainingEnumCalledType { + enum Type { + TYPE_FOO = 0; + } + map type = 1; +} + +// Previously, message cannot contain map field called "entry". +message MessageContainingMapCalledEntry { + map entry = 1; +} diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index f58be848..276d7de5 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -465,10 +465,21 @@ struct ShutdownRepeatedFieldRegister { } // namespace internal namespace internal { -// Macro defined in repeated_field.h. We can only define the Message-specific -// GenericTypeHandler specializations here because we depend on Message, which -// is not part of proto2-lite hence is not available in repeated_field.h. -DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES_NOINLINE(Message); +template<> +Message* GenericTypeHandler::NewFromPrototype( + const Message* prototype, google::protobuf::Arena* arena) { + return prototype->New(arena); +} +template<> +google::protobuf::Arena* GenericTypeHandler::GetArena( + Message* value) { + return value->GetArena(); +} +template<> +void* GenericTypeHandler::GetMaybeArenaPointer( + Message* value) { + return value->GetMaybeArenaPointer(); +} } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 6e1929e5..18c092d0 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -98,11 +98,11 @@ // // // Use the reflection interface to examine the contents. // const Reflection* reflection = foo->GetReflection(); -// assert(reflection->GetString(foo, text_field) == "Hello World!"); -// assert(reflection->FieldSize(foo, numbers_field) == 3); -// assert(reflection->GetRepeatedInt32(foo, numbers_field, 0) == 1); -// assert(reflection->GetRepeatedInt32(foo, numbers_field, 1) == 5); -// assert(reflection->GetRepeatedInt32(foo, numbers_field, 2) == 42); +// assert(reflection->GetString(*foo, text_field) == "Hello World!"); +// assert(reflection->FieldSize(*foo, numbers_field) == 3); +// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 0) == 1); +// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 1) == 5); +// assert(reflection->GetRepeatedInt32(*foo, numbers_field, 2) == 42); // // delete foo; // } @@ -229,6 +229,11 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { // Computes (an estimate of) the total number of bytes currently used for // storing the message in memory. The default implementation calls the // Reflection object's SpaceUsed() method. + // + // SpaceUsed() is noticeably slower than ByteSize(), as it is implemented + // using reflection (rather than the generated code implementation for + // ByteSize()). Like ByteSize(), its CPU time is linear in the number of + // fields defined for the proto. virtual int SpaceUsed() const; // Debugging & Testing---------------------------------------------- diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 63be0e9b..4f63ad2b 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -337,7 +337,7 @@ bool MessageLite::SerializePartialToArray(void* data, int size) const { string MessageLite::SerializeAsString() const { // If the compiler implements the (Named) Return Value Optimization, - // the local variable 'result' will not actually reside on the stack + // the local variable 'output' will not actually reside on the stack // of this function, but will be overlaid with the object that the // caller supplied for the return value to be constructed in. string output; diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index eab61c14..4c16f4c0 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -238,6 +238,9 @@ class LIBPROTOBUF_EXPORT MessageLite { // Computes the serialized size of the message. This recursively calls // ByteSize() on all embedded messages. If a subclass does not override // this, it MUST override SetCachedSize(). + // + // ByteSize() is generally linear in the number of fields defined for the + // proto. virtual int ByteSize() const = 0; // Serializes the message without recomputing the size. The message must diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc index ebfb4321..75d60b8b 100644 --- a/src/google/protobuf/message_unittest.cc +++ b/src/google/protobuf/message_unittest.cc @@ -45,12 +45,13 @@ #include #include -#include +#include +#include #include -#include +#include #include -#include -#include +#include +#include #include #include @@ -205,6 +206,28 @@ TEST(MessageTest, InitializationErrorString) { EXPECT_EQ("a, b, c", message.InitializationErrorString()); } +TEST(MessageTest, DynamicCastToGenerated) { + unittest::TestAllTypes test_all_types; + + google::protobuf::Message* test_all_types_pointer = &test_all_types; + EXPECT_EQ(&test_all_types, + google::protobuf::internal::DynamicCastToGenerated( + test_all_types_pointer)); + EXPECT_EQ(NULL, + google::protobuf::internal::DynamicCastToGenerated( + test_all_types_pointer)); + + const google::protobuf::Message* test_all_types_pointer_const = &test_all_types; + EXPECT_EQ( + &test_all_types, + google::protobuf::internal::DynamicCastToGenerated( + test_all_types_pointer_const)); + EXPECT_EQ( + NULL, + google::protobuf::internal::DynamicCastToGenerated( + test_all_types_pointer_const)); +} + #ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet. TEST(MessageTest, SerializeFailsIfNotInitialized) { diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc index c3b5996f..da4be673 100644 --- a/src/google/protobuf/proto3_arena_unittest.cc +++ b/src/google/protobuf/proto3_arena_unittest.cc @@ -180,6 +180,16 @@ TEST(ArenaTest, ReleaseMessage) { EXPECT_EQ(118, nested->bb()); } +TEST(ArenaTest, MessageFieldClear) { + // GitHub issue #310: https://github.com/google/protobuf/issues/310 + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage(&arena); + arena_message->mutable_optional_nested_message()->set_bb(118); + // This should not crash, but prior to the bugfix, it tried to use `operator + // delete` the nested message (which is on the arena): + arena_message->Clear(); +} + } // namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h index 03c761c1..4ff0f6b4 100755 --- a/src/google/protobuf/reflection.h +++ b/src/google/protobuf/reflection.h @@ -39,6 +39,7 @@ #endif #include +#include namespace google { namespace protobuf { diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index 7bfdc40a..5a2fb409 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -576,26 +576,21 @@ class GenericTypeHandler { } }; -// Macros for specializing GenericTypeHandler for base proto types, these are -// are defined here, to allow inlining them at their callsites. -#define DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Inline, TypeName) \ - template<> \ - Inline TypeName* GenericTypeHandler::NewFromPrototype( \ - const TypeName* prototype, google::protobuf::Arena* arena) { \ - return prototype->New(arena); \ - } \ - template<> \ - Inline google::protobuf::Arena* GenericTypeHandler::GetArena( \ - TypeName* value) { \ - return value->GetArena(); \ - } \ - template<> \ - Inline void* GenericTypeHandler::GetMaybeArenaPointer( \ - TypeName* value) { \ - return value->GetMaybeArenaPointer(); \ - } -#define DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES_NOINLINE(TypeName) \ - DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(, TypeName) +template<> +inline MessageLite* GenericTypeHandler::NewFromPrototype( + const MessageLite* prototype, google::protobuf::Arena* arena) { + return prototype->New(arena); +} +template<> +inline google::protobuf::Arena* GenericTypeHandler::GetArena( + MessageLite* value) { + return value->GetArena(); +} +template<> +inline void* GenericTypeHandler::GetMaybeArenaPointer( + MessageLite* value) { + return value->GetMaybeArenaPointer(); +} // Implements GenericTypeHandler specialization required by RepeatedPtrFields // to work with MessageLite type. @@ -605,8 +600,6 @@ inline void GenericTypeHandler::Merge( to->CheckTypeAndMergeFrom(from); } -DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(inline, MessageLite); - // Declarations of the specialization as we cannot define them here, as the // header that defines ProtocolMessage depends on types defined in this header. #define DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(TypeName) \ @@ -1235,6 +1228,7 @@ void RepeatedField::Reserve(int new_size) { kRepHeaderSize + sizeof(Element)*new_size)); } rep_->arena = arena; + int old_total_size = total_size_; total_size_ = new_size; // Invoke placement-new on newly allocated elements. We shouldn't have to do // this, since Element is supposed to be POD, but a previous version of this @@ -1253,15 +1247,17 @@ void RepeatedField::Reserve(int new_size) { if (current_size_ > 0) { MoveArray(rep_->elements, old_rep->elements, current_size_); } - // Likewise, we need to invoke destructors on the old array. If Element has no - // destructor, this loop will disappear. - e = &old_rep->elements[0]; - limit = &old_rep->elements[current_size_]; - for (; e < limit; e++) { - e->Element::~Element(); - } - if (arena == NULL) { - delete[] reinterpret_cast(old_rep); + if (old_rep) { + // Likewise, we need to invoke destructors on the old array. If Element has + // no destructor, this loop will disappear. + e = &old_rep->elements[0]; + limit = &old_rep->elements[old_total_size]; + for (; e < limit; e++) { + e->Element::~Element(); + } + if (arena == NULL) { + delete[] reinterpret_cast(old_rep); + } } } @@ -1418,7 +1414,7 @@ void RepeatedPtrFieldBase::Clear() { const int n = current_size_; GOOGLE_DCHECK_GE(n, 0); if (n > 0) { - void* const* elements = raw_data(); + void* const* elements = rep_->elements; int i = 0; do { TypeHandler::Clear(cast(elements[i++])); diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 66e74523..af397932 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -456,6 +456,28 @@ TEST(RepeatedField, ExtractSubrange) { } } +TEST(RepeatedField, ClearThenReserveMore) { + // Test that Reserve properly destroys the old internal array when it's forced + // to allocate a new one, even when cleared-but-not-deleted objects are + // present. Use a 'string' and > 16 bytes length so that the elements are + // non-POD and allocate -- the leak checker will catch any skipped destructor + // calls here. + RepeatedField field; + for (int i = 0; i < 32; i++) { + field.Add(string("abcdefghijklmnopqrstuvwxyz0123456789")); + } + EXPECT_EQ(32, field.size()); + field.Clear(); + EXPECT_EQ(0, field.size()); + EXPECT_EQ(32, field.Capacity()); + + field.Reserve(1024); + EXPECT_EQ(0, field.size()); + EXPECT_EQ(1024, field.Capacity()); + // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed + // strings. +} + // =================================================================== // RepeatedPtrField tests. These pretty much just mirror the RepeatedField // tests above. diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index 0926e747..3b3799a9 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -114,7 +114,7 @@ const int SourceContext::kFileNameFieldNumber; #endif // !_MSC_VER SourceContext::SourceContext() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.SourceContext) } @@ -277,9 +277,9 @@ int SourceContext::ByteSize() const { void SourceContext::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const SourceContext* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const SourceContext* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -334,7 +334,7 @@ void SourceContext::InternalSwap(SourceContext* other) { // SourceContext // optional string file_name = 1; - void SourceContext::clear_file_name() { +void SourceContext::clear_file_name() { file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& SourceContext::file_name() const { diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index 4405a5bf..30113cdb 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -217,7 +217,7 @@ const int Struct::kFieldsFieldNumber; #endif // !_MSC_VER Struct::Struct() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Struct) } @@ -295,7 +295,8 @@ bool Struct::MergePartialFromCodedStream( // map fields = 1; case 1: { if (tag == 10) { - parse_fields: + DO_(input->IncrementRecursionDepth()); + parse_loop_fields: ::google::protobuf::scoped_ptr entry(fields_.NewEntry()); DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, entry.get())); @@ -303,7 +304,8 @@ bool Struct::MergePartialFromCodedStream( } else { goto handle_unusual; } - if (input->ExpectTag(10)) goto parse_fields; + if (input->ExpectTag(10)) goto parse_loop_fields; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -336,7 +338,8 @@ void Struct::SerializeWithCachedSizes( { ::google::protobuf::scoped_ptr entry; for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = fields().begin(); it != fields().end(); ++it) { + it = this->fields().begin(); + it != this->fields().end(); ++it) { entry.reset(fields_.NewEntryWrapper(it->first, it->second)); ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( 1, *entry, output); @@ -353,7 +356,8 @@ void Struct::SerializeWithCachedSizes( { ::google::protobuf::scoped_ptr entry; for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = fields().begin(); it != fields().end(); ++it) { + it = this->fields().begin(); + it != this->fields().end(); ++it) { entry.reset(fields_.NewEntryWrapper(it->first, it->second)); target = ::google::protobuf::internal::WireFormatLite:: WriteMessageNoVirtualToArray( @@ -373,7 +377,8 @@ int Struct::ByteSize() const { { ::google::protobuf::scoped_ptr entry; for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = fields().begin(); it != fields().end(); ++it) { + it = this->fields().begin(); + it != this->fields().end(); ++it) { entry.reset(fields_.NewEntryWrapper(it->first, it->second)); total_size += ::google::protobuf::internal::WireFormatLite:: MessageSizeNoVirtual(*entry); @@ -388,9 +393,9 @@ int Struct::ByteSize() const { void Struct::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Struct* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Struct* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -442,10 +447,10 @@ void Struct::InternalSwap(Struct* other) { // Struct // map fields = 1; - int Struct::fields_size() const { +int Struct::fields_size() const { return fields_.size(); } - void Struct::clear_fields() { +void Struct::clear_fields() { fields_.Clear(); } const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >& @@ -473,7 +478,7 @@ const int Value::kListValueFieldNumber; #endif // !_MSC_VER Value::Value() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Value) } @@ -845,9 +850,9 @@ int Value::ByteSize() const { void Value::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Value* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Value* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -928,13 +933,13 @@ void Value::InternalSwap(Value* other) { // Value // optional .google.protobuf.NullValue null_value = 1; - bool Value::has_null_value() const { +bool Value::has_null_value() const { return kind_case() == kNullValue; } - void Value::set_has_null_value() { +void Value::set_has_null_value() { _oneof_case_[0] = kNullValue; } - void Value::clear_null_value() { +void Value::clear_null_value() { if (has_null_value()) { kind_.null_value_ = 0; clear_has_kind(); @@ -957,13 +962,13 @@ void Value::InternalSwap(Value* other) { } // optional double number_value = 2; - bool Value::has_number_value() const { +bool Value::has_number_value() const { return kind_case() == kNumberValue; } - void Value::set_has_number_value() { +void Value::set_has_number_value() { _oneof_case_[0] = kNumberValue; } - void Value::clear_number_value() { +void Value::clear_number_value() { if (has_number_value()) { kind_.number_value_ = 0; clear_has_kind(); @@ -986,13 +991,13 @@ void Value::InternalSwap(Value* other) { } // optional string string_value = 3; - bool Value::has_string_value() const { +bool Value::has_string_value() const { return kind_case() == kStringValue; } - void Value::set_has_string_value() { +void Value::set_has_string_value() { _oneof_case_[0] = kStringValue; } - void Value::clear_string_value() { +void Value::clear_string_value() { if (has_string_value()) { kind_.string_value_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); clear_has_kind(); @@ -1066,13 +1071,13 @@ void Value::InternalSwap(Value* other) { } // optional bool bool_value = 4; - bool Value::has_bool_value() const { +bool Value::has_bool_value() const { return kind_case() == kBoolValue; } - void Value::set_has_bool_value() { +void Value::set_has_bool_value() { _oneof_case_[0] = kBoolValue; } - void Value::clear_bool_value() { +void Value::clear_bool_value() { if (has_bool_value()) { kind_.bool_value_ = false; clear_has_kind(); @@ -1095,13 +1100,13 @@ void Value::InternalSwap(Value* other) { } // optional .google.protobuf.Struct struct_value = 5; - bool Value::has_struct_value() const { +bool Value::has_struct_value() const { return kind_case() == kStructValue; } - void Value::set_has_struct_value() { +void Value::set_has_struct_value() { _oneof_case_[0] = kStructValue; } - void Value::clear_struct_value() { +void Value::clear_struct_value() { if (has_struct_value()) { delete kind_.struct_value_; clear_has_kind(); @@ -1141,13 +1146,13 @@ void Value::InternalSwap(Value* other) { } // optional .google.protobuf.ListValue list_value = 6; - bool Value::has_list_value() const { +bool Value::has_list_value() const { return kind_case() == kListValue; } - void Value::set_has_list_value() { +void Value::set_has_list_value() { _oneof_case_[0] = kListValue; } - void Value::clear_list_value() { +void Value::clear_list_value() { if (has_list_value()) { delete kind_.list_value_; clear_has_kind(); @@ -1186,10 +1191,10 @@ void Value::InternalSwap(Value* other) { // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value) } - bool Value::has_kind() const { +bool Value::has_kind() const { return kind_case() != KIND_NOT_SET; } - void Value::clear_has_kind() { +void Value::clear_has_kind() { _oneof_case_[0] = KIND_NOT_SET; } Value::KindCase Value::kind_case() const { @@ -1204,7 +1209,7 @@ const int ListValue::kValuesFieldNumber; #endif // !_MSC_VER ListValue::ListValue() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.ListValue) } @@ -1278,13 +1283,15 @@ bool ListValue::MergePartialFromCodedStream( // repeated .google.protobuf.Value values = 1; case 1: { if (tag == 10) { - parse_values: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_values: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_values())); } else { goto handle_unusual; } - if (input->ExpectTag(10)) goto parse_values; + if (input->ExpectTag(10)) goto parse_loop_values; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -1355,9 +1362,9 @@ int ListValue::ByteSize() const { void ListValue::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const ListValue* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const ListValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1409,10 +1416,10 @@ void ListValue::InternalSwap(ListValue* other) { // ListValue // repeated .google.protobuf.Value values = 1; - int ListValue::values_size() const { +int ListValue::values_size() const { return values_.size(); } - void ListValue::clear_values() { +void ListValue::clear_values() { values_.Clear(); } const ::google::protobuf::Value& ListValue::values(int index) const { diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h index 46482142..2889c8fe 100644 --- a/src/google/protobuf/struct.pb.h +++ b/src/google/protobuf/struct.pb.h @@ -735,6 +735,10 @@ ListValue::mutable_values() { } #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index 37123c7b..3acaeba1 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -1141,6 +1141,14 @@ class LIBPROTOBUF_EXPORT Mutex { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Mutex); }; +// Undefine the macros to workaround the conflicts with Google internal +// MutexLock implementation. +// TODO(liujisi): Remove the undef once internal macros are removed. +#undef MutexLock +#undef ReaderMutexLock +#undef WriterMutexLock +#undef MutexLockMaybe + // MutexLock(mu) acquires mu when constructed and releases it when destroyed. class LIBPROTOBUF_EXPORT MutexLock { public: diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 7955d261..7ecc17ee 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -1285,24 +1285,6 @@ char* FloatToBuffer(float value, char* buffer) { return buffer; } -string ToHex(uint64 num) { - if (num == 0) { - return string("0"); - } - - // Compute hex bytes in reverse order, writing to the back of the - // buffer. - char buf[16]; // No more than 16 hex digits needed. - char* bufptr = buf + 16; - static const char kHexChars[] = "0123456789abcdef"; - while (num != 0) { - *--bufptr = kHexChars[num & 0xf]; - num >>= 4; - } - - return string(bufptr, buf + 16 - bufptr); -} - namespace strings { AlphaNum::AlphaNum(strings::Hex hex) { diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index 920701eb..5faa81e0 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -682,12 +682,6 @@ string Join(const Range& components, return result; } -// ---------------------------------------------------------------------- -// ToHex() -// Return a lower-case hex string representation of the given integer. -// ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT string ToHex(uint64 num); - // ---------------------------------------------------------------------- // GlobalReplaceSubstring() // Replaces all instances of a substring in a string. Does nothing diff --git a/src/google/protobuf/testdata/golden_message_proto3 b/src/google/protobuf/testdata/golden_message_proto3 index 934f36fa..bd646a0d 100644 Binary files a/src/google/protobuf/testdata/golden_message_proto3 and b/src/google/protobuf/testdata/golden_message_proto3 differ diff --git a/src/google/protobuf/testdata/map_test_data.txt b/src/google/protobuf/testdata/map_test_data.txt new file mode 100644 index 00000000..bc272321 --- /dev/null +++ b/src/google/protobuf/testdata/map_test_data.txt @@ -0,0 +1,140 @@ +map_int32_int32 { + key: 0 + value: 0 +} +map_int32_int32 { + key: 1 + value: 1 +} +map_int64_int64 { + key: 0 + value: 0 +} +map_int64_int64 { + key: 1 + value: 1 +} +map_uint32_uint32 { + key: 0 + value: 0 +} +map_uint32_uint32 { + key: 1 + value: 1 +} +map_uint64_uint64 { + key: 0 + value: 0 +} +map_uint64_uint64 { + key: 1 + value: 1 +} +map_sint32_sint32 { + key: 0 + value: 0 +} +map_sint32_sint32 { + key: 1 + value: 1 +} +map_sint64_sint64 { + key: 0 + value: 0 +} +map_sint64_sint64 { + key: 1 + value: 1 +} +map_fixed32_fixed32 { + key: 0 + value: 0 +} +map_fixed32_fixed32 { + key: 1 + value: 1 +} +map_fixed64_fixed64 { + key: 0 + value: 0 +} +map_fixed64_fixed64 { + key: 1 + value: 1 +} +map_sfixed32_sfixed32 { + key: 0 + value: 0 +} +map_sfixed32_sfixed32 { + key: 1 + value: 1 +} +map_sfixed64_sfixed64 { + key: 0 + value: 0 +} +map_sfixed64_sfixed64 { + key: 1 + value: 1 +} +map_int32_float { + key: 0 + value: 0 +} +map_int32_float { + key: 1 + value: 1 +} +map_int32_double { + key: 0 + value: 0 +} +map_int32_double { + key: 1 + value: 1 +} +map_bool_bool { + key: false + value: false +} +map_bool_bool { + key: true + value: true +} +map_string_string { + key: "0" + value: "0" +} +map_string_string { + key: "1" + value: "1" +} +map_int32_bytes { + key: 0 + value: "0" +} +map_int32_bytes { + key: 1 + value: "1" +} +map_int32_enum { + key: 0 + value: MAP_ENUM_BAR +} +map_int32_enum { + key: 1 + value: MAP_ENUM_BAZ +} +map_int32_foreign_message { + key: 0 + value { + c: 0 + } +} +map_int32_foreign_message { + key: 1 + value { + c: 1 + } +} diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index ec070c51..61dfa5d6 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -43,6 +43,8 @@ #include #include +#include +#include #include #include #include @@ -50,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -70,6 +73,18 @@ inline bool IsOctNumber(const string& str) { (str[1] >= '0' && str[1] < '8')); } +inline bool GetAnyFieldDescriptors(const Message& message, + const FieldDescriptor** type_url_field, + const FieldDescriptor** value_field) { + const Descriptor* descriptor = message.GetDescriptor(); + *type_url_field = descriptor->FindFieldByNumber(1); + *value_field = descriptor->FindFieldByNumber(2); + return (*type_url_field != NULL && + (*type_url_field)->type() == FieldDescriptor::TYPE_STRING && + *value_field != NULL && + (*value_field)->type() == FieldDescriptor::TYPE_BYTES); +} + } // namespace string Message::DebugString() const { @@ -330,7 +345,17 @@ class TextFormat::Parser::ParserImpl { // Confirm that we have a valid ending delimiter. DO(Consume(delimiter)); + return true; + } + // Consume either "<" or "{". + bool ConsumeMessageDelimiter(string* delimiter) { + if (TryConsume("<")) { + *delimiter = ">"; + } else { + DO(Consume("{")); + *delimiter = "}"; + } return true; } @@ -347,15 +372,28 @@ class TextFormat::Parser::ParserImpl { int start_line = tokenizer_.current().line; int start_column = tokenizer_.current().column; + const FieldDescriptor* any_type_url_field; + const FieldDescriptor* any_value_field; + if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field, + &any_value_field) && + TryConsume("[")) { + string full_type_name; + DO(ConsumeAnyTypeUrl(&full_type_name)); + DO(Consume("]")); + string serialized_value; + DO(ConsumeAnyValue(full_type_name, + message->GetDescriptor()->file()->pool(), + &serialized_value)); + reflection->SetString( + message, any_type_url_field, + string(internal::kTypeGoogleApisComPrefix) + full_type_name); + reflection->SetString(message, any_value_field, serialized_value); + return true; + // Fall through. + } if (TryConsume("[")) { // Extension. - DO(ConsumeIdentifier(&field_name)); - while (TryConsume(".")) { - string part; - DO(ConsumeIdentifier(&part)); - field_name += "."; - field_name += part; - } + DO(ConsumeFullTypeName(&field_name)); DO(Consume("]")); field = (finder_ != NULL @@ -512,13 +550,7 @@ class TextFormat::Parser::ParserImpl { string field_name; if (TryConsume("[")) { // Extension name. - DO(ConsumeIdentifier(&field_name)); - while (TryConsume(".")) { - string part; - DO(ConsumeIdentifier(&part)); - field_name += "."; - field_name += part; - } + DO(ConsumeFullTypeName(&field_name)); DO(Consume("]")); } else { DO(ConsumeIdentifier(&field_name)); @@ -553,13 +585,7 @@ class TextFormat::Parser::ParserImpl { } string delimiter; - if (TryConsume("<")) { - delimiter = ">"; - } else { - DO(Consume("{")); - delimiter = "}"; - } - + DO(ConsumeMessageDelimiter(&delimiter)); if (field->is_repeated()) { DO(ConsumeMessage(reflection->AddMessage(message, field), delimiter)); } else { @@ -576,12 +602,7 @@ class TextFormat::Parser::ParserImpl { // the ending delimiter. bool SkipFieldMessage() { string delimiter; - if (TryConsume("<")) { - delimiter = ">"; - } else { - DO(Consume("{")); - delimiter = "}"; - } + DO(ConsumeMessageDelimiter(&delimiter)); while (!LookingAt(">") && !LookingAt("}")) { DO(SkipField()); } @@ -808,6 +829,18 @@ class TextFormat::Parser::ParserImpl { return false; } + // Consume a string of form ".....". + bool ConsumeFullTypeName(string* name) { + DO(ConsumeIdentifier(name)); + while (TryConsume(".")) { + string part; + DO(ConsumeIdentifier(&part)); + *name += "."; + *name += part; + } + return true; + } + // Consumes a string and saves its value in the text parameter. // Returns false if the token is not of type STRING. bool ConsumeString(string* text) { @@ -947,6 +980,54 @@ class TextFormat::Parser::ParserImpl { return true; } + // Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name" + bool ConsumeAnyTypeUrl(string* full_type_name) { + // TODO(saito) Extend Consume() to consume multiple tokens at once, so that + // this code can be written as just DO(Consume(kGoogleApisTypePrefix)). + string url1, url2, url3; + DO(ConsumeIdentifier(&url1)); // type + DO(Consume(".")); + DO(ConsumeIdentifier(&url2)); // googleapis + DO(Consume(".")); + DO(ConsumeIdentifier(&url3)); // com + DO(Consume("/")); + DO(ConsumeFullTypeName(full_type_name)); + + const string prefix = url1 + "." + url2 + "." + url3 + "/"; + if (prefix != internal::kTypeGoogleApisComPrefix) { + ReportError("TextFormat::Parser for Any supports only " + "type.googleapi.com, but found \"" + prefix + "\""); + return false; + } + return true; + } + + // A helper function for reconstructing Any::value. Consumes a text of + // full_type_name, then serializes it into serialized_value. "pool" is used to + // look up and create a temporary object with full_type_name. + bool ConsumeAnyValue(const string& full_type_name, const DescriptorPool* pool, + string* serialized_value) { + const Descriptor* value_descriptor = + pool->FindMessageTypeByName(full_type_name); + if (value_descriptor == NULL) { + ReportError("Could not find type \"" + full_type_name + + "\" stored in google.protobuf.Any."); + return false; + } + DynamicMessageFactory factory; + const Message* value_prototype = factory.GetPrototype(value_descriptor); + if (value_prototype == NULL) { + return false; + } + google::protobuf::scoped_ptr value(value_prototype->New()); + string sub_delimiter; + DO(ConsumeMessageDelimiter(&sub_delimiter)); + DO(ConsumeMessage(value.get(), sub_delimiter)); + + value->AppendToString(serialized_value); + return true; + } + // Consumes a token and confirms that it matches that specified in the // value parameter. Returns false if the token found does not match that // which was specified. @@ -1338,7 +1419,8 @@ TextFormat::Printer::Printer() use_field_number_(false), use_short_repeated_primitives_(false), hide_unknown_fields_(false), - print_message_fields_in_index_order_(false) { + print_message_fields_in_index_order_(false), + expand_any_(false) { SetUseUtf8StringEscaping(false); } @@ -1413,11 +1495,63 @@ struct FieldIndexSorter { return left->index() < right->index(); } }; + } // namespace +bool TextFormat::Printer::PrintAny(const Message& message, + TextGenerator& generator) const { + const FieldDescriptor* type_url_field; + const FieldDescriptor* value_field; + if (!internal::GetAnyFieldDescriptors(message, &type_url_field, + &value_field)) { + return false; + } + + const Reflection* reflection = message.GetReflection(); + + // Extract the full type name from the type_url field. + const string& type_url = reflection->GetString(message, type_url_field); + string full_type_name; + if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) { + return false; + } + + // Print the "value" in text. + const google::protobuf::Descriptor* value_descriptor = + message.GetDescriptor()->file()->pool()->FindMessageTypeByName( + full_type_name); + if (value_descriptor == NULL) { + GOOGLE_LOG(WARNING) << "Proto type " << type_url << " not found"; + return false; + } + DynamicMessageFactory factory; + google::protobuf::scoped_ptr value_message( + factory.GetPrototype(value_descriptor)->New()); + string serialized_value = reflection->GetString(message, value_field); + if (!value_message->ParseFromString(serialized_value)) { + GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents"; + return false; + } + generator.Print(StrCat("[", type_url, "]")); + const FieldValuePrinter* printer = FindWithDefault( + custom_printers_, value_field, default_field_value_printer_.get()); + generator.Print( + printer->PrintMessageStart(message, -1, 0, single_line_mode_)); + generator.Indent(); + Print(*value_message, generator); + generator.Outdent(); + generator.Print(printer->PrintMessageEnd(message, -1, 0, single_line_mode_)); + return true; +} + void TextFormat::Printer::Print(const Message& message, TextGenerator& generator) const { + const Descriptor* descriptor = message.GetDescriptor(); const Reflection* reflection = message.GetReflection(); + if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ && + PrintAny(message, generator)) { + return; + } vector fields; reflection->ListFields(message, &fields); if (print_message_fields_in_index_order_) { @@ -1446,6 +1580,54 @@ void TextFormat::Printer::PrintFieldValueToString( PrintFieldValue(message, message.GetReflection(), field, index, generator); } +class MapEntryMessageComparator { + public: + explicit MapEntryMessageComparator(const Descriptor* descriptor) + : field_(descriptor->field(0)) {} + + bool operator()(const Message* a, const Message* b) { + const Reflection* reflection = a->GetReflection(); + switch (field_->cpp_type()) { + case FieldDescriptor::CPPTYPE_BOOL: { + bool first = reflection->GetBool(*a, field_); + bool second = reflection->GetBool(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_INT32: { + int32 first = reflection->GetInt32(*a, field_); + int32 second = reflection->GetInt32(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_INT64: { + int64 first = reflection->GetInt64(*a, field_); + int64 second = reflection->GetInt64(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_UINT32: { + uint32 first = reflection->GetUInt32(*a, field_); + uint32 second = reflection->GetUInt32(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_UINT64: { + uint64 first = reflection->GetUInt64(*a, field_); + uint64 second = reflection->GetUInt64(*b, field_); + return first < second; + } + case FieldDescriptor::CPPTYPE_STRING: { + string first = reflection->GetString(*a, field_); + string second = reflection->GetString(*b, field_); + return first < second; + } + default: + GOOGLE_LOG(DFATAL) << "Invalid key for map field."; + return true; + } + } + + private: + const FieldDescriptor* field_; +}; + void TextFormat::Printer::PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, @@ -1466,6 +1648,21 @@ void TextFormat::Printer::PrintField(const Message& message, count = 1; } + std::vector sorted_map_field; + if (field->is_map()) { + const RepeatedPtrField& map_field = + reflection->GetRepeatedPtrField(message, field); + for (RepeatedPtrField::const_pointer_iterator it = + map_field.pointer_begin(); + it != map_field.pointer_end(); ++it) { + sorted_map_field.push_back(*it); + } + + MapEntryMessageComparator comparator(field->message_type()); + std::stable_sort(sorted_map_field.begin(), sorted_map_field.end(), + comparator); + } + for (int j = 0; j < count; ++j) { const int field_index = field->is_repeated() ? j : -1; @@ -1475,8 +1672,10 @@ void TextFormat::Printer::PrintField(const Message& message, const FieldValuePrinter* printer = FindWithDefault( custom_printers_, field, default_field_value_printer_.get()); const Message& sub_message = - field->is_repeated() - ? reflection->GetRepeatedMessage(message, field, j) + field->is_repeated() + ? (field->is_map() + ? *sorted_map_field[j] + : reflection->GetRepeatedMessage(message, field, j)) : reflection->GetMessage(message, field); generator.Print( printer->PrintMessageStart( @@ -1680,8 +1879,8 @@ void TextFormat::Printer::PrintUnknownFields( case UnknownField::TYPE_FIXED32: { generator.Print(field_number); generator.Print(": 0x"); - char buffer[kFastToBufferSize]; - generator.Print(FastHex32ToBuffer(field.fixed32(), buffer)); + generator.Print( + StrCat(strings::Hex(field.fixed32(), strings::Hex::ZERO_PAD_8))); if (single_line_mode_) { generator.Print(" "); } else { @@ -1692,8 +1891,8 @@ void TextFormat::Printer::PrintUnknownFields( case UnknownField::TYPE_FIXED64: { generator.Print(field_number); generator.Print(": 0x"); - char buffer[kFastToBufferSize]; - generator.Print(FastHex64ToBuffer(field.fixed64(), buffer)); + generator.Print( + StrCat(strings::Hex(field.fixed64(), strings::Hex::ZERO_PAD_16))); if (single_line_mode_) { generator.Print(" "); } else { diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index 9e2cb070..6717aecd 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -208,6 +208,17 @@ class LIBPROTOBUF_EXPORT TextFormat { print_message_fields_in_index_order; } + // If expand==true, expand google.protobuf.Any payloads. The output + // will be of form + // [type_url] { } + // + // If expand==false, print Any using the default printer. The output will + // look like + // type_url: "" value: "serialized_content" + void SetExpandAny(bool expand) { + expand_any_ = expand; + } + // Register a custom field-specific FieldValuePrinter for fields // with a particular FieldDescriptor. // Returns "true" if the registration succeeded, or "false", if there is @@ -259,6 +270,8 @@ class LIBPROTOBUF_EXPORT TextFormat { void PrintUnknownFields(const UnknownFieldSet& unknown_fields, TextGenerator& generator) const; + bool PrintAny(const Message& message, TextGenerator& generator) const; + int initial_indent_level_; bool single_line_mode_; @@ -271,6 +284,8 @@ class LIBPROTOBUF_EXPORT TextFormat { bool print_message_fields_in_index_order_; + bool expand_any_; + google::protobuf::scoped_ptr default_field_value_printer_; typedef map CustomPrinterMap; diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index 477fdcbd..1b18c5ed 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -32,23 +32,24 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include #include -#include -#include -#include -#include -#include -#include - #include #include -#include -#include +#include +#include +#include +#include +#include #include #include +#include +#include + namespace google { namespace protobuf { @@ -451,7 +452,7 @@ TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) { class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter { public: virtual string PrintInt32(int32 v) const { - return StrCat(FieldValuePrinter::PrintInt32(v), " # x", ToHex(v)); + return StrCat(FieldValuePrinter::PrintInt32(v), " # x", strings::Hex(v)); } virtual string PrintMessageStart(const Message& message, diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 6edfe056..877dc8f3 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -117,7 +117,7 @@ const int Timestamp::kNanosFieldNumber; #endif // !_MSC_VER Timestamp::Timestamp() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Timestamp) } @@ -310,9 +310,9 @@ int Timestamp::ByteSize() const { void Timestamp::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Timestamp* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Timestamp* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -370,7 +370,7 @@ void Timestamp::InternalSwap(Timestamp* other) { // Timestamp // optional int64 seconds = 1; - void Timestamp::clear_seconds() { +void Timestamp::clear_seconds() { seconds_ = GOOGLE_LONGLONG(0); } ::google::protobuf::int64 Timestamp::seconds() const { @@ -384,7 +384,7 @@ void Timestamp::InternalSwap(Timestamp* other) { } // optional int32 nanos = 2; - void Timestamp::clear_nanos() { +void Timestamp::clear_nanos() { nanos_ = 0; } ::google::protobuf::int32 Timestamp::nanos() const { diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index d77bc6ce..8b08909e 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -267,7 +267,7 @@ const int Type::kSourceContextFieldNumber; #endif // !_MSC_VER Type::Type() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Type) } @@ -332,7 +332,7 @@ Type* Type::New(::google::protobuf::Arena* arena) const { void Type::Clear() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (source_context_ != NULL) delete source_context_; + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; fields_.Clear(); oneofs_.Clear(); @@ -369,12 +369,15 @@ bool Type::MergePartialFromCodedStream( case 2: { if (tag == 18) { parse_fields: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_fields: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_fields())); } else { goto handle_unusual; } - if (input->ExpectTag(18)) goto parse_fields; + if (input->ExpectTag(18)) goto parse_loop_fields; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(26)) goto parse_oneofs; break; } @@ -402,12 +405,15 @@ bool Type::MergePartialFromCodedStream( case 4: { if (tag == 34) { parse_options: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_options())); } else { goto handle_unusual; } - if (input->ExpectTag(34)) goto parse_options; + if (input->ExpectTag(34)) goto parse_loop_options; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(42)) goto parse_source_context; break; } @@ -587,9 +593,9 @@ int Type::ByteSize() const { void Type::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Type* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Type* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -654,7 +660,7 @@ void Type::InternalSwap(Type* other) { // Type // optional string name = 1; - void Type::clear_name() { +void Type::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Type::name() const { @@ -697,10 +703,10 @@ void Type::InternalSwap(Type* other) { } // repeated .google.protobuf.Field fields = 2; - int Type::fields_size() const { +int Type::fields_size() const { return fields_.size(); } - void Type::clear_fields() { +void Type::clear_fields() { fields_.Clear(); } const ::google::protobuf::Field& Type::fields(int index) const { @@ -727,10 +733,10 @@ Type::mutable_fields() { } // repeated string oneofs = 3; - int Type::oneofs_size() const { +int Type::oneofs_size() const { return oneofs_.size(); } - void Type::clear_oneofs() { +void Type::clear_oneofs() { oneofs_.Clear(); } const ::std::string& Type::oneofs(int index) const { @@ -781,10 +787,10 @@ Type::mutable_oneofs() { } // repeated .google.protobuf.Option options = 4; - int Type::options_size() const { +int Type::options_size() const { return options_.size(); } - void Type::clear_options() { +void Type::clear_options() { options_.Clear(); } const ::google::protobuf::Option& Type::options(int index) const { @@ -811,11 +817,11 @@ Type::mutable_options() { } // optional .google.protobuf.SourceContext source_context = 5; - bool Type::has_source_context() const { +bool Type::has_source_context() const { return !_is_default_instance_ && source_context_ != NULL; } - void Type::clear_source_context() { - if (source_context_ != NULL) delete source_context_; +void Type::clear_source_context() { + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; } const ::google::protobuf::SourceContext& Type::source_context() const { @@ -941,7 +947,7 @@ const int Field::kOptionsFieldNumber; #endif // !_MSC_VER Field::Field() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Field) } @@ -1153,12 +1159,15 @@ bool Field::MergePartialFromCodedStream( case 9: { if (tag == 74) { parse_options: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_options())); } else { goto handle_unusual; } - if (input->ExpectTag(74)) goto parse_options; + if (input->ExpectTag(74)) goto parse_loop_options; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -1370,9 +1379,9 @@ int Field::ByteSize() const { void Field::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Field* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Field* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1454,7 +1463,7 @@ void Field::InternalSwap(Field* other) { // Field // optional .google.protobuf.Field.Kind kind = 1; - void Field::clear_kind() { +void Field::clear_kind() { kind_ = 0; } ::google::protobuf::Field_Kind Field::kind() const { @@ -1468,7 +1477,7 @@ void Field::InternalSwap(Field* other) { } // optional .google.protobuf.Field.Cardinality cardinality = 2; - void Field::clear_cardinality() { +void Field::clear_cardinality() { cardinality_ = 0; } ::google::protobuf::Field_Cardinality Field::cardinality() const { @@ -1482,7 +1491,7 @@ void Field::InternalSwap(Field* other) { } // optional int32 number = 3; - void Field::clear_number() { +void Field::clear_number() { number_ = 0; } ::google::protobuf::int32 Field::number() const { @@ -1496,7 +1505,7 @@ void Field::InternalSwap(Field* other) { } // optional string name = 4; - void Field::clear_name() { +void Field::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Field::name() const { @@ -1539,7 +1548,7 @@ void Field::InternalSwap(Field* other) { } // optional string type_url = 6; - void Field::clear_type_url() { +void Field::clear_type_url() { type_url_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Field::type_url() const { @@ -1582,7 +1591,7 @@ void Field::InternalSwap(Field* other) { } // optional int32 oneof_index = 7; - void Field::clear_oneof_index() { +void Field::clear_oneof_index() { oneof_index_ = 0; } ::google::protobuf::int32 Field::oneof_index() const { @@ -1596,7 +1605,7 @@ void Field::InternalSwap(Field* other) { } // optional bool packed = 8; - void Field::clear_packed() { +void Field::clear_packed() { packed_ = false; } bool Field::packed() const { @@ -1610,10 +1619,10 @@ void Field::InternalSwap(Field* other) { } // repeated .google.protobuf.Option options = 9; - int Field::options_size() const { +int Field::options_size() const { return options_.size(); } - void Field::clear_options() { +void Field::clear_options() { options_.Clear(); } const ::google::protobuf::Option& Field::options(int index) const { @@ -1651,7 +1660,7 @@ const int Enum::kSourceContextFieldNumber; #endif // !_MSC_VER Enum::Enum() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Enum) } @@ -1716,7 +1725,7 @@ Enum* Enum::New(::google::protobuf::Arena* arena) const { void Enum::Clear() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (source_context_ != NULL) delete source_context_; + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; enumvalue_.Clear(); options_.Clear(); @@ -1752,26 +1761,31 @@ bool Enum::MergePartialFromCodedStream( case 2: { if (tag == 18) { parse_enumvalue: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_enumvalue: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_enumvalue())); } else { goto handle_unusual; } - if (input->ExpectTag(18)) goto parse_enumvalue; - if (input->ExpectTag(26)) goto parse_options; + if (input->ExpectTag(18)) goto parse_loop_enumvalue; + if (input->ExpectTag(26)) goto parse_loop_options; + input->UnsafeDecrementRecursionDepth(); break; } // repeated .google.protobuf.Option options = 3; case 3: { if (tag == 26) { - parse_options: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_options())); } else { goto handle_unusual; } - if (input->ExpectTag(26)) goto parse_options; + if (input->ExpectTag(26)) goto parse_loop_options; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectTag(34)) goto parse_source_context; break; } @@ -1924,9 +1938,9 @@ int Enum::ByteSize() const { void Enum::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Enum* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Enum* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1989,7 +2003,7 @@ void Enum::InternalSwap(Enum* other) { // Enum // optional string name = 1; - void Enum::clear_name() { +void Enum::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Enum::name() const { @@ -2032,10 +2046,10 @@ void Enum::InternalSwap(Enum* other) { } // repeated .google.protobuf.EnumValue enumvalue = 2; - int Enum::enumvalue_size() const { +int Enum::enumvalue_size() const { return enumvalue_.size(); } - void Enum::clear_enumvalue() { +void Enum::clear_enumvalue() { enumvalue_.Clear(); } const ::google::protobuf::EnumValue& Enum::enumvalue(int index) const { @@ -2062,10 +2076,10 @@ Enum::mutable_enumvalue() { } // repeated .google.protobuf.Option options = 3; - int Enum::options_size() const { +int Enum::options_size() const { return options_.size(); } - void Enum::clear_options() { +void Enum::clear_options() { options_.Clear(); } const ::google::protobuf::Option& Enum::options(int index) const { @@ -2092,11 +2106,11 @@ Enum::mutable_options() { } // optional .google.protobuf.SourceContext source_context = 4; - bool Enum::has_source_context() const { +bool Enum::has_source_context() const { return !_is_default_instance_ && source_context_ != NULL; } - void Enum::clear_source_context() { - if (source_context_ != NULL) delete source_context_; +void Enum::clear_source_context() { + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; } const ::google::protobuf::SourceContext& Enum::source_context() const { @@ -2139,7 +2153,7 @@ const int EnumValue::kOptionsFieldNumber; #endif // !_MSC_VER EnumValue::EnumValue() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.EnumValue) } @@ -2251,12 +2265,15 @@ bool EnumValue::MergePartialFromCodedStream( case 3: { if (tag == 26) { parse_options: - DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + DO_(input->IncrementRecursionDepth()); + parse_loop_options: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( input, add_options())); } else { goto handle_unusual; } - if (input->ExpectTag(26)) goto parse_options; + if (input->ExpectTag(26)) goto parse_loop_options; + input->UnsafeDecrementRecursionDepth(); if (input->ExpectAtEnd()) goto success; break; } @@ -2372,9 +2389,9 @@ int EnumValue::ByteSize() const { void EnumValue::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const EnumValue* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const EnumValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -2435,7 +2452,7 @@ void EnumValue::InternalSwap(EnumValue* other) { // EnumValue // optional string name = 1; - void EnumValue::clear_name() { +void EnumValue::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& EnumValue::name() const { @@ -2478,7 +2495,7 @@ void EnumValue::InternalSwap(EnumValue* other) { } // optional int32 number = 2; - void EnumValue::clear_number() { +void EnumValue::clear_number() { number_ = 0; } ::google::protobuf::int32 EnumValue::number() const { @@ -2492,10 +2509,10 @@ void EnumValue::InternalSwap(EnumValue* other) { } // repeated .google.protobuf.Option options = 3; - int EnumValue::options_size() const { +int EnumValue::options_size() const { return options_.size(); } - void EnumValue::clear_options() { +void EnumValue::clear_options() { options_.Clear(); } const ::google::protobuf::Option& EnumValue::options(int index) const { @@ -2531,7 +2548,7 @@ const int Option::kValueFieldNumber; #endif // !_MSC_VER Option::Option() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Option) } @@ -2596,7 +2613,7 @@ Option* Option::New(::google::protobuf::Arena* arena) const { void Option::Clear() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); - if (value_ != NULL) delete value_; + if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_; value_ = NULL; } @@ -2732,9 +2749,9 @@ int Option::ByteSize() const { void Option::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Option* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Option* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -2793,7 +2810,7 @@ void Option::InternalSwap(Option* other) { // Option // optional string name = 1; - void Option::clear_name() { +void Option::clear_name() { name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& Option::name() const { @@ -2836,11 +2853,11 @@ void Option::InternalSwap(Option* other) { } // optional .google.protobuf.Any value = 2; - bool Option::has_value() const { +bool Option::has_value() const { return !_is_default_instance_ && value_ != NULL; } - void Option::clear_value() { - if (value_ != NULL) delete value_; +void Option::clear_value() { + if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_; value_ = NULL; } const ::google::protobuf::Any& Option::value() const { diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h index a14edd4a..c9952efa 100644 --- a/src/google/protobuf/type.pb.h +++ b/src/google/protobuf/type.pb.h @@ -936,7 +936,7 @@ inline bool Type::has_source_context() const { return !_is_default_instance_ && source_context_ != NULL; } inline void Type::clear_source_context() { - if (source_context_ != NULL) delete source_context_; + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; } inline const ::google::protobuf::SourceContext& Type::source_context() const { @@ -1270,7 +1270,7 @@ inline bool Enum::has_source_context() const { return !_is_default_instance_ && source_context_ != NULL; } inline void Enum::clear_source_context() { - if (source_context_ != NULL) delete source_context_; + if (GetArenaNoVirtual() == NULL && source_context_ != NULL) delete source_context_; source_context_ = NULL; } inline const ::google::protobuf::SourceContext& Enum::source_context() const { @@ -1445,7 +1445,7 @@ inline bool Option::has_value() const { return !_is_default_instance_ && value_ != NULL; } inline void Option::clear_value() { - if (value_ != NULL) delete value_; + if (GetArenaNoVirtual() == NULL && value_ != NULL) delete value_; value_ = NULL; } inline const ::google::protobuf::Any& Option::value() const { @@ -1478,6 +1478,14 @@ inline void Option::set_allocated_value(::google::protobuf::Any* value) { } #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto index a32291e0..834c9b56 100644 --- a/src/google/protobuf/unittest.proto +++ b/src/google/protobuf/unittest.proto @@ -185,6 +185,7 @@ message TestAllTypes { message NestedTestAllTypes { optional NestedTestAllTypes child = 1; optional TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; } message TestDeprecatedFields { @@ -203,6 +204,11 @@ enum ForeignEnum { FOREIGN_BAZ = 6; } +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} + message TestAllExtensions { extensions 1 to max; } diff --git a/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto index 1b35fad0..faaddc6e 100644 --- a/src/google/protobuf/unittest_drop_unknown_fields.proto +++ b/src/google/protobuf/unittest_drop_unknown_fields.proto @@ -41,8 +41,8 @@ message Foo { BAR = 1; BAZ = 2; } - optional int32 int32_value = 1; - optional NestedEnum enum_value = 2; + int32 int32_value = 1; + NestedEnum enum_value = 2; } message FooWithExtraFields { @@ -52,7 +52,7 @@ message FooWithExtraFields { BAZ = 2; QUX = 3; } - optional int32 int32_value = 1; - optional NestedEnum enum_value = 2; - optional int32 extra_int32_value = 3; + int32 int32_value = 1; + NestedEnum enum_value = 2; + int32 extra_int32_value = 3; } diff --git a/src/google/protobuf/unittest_no_field_presence.proto b/src/google/protobuf/unittest_no_field_presence.proto index f261b58e..f5cc4cc3 100644 --- a/src/google/protobuf/unittest_no_field_presence.proto +++ b/src/google/protobuf/unittest_no_field_presence.proto @@ -43,7 +43,7 @@ option csharp_namespace = "Google.ProtocolBuffers.TestProtos.Proto3"; // forms. message TestAllTypes { message NestedMessage { - optional int32 bb = 1; + int32 bb = 1; } enum NestedEnum { @@ -55,36 +55,36 @@ message TestAllTypes { // Singular // TODO: remove 'optional' labels as soon as CL 69188077 is LGTM'd to make // 'optional' optional. - optional int32 optional_int32 = 1; - optional int64 optional_int64 = 2; - optional uint32 optional_uint32 = 3; - optional uint64 optional_uint64 = 4; - optional sint32 optional_sint32 = 5; - optional sint64 optional_sint64 = 6; - optional fixed32 optional_fixed32 = 7; - optional fixed64 optional_fixed64 = 8; - optional sfixed32 optional_sfixed32 = 9; - optional sfixed64 optional_sfixed64 = 10; - optional float optional_float = 11; - optional double optional_double = 12; - optional bool optional_bool = 13; - optional string optional_string = 14; - optional bytes optional_bytes = 15; - - optional NestedMessage optional_nested_message = 18; - optional ForeignMessage optional_foreign_message = 19; - optional protobuf_unittest.TestAllTypes optional_proto2_message = 20; - - optional NestedEnum optional_nested_enum = 21; - optional ForeignEnum optional_foreign_enum = 22; + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + protobuf_unittest.TestAllTypes optional_proto2_message = 20; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; // N.B.: proto2-enum-type fields not allowed, because their default values // might not be zero. //optional protobuf_unittest.ForeignEnum optional_proto2_enum = 23; - optional string optional_string_piece = 24 [ctype=STRING_PIECE]; - optional string optional_cord = 25 [ctype=CORD]; + string optional_string_piece = 24 [ctype=STRING_PIECE]; + string optional_cord = 25 [ctype=CORD]; - optional NestedMessage optional_lazy_message = 30 [lazy=true]; + NestedMessage optional_lazy_message = 30 [lazy=true]; // Repeated repeated int32 repeated_int32 = 31; @@ -124,13 +124,13 @@ message TestAllTypes { } message TestProto2Required { - optional protobuf_unittest.TestRequired proto2 = 1; + protobuf_unittest.TestRequired proto2 = 1; } // Define these after TestAllTypes to make sure the compiler can handle // that. message ForeignMessage { - optional int32 c = 1; + int32 c = 1; } enum ForeignEnum { diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto index 24e6828f..abc3de28 100644 --- a/src/google/protobuf/unittest_preserve_unknown_enum.proto +++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto @@ -49,7 +49,7 @@ enum MyEnumPlusExtra { } message MyMessage { - optional MyEnum e = 1; + MyEnum e = 1; repeated MyEnum repeated_e = 2; repeated MyEnum repeated_packed_e = 3 [packed=true]; repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4; // not packed @@ -60,7 +60,7 @@ message MyMessage { } message MyMessagePlusExtra { - optional MyEnumPlusExtra e = 1; + MyEnumPlusExtra e = 1; repeated MyEnumPlusExtra repeated_e = 2; repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true]; repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true]; diff --git a/src/google/protobuf/unittest_proto3_arena.proto b/src/google/protobuf/unittest_proto3_arena.proto index 6d7bada8..b835a6ba 100644 --- a/src/google/protobuf/unittest_proto3_arena.proto +++ b/src/google/protobuf/unittest_proto3_arena.proto @@ -43,7 +43,7 @@ message TestAllTypes { // The field name "b" fails to compile in proto1 because it conflicts with // a local variable named "b" in one of the generated methods. Doh. // This file needs to compile in proto1 to test backwards-compatibility. - optional int32 bb = 1; + int32 bb = 1; } enum NestedEnum { @@ -55,46 +55,47 @@ message TestAllTypes { } // Singular - optional int32 optional_int32 = 1; - optional int64 optional_int64 = 2; - optional uint32 optional_uint32 = 3; - optional uint64 optional_uint64 = 4; - optional sint32 optional_sint32 = 5; - optional sint64 optional_sint64 = 6; - optional fixed32 optional_fixed32 = 7; - optional fixed64 optional_fixed64 = 8; - optional sfixed32 optional_sfixed32 = 9; - optional sfixed64 optional_sfixed64 = 10; - optional float optional_float = 11; - optional double optional_double = 12; - optional bool optional_bool = 13; - optional string optional_string = 14; - optional bytes optional_bytes = 15; - - optional group OptionalGroup = 16 { - optional int32 a = 17; - } - - optional NestedMessage optional_nested_message = 18; - optional ForeignMessage optional_foreign_message = 19; - optional protobuf_unittest_import.ImportMessage optional_import_message = 20; - - optional NestedEnum optional_nested_enum = 21; - optional ForeignEnum optional_foreign_enum = 22; + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + // Groups are not allowed in proto3. + // optional group OptionalGroup = 16 { + // optional int32 a = 17; + // } + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + protobuf_unittest_import.ImportMessage optional_import_message = 20; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; // Omitted (compared to unittest.proto) because proto2 enums are not allowed // inside proto2 messages. // // optional protobuf_unittest_import.ImportEnum optional_import_enum = 23; - optional string optional_string_piece = 24 [ctype=STRING_PIECE]; - optional string optional_cord = 25 [ctype=CORD]; + string optional_string_piece = 24 [ctype=STRING_PIECE]; + string optional_cord = 25 [ctype=CORD]; // Defined in unittest_import_public.proto - optional protobuf_unittest_import.PublicImportMessage + protobuf_unittest_import.PublicImportMessage optional_public_import_message = 26; - optional NestedMessage optional_lazy_message = 27 [lazy=true]; + NestedMessage optional_lazy_message = 27 [lazy=true]; // Repeated repeated int32 repeated_int32 = 31; @@ -113,9 +114,10 @@ message TestAllTypes { repeated string repeated_string = 44; repeated bytes repeated_bytes = 45; - repeated group RepeatedGroup = 46 { - optional int32 a = 47; - } + // Groups are not allowed in proto3. + // repeated group RepeatedGroup = 46 { + // optional int32 a = 47; + // } repeated NestedMessage repeated_nested_message = 48; repeated ForeignMessage repeated_foreign_message = 49; @@ -161,6 +163,24 @@ message TestPackedTypes { repeated ForeignEnum packed_enum = 103 [packed = true]; } +// Explicitly set packed to false +message TestUnpackedTypes { + repeated int32 repeated_int32 = 1 [packed = false]; + repeated int64 repeated_int64 = 2 [packed = false]; + repeated uint32 repeated_uint32 = 3 [packed = false]; + repeated uint64 repeated_uint64 = 4 [packed = false]; + repeated sint32 repeated_sint32 = 5 [packed = false]; + repeated sint64 repeated_sint64 = 6 [packed = false]; + repeated fixed32 repeated_fixed32 = 7 [packed = false]; + repeated fixed64 repeated_fixed64 = 8 [packed = false]; + repeated sfixed32 repeated_sfixed32 = 9 [packed = false]; + repeated sfixed64 repeated_sfixed64 = 10 [packed = false]; + repeated float repeated_float = 11 [packed = false]; + repeated double repeated_double = 12 [packed = false]; + repeated bool repeated_bool = 13 [packed = false]; + repeated TestAllTypes.NestedEnum repeated_nested_enum = 14 [packed = false]; +} + // This proto includes a recusively nested message. message NestedTestAllTypes { NestedTestAllTypes child = 1; @@ -170,7 +190,7 @@ message NestedTestAllTypes { // Define these after TestAllTypes to make sure the compiler can handle // that. message ForeignMessage { - optional int32 c = 1; + int32 c = 1; } enum ForeignEnum { diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc index e15280c8..76644900 100644 --- a/src/google/protobuf/unknown_field_set.cc +++ b/src/google/protobuf/unknown_field_set.cc @@ -93,7 +93,7 @@ void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) { fields_ = new vector(); for (int i = 0; i < other_field_count; i++) { fields_->push_back((*other.fields_)[i]); - fields_->back().DeepCopy(); + fields_->back().DeepCopy((*other.fields_)[i]); } } } @@ -104,7 +104,7 @@ void UnknownFieldSet::MergeFrom(const UnknownFieldSet& other) { if (fields_ == NULL) fields_ = new vector(); for (int i = 0; i < other_field_count; i++) { fields_->push_back((*other.fields_)[i]); - fields_->back().DeepCopy(); + fields_->back().DeepCopy((*other.fields_)[i]); } } } @@ -202,7 +202,7 @@ UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { void UnknownFieldSet::AddField(const UnknownField& field) { if (fields_ == NULL) fields_ = new vector(); fields_->push_back(field); - fields_->back().DeepCopy(); + fields_->back().DeepCopy(field); } void UnknownFieldSet::DeleteSubrange(int start, int num) { @@ -303,7 +303,7 @@ void UnknownField::Reset() { } } -void UnknownField::DeepCopy() { +void UnknownField::DeepCopy(const UnknownField& other) { switch (type()) { case UnknownField::TYPE_LENGTH_DELIMITED: length_delimited_.string_value_ = new string( diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h index 987b1979..6781cd0f 100644 --- a/src/google/protobuf/unknown_field_set.h +++ b/src/google/protobuf/unknown_field_set.h @@ -216,7 +216,7 @@ class LIBPROTOBUF_EXPORT UnknownField { void Reset(); // Make a deep copy of any pointers in this UnknownField. - void DeepCopy(); + void DeepCopy(const UnknownField& other); // Set the wire type of this UnknownField. Should only be used when this // UnknownField is being created. diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index c5bbbf2e..54cd653a 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -829,7 +829,7 @@ void WireFormat::SerializeFieldWithCachedSizes( count = 1; } - const bool is_packed = field->options().packed(); + const bool is_packed = field->is_packed(); if (is_packed && count > 0) { WireFormatLite::WriteTag(field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); @@ -996,7 +996,7 @@ int WireFormat::FieldByteSize( const int data_size = FieldDataOnlyByteSize(field, message); int our_size = data_size; - if (field->options().packed()) { + if (field->is_packed()) { if (data_size > 0) { // Packed fields get serialized like a string, not their native type. // Technically this doesn't really matter; the size only changes if it's diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h index 76bc75a1..ac83abdc 100644 --- a/src/google/protobuf/wire_format_lite.h +++ b/src/google/protobuf/wire_format_lite.h @@ -330,6 +330,17 @@ class LIBPROTOBUF_EXPORT WireFormatLite { template static inline bool ReadMessageNoVirtual(input, MessageType* value); + // The same, but do not modify input's recursion depth. This is useful + // when reading a bunch of groups or messages in a loop, because then the + // recursion depth can be incremented before the loop and decremented after. + template + static inline bool ReadGroupNoVirtualNoRecursionDepth(field_number, input, + MessageType* value); + + template + static inline bool ReadMessageNoVirtualNoRecursionDepth(input, + MessageType* value); + // Write a tag. The Write*() functions typically include the tag, so // normally there's no need to call this unless using the Write*NoTag() // variants. diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h index 129fc63f..d073ff92 100644 --- a/src/google/protobuf/wire_format_lite_inl.h +++ b/src/google/protobuf/wire_format_lite_inl.h @@ -470,7 +470,7 @@ inline bool WireFormatLite::ReadGroupNoVirtual( if (!value-> MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) return false; - input->DecrementRecursionDepth(); + input->UnsafeDecrementRecursionDepth(); // Make sure the last thing read was an end tag for this group. if (!input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP))) { return false; @@ -478,6 +478,14 @@ inline bool WireFormatLite::ReadGroupNoVirtual( return true; } template +inline bool WireFormatLite::ReadGroupNoVirtualNoRecursionDepth( + int field_number, io::CodedInputStream* input, + MessageType_WorkAroundCppLookupDefect* value) { + return value->MessageType_WorkAroundCppLookupDefect:: + MergePartialFromCodedStream(input) && + input->LastTagWas(MakeTag(field_number, WIRETYPE_END_GROUP)); +} +template inline bool WireFormatLite::ReadMessageNoVirtual( io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) { uint32 length; @@ -491,6 +499,17 @@ inline bool WireFormatLite::ReadMessageNoVirtual( // tag. return input->DecrementRecursionDepthAndPopLimit(p.first); } +template +inline bool WireFormatLite::ReadMessageNoVirtualNoRecursionDepth( + io::CodedInputStream* input, MessageType_WorkAroundCppLookupDefect* value) { + io::CodedInputStream::Limit old_limit = input->ReadLengthAndPushLimit(); + if (!value-> + MessageType_WorkAroundCppLookupDefect::MergePartialFromCodedStream(input)) + return false; + // Make sure that parsing stopped when the limit was hit, not at an endgroup + // tag. + return input->CheckEntireMessageConsumedAndPopLimit(old_limit); +} // =================================================================== diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc index a3062a6a..e80c5a71 100644 --- a/src/google/protobuf/wire_format_unittest.cc +++ b/src/google/protobuf/wire_format_unittest.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -794,6 +795,137 @@ TEST(WireFormatTest, CompatibleTypes) { ASSERT_EQ(static_cast(data), msg5.data()); } +class Proto3PrimitiveRepeatedWireFormatTest + : public ::testing::TestWithParam { + protected: + template + void SetProto3PrimitiveRepeatedFields(Proto* message) { + message->add_repeated_int32(1); + message->add_repeated_int64(1); + message->add_repeated_uint32(1); + message->add_repeated_uint64(1); + message->add_repeated_sint32(1); + message->add_repeated_sint64(1); + message->add_repeated_fixed32(1); + message->add_repeated_fixed64(1); + message->add_repeated_sfixed32(1); + message->add_repeated_sfixed64(1); + message->add_repeated_float(1.0); + message->add_repeated_double(1.0); + message->add_repeated_bool(true); + message->add_repeated_nested_enum( + proto3_arena_unittest::TestAllTypes_NestedEnum_FOO); + } + + template + void ExpectProto3PrimitiveRepeatedFieldsSet(const Proto& message) { + EXPECT_EQ(1, message.repeated_int32(0)); + EXPECT_EQ(1, message.repeated_int64(0)); + EXPECT_EQ(1, message.repeated_uint32(0)); + EXPECT_EQ(1, message.repeated_uint64(0)); + EXPECT_EQ(1, message.repeated_sint32(0)); + EXPECT_EQ(1, message.repeated_sint64(0)); + EXPECT_EQ(1, message.repeated_fixed32(0)); + EXPECT_EQ(1, message.repeated_fixed64(0)); + EXPECT_EQ(1, message.repeated_sfixed32(0)); + EXPECT_EQ(1, message.repeated_sfixed64(0)); + EXPECT_EQ(1.0, message.repeated_float(0)); + EXPECT_EQ(1.0, message.repeated_double(0)); + EXPECT_EQ(true, message.repeated_bool(0)); + EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_FOO, + message.repeated_nested_enum(0)); + } + + template + void TestProto3PrimitiveRepeatedFields(Proto* message, + const string& expected) { + SetProto3PrimitiveRepeatedFields(message); + + int size = message->ByteSize(); + + // Serialize using the generated code. + string generated_data; + { + io::StringOutputStream raw_output(&generated_data); + io::CodedOutputStream output(&raw_output); + message->SerializeWithCachedSizes(&output); + ASSERT_FALSE(output.HadError()); + } + + EXPECT_TRUE(expected == generated_data); + + message->Clear(); + message->ParseFromString(generated_data); + ExpectProto3PrimitiveRepeatedFieldsSet(*message); + + // Serialize using the dynamic code. + string dynamic_data; + { + io::StringOutputStream raw_output(&dynamic_data); + io::CodedOutputStream output(&raw_output); + WireFormat::SerializeWithCachedSizes(*message, size, &output); + ASSERT_FALSE(output.HadError()); + } + + EXPECT_TRUE(expected == dynamic_data); + + message->Clear(); + io::CodedInputStream input( + reinterpret_cast(dynamic_data.data()), + dynamic_data.size()); + WireFormat::ParseAndMergePartial(&input, message); + ExpectProto3PrimitiveRepeatedFieldsSet(*message); + } +}; +INSTANTIATE_TEST_CASE_P(SetPacked, + Proto3PrimitiveRepeatedWireFormatTest, + ::testing::Values(false, true)); + +TEST_P(Proto3PrimitiveRepeatedWireFormatTest, Proto3PrimitiveRepeated) { + proto3_arena_unittest::TestAllTypes packed_message; + proto3_arena_unittest::TestUnpackedTypes unpacked_message; + + const string packedExpected( + "\xFA\x01\x01\x01" + "\x82\x02\x01\x01" + "\x8A\x02\x01\x01" + "\x92\x02\x01\x01" + "\x9A\x02\x01\x02" + "\xA2\x02\x01\x02" + "\xAA\x02\x04\x01\x00\x00\x00" + "\xB2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00" + "\xBA\x02\x04\x01\x00\x00\x00" + "\xC2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00" + "\xCA\x02\x04\x00\x00\x80\x3f" + "\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xf0\x3f" + "\xDA\x02\x01\x01" + "\x9A\x03\x01\x01", + 86); + + const string unpackedExpected( + "\x08\x01" + "\x10\x01" + "\x18\x01" + "\x20\x01" + "\x28\x02" + "\x30\x02" + "\x3D\x01\x00\x00\x00" + "\x41\x01\x00\x00\x00\x00\x00\x00\x00" + "\x4D\x01\x00\x00\x00" + "\x51\x01\x00\x00\x00\x00\x00\x00\x00" + "\x5D\x00\x00\x80\x3f" + "\x61\x00\x00\x00\x00\x00\x00\xf0\x3f" + "\x68\x01" + "\x70\x01", + 58); + + if (GetParam()) { + TestProto3PrimitiveRepeatedFields(&packed_message, packedExpected); + } else { + TestProto3PrimitiveRepeatedFields(&unpacked_message, unpackedExpected); + } +} + class WireFormatInvalidInputTest : public testing::Test { protected: // Make a serialized TestAllTypes in which the field optional_nested_message diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index 4d91ed56..ffc77f1c 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -312,7 +312,7 @@ const int DoubleValue::kValueFieldNumber; #endif // !_MSC_VER DoubleValue::DoubleValue() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.DoubleValue) } @@ -458,9 +458,9 @@ int DoubleValue::ByteSize() const { void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const DoubleValue* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const DoubleValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -514,7 +514,7 @@ void DoubleValue::InternalSwap(DoubleValue* other) { // DoubleValue // optional double value = 1; - void DoubleValue::clear_value() { +void DoubleValue::clear_value() { value_ = 0; } double DoubleValue::value() const { @@ -536,7 +536,7 @@ const int FloatValue::kValueFieldNumber; #endif // !_MSC_VER FloatValue::FloatValue() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.FloatValue) } @@ -682,9 +682,9 @@ int FloatValue::ByteSize() const { void FloatValue::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const FloatValue* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const FloatValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -738,7 +738,7 @@ void FloatValue::InternalSwap(FloatValue* other) { // FloatValue // optional float value = 1; - void FloatValue::clear_value() { +void FloatValue::clear_value() { value_ = 0; } float FloatValue::value() const { @@ -760,7 +760,7 @@ const int Int64Value::kValueFieldNumber; #endif // !_MSC_VER Int64Value::Int64Value() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Int64Value) } @@ -908,9 +908,9 @@ int Int64Value::ByteSize() const { void Int64Value::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Int64Value* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Int64Value* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -964,7 +964,7 @@ void Int64Value::InternalSwap(Int64Value* other) { // Int64Value // optional int64 value = 1; - void Int64Value::clear_value() { +void Int64Value::clear_value() { value_ = GOOGLE_LONGLONG(0); } ::google::protobuf::int64 Int64Value::value() const { @@ -986,7 +986,7 @@ const int UInt64Value::kValueFieldNumber; #endif // !_MSC_VER UInt64Value::UInt64Value() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.UInt64Value) } @@ -1134,9 +1134,9 @@ int UInt64Value::ByteSize() const { void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const UInt64Value* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const UInt64Value* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1190,7 +1190,7 @@ void UInt64Value::InternalSwap(UInt64Value* other) { // UInt64Value // optional uint64 value = 1; - void UInt64Value::clear_value() { +void UInt64Value::clear_value() { value_ = GOOGLE_ULONGLONG(0); } ::google::protobuf::uint64 UInt64Value::value() const { @@ -1212,7 +1212,7 @@ const int Int32Value::kValueFieldNumber; #endif // !_MSC_VER Int32Value::Int32Value() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.Int32Value) } @@ -1360,9 +1360,9 @@ int Int32Value::ByteSize() const { void Int32Value::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const Int32Value* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const Int32Value* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1416,7 +1416,7 @@ void Int32Value::InternalSwap(Int32Value* other) { // Int32Value // optional int32 value = 1; - void Int32Value::clear_value() { +void Int32Value::clear_value() { value_ = 0; } ::google::protobuf::int32 Int32Value::value() const { @@ -1438,7 +1438,7 @@ const int UInt32Value::kValueFieldNumber; #endif // !_MSC_VER UInt32Value::UInt32Value() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.UInt32Value) } @@ -1586,9 +1586,9 @@ int UInt32Value::ByteSize() const { void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const UInt32Value* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const UInt32Value* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1642,7 +1642,7 @@ void UInt32Value::InternalSwap(UInt32Value* other) { // UInt32Value // optional uint32 value = 1; - void UInt32Value::clear_value() { +void UInt32Value::clear_value() { value_ = 0u; } ::google::protobuf::uint32 UInt32Value::value() const { @@ -1664,7 +1664,7 @@ const int BoolValue::kValueFieldNumber; #endif // !_MSC_VER BoolValue::BoolValue() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.BoolValue) } @@ -1810,9 +1810,9 @@ int BoolValue::ByteSize() const { void BoolValue::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const BoolValue* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const BoolValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -1866,7 +1866,7 @@ void BoolValue::InternalSwap(BoolValue* other) { // BoolValue // optional bool value = 1; - void BoolValue::clear_value() { +void BoolValue::clear_value() { value_ = false; } bool BoolValue::value() const { @@ -1888,7 +1888,7 @@ const int StringValue::kValueFieldNumber; #endif // !_MSC_VER StringValue::StringValue() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.StringValue) } @@ -2051,9 +2051,9 @@ int StringValue::ByteSize() const { void StringValue::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const StringValue* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const StringValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -2108,7 +2108,7 @@ void StringValue::InternalSwap(StringValue* other) { // StringValue // optional string value = 1; - void StringValue::clear_value() { +void StringValue::clear_value() { value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& StringValue::value() const { @@ -2159,7 +2159,7 @@ const int BytesValue::kValueFieldNumber; #endif // !_MSC_VER BytesValue::BytesValue() - : ::google::protobuf::Message() , _internal_metadata_(NULL) { + : ::google::protobuf::Message(), _internal_metadata_(NULL) { SharedCtor(); // @@protoc_insertion_point(constructor:google.protobuf.BytesValue) } @@ -2310,9 +2310,9 @@ int BytesValue::ByteSize() const { void BytesValue::MergeFrom(const ::google::protobuf::Message& from) { if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); - const BytesValue* source = - ::google::protobuf::internal::dynamic_cast_if_available( - &from); + const BytesValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); if (source == NULL) { ::google::protobuf::internal::ReflectionOps::Merge(from, this); } else { @@ -2367,7 +2367,7 @@ void BytesValue::InternalSwap(BytesValue* other) { // BytesValue // optional bytes value = 1; - void BytesValue::clear_value() { +void BytesValue::clear_value() { value_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } const ::std::string& BytesValue::value() const { diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h index c318f950..387ebd7c 100644 --- a/src/google/protobuf/wrappers.pb.h +++ b/src/google/protobuf/wrappers.pb.h @@ -984,6 +984,22 @@ inline void BytesValue::set_allocated_value(::std::string* value) { } #endif // !PROTOBUF_INLINE_NOT_IN_HEADERS +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/vsprojects/libprotoc.vcproj b/vsprojects/libprotoc.vcproj index d1f065e2..3474d21f 100644 --- a/vsprojects/libprotoc.vcproj +++ b/vsprojects/libprotoc.vcproj @@ -295,6 +295,10 @@ RelativePath="..\src\google\protobuf\compiler\java\java_enum_field.h" > + + @@ -323,14 +327,34 @@ RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.h" > + + + + + + + + + + @@ -339,6 +363,10 @@ RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.h" > + + @@ -351,6 +379,10 @@ RelativePath="..\src\google\protobuf\compiler\java\java_string_field.h" > + + @@ -607,18 +639,42 @@ RelativePath="..\src\google\protobuf\compiler\java\java_lazy_message_field.cc" > + + + + + + + + + + + + @@ -627,6 +683,10 @@ RelativePath="..\src\google\protobuf\compiler\java\java_primitive_field.cc" > + + @@ -639,6 +699,10 @@ RelativePath="..\src\google\protobuf\compiler\java\java_string_field.cc" > + + -- cgit v1.2.3 From 1dcc329427fd103a0abd96ab787270f5d0a31861 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Thu, 21 May 2015 17:14:52 -0400 Subject: Objective C Second Alpha Drop - Style fixups in the code. - map<> serialization fixes and more tests. - Autocreation of map<> fields (to match repeated fields). - @@protoc_insertion_point(global_scope|imports). - Fixup proto2 syntax extension support. - Move all startup code to +initialize so it happen on class usage and not app startup. - Have generated headers use forward declarations and move imports into generated code, reduces what is need at compile time to speed up compiled and avoid pointless rippling of rebuilds. --- Makefile.am | 4 +- configure.ac | 2 +- objectivec/DevTools/check_version_stamps.sh | 4 +- objectivec/DevTools/full_mac_build.sh | 228 ++++++ objectivec/DevTools/generate_descriptors_proto.sh | 36 - objectivec/GPBArray.m | 80 +- objectivec/GPBBootstrap.h | 6 +- objectivec/GPBCodedInputStream.h | 8 +- objectivec/GPBDescriptor.h | 3 - objectivec/GPBDescriptor.m | 36 +- objectivec/GPBDescriptor_PackagePrivate.h | 1 - objectivec/GPBDictionary.m | 813 +++++++++++++++++-- objectivec/GPBDictionary_PackagePrivate.h | 558 ++++++------- objectivec/GPBExtensionRegistry.h | 19 +- objectivec/GPBExtensionRegistry.m | 10 +- objectivec/GPBExtensionRegistry_PackagePrivate.h | 40 - objectivec/GPBMessage.h | 94 ++- objectivec/GPBMessage.m | 867 +++++++++++++-------- objectivec/GPBMessage_PackagePrivate.h | 6 +- objectivec/GPBProtocolBuffers_RuntimeSupport.h | 2 +- objectivec/GPBRootObject.m | 61 +- objectivec/GPBRootObject_PackagePrivate.h | 4 + objectivec/GPBUtilities.m | 97 ++- .../ProtocolBuffers_OSX.xcodeproj/project.pbxproj | 5 +- .../xcschemes/ProtocolBuffers.xcscheme | 14 + .../ProtocolBuffers_iOS.xcodeproj/project.pbxproj | 5 +- .../xcschemes/ProtocolBuffers.xcscheme | 14 + objectivec/README.md | 77 ++ objectivec/Tests/GPBArrayTests.m | 87 ++- objectivec/Tests/GPBCodedInputStreamTests.m | 12 +- objectivec/Tests/GPBConcurrencyTests.m | 48 ++ objectivec/Tests/GPBDictionaryTests+Bool.m | 5 +- objectivec/Tests/GPBDictionaryTests+Int32.m | 5 +- objectivec/Tests/GPBDictionaryTests+Int64.m | 5 +- objectivec/Tests/GPBDictionaryTests+String.m | 5 +- objectivec/Tests/GPBDictionaryTests+UInt32.m | 5 +- objectivec/Tests/GPBDictionaryTests+UInt64.m | 5 +- objectivec/Tests/GPBDictionaryTests.pddm | 4 - objectivec/Tests/GPBMessageTests+Merge.m | 5 +- objectivec/Tests/GPBMessageTests+Runtime.m | 11 +- objectivec/Tests/GPBMessageTests+Serialization.m | 183 +++-- objectivec/Tests/GPBMessageTests.m | 285 ++++++- objectivec/Tests/GPBPerfTests.m | 9 +- objectivec/Tests/GPBStringTests.m | 5 +- objectivec/Tests/GPBSwiftTests.swift | 57 +- objectivec/Tests/GPBTestUtilities.h | 7 + objectivec/Tests/GPBTestUtilities.m | 20 +- objectivec/Tests/GPBUnknownFieldSetTest.m | 17 +- objectivec/Tests/GPBWireFormatTests.m | 28 +- objectivec/Tests/unittest_objc.proto | 2 + objectivec/Tests/unittest_runtime_proto2.proto | 21 + objectivec/Tests/unittest_runtime_proto3.proto | 21 + objectivec/generate_descriptors_proto.sh | 54 ++ objectivec/google/protobuf/Any.pbobjc.h | 100 +++ objectivec/google/protobuf/Any.pbobjc.m | 93 +++ objectivec/google/protobuf/Api.pbobjc.h | 121 +++ objectivec/google/protobuf/Api.pbobjc.m | 262 +++++++ objectivec/google/protobuf/Descriptor.pbobjc.h | 23 +- objectivec/google/protobuf/Descriptor.pbobjc.m | 4 +- objectivec/google/protobuf/Duration.pbobjc.h | 12 +- objectivec/google/protobuf/Duration.pbobjc.m | 4 +- objectivec/google/protobuf/Empty.pbobjc.h | 41 + objectivec/google/protobuf/Empty.pbobjc.m | 61 ++ objectivec/google/protobuf/FieldMask.pbobjc.h | 160 ++++ objectivec/google/protobuf/FieldMask.pbobjc.m | 74 ++ objectivec/google/protobuf/SourceContext.pbobjc.h | 44 ++ objectivec/google/protobuf/SourceContext.pbobjc.m | 74 ++ objectivec/google/protobuf/Struct.pbobjc.h | 134 ++++ objectivec/google/protobuf/Struct.pbobjc.m | 284 +++++++ objectivec/google/protobuf/Timestamp.pbobjc.h | 12 +- objectivec/google/protobuf/Timestamp.pbobjc.m | 4 +- objectivec/google/protobuf/Type.pbobjc.h | 274 +++++++ objectivec/google/protobuf/Type.pbobjc.m | 628 +++++++++++++++ objectivec/google/protobuf/Wrappers.pbobjc.h | 154 ++++ objectivec/google/protobuf/Wrappers.pbobjc.m | 458 +++++++++++ .../protobuf/compiler/objectivec/objectivec_enum.h | 2 +- .../compiler/objectivec/objectivec_enum_field.cc | 23 +- .../compiler/objectivec/objectivec_enum_field.h | 3 +- .../compiler/objectivec/objectivec_extension.cc | 4 +- .../compiler/objectivec/objectivec_extension.h | 4 +- .../compiler/objectivec/objectivec_field.cc | 21 +- .../compiler/objectivec/objectivec_field.h | 12 +- .../compiler/objectivec/objectivec_file.cc | 136 ++-- .../protobuf/compiler/objectivec/objectivec_file.h | 11 +- .../compiler/objectivec/objectivec_helpers.cc | 51 +- .../compiler/objectivec/objectivec_helpers.h | 3 + .../compiler/objectivec/objectivec_map_field.cc | 2 + .../compiler/objectivec/objectivec_map_field.h | 2 +- .../compiler/objectivec/objectivec_message.cc | 23 +- .../compiler/objectivec/objectivec_message.h | 2 +- .../objectivec/objectivec_message_field.cc | 6 + .../compiler/objectivec/objectivec_message_field.h | 7 +- .../compiler/objectivec/objectivec_oneof.h | 2 +- .../objectivec/objectivec_primitive_field.cc | 4 + .../objectivec/objectivec_primitive_field.h | 6 +- 95 files changed, 6091 insertions(+), 1254 deletions(-) create mode 100755 objectivec/DevTools/full_mac_build.sh delete mode 100755 objectivec/DevTools/generate_descriptors_proto.sh delete mode 100644 objectivec/GPBExtensionRegistry_PackagePrivate.h create mode 100644 objectivec/README.md create mode 100755 objectivec/generate_descriptors_proto.sh create mode 100644 objectivec/google/protobuf/Any.pbobjc.h create mode 100644 objectivec/google/protobuf/Any.pbobjc.m create mode 100644 objectivec/google/protobuf/Api.pbobjc.h create mode 100644 objectivec/google/protobuf/Api.pbobjc.m create mode 100644 objectivec/google/protobuf/Empty.pbobjc.h create mode 100644 objectivec/google/protobuf/Empty.pbobjc.m create mode 100644 objectivec/google/protobuf/FieldMask.pbobjc.h create mode 100644 objectivec/google/protobuf/FieldMask.pbobjc.m create mode 100644 objectivec/google/protobuf/SourceContext.pbobjc.h create mode 100644 objectivec/google/protobuf/SourceContext.pbobjc.m create mode 100644 objectivec/google/protobuf/Struct.pbobjc.h create mode 100644 objectivec/google/protobuf/Struct.pbobjc.m create mode 100644 objectivec/google/protobuf/Type.pbobjc.h create mode 100644 objectivec/google/protobuf/Type.pbobjc.m create mode 100644 objectivec/google/protobuf/Wrappers.pbobjc.h create mode 100644 objectivec/google/protobuf/Wrappers.pbobjc.m (limited to 'src/google/protobuf/compiler') diff --git a/Makefile.am b/Makefile.am index eecffa1f..22a4274d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -198,9 +198,10 @@ javanano_EXTRA_DIST= javanano/pom.xml objectivec_EXTRA_DIST= \ - objectivec/DevTools/generate_descriptors_proto.sh \ + objectivec/DevTools/check_version_stamps.sh \ objectivec/DevTools/pddm.py \ objectivec/DevTools/pddm_tests.py \ + objectivec/generate_descriptors_proto.sh \ objectivec/google/protobuf/Descriptor.pbobjc.h \ objectivec/google/protobuf/Descriptor.pbobjc.m \ objectivec/google/protobuf/Duration.pbobjc.h \ @@ -227,7 +228,6 @@ objectivec_EXTRA_DIST= \ objectivec/GPBExtensionField_PackagePrivate.h \ objectivec/GPBExtensionRegistry.h \ objectivec/GPBExtensionRegistry.m \ - objectivec/GPBExtensionRegistry_PackagePrivate.h \ objectivec/GPBField.h \ objectivec/GPBField.m \ objectivec/GPBField_PackagePrivate.h \ diff --git a/configure.ac b/configure.ac index 0615cd85..8338c18d 100644 --- a/configure.ac +++ b/configure.ac @@ -23,7 +23,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_ARG_VAR(DIST_LANG, [language to include in the distribution package (i.e., make dist)]) case "$DIST_LANG" in "") DIST_LANG=all ;; - all | cpp | java | python | javanano | ruby) ;; + all | cpp | java | python | javanano | objectivec | ruby) ;; *) AC_MSG_FAILURE([unknown language: $DIST_LANG]) ;; esac AC_SUBST(DIST_LANG) diff --git a/objectivec/DevTools/check_version_stamps.sh b/objectivec/DevTools/check_version_stamps.sh index 7fc44265..325b71dd 100755 --- a/objectivec/DevTools/check_version_stamps.sh +++ b/objectivec/DevTools/check_version_stamps.sh @@ -29,7 +29,7 @@ readonly PluginVersion=$( \ ) if [[ -z "${PluginVersion}" ]] ; then - die "Failed to fine ${ConstantName} in the plugin source (${PluginSrc})." + die "Failed to find ${ConstantName} in the plugin source (${PluginSrc})." fi # Collect version from runtime sources. @@ -41,7 +41,7 @@ readonly RuntimeVersion=$( \ ) if [[ -z "${RuntimeVersion}" ]] ; then - die "Failed to fine ${ConstantName} in the runtime source (${RuntimeSrc})." + die "Failed to find ${ConstantName} in the runtime source (${RuntimeSrc})." fi # Compare them. diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh new file mode 100755 index 00000000..57c4f438 --- /dev/null +++ b/objectivec/DevTools/full_mac_build.sh @@ -0,0 +1,228 @@ +#!/bin/bash +# +# Helper to do build so you don't have to remember all the steps/args. + + +set -eu + +# Some base locations. +readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") +readonly ProtoRootDir="${ScriptDir}/../.." + +printUsage() { + NAME=$(basename "${0}") + cat << EOF +usage: ${NAME} [OPTIONS] + +This script does the common build steps needed. + +OPTIONS: + + General: + + -h, --help + Show this message + -c, --clean + Issue a clean before the normal build. + -a, --autogen + Start by rerunning autogen & configure. + -r, --regenerate-descriptors + The descriptor.proto is checked in generated, cause it to regenerate. + -j #, --jobs # + Force the number of parallel jobs (useful for debugging build issues). + --skip-xcode + Skip the invoke of Xcode to test the runtime on both iOS and OS X. + --skip-xcode-ios + Skip the invoke of Xcode to test the runtime on iOS. + --skip-xcode-osx + Skip the invoke of Xcode to test the runtime on OS X. + +EOF +} + +header() { + echo "" + echo "========================================================================" + echo " ${@}" + echo "========================================================================" +} + +# Thanks to libtool, builds can fail in odd ways and since it eats some output +# it can be hard to spot, so force error output if make exits with a non zero. +wrapped_make() { + set +e # Don't stop if the command fails. + make $* + MAKE_EXIT_STATUS=$? + if [ ${MAKE_EXIT_STATUS} -ne 0 ]; then + echo "Error: 'make $*' exited with status ${MAKE_EXIT_STATUS}" + exit ${MAKE_EXIT_STATUS} + fi + set -e +} + +NUM_MAKE_JOBS=$(/usr/sbin/sysctl -n hw.ncpu) +if [[ "${NUM_MAKE_JOBS}" -lt 4 ]] ; then + NUM_MAKE_JOBS=4 +fi + +DO_AUTOGEN=no +DO_CLEAN=no +REGEN_CPP_DESCRIPTORS=no +DO_XCODE_IOS_TESTS=yes +DO_XCODE_OSX_TESTS=yes +while [[ $# != 0 ]]; do + case "${1}" in + -h | --help ) + printUsage + exit 0 + ;; + -c | --clean ) + DO_CLEAN=yes + ;; + -a | --autogen ) + DO_AUTOGEN=yes + ;; + -r | --regenerate-cpp-descriptors ) + REGEN_CPP_DESCRIPTORS=yes + ;; + -j | --jobs ) + shift + NUM_MAKE_JOBS="${1}" + ;; + --skip-xcode ) + DO_XCODE_IOS_TESTS=no + DO_XCODE_OSX_TESTS=no + ;; + --skip-xcode-ios ) + DO_XCODE_IOS_TESTS=no + ;; + --skip-xcode-osx ) + DO_XCODE_OSX_TESTS=no + ;; + -*) + echo "ERROR: Unknown option: ${1}" 1>&2 + printUsage + exit 1 + ;; + *) + echo "ERROR: Unknown argument: ${1}" 1>&2 + printUsage + exit 1 + ;; + esac + shift +done + +# Into the proto dir. +pushd "${ProtoRootDir}" + +# if no Makefile, force the autogen. +if [[ ! -f Makefile ]] ; then + DO_AUTOGEN=yes +fi + +if [[ "${DO_AUTOGEN}" == "yes" ]] ; then + header "Running autogen & configure" + ./autogen.sh + ./configure CXXFLAGS="-mmacosx-version-min=10.9 -Wnon-virtual-dtor -Woverloaded-virtual -Wunused-const-variable -Wunused-function" +fi + +if [[ "${DO_CLEAN}" == "yes" ]] ; then + header "Cleaning" + wrapped_make clean + if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then + XCODEBUILD_CLEAN_BASE_IOS=( + xcodebuild + -project objectivec/ProtocolBuffers_iOS.xcodeproj + -scheme ProtocolBuffers + ) + "${XCODEBUILD_CLEAN_BASE_IOS[@]}" -configuration Debug clean + "${XCODEBUILD_CLEAN_BASE_IOS[@]}" -configuration Release clean + fi + if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then + XCODEBUILD_CLEAN_BASE_OSX=( + xcodebuild + -project objectivec/ProtocolBuffers_OSX.xcodeproj + -scheme ProtocolBuffers + ) + "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Debug clean + "${XCODEBUILD_CLEAN_BASE_OSX[@]}" -configuration Release clean + fi +fi + +if [[ "${REGEN_CPP_DESCRIPTORS}" == "yes" ]] ; then + header "Regenerating the C++ descriptor sources." + ./generate_descriptor_proto.sh -j "${NUM_MAKE_JOBS}" +fi + +header "Building" +# Can't issue these together, when fully parallel, something sometimes chokes +# at random. +wrapped_make -j "${NUM_MAKE_JOBS}" all +wrapped_make -j "${NUM_MAKE_JOBS}" check + +header "Ensuring the ObjC descriptors are current." +# Find the newest input file (protos, compiler, and this script). +# (these patterns catch some extra stuff, but better to over sample than under) +readonly NewestInput=$(find \ + src/google/protobuf/*.proto \ + src/.libs src/*.la src/protoc \ + objectivec/generate_descriptors_proto.sh \ + -type f -print0 \ + | xargs -0 stat -f "%m %N" \ + | sort -n | tail -n1 | cut -f2- -d" ") +# Find the oldest output file. +readonly OldestOutput=$(find \ + "${ProtoRootDir}/objectivec/google" \ + -type f -print0 \ + | xargs -0 stat -f "%m %N" \ + | sort -n -r | tail -n1 | cut -f2- -d" ") +# If the newest input is newer than the oldest output, regenerate. +if [[ "${NewestInput}" -nt "${OldestOutput}" ]] ; then + echo ">> Newest input is newer than oldest output, regenerating." + objectivec/generate_descriptors_proto.sh -j "${NUM_MAKE_JOBS}" +else + echo ">> Newest input is older than oldest output, no need to regenerating." +fi + +header "Checking on the ObjC Runtime Code" +objectivec/DevTools/pddm_tests.py +if ! objectivec/DevTools/pddm.py --dry-run objectivec/*.[hm] objectivec/Tests/*.[hm] ; then + echo "" + echo "Update by running:" + echo " objectivec/DevTools/pddm.py objectivec/*.[hm] objectivec/Tests/*.[hm]" + exit 1 +fi + +if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then + XCODEBUILD_TEST_BASE_IOS=( + xcodebuild + -project objectivec/ProtocolBuffers_iOS.xcodeproj + -scheme ProtocolBuffers + # Don't need to worry about form factors or retina/non retina; + # just pick a mix of OS Versions and 32/64 bit. + -destination "platform=iOS Simulator,name=iPhone 4s,OS=7.1" # 32bit + -destination "platform=iOS Simulator,name=iPhone 6,OS=8.3" # 64bit + -destination "platform=iOS Simulator,name=iPad 2,OS=7.1" # 32bit + -destination "platform=iOS Simulator,name=iPad Air,OS=8.3" # 64bit + ) + header "Doing Xcode iOS build/tests - Debug" + "${XCODEBUILD_TEST_BASE_IOS[@]}" -configuration Debug test + header "Doing Xcode iOS build/tests - Release" + "${XCODEBUILD_TEST_BASE_IOS[@]}" -configuration Release test + # Don't leave the simulator in the developer's face. + killall "iOS Simulator" +fi +if [[ "${DO_XCODE_OSX_TESTS}" == "yes" ]] ; then + XCODEBUILD_TEST_BASE_OSX=( + xcodebuild + -project objectivec/ProtocolBuffers_OSX.xcodeproj + -scheme ProtocolBuffers + # Since the ObjC 2.0 Runtime is required, 32bit OS X isn't supported. + -destination "platform=OS X,arch=x86_64" # 64bit + ) + header "Doing Xcode OS X build/tests - Debug" + "${XCODEBUILD_TEST_BASE_OSX[@]}" -configuration Debug test + header "Doing Xcode OS X build/tests - Release" + "${XCODEBUILD_TEST_BASE_OSX[@]}" -configuration Release test +fi diff --git a/objectivec/DevTools/generate_descriptors_proto.sh b/objectivec/DevTools/generate_descriptors_proto.sh deleted file mode 100755 index 42502bfe..00000000 --- a/objectivec/DevTools/generate_descriptors_proto.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -# This script will generate the common descriptors needed by the Objective C -# runtime. - -# HINT: Flags passed to generate_descriptor_proto.sh will be passed directly -# to make when building protoc. This is particularly useful for passing -# -j4 to run 4 jobs simultaneously. - -set -eu - -readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") -readonly ProtoRootDir="${ScriptDir}/../.." -readonly ProtoC="${ProtoRootDir}/src/protoc" - -pushd "${ProtoRootDir}" > /dev/null - -# Compiler build fails if config.h hasn't been made yet (even if configure/etc. -# have been run, so get that made first). -make $@ config.h - -# Make sure the compiler is current. -cd src -make $@ protoc - -# These really should only be run when the inputs or compiler are newer than -# the outputs. - -# Needed by the runtime. -./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/descriptor.proto - -# Well known types that the library provides helpers for. -./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/timestamp.proto -./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/duration.proto - -popd > /dev/null diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m index 6aa3df2e..60b08ad1 100644 --- a/objectivec/GPBArray.m +++ b/objectivec/GPBArray.m @@ -149,7 +149,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { //%PDDM-DEFINE ARRAY_IMMUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT) //%- (void)dealloc { -//% NSAssert(!_autocreator, @"Autocreator must be cleared before release."); +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); //% free(_values); //% [super dealloc]; //%} @@ -214,7 +216,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { //% if (values == NULL || count == 0) return; //%MUTATION_HOOK_##HOOK_1() NSUInteger initialCount = _count; //% NSUInteger newCount = initialCount + count; -//%MAYBE_GROW_TO_SET_COUNT(newCount); +//%MAYBE_GROW_TO_SET_COUNT(newCount) //% memcpy(&_values[initialCount], values, count * sizeof(TYPE)); //% if (_autocreator) { //% GPBAutocreatedArrayModified(_autocreator, self); @@ -225,7 +227,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { //%VALIDATE_RANGE(index, _count + 1) //%MUTATION_HOOK_##HOOK_2() NSUInteger initialCount = _count; //% NSUInteger newCount = initialCount + 1; -//%MAYBE_GROW_TO_SET_COUNT(newCount); +//%MAYBE_GROW_TO_SET_COUNT(newCount) //% if (index != initialCount) { //% memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(TYPE)); //% } @@ -355,7 +357,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); free(_values); [super dealloc]; } @@ -442,7 +446,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(int32_t)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -460,7 +464,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); } @@ -598,7 +602,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); free(_values); [super dealloc]; } @@ -685,7 +691,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(uint32_t)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -703,7 +709,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint32_t)); } @@ -841,7 +847,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); free(_values); [super dealloc]; } @@ -928,7 +936,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(int64_t)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -946,7 +954,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int64_t)); } @@ -1084,7 +1092,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); free(_values); [super dealloc]; } @@ -1171,7 +1181,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(uint64_t)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -1189,7 +1199,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint64_t)); } @@ -1327,7 +1337,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); free(_values); [super dealloc]; } @@ -1414,7 +1426,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(float)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -1432,7 +1444,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(float)); } @@ -1570,7 +1582,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); free(_values); [super dealloc]; } @@ -1657,7 +1671,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(double)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -1675,7 +1689,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(double)); } @@ -1813,7 +1827,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); free(_values); [super dealloc]; } @@ -1900,7 +1916,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(BOOL)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -1918,7 +1934,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(BOOL)); } @@ -2083,7 +2099,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { // This block of code is generated, do not edit it directly. - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); free(_values); [super dealloc]; } @@ -2229,7 +2247,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(int32_t)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -2247,7 +2265,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); } @@ -2332,7 +2350,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; memcpy(&_values[initialCount], values, count * sizeof(int32_t)); if (_autocreator) { GPBAutocreatedArrayModified(_autocreator, self); @@ -2355,7 +2373,7 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { if (newCount > _capacity) { [self internalResizeToCapacity:CapacityFromCount(newCount)]; } - _count = newCount;; + _count = newCount; if (index != initialCount) { memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t)); } @@ -2407,7 +2425,9 @@ static BOOL ArrayDefault_IsValidValue(int32_t value) { } - (void)dealloc { - NSAssert(!_autocreator, @"Autocreator must be cleared before release."); + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_array release]; [super dealloc]; } diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h index 530eb5cb..3dd2de83 100644 --- a/objectivec/GPBBootstrap.h +++ b/objectivec/GPBBootstrap.h @@ -51,11 +51,11 @@ // the Swift bridge will have one where the names line up to support short // names since they are scoped to the enum. // https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_11 -#define GPB_ENUM(X) enum X##_ : int32_t X; typedef NS_ENUM(int32_t, X##_) -// GPB_ENUM_FWD_DECLARE is used for forward declaring enums ex: +#define GPB_ENUM(X) NS_ENUM(int32_t, X) +// GPB_ENUM_FWD_DECLARE is used for forward declaring enums, ex: // GPB_ENUM_FWD_DECLARE(Foo_Enum) // @property (nonatomic) Foo_Enum value; -#define GPB_ENUM_FWD_DECLARE(_name) enum _name : int32_t +#define GPB_ENUM_FWD_DECLARE(X) enum X : int32_t // Based upon CF_INLINE. Forces inlining in release. #if !defined(DEBUG) diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h index db39c268..e9b27e22 100644 --- a/objectivec/GPBCodedInputStream.h +++ b/objectivec/GPBCodedInputStream.h @@ -66,7 +66,9 @@ - (void)readMessage:(GPBMessage *)message extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; -// Reads and discards a single field, given its tag value. +// Reads and discards a single field, given its tag value. Returns NO if the +// tag is an endgroup tag, in which case nothing is skipped. Otherwise, +// returns YES. - (BOOL)skipField:(int32_t)tag; // Reads and discards an entire message. This will read either until EOF @@ -74,8 +76,8 @@ - (void)skipMessage; // Verifies that the last call to readTag() returned the given tag value. -// This is used to verify that a nested group ended with the correct -// end tag. +// This is used to verify that a nested group ended with the correct end tag. +// Throws NSParseErrorException if value does not match the last tag. - (void)checkLastTagWas:(int32_t)value; @end diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h index d8c369c1..97b46b3c 100644 --- a/objectivec/GPBDescriptor.h +++ b/objectivec/GPBDescriptor.h @@ -56,7 +56,6 @@ typedef NS_ENUM(NSInteger, GPBFieldType) { @property(nonatomic, readonly, strong) NSArray *fields; @property(nonatomic, readonly, strong) NSArray *oneofs; @property(nonatomic, readonly, strong) NSArray *enums; -@property(nonatomic, readonly, strong) NSArray *extensions; @property(nonatomic, readonly) const GPBExtensionRange *extensionRanges; @property(nonatomic, readonly) NSUInteger extensionRangesCount; @property(nonatomic, readonly, assign) GPBFileDescriptor *file; @@ -68,8 +67,6 @@ typedef NS_ENUM(NSInteger, GPBFieldType) { - (GPBFieldDescriptor *)fieldWithName:(NSString *)name; - (GPBOneofDescriptor *)oneofWithName:(NSString *)name; - (GPBEnumDescriptor *)enumWithName:(NSString *)name; -- (GPBFieldDescriptor *)extensionWithNumber:(uint32_t)fieldNumber; -- (GPBFieldDescriptor *)extensionWithName:(NSString *)name; @end diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index 6730d532..b955018c 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -93,7 +93,6 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, @implementation GPBDescriptor { Class messageClass_; NSArray *enums_; - NSArray *extensions_; GPBFileDescriptor *file_; BOOL wireFormat_; } @@ -102,7 +101,6 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, @synthesize fields = fields_; @synthesize oneofs = oneofs_; @synthesize enums = enums_; -@synthesize extensions = extensions_; @synthesize extensionRanges = extensionRanges_; @synthesize extensionRangesCount = extensionRangesCount_; @synthesize file = file_; @@ -161,13 +159,11 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, [enums addObject:enumDescriptor]; } - // TODO(dmaclach): Add support for extensions GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass file:file fields:fields oneofs:oneofs enums:enums - extensions:nil extensionRanges:ranges extensionRangesCount:rangeCount storageSize:storageSize @@ -226,7 +222,6 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, fields:(NSArray *)fields oneofs:(NSArray *)oneofs enums:(NSArray *)enums - extensions:(NSArray *)extensions extensionRanges:(const GPBExtensionRange *)extensionRanges extensionRangesCount:(NSUInteger)extensionRangesCount storageSize:(size_t)storageSize @@ -237,7 +232,6 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, fields_ = [fields retain]; oneofs_ = [oneofs retain]; enums_ = [enums retain]; - extensions_ = [extensions retain]; extensionRanges_ = extensionRanges; extensionRangesCount_ = extensionRangesCount; storageSize_ = storageSize; @@ -250,7 +244,6 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, [fields_ release]; [oneofs_ release]; [enums_ release]; - [extensions_ release]; [super dealloc]; } @@ -299,24 +292,6 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, return nil; } -- (GPBFieldDescriptor *)extensionWithNumber:(uint32_t)fieldNumber { - for (GPBFieldDescriptor *descriptor in extensions_) { - if (GPBFieldNumber(descriptor) == fieldNumber) { - return descriptor; - } - } - return nil; -} - -- (GPBFieldDescriptor *)extensionWithName:(NSString *)name { - for (GPBFieldDescriptor *descriptor in extensions_) { - if ([descriptor.name isEqual:name]) { - return descriptor; - } - } - return nil; -} - @end @implementation GPBFileDescriptor { @@ -366,7 +341,7 @@ static NSArray *NewFieldsArrayForHasIndex(int hasIndex, } - (NSString *)name { - return [NSString stringWithUTF8String:oneofDescription_->name]; + return @(oneofDescription_->name); } - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber { @@ -455,7 +430,8 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { freeWhenDone:NO]; GPBExtensionRegistry *registry = [rootClass extensionRegistry]; fieldOptions_ = [[GPBFieldOptions parseFromData:optionsData - extensionRegistry:registry] retain]; + extensionRegistry:registry + error:NULL] retain]; } } @@ -532,7 +508,7 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } - (NSString *)name { - return [NSString stringWithUTF8String:description_->name]; + return @(description_->name); } - (BOOL)isRequired { @@ -809,7 +785,7 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { NSString *result = nil; // Naming adds an underscore between enum name and value name, skip that also. - NSString *shortName = [NSString stringWithUTF8String:valueDescriptor->name]; + NSString *shortName = @(valueDescriptor->name); // See if it is in the map of special format handling. if (extraTextFormatInfo_) { @@ -846,7 +822,7 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } - (NSString *)singletonName { - return [NSString stringWithUTF8String:description_->singletonName]; + return @(description_->singletonName); } - (const char *)singletonNameC { diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index acb4fe70..b289a48b 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -186,7 +186,6 @@ typedef struct GPBExtensionDescription { fields:(NSArray *)fields oneofs:(NSArray *)oneofs enums:(NSArray *)enums - extensions:(NSArray *)extensions extensionRanges:(const GPBExtensionRange *)ranges extensionRangesCount:(NSUInteger)rangeCount storageSize:(size_t)storage diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m index de7347e8..3769c697 100644 --- a/objectivec/GPBDictionary.m +++ b/objectivec/GPBDictionary.m @@ -45,8 +45,10 @@ // directly. // ------------------------------------------------------------------ -#define kMapKeyFieldNumber 1 -#define kMapValueFieldNumber 2 +enum { + kMapKeyFieldNumber = 1, + kMapValueFieldNumber = 2, +}; static BOOL DictDefault_IsValidValue(int32_t value) { // Anything but the bad value marker is allowed. @@ -55,58 +57,62 @@ static BOOL DictDefault_IsValidValue(int32_t value) { //%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBTYPE_NAME1, GPBTYPE_NAME2) //%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) { -//% NSCAssert((wireType == GPBType##GPBTYPE_NAME1) || (wireType == GPBType##GPBTYPE_NAME2), -//% @"bad type: %d", wireType); //% if (wireType == GPBType##GPBTYPE_NAME1) { //% return GPBCompute##GPBTYPE_NAME1##Size(fieldNum, value); -//% } else { // wireType == GPBType##GPBTYPE_NAME2 +//% } else if (wireType == GPBType##GPBTYPE_NAME2) { //% return GPBCompute##GPBTYPE_NAME2##Size(fieldNum, value); +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% return 0; //% } //%} //% //%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) { -//% NSCAssert((wireType == GPBType##GPBTYPE_NAME1) || (wireType == GPBType##GPBTYPE_NAME2), -//% @"bad type: %d", wireType); //% if (wireType == GPBType##GPBTYPE_NAME1) { //% [stream write##GPBTYPE_NAME1##:fieldNum value:value]; -//% } else { // wireType == GPBType##GPBTYPE_NAME2 +//% } else if (wireType == GPBType##GPBTYPE_NAME2) { //% [stream write##GPBTYPE_NAME2##:fieldNum value:value]; +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", wireType); //% } //%} //% //%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBTYPE_NAME1, GPBTYPE_NAME2, GPBTYPE_NAME3) //%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) { -//% NSCAssert((wireType == GPBType##GPBTYPE_NAME1) || (wireType == GPBType##GPBTYPE_NAME2) || (wireType == GPBType##GPBTYPE_NAME3), -//% @"bad type: %d", wireType); //% if (wireType == GPBType##GPBTYPE_NAME1) { //% return GPBCompute##GPBTYPE_NAME1##Size(fieldNum, value); //% } else if (wireType == GPBType##GPBTYPE_NAME2) { //% return GPBCompute##GPBTYPE_NAME2##Size(fieldNum, value); -//% } else { // wireType == GPBType##GPBTYPE_NAME3 +//% } else if (wireType == GPBType##GPBTYPE_NAME3) { //% return GPBCompute##GPBTYPE_NAME3##Size(fieldNum, value); +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% return 0; //% } //%} //% //%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) { -//% NSCAssert((wireType == GPBType##GPBTYPE_NAME1) || (wireType == GPBType##GPBTYPE_NAME2) || (wireType == GPBType##GPBTYPE_NAME3), -//% @"bad type: %d", wireType); //% if (wireType == GPBType##GPBTYPE_NAME1) { //% [stream write##GPBTYPE_NAME1##:fieldNum value:value]; //% } else if (wireType == GPBType##GPBTYPE_NAME2) { //% [stream write##GPBTYPE_NAME2##:fieldNum value:value]; -//% } else { // wireType == GPBType##GPBTYPE_NAME3 +//% } else if (wireType == GPBType##GPBTYPE_NAME3) { //% [stream write##GPBTYPE_NAME3##:fieldNum value:value]; +//% } else { +//% NSCAssert(NO, @"Unexpected type %d", wireType); //% } //%} //% //%PDDM-DEFINE SIMPLE_SERIALIZE_SUPPORT(VALUE_NAME, VALUE_TYPE, VisP) //%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBType wireType) { //% NSCAssert(wireType == GPBType##VALUE_NAME, @"bad type: %d", wireType); +//% #pragma unused(wireType) // For when asserts are off in release. //% return GPBCompute##VALUE_NAME##Size(fieldNum, value); //%} //% //%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBType wireType) { //% NSCAssert(wireType == GPBType##VALUE_NAME, @"bad type: %d", wireType); +//% #pragma unused(wireType) // For when asserts are off in release. //% [stream write##VALUE_NAME##:fieldNum value:value]; //%} //% @@ -125,171 +131,185 @@ static BOOL DictDefault_IsValidValue(int32_t value) { // This block of code is generated, do not edit it directly. GPB_INLINE size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeInt32) || (wireType == GPBTypeSInt32) || (wireType == GPBTypeSFixed32), - @"bad type: %d", wireType); if (wireType == GPBTypeInt32) { return GPBComputeInt32Size(fieldNum, value); } else if (wireType == GPBTypeSInt32) { return GPBComputeSInt32Size(fieldNum, value); - } else { // wireType == GPBTypeSFixed32 + } else if (wireType == GPBTypeSFixed32) { return GPBComputeSFixed32Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); + return 0; } } GPB_INLINE void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeInt32) || (wireType == GPBTypeSInt32) || (wireType == GPBTypeSFixed32), - @"bad type: %d", wireType); if (wireType == GPBTypeInt32) { [stream writeInt32:fieldNum value:value]; } else if (wireType == GPBTypeSInt32) { [stream writeSInt32:fieldNum value:value]; - } else { // wireType == GPBTypeSFixed32 + } else if (wireType == GPBTypeSFixed32) { [stream writeSFixed32:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); } } GPB_INLINE size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeUInt32) || (wireType == GPBTypeFixed32), - @"bad type: %d", wireType); if (wireType == GPBTypeUInt32) { return GPBComputeUInt32Size(fieldNum, value); - } else { // wireType == GPBTypeFixed32 + } else if (wireType == GPBTypeFixed32) { return GPBComputeFixed32Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); + return 0; } } GPB_INLINE void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeUInt32) || (wireType == GPBTypeFixed32), - @"bad type: %d", wireType); if (wireType == GPBTypeUInt32) { [stream writeUInt32:fieldNum value:value]; - } else { // wireType == GPBTypeFixed32 + } else if (wireType == GPBTypeFixed32) { [stream writeFixed32:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); } } GPB_INLINE size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeInt64) || (wireType == GPBTypeSInt64) || (wireType == GPBTypeSFixed64), - @"bad type: %d", wireType); if (wireType == GPBTypeInt64) { return GPBComputeInt64Size(fieldNum, value); } else if (wireType == GPBTypeSInt64) { return GPBComputeSInt64Size(fieldNum, value); - } else { // wireType == GPBTypeSFixed64 + } else if (wireType == GPBTypeSFixed64) { return GPBComputeSFixed64Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); + return 0; } } GPB_INLINE void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeInt64) || (wireType == GPBTypeSInt64) || (wireType == GPBTypeSFixed64), - @"bad type: %d", wireType); if (wireType == GPBTypeInt64) { [stream writeInt64:fieldNum value:value]; } else if (wireType == GPBTypeSInt64) { [stream writeSInt64:fieldNum value:value]; - } else { // wireType == GPBTypeSFixed64 + } else if (wireType == GPBTypeSFixed64) { [stream writeSFixed64:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); } } GPB_INLINE size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeUInt64) || (wireType == GPBTypeFixed64), - @"bad type: %d", wireType); if (wireType == GPBTypeUInt64) { return GPBComputeUInt64Size(fieldNum, value); - } else { // wireType == GPBTypeFixed64 + } else if (wireType == GPBTypeFixed64) { return GPBComputeFixed64Size(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); + return 0; } } GPB_INLINE void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeUInt64) || (wireType == GPBTypeFixed64), - @"bad type: %d", wireType); if (wireType == GPBTypeUInt64) { [stream writeUInt64:fieldNum value:value]; - } else { // wireType == GPBTypeFixed64 + } else if (wireType == GPBTypeFixed64) { [stream writeFixed64:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); } } GPB_INLINE size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. return GPBComputeBoolSize(fieldNum, value); } GPB_INLINE void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. [stream writeBool:fieldNum value:value]; } GPB_INLINE size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeEnum, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. return GPBComputeEnumSize(fieldNum, value); } GPB_INLINE void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeEnum, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. [stream writeEnum:fieldNum value:value]; } GPB_INLINE size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. return GPBComputeFloatSize(fieldNum, value); } GPB_INLINE void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. [stream writeFloat:fieldNum value:value]; } GPB_INLINE size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. return GPBComputeDoubleSize(fieldNum, value); } GPB_INLINE void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. [stream writeDouble:fieldNum value:value]; } GPB_INLINE size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. return GPBComputeStringSize(fieldNum, value); } GPB_INLINE void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBType wireType) { NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType); + #pragma unused(wireType) // For when asserts are off in release. [stream writeString:fieldNum value:value]; } GPB_INLINE size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeMessage) || (wireType == GPBTypeString) || (wireType == GPBTypeData), - @"bad type: %d", wireType); if (wireType == GPBTypeMessage) { return GPBComputeMessageSize(fieldNum, value); } else if (wireType == GPBTypeString) { return GPBComputeStringSize(fieldNum, value); - } else { // wireType == GPBTypeData + } else if (wireType == GPBTypeData) { return GPBComputeDataSize(fieldNum, value); + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); + return 0; } } GPB_INLINE void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBType wireType) { - NSCAssert((wireType == GPBTypeMessage) || (wireType == GPBTypeString) || (wireType == GPBTypeData), - @"bad type: %d", wireType); if (wireType == GPBTypeMessage) { [stream writeMessage:fieldNum value:value]; } else if (wireType == GPBTypeString) { [stream writeString:fieldNum value:value]; - } else { // wireType == GPBTypeData + } else if (wireType == GPBTypeData) { [stream writeData:fieldNum value:value]; + } else { + NSCAssert(NO, @"Unexpected type %d", wireType); } } //%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS() size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { - NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type"); GPBType mapValueType = GPBGetFieldType(field); __block size_t result = 0; [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { @@ -319,7 +339,7 @@ void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream // Write the size and fields. [outputStream writeInt32NoTag:(int32_t)msgSize]; - [outputStream writeString:kMapValueFieldNumber value:obj]; + [outputStream writeString:kMapKeyFieldNumber value:key]; WriteDictObjectField(outputStream, obj, kMapValueFieldNumber, mapValueType); }]; } @@ -327,6 +347,7 @@ void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type"); NSCAssert(GPBGetFieldType(field) == GPBTypeMessage, @"Unexpected value type"); + #pragma unused(field) // For when asserts are off in release. for (GPBMessage *msg in [dict objectEnumerator]) { if (!msg.initialized) { return NO; @@ -488,8 +509,12 @@ void GPBDictionaryReadEntry(id mapDictionary, } } - if (GPBTypeIsObject(keyType)) [key.valueString release]; - if (GPBTypeIsObject(valueType)) [value.valueString release]; + if (GPBTypeIsObject(keyType)) { + [key.valueString release]; + } + if (GPBTypeIsObject(valueType)) { + [value.valueString release]; + } } // @@ -751,6 +776,9 @@ void GPBDictionaryReadEntry(id mapDictionary, //% } //% //% [_dictionary setObject:WRAPPED##VHELPER(value) forKey:WRAPPED##KHELPER(key)]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } //%} //% //%@end @@ -758,6 +786,9 @@ void GPBDictionaryReadEntry(id mapDictionary, //%PDDM-DEFINE DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, ACCESSOR_NAME) //%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); //% [_dictionary release]; //% [super dealloc]; //%} @@ -854,11 +885,17 @@ void GPBDictionaryReadEntry(id mapDictionary, //%- (void)add##ACCESSOR_NAME##EntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary { //% if (otherDictionary) { //% [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } //% } //%} //% //%- (void)set##ACCESSOR_NAME##Value:(VALUE_TYPE)value forKey:(KEY_TYPE##KisP$S##KisP)key { //% [_dictionary setObject:WRAPPED##VHELPER(value) forKey:WRAPPED##KHELPER(key)]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } //%} //% //%- (void)removeValueForKey:(KEY_TYPE##KisP$S##KisP)aKey { @@ -930,7 +967,9 @@ void GPBDictionaryReadEntry(id mapDictionary, //% return [self initWithValues:NULL forKeys:NULL count:0]; //%} //% -//%BOOL_DICT_DEALLOC##HELPER()- (instancetype)copyWithZone:(NSZone *)zone { +//%BOOL_DICT_DEALLOC##HELPER() +//% +//%- (instancetype)copyWithZone:(NSZone *)zone { //% return [[GPBBool##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self]; //%} //% @@ -1158,7 +1197,14 @@ void GPBDictionaryReadEntry(id mapDictionary, //% return self; //%} //%PDDM-DEFINE BOOL_DICT_DEALLOCPOD() -// Empty +//%#if !defined(NS_BLOCK_ASSERTIONS) +//%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); +//% [super dealloc]; +//%} +//%#endif // !defined(NS_BLOCK_ASSERTIONS) //%PDDM-DEFINE BOOL_DICT_W_HASPOD(IDX, REF) //%BOOL_DICT_HASPOD(IDX, REF) //%PDDM-DEFINE BOOL_DICT_HASPOD(IDX, REF) @@ -1189,6 +1235,9 @@ void GPBDictionaryReadEntry(id mapDictionary, //% _values[i] = otherDictionary->_values[i]; //% } //% } +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } //% } //%} //% @@ -1196,6 +1245,9 @@ void GPBDictionaryReadEntry(id mapDictionary, //% int idx = (key ? 1 : 0); //% _values[idx] = value; //% _valueSet[idx] = YES; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } //%} //% //%- (void)removeValueForKey:(BOOL)aKey { @@ -1333,12 +1385,13 @@ void GPBDictionaryReadEntry(id mapDictionary, //%} //%PDDM-DEFINE BOOL_DICT_DEALLOCOBJECT() //%- (void)dealloc { +//% NSAssert(!_autocreator, +//% @"%@: Autocreator must be cleared before release, autocreator: %@", +//% [self class], _autocreator); //% [_values[0] release]; //% [_values[1] release]; //% [super dealloc]; //%} -//% -//% //%PDDM-DEFINE BOOL_DICT_W_HASOBJECT(IDX, REF) //%(BOOL_DICT_HASOBJECT(IDX, REF)) //%PDDM-DEFINE BOOL_DICT_HASOBJECT(IDX, REF) @@ -1363,6 +1416,9 @@ void GPBDictionaryReadEntry(id mapDictionary, //% _values[i] = [otherDictionary->_values[i] retain]; //% } //% } +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } //% } //%} //% @@ -1370,6 +1426,9 @@ void GPBDictionaryReadEntry(id mapDictionary, //% int idx = (key ? 1 : 0); //% [_values[idx] release]; //% _values[idx] = [value retain]; +//% if (_autocreator) { +//% GPBAutocreatedDictionaryModified(_autocreator, self); +//% } //%} //% //%- (void)removeValueForKey:(BOOL)aKey { @@ -1466,6 +1525,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -1570,11 +1632,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint32_t)value forKey:(uint32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -1662,6 +1730,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -1766,11 +1837,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int32_t)value forKey:(uint32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -1858,6 +1935,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -1962,11 +2042,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint64_t)value forKey:(uint32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -2054,6 +2140,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -2158,11 +2247,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int64_t)value forKey:(uint32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -2250,6 +2345,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -2354,11 +2452,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(BOOL)value forKey:(uint32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -2446,6 +2550,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -2550,11 +2657,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(float)value forKey:(uint32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -2642,6 +2755,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -2746,11 +2862,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(double)value forKey:(uint32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -2866,6 +2988,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -3008,11 +3133,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setRawValue:(int32_t)value forKey:(uint32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -3031,6 +3162,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } @end @@ -3110,6 +3244,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -3234,11 +3371,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(id)value forKey:(uint32_t)key { [_dictionary setObject:value forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint32_t)aKey { @@ -3329,6 +3472,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -3433,11 +3579,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint32_t)value forKey:(int32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -3525,6 +3677,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -3629,11 +3784,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int32_t)value forKey:(int32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -3721,6 +3882,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -3825,11 +3989,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint64_t)value forKey:(int32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -3917,6 +4087,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -4021,11 +4194,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int64_t)value forKey:(int32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -4113,6 +4292,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -4217,11 +4399,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(BOOL)value forKey:(int32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -4309,6 +4497,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -4413,11 +4604,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(float)value forKey:(int32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -4505,6 +4702,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -4609,11 +4809,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(double)value forKey:(int32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -4729,6 +4935,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -4871,11 +5080,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setRawValue:(int32_t)value forKey:(int32_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -4894,6 +5109,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } @end @@ -4973,6 +5191,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -5097,11 +5318,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(id)value forKey:(int32_t)key { [_dictionary setObject:value forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int32_t)aKey { @@ -5192,6 +5419,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -5296,11 +5526,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint32_t)value forKey:(uint64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -5388,6 +5624,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -5492,11 +5731,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int32_t)value forKey:(uint64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -5584,6 +5829,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -5688,11 +5936,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint64_t)value forKey:(uint64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -5780,6 +6034,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -5884,11 +6141,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int64_t)value forKey:(uint64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -5976,6 +6239,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -6080,11 +6346,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(BOOL)value forKey:(uint64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -6172,6 +6444,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -6276,11 +6551,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(float)value forKey:(uint64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -6368,6 +6649,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -6472,11 +6756,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(double)value forKey:(uint64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -6592,6 +6882,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -6734,11 +7027,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setRawValue:(int32_t)value forKey:(uint64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -6757,6 +7056,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } @end @@ -6836,6 +7138,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -6960,11 +7265,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(id)value forKey:(uint64_t)key { [_dictionary setObject:value forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(uint64_t)aKey { @@ -7055,6 +7366,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -7159,11 +7473,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint32_t)value forKey:(int64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -7251,6 +7571,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -7355,11 +7678,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int32_t)value forKey:(int64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -7447,6 +7776,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -7551,11 +7883,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint64_t)value forKey:(int64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -7643,6 +7981,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -7747,11 +8088,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int64_t)value forKey:(int64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -7839,6 +8186,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -7943,11 +8293,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(BOOL)value forKey:(int64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -8035,6 +8391,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -8139,11 +8498,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(float)value forKey:(int64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -8231,6 +8596,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -8335,11 +8703,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(double)value forKey:(int64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -8455,6 +8829,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -8597,11 +8974,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setRawValue:(int32_t)value forKey:(int64_t)key { [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -8620,6 +9003,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } [_dictionary setObject:@(value) forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } @end @@ -8699,6 +9085,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -8823,11 +9212,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(id)value forKey:(int64_t)key { [_dictionary setObject:value forKey:@(key)]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(int64_t)aKey { @@ -8918,6 +9313,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -9022,11 +9420,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint32_t)value forKey:(NSString *)key { [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(NSString *)aKey { @@ -9114,6 +9518,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -9218,11 +9625,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int32_t)value forKey:(NSString *)key { [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(NSString *)aKey { @@ -9310,6 +9723,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -9414,11 +9830,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(uint64_t)value forKey:(NSString *)key { [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(NSString *)aKey { @@ -9506,6 +9928,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -9610,11 +10035,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(int64_t)value forKey:(NSString *)key { [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(NSString *)aKey { @@ -9702,6 +10133,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -9806,11 +10240,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(BOOL)value forKey:(NSString *)key { [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(NSString *)aKey { @@ -9898,6 +10338,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -10002,11 +10445,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(float)value forKey:(NSString *)key { [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(NSString *)aKey { @@ -10094,6 +10543,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -10198,11 +10650,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setValue:(double)value forKey:(NSString *)key { [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(NSString *)aKey { @@ -10318,6 +10776,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_dictionary release]; [super dealloc]; } @@ -10460,11 +10921,17 @@ void GPBDictionaryReadEntry(id mapDictionary, - (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary { if (otherDictionary) { [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } - (void)setRawValue:(int32_t)value forKey:(NSString *)key { [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(NSString *)aKey { @@ -10483,6 +10950,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } [_dictionary setObject:@(value) forKey:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } @end @@ -10572,6 +11042,15 @@ void GPBDictionaryReadEntry(id mapDictionary, return [self initWithValues:NULL forKeys:NULL count:0]; } +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + - (instancetype)copyWithZone:(NSZone *)zone { return [[GPBBoolUInt32Dictionary allocWithZone:zone] initWithDictionary:self]; } @@ -10695,6 +11174,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = otherDictionary->_values[i]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -10702,6 +11184,9 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); _values[idx] = value; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -10797,6 +11282,15 @@ void GPBDictionaryReadEntry(id mapDictionary, return [self initWithValues:NULL forKeys:NULL count:0]; } +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + - (instancetype)copyWithZone:(NSZone *)zone { return [[GPBBoolInt32Dictionary allocWithZone:zone] initWithDictionary:self]; } @@ -10920,6 +11414,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = otherDictionary->_values[i]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -10927,6 +11424,9 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); _values[idx] = value; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -11022,6 +11522,15 @@ void GPBDictionaryReadEntry(id mapDictionary, return [self initWithValues:NULL forKeys:NULL count:0]; } +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + - (instancetype)copyWithZone:(NSZone *)zone { return [[GPBBoolUInt64Dictionary allocWithZone:zone] initWithDictionary:self]; } @@ -11145,6 +11654,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = otherDictionary->_values[i]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -11152,6 +11664,9 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); _values[idx] = value; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -11247,6 +11762,15 @@ void GPBDictionaryReadEntry(id mapDictionary, return [self initWithValues:NULL forKeys:NULL count:0]; } +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + - (instancetype)copyWithZone:(NSZone *)zone { return [[GPBBoolInt64Dictionary allocWithZone:zone] initWithDictionary:self]; } @@ -11370,6 +11894,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = otherDictionary->_values[i]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -11377,6 +11904,9 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); _values[idx] = value; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -11472,6 +12002,15 @@ void GPBDictionaryReadEntry(id mapDictionary, return [self initWithValues:NULL forKeys:NULL count:0]; } +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + - (instancetype)copyWithZone:(NSZone *)zone { return [[GPBBoolBoolDictionary allocWithZone:zone] initWithDictionary:self]; } @@ -11595,6 +12134,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = otherDictionary->_values[i]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -11602,6 +12144,9 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); _values[idx] = value; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -11697,6 +12242,15 @@ void GPBDictionaryReadEntry(id mapDictionary, return [self initWithValues:NULL forKeys:NULL count:0]; } +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + - (instancetype)copyWithZone:(NSZone *)zone { return [[GPBBoolFloatDictionary allocWithZone:zone] initWithDictionary:self]; } @@ -11820,6 +12374,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = otherDictionary->_values[i]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -11827,6 +12384,9 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); _values[idx] = value; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -11922,6 +12482,15 @@ void GPBDictionaryReadEntry(id mapDictionary, return [self initWithValues:NULL forKeys:NULL count:0]; } +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + - (instancetype)copyWithZone:(NSZone *)zone { return [[GPBBoolDoubleDictionary allocWithZone:zone] initWithDictionary:self]; } @@ -12045,6 +12614,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = otherDictionary->_values[i]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -12052,6 +12624,9 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); _values[idx] = value; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -12143,6 +12718,9 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); [_values[0] release]; [_values[1] release]; [super dealloc]; @@ -12285,6 +12863,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = [otherDictionary->_values[i] retain]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -12292,6 +12873,9 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); [_values[idx] release]; _values[idx] = [value retain]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -12418,6 +13002,15 @@ void GPBDictionaryReadEntry(id mapDictionary, return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0]; } +#if !defined(NS_BLOCK_ASSERTIONS) +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [super dealloc]; +} +#endif // !defined(NS_BLOCK_ASSERTIONS) + - (instancetype)copyWithZone:(NSZone *)zone { return [[GPBBoolEnumDictionary allocWithZone:zone] initWithDictionary:self]; } @@ -12595,6 +13188,9 @@ void GPBDictionaryReadEntry(id mapDictionary, _values[i] = otherDictionary->_values[i]; } } + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } } @@ -12607,12 +13203,18 @@ void GPBDictionaryReadEntry(id mapDictionary, int idx = (key ? 1 : 0); _values[idx] = value; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key { int idx = (key ? 1 : 0); _values[idx] = rawValue; _valueSet[idx] = YES; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } } - (void)removeValueForKey:(BOOL)aKey { @@ -12625,3 +13227,110 @@ void GPBDictionaryReadEntry(id mapDictionary, } @end + +#pragma mark - NSDictionary Subclass + +@implementation GPBAutocreatedDictionary { + NSMutableDictionary *_dictionary; +} + +- (void)dealloc { + NSAssert(!_autocreator, + @"%@: Autocreator must be cleared before release, autocreator: %@", + [self class], _autocreator); + [_dictionary release]; + [super dealloc]; +} + +#pragma mark Required NSDictionary overrides + +- (instancetype)initWithObjects:(const id [])objects + forKeys:(const id [])keys + count:(NSUInteger)count { + self = [super init]; + if (self) { + _dictionary = [[NSMutableDictionary alloc] initWithObjects:objects + forKeys:keys + count:count]; + } + return self; +} + +- (NSUInteger)count { + return [_dictionary count]; +} + +- (id)objectForKey:(id)aKey { + return [_dictionary objectForKey:aKey]; +} + +- (NSEnumerator *)keyEnumerator { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + return [_dictionary keyEnumerator]; +} + +#pragma mark Required NSMutableDictionary overrides + +// Only need to call GPBAutocreatedDictionaryModified() when adding things +// since we only autocreate empty dictionaries. + +- (void)setObject:(id)anObject forKey:(id)aKey { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + [_dictionary setObject:anObject forKey:aKey]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)removeObjectForKey:(id)aKey { + [_dictionary removeObjectForKey:aKey]; +} + +#pragma mark Extra things hooked + +- (id)copyWithZone:(NSZone *)zone { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + return [_dictionary copyWithZone:zone]; +} + +- (id)mutableCopyWithZone:(NSZone *)zone { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + return [_dictionary mutableCopyWithZone:zone]; +} + +- (id)objectForKeyedSubscript:(id)key { + return [_dictionary objectForKeyedSubscript:key]; +} + +- (void)setObject:(id)obj forKeyedSubscript:(id)key { + if (_dictionary == nil) { + _dictionary = [[NSMutableDictionary alloc] init]; + } + [_dictionary setObject:obj forKeyedSubscript:key]; + if (_autocreator) { + GPBAutocreatedDictionaryModified(_autocreator, self); + } +} + +- (void)enumerateKeysAndObjectsUsingBlock:(void (^)(id key, + id obj, + BOOL *stop))block { + [_dictionary enumerateKeysAndObjectsUsingBlock:block]; +} + +- (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts + usingBlock:(void (^)(id key, + id obj, + BOOL *stop))block { + [_dictionary enumerateKeysAndObjectsWithOptions:opts usingBlock:block]; +} + +@end diff --git a/objectivec/GPBDictionary_PackagePrivate.h b/objectivec/GPBDictionary_PackagePrivate.h index 54b37dd8..9c3c5915 100644 --- a/objectivec/GPBDictionary_PackagePrivate.h +++ b/objectivec/GPBDictionary_PackagePrivate.h @@ -37,6 +37,14 @@ @class GPBExtensionRegistry; @class GPBFieldDescriptor; +@protocol GPBDictionaryInternalsProtocol +- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; +- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream + asField:(GPBFieldDescriptor *)field; +- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; +- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@end + //%PDDM-DEFINE DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(KEY_NAME) //%DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME) //%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Object, Object) @@ -51,12 +59,10 @@ //%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Enum, Enum) //%PDDM-DEFINE DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, VALUE_NAME, HELPER) -//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary () -//%- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream -//% asField:(GPBFieldDescriptor *)field; -//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -//%- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary () { +//% @package +//% GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +//%} //%EXTRA_DICTIONARY_PRIVATE_INTERFACES_##HELPER()@end //% @@ -76,79 +82,61 @@ //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32) // This block of code is generated, do not edit it directly. -@interface GPBUInt32UInt32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt32Int32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt32UInt64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt32Int64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt32BoolDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt32FloatDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt32DoubleDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt32EnumDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (NSData *)serializedDataForUnknownValue:(int32_t)value forKey:(GPBValue *)key keyType:(GPBType)keyType; @end -@interface GPBUInt32ObjectDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt32ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (BOOL)isInitialized; - (instancetype)deepCopyWithZone:(NSZone *)zone __attribute__((ns_returns_retained)); @@ -157,79 +145,61 @@ //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int32) // This block of code is generated, do not edit it directly. -@interface GPBInt32UInt32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt32Int32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt32UInt64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt32Int64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt32BoolDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt32FloatDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt32DoubleDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt32EnumDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (NSData *)serializedDataForUnknownValue:(int32_t)value forKey:(GPBValue *)key keyType:(GPBType)keyType; @end -@interface GPBInt32ObjectDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt32ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (BOOL)isInitialized; - (instancetype)deepCopyWithZone:(NSZone *)zone __attribute__((ns_returns_retained)); @@ -238,79 +208,61 @@ //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt64) // This block of code is generated, do not edit it directly. -@interface GPBUInt64UInt32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt64Int32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt64UInt64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt64Int64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt64BoolDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt64FloatDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt64DoubleDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBUInt64EnumDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (NSData *)serializedDataForUnknownValue:(int32_t)value forKey:(GPBValue *)key keyType:(GPBType)keyType; @end -@interface GPBUInt64ObjectDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBUInt64ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (BOOL)isInitialized; - (instancetype)deepCopyWithZone:(NSZone *)zone __attribute__((ns_returns_retained)); @@ -319,79 +271,61 @@ //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int64) // This block of code is generated, do not edit it directly. -@interface GPBInt64UInt32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64UInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt64Int32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64Int32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt64UInt64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64UInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt64Int64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64Int64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt64BoolDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64BoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt64FloatDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64FloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt64DoubleDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64DoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBInt64EnumDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64EnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (NSData *)serializedDataForUnknownValue:(int32_t)value forKey:(GPBValue *)key keyType:(GPBType)keyType; @end -@interface GPBInt64ObjectDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBInt64ObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (BOOL)isInitialized; - (instancetype)deepCopyWithZone:(NSZone *)zone __attribute__((ns_returns_retained)); @@ -400,79 +334,61 @@ //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Bool) // This block of code is generated, do not edit it directly. -@interface GPBBoolUInt32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolUInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBBoolInt32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBBoolUInt64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolUInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBBoolInt64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBBoolBoolDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolBoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBBoolFloatDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolFloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBBoolDoubleDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolDoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBBoolEnumDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolEnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (NSData *)serializedDataForUnknownValue:(int32_t)value forKey:(GPBValue *)key keyType:(GPBType)keyType; @end -@interface GPBBoolObjectDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBBoolObjectDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (BOOL)isInitialized; - (instancetype)deepCopyWithZone:(NSZone *)zone __attribute__((ns_returns_retained)); @@ -481,68 +397,52 @@ //%PDDM-EXPAND DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(String) // This block of code is generated, do not edit it directly. -@interface GPBStringUInt32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBStringUInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBStringInt32Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBStringInt32Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBStringUInt64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBStringUInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBStringInt64Dictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBStringInt64Dictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBStringBoolDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBStringBoolDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBStringFloatDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBStringFloatDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBStringDoubleDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBStringDoubleDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} @end -@interface GPBStringEnumDictionary () -- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; -- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream - asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; -- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; +@interface GPBStringEnumDictionary () { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} - (NSData *)serializedDataForUnknownValue:(int32_t)value forKey:(GPBValue *)key keyType:(GPBType)keyType; @@ -550,6 +450,16 @@ //%PDDM-EXPAND-END (6 expansions) +#pragma mark - NSDictionary Subclass + +@interface GPBAutocreatedDictionary : NSMutableDictionary { + @package + GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; +} +@end + +#pragma mark - Helpers + CF_EXTERN_C_BEGIN // Helper to compute size when an NSDictionary is used for the map instead diff --git a/objectivec/GPBExtensionRegistry.h b/objectivec/GPBExtensionRegistry.h index ce1f8fab..e382971c 100644 --- a/objectivec/GPBExtensionRegistry.h +++ b/objectivec/GPBExtensionRegistry.h @@ -38,7 +38,24 @@ // ExtensionRegistry in which you have registered any extensions that you want // to be able to parse. Otherwise, those extensions will just be treated like // unknown fields. -@interface GPBExtensionRegistry : NSObject +// +// The *Root classes provide +extensionRegistry for the extensions defined in a +// given file *and* all files it imports. You can also create a +// GPBExtensionRegistry, and merge those registries to handle parsing extensions +// defined from non overlapping files. +// +// GPBExtensionRegistry *registry = +// [[[MyProtoFileRoot extensionRegistry] copy] autorelease]; +// [registry addExtension:[OtherMessage neededExtension]; // Not in MyProtoFile +// NSError *parseError = nil; +// MyMessage *msg = [MyMessage parseData:data +// extensionRegistry:registry +// error:&parseError]; +// +@interface GPBExtensionRegistry : NSObject + +- (void)addExtension:(GPBExtensionField *)extension; +- (void)addExtensions:(GPBExtensionRegistry *)registry; - (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType fieldNumber:(NSInteger)fieldNumber; diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m index a191dace..4f234f55 100644 --- a/objectivec/GPBExtensionRegistry.m +++ b/objectivec/GPBExtensionRegistry.m @@ -28,7 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#import "GPBExtensionRegistry_PackagePrivate.h" +#import "GPBExtensionRegistry.h" #import "GPBBootstrap.h" #import "GPBDescriptor.h" @@ -52,6 +52,14 @@ [super dealloc]; } +- (instancetype)copyWithZone:(NSZone *)zone { + GPBExtensionRegistry *result = [[[self class] allocWithZone:zone] init]; + if (result && mutableClassMap_.count) { + [result->mutableClassMap_ addEntriesFromDictionary:mutableClassMap_]; + } + return result; +} + - (NSMutableDictionary *)extensionMapForContainingType: (GPBDescriptor *)containingType { NSMutableDictionary *extensionMap = diff --git a/objectivec/GPBExtensionRegistry_PackagePrivate.h b/objectivec/GPBExtensionRegistry_PackagePrivate.h deleted file mode 100644 index 968cb1fd..00000000 --- a/objectivec/GPBExtensionRegistry_PackagePrivate.h +++ /dev/null @@ -1,40 +0,0 @@ -// 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. - -#import - -#import "GPBExtensionRegistry.h" - -@interface GPBExtensionRegistry () - -- (void)addExtension:(GPBExtensionField *)extension; -- (void)addExtensions:(GPBExtensionRegistry *)registry; - -@end diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h index 2483f5d3..1c6c091d 100644 --- a/objectivec/GPBMessage.h +++ b/objectivec/GPBMessage.h @@ -28,15 +28,28 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#import "GPBRootObject.h" +#import + +#import "GPBBootstrap.h" @class GPBDescriptor; @class GPBCodedInputStream; @class GPBCodedOutputStream; @class GPBExtensionField; +@class GPBExtensionRegistry; @class GPBFieldDescriptor; @class GPBUnknownFieldSet; +CF_EXTERN_C_BEGIN + +// NSError domain used for errors. +extern NSString *const GPBMessageErrorDomain; + +typedef NS_ENUM(NSInteger, GPBMessageErrorCode) { + GPBMessageErrorCodeMalformedData = -100, + GPBMessageErrorCodeMissingRequiredField = -101, +}; + // In DEBUG ONLY, an NSException is thrown when a parsed message doesn't // contain required fields. This key allows you to retrieve the parsed message // from the exception's |userInfo| dictionary. @@ -44,12 +57,14 @@ extern NSString *const GPBExceptionMessageKey; #endif // DEBUG -// NOTE: -// If you add a instance method/property to this class that may conflict with -// methods declared in protos, you need to update objective_helpers.cc. +CF_EXTERN_C_END + +@interface GPBMessage : NSObject + +// NOTE: If you add a instance method/property to this class that may conflict +// with methods declared in protos, you need to update objective_helpers.cc. // The main cases are methods that take no arguments, or setFoo:/hasFoo: type // methods. -@interface GPBMessage : GPBRootObject @property(nonatomic, readonly) GPBUnknownFieldSet *unknownFields; @@ -59,29 +74,38 @@ extern NSString *const GPBExceptionMessageKey; // Returns an autoreleased instance. + (instancetype)message; -// Create a message based on a variety of inputs. -// In DEBUG ONLY -// @throws NSInternalInconsistencyException The message is missing one or more -// required fields (i.e. -[isInitialized] returns false). Use -// GGPBExceptionMessageKey to retrieve the message from |userInfo|. -+ (instancetype)parseFromData:(NSData *)data; +// Create a message based on a variety of inputs. If there is a data parse +// error, nil is returned and if not NULL, errorPtr is filled in. +// NOTE: In DEBUG ONLY, the message is also checked for all required field, +// if one is missing, the parse will fail (returning nil, filling in errorPtr). ++ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr; + (instancetype)parseFromData:(NSData *)data - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input extensionRegistry: - (GPBExtensionRegistry *)extensionRegistry; + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; -// Create a message based on delimited input. +// Create a message based on delimited input. If there is a data parse +// error, nil is returned and if not NULL, errorPtr is filled in. + (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input extensionRegistry: - (GPBExtensionRegistry *)extensionRegistry; - -- (instancetype)initWithData:(NSData *)data; + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; + +// If there is a data parse error, nil is returned and if not NULL, errorPtr is +// filled in. +// NOTE: In DEBUG ONLY, the message is also checked for all required field, +// if one is missing, the parse will fail (returning nil, filling in errorPtr). +- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr; - (instancetype)initWithData:(NSData *)data - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; - (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input extensionRegistry: - (GPBExtensionRegistry *)extensionRegistry; + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr; // Serializes the message and writes it to output. - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output; @@ -93,11 +117,10 @@ extern NSString *const GPBExceptionMessageKey; - (void)writeDelimitedToOutputStream:(NSOutputStream *)output; // Serializes the message to an NSData. Note that this value is not cached, so -// if you are using it repeatedly, cache it yourself. -// In DEBUG ONLY: -// @throws NSInternalInconsistencyException The message is missing one or more -// required fields (i.e. -[isInitialized] returns false). Use -// GPBExceptionMessageKey to retrieve the message from |userInfo|. +// if you are using it repeatedly, cache it yourself. If there is an error +// while generating the data, nil is returned. +// NOTE: In DEBUG ONLY, the message is also checked for all required field, +// if one is missing, nil will be returned. - (NSData *)data; // Same as -[data], except a delimiter is added to the start of the data @@ -106,16 +129,16 @@ extern NSString *const GPBExceptionMessageKey; // Returns the size of the object if it were serialized. // This is not a cached value. If you are following a pattern like this: -// size_t size = [aMsg serializedSize]; -// NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)]; -// [foo writeSize:size]; -// [foo appendData:[aMsg data]]; +// size_t size = [aMsg serializedSize]; +// NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)]; +// [foo writeSize:size]; +// [foo appendData:[aMsg data]]; // you would be better doing: -// NSData *data = [aMsg data]; -// NSUInteger size = [aMsg length]; -// NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)]; -// [foo writeSize:size]; -// [foo appendData:data]; +// NSData *data = [aMsg data]; +// NSUInteger size = [aMsg length]; +// NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)]; +// [foo writeSize:size]; +// [foo appendData:data]; - (size_t)serializedSize; // Return the descriptor for the message @@ -123,8 +146,8 @@ extern NSString *const GPBExceptionMessageKey; - (GPBDescriptor *)descriptor; // Extensions use boxed values (NSNumbers) for PODs, NSMutableArrays for -// repeated. If the extension is a Message, just like fields, one will be -// auto created for you and returned. +// repeated. If the extension is a Message one will be auto created for you +// and returned similar to fields. - (BOOL)hasExtension:(GPBExtensionField *)extension; - (id)getExtension:(GPBExtensionField *)extension; - (void)setExtension:(GPBExtensionField *)extension value:(id)value; @@ -141,6 +164,7 @@ extern NSString *const GPBExceptionMessageKey; // Parses a message of this type from the input and merges it with this // message. +// NOTE: This will throw if there is an error parsing the data. - (void)mergeFromData:(NSData *)data extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index 63ffc3bc..bd3235f1 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -39,15 +39,21 @@ #import "GPBDescriptor_PackagePrivate.h" #import "GPBDictionary_PackagePrivate.h" #import "GPBExtensionField_PackagePrivate.h" -#import "GPBExtensionRegistry_PackagePrivate.h" +#import "GPBExtensionRegistry.h" +#import "GPBRootObject_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h" #import "GPBUtilities_PackagePrivate.h" +NSString *const GPBMessageErrorDomain = + GPBNSStringifySymbol(GPBMessageErrorDomain); + #ifdef DEBUG NSString *const GPBExceptionMessageKey = GPBNSStringifySymbol(GPBExceptionMessage); #endif // DEBUG +static NSString *const kGPBDataCoderKey = @"GPBData"; + // // PLEASE REMEMBER: // @@ -78,13 +84,32 @@ static id GetOrCreateArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax); static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); +static id CreateMapForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) + __attribute__((ns_returns_retained)); static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax); +static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone) __attribute__((ns_returns_retained)); +static NSError *MessageError(NSInteger code, NSDictionary *userInfo) { + return [NSError errorWithDomain:GPBMessageErrorDomain + code:code + userInfo:userInfo]; +} + +static NSError *MessageErrorWithReason(NSInteger code, NSString *reason) { + NSDictionary *userInfo = nil; + if ([reason length]) { + userInfo = @{ @"Reason" : reason }; + } + return MessageError(code, userInfo); +} + + static void CheckExtension(GPBMessage *self, GPBExtensionField *extension) { if ([[self class] descriptor] != [extension containingType]) { [NSException @@ -201,6 +226,303 @@ static id CreateArrayForField(GPBFieldDescriptor *field, return result; } +static id CreateMapForField(GPBFieldDescriptor *field, + GPBMessage *autocreator) { + id result; + GPBType keyType = field.mapKeyType; + GPBType valueType = GPBGetFieldType(field); + switch (keyType) { + case GPBTypeBool: + switch (valueType) { + case GPBTypeBool: + result = [[GPBBoolBoolDictionary alloc] init]; + break; + case GPBTypeFixed32: + case GPBTypeUInt32: + result = [[GPBBoolUInt32Dictionary alloc] init]; + break; + case GPBTypeInt32: + case GPBTypeSFixed32: + case GPBTypeSInt32: + result = [[GPBBoolInt32Dictionary alloc] init]; + break; + case GPBTypeFixed64: + case GPBTypeUInt64: + result = [[GPBBoolUInt64Dictionary alloc] init]; + break; + case GPBTypeInt64: + case GPBTypeSFixed64: + case GPBTypeSInt64: + result = [[GPBBoolInt64Dictionary alloc] init]; + break; + case GPBTypeFloat: + result = [[GPBBoolFloatDictionary alloc] init]; + break; + case GPBTypeDouble: + result = [[GPBBoolDoubleDictionary alloc] init]; + break; + case GPBTypeEnum: + result = [[GPBBoolEnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBTypeData: + case GPBTypeMessage: + case GPBTypeString: + result = [[GPBBoolObjectDictionary alloc] init]; + break; + case GPBTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBTypeFixed32: + case GPBTypeUInt32: + switch (valueType) { + case GPBTypeBool: + result = [[GPBUInt32BoolDictionary alloc] init]; + break; + case GPBTypeFixed32: + case GPBTypeUInt32: + result = [[GPBUInt32UInt32Dictionary alloc] init]; + break; + case GPBTypeInt32: + case GPBTypeSFixed32: + case GPBTypeSInt32: + result = [[GPBUInt32Int32Dictionary alloc] init]; + break; + case GPBTypeFixed64: + case GPBTypeUInt64: + result = [[GPBUInt32UInt64Dictionary alloc] init]; + break; + case GPBTypeInt64: + case GPBTypeSFixed64: + case GPBTypeSInt64: + result = [[GPBUInt32Int64Dictionary alloc] init]; + break; + case GPBTypeFloat: + result = [[GPBUInt32FloatDictionary alloc] init]; + break; + case GPBTypeDouble: + result = [[GPBUInt32DoubleDictionary alloc] init]; + break; + case GPBTypeEnum: + result = [[GPBUInt32EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBTypeData: + case GPBTypeMessage: + case GPBTypeString: + result = [[GPBUInt32ObjectDictionary alloc] init]; + break; + case GPBTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBTypeInt32: + case GPBTypeSFixed32: + case GPBTypeSInt32: + switch (valueType) { + case GPBTypeBool: + result = [[GPBInt32BoolDictionary alloc] init]; + break; + case GPBTypeFixed32: + case GPBTypeUInt32: + result = [[GPBInt32UInt32Dictionary alloc] init]; + break; + case GPBTypeInt32: + case GPBTypeSFixed32: + case GPBTypeSInt32: + result = [[GPBInt32Int32Dictionary alloc] init]; + break; + case GPBTypeFixed64: + case GPBTypeUInt64: + result = [[GPBInt32UInt64Dictionary alloc] init]; + break; + case GPBTypeInt64: + case GPBTypeSFixed64: + case GPBTypeSInt64: + result = [[GPBInt32Int64Dictionary alloc] init]; + break; + case GPBTypeFloat: + result = [[GPBInt32FloatDictionary alloc] init]; + break; + case GPBTypeDouble: + result = [[GPBInt32DoubleDictionary alloc] init]; + break; + case GPBTypeEnum: + result = [[GPBInt32EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBTypeData: + case GPBTypeMessage: + case GPBTypeString: + result = [[GPBInt32ObjectDictionary alloc] init]; + break; + case GPBTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBTypeFixed64: + case GPBTypeUInt64: + switch (valueType) { + case GPBTypeBool: + result = [[GPBUInt64BoolDictionary alloc] init]; + break; + case GPBTypeFixed32: + case GPBTypeUInt32: + result = [[GPBUInt64UInt32Dictionary alloc] init]; + break; + case GPBTypeInt32: + case GPBTypeSFixed32: + case GPBTypeSInt32: + result = [[GPBUInt64Int32Dictionary alloc] init]; + break; + case GPBTypeFixed64: + case GPBTypeUInt64: + result = [[GPBUInt64UInt64Dictionary alloc] init]; + break; + case GPBTypeInt64: + case GPBTypeSFixed64: + case GPBTypeSInt64: + result = [[GPBUInt64Int64Dictionary alloc] init]; + break; + case GPBTypeFloat: + result = [[GPBUInt64FloatDictionary alloc] init]; + break; + case GPBTypeDouble: + result = [[GPBUInt64DoubleDictionary alloc] init]; + break; + case GPBTypeEnum: + result = [[GPBUInt64EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBTypeData: + case GPBTypeMessage: + case GPBTypeString: + result = [[GPBUInt64ObjectDictionary alloc] init]; + break; + case GPBTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBTypeInt64: + case GPBTypeSFixed64: + case GPBTypeSInt64: + switch (valueType) { + case GPBTypeBool: + result = [[GPBInt64BoolDictionary alloc] init]; + break; + case GPBTypeFixed32: + case GPBTypeUInt32: + result = [[GPBInt64UInt32Dictionary alloc] init]; + break; + case GPBTypeInt32: + case GPBTypeSFixed32: + case GPBTypeSInt32: + result = [[GPBInt64Int32Dictionary alloc] init]; + break; + case GPBTypeFixed64: + case GPBTypeUInt64: + result = [[GPBInt64UInt64Dictionary alloc] init]; + break; + case GPBTypeInt64: + case GPBTypeSFixed64: + case GPBTypeSInt64: + result = [[GPBInt64Int64Dictionary alloc] init]; + break; + case GPBTypeFloat: + result = [[GPBInt64FloatDictionary alloc] init]; + break; + case GPBTypeDouble: + result = [[GPBInt64DoubleDictionary alloc] init]; + break; + case GPBTypeEnum: + result = [[GPBInt64EnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBTypeData: + case GPBTypeMessage: + case GPBTypeString: + result = [[GPBInt64ObjectDictionary alloc] init]; + break; + case GPBTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + case GPBTypeString: + switch (valueType) { + case GPBTypeBool: + result = [[GPBStringBoolDictionary alloc] init]; + break; + case GPBTypeFixed32: + case GPBTypeUInt32: + result = [[GPBStringUInt32Dictionary alloc] init]; + break; + case GPBTypeInt32: + case GPBTypeSFixed32: + case GPBTypeSInt32: + result = [[GPBStringInt32Dictionary alloc] init]; + break; + case GPBTypeFixed64: + case GPBTypeUInt64: + result = [[GPBStringUInt64Dictionary alloc] init]; + break; + case GPBTypeInt64: + case GPBTypeSFixed64: + case GPBTypeSInt64: + result = [[GPBStringInt64Dictionary alloc] init]; + break; + case GPBTypeFloat: + result = [[GPBStringFloatDictionary alloc] init]; + break; + case GPBTypeDouble: + result = [[GPBStringDoubleDictionary alloc] init]; + break; + case GPBTypeEnum: + result = [[GPBStringEnumDictionary alloc] + initWithValidationFunction:field.enumDescriptor.enumVerifier]; + break; + case GPBTypeData: + case GPBTypeMessage: + case GPBTypeString: + if (autocreator) { + result = [[GPBAutocreatedDictionary alloc] init]; + } else { + result = [[NSMutableDictionary alloc] init]; + } + break; + case GPBTypeGroup: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + break; + + case GPBTypeFloat: + case GPBTypeDouble: + case GPBTypeEnum: + case GPBTypeData: + case GPBTypeGroup: + case GPBTypeMessage: + NSCAssert(NO, @"shouldn't happen"); + return nil; + } + + if (autocreator) { + if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) { + GPBAutocreatedDictionary *autoDict = result; + autoDict->_autocreator = autocreator; + } else { + GPBInt32Int32Dictionary *gpbDict = result; + gpbDict->_autocreator = autocreator; + } + } + + return result; +} #if !defined(__clang_analyzer__) // These functions are blocked from the analyzer because the analyzer sees the @@ -249,285 +571,27 @@ static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFileSyntax syntax) { id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (!dict) { - GPBType keyType = field.mapKeyType; - GPBType valueType = GPBGetFieldType(field); - switch (keyType) { - case GPBTypeBool: - switch (valueType) { - case GPBTypeBool: - dict = [[GPBBoolBoolDictionary alloc] init]; - break; - case GPBTypeFixed32: - case GPBTypeUInt32: - dict = [[GPBBoolUInt32Dictionary alloc] init]; - break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - dict = [[GPBBoolInt32Dictionary alloc] init]; - break; - case GPBTypeFixed64: - case GPBTypeUInt64: - dict = [[GPBBoolUInt64Dictionary alloc] init]; - break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - dict = [[GPBBoolInt64Dictionary alloc] init]; - break; - case GPBTypeFloat: - dict = [[GPBBoolFloatDictionary alloc] init]; - break; - case GPBTypeDouble: - dict = [[GPBBoolDoubleDictionary alloc] init]; - break; - case GPBTypeEnum: - dict = [[GPBBoolEnumDictionary alloc] - initWithValidationFunction:field.enumDescriptor.enumVerifier]; - break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: - dict = [[GPBBoolObjectDictionary alloc] init]; - break; - case GPBTypeGroup: - NSCAssert(NO, @"shouldn't happen"); - return nil; - } - break; - case GPBTypeFixed32: - case GPBTypeUInt32: - switch (valueType) { - case GPBTypeBool: - dict = [[GPBUInt32BoolDictionary alloc] init]; - break; - case GPBTypeFixed32: - case GPBTypeUInt32: - dict = [[GPBUInt32UInt32Dictionary alloc] init]; - break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - dict = [[GPBUInt32Int32Dictionary alloc] init]; - break; - case GPBTypeFixed64: - case GPBTypeUInt64: - dict = [[GPBUInt32UInt64Dictionary alloc] init]; - break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - dict = [[GPBUInt32Int64Dictionary alloc] init]; - break; - case GPBTypeFloat: - dict = [[GPBUInt32FloatDictionary alloc] init]; - break; - case GPBTypeDouble: - dict = [[GPBUInt32DoubleDictionary alloc] init]; - break; - case GPBTypeEnum: - dict = [[GPBUInt32EnumDictionary alloc] - initWithValidationFunction:field.enumDescriptor.enumVerifier]; - break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: - dict = [[GPBUInt32ObjectDictionary alloc] init]; - break; - case GPBTypeGroup: - NSCAssert(NO, @"shouldn't happen"); - return nil; - } - break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - switch (valueType) { - case GPBTypeBool: - dict = [[GPBInt32BoolDictionary alloc] init]; - break; - case GPBTypeFixed32: - case GPBTypeUInt32: - dict = [[GPBInt32UInt32Dictionary alloc] init]; - break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - dict = [[GPBInt32Int32Dictionary alloc] init]; - break; - case GPBTypeFixed64: - case GPBTypeUInt64: - dict = [[GPBInt32UInt64Dictionary alloc] init]; - break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - dict = [[GPBInt32Int64Dictionary alloc] init]; - break; - case GPBTypeFloat: - dict = [[GPBInt32FloatDictionary alloc] init]; - break; - case GPBTypeDouble: - dict = [[GPBInt32DoubleDictionary alloc] init]; - break; - case GPBTypeEnum: - dict = [[GPBInt32EnumDictionary alloc] - initWithValidationFunction:field.enumDescriptor.enumVerifier]; - break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: - dict = [[GPBInt32ObjectDictionary alloc] init]; - break; - case GPBTypeGroup: - NSCAssert(NO, @"shouldn't happen"); - return nil; - } - break; - case GPBTypeFixed64: - case GPBTypeUInt64: - switch (valueType) { - case GPBTypeBool: - dict = [[GPBUInt64BoolDictionary alloc] init]; - break; - case GPBTypeFixed32: - case GPBTypeUInt32: - dict = [[GPBUInt64UInt32Dictionary alloc] init]; - break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - dict = [[GPBUInt64Int32Dictionary alloc] init]; - break; - case GPBTypeFixed64: - case GPBTypeUInt64: - dict = [[GPBUInt64UInt64Dictionary alloc] init]; - break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - dict = [[GPBUInt64Int64Dictionary alloc] init]; - break; - case GPBTypeFloat: - dict = [[GPBUInt64FloatDictionary alloc] init]; - break; - case GPBTypeDouble: - dict = [[GPBUInt64DoubleDictionary alloc] init]; - break; - case GPBTypeEnum: - dict = [[GPBUInt64EnumDictionary alloc] - initWithValidationFunction:field.enumDescriptor.enumVerifier]; - break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: - dict = [[GPBUInt64ObjectDictionary alloc] init]; - break; - case GPBTypeGroup: - NSCAssert(NO, @"shouldn't happen"); - return nil; - } - break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - switch (valueType) { - case GPBTypeBool: - dict = [[GPBInt64BoolDictionary alloc] init]; - break; - case GPBTypeFixed32: - case GPBTypeUInt32: - dict = [[GPBInt64UInt32Dictionary alloc] init]; - break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - dict = [[GPBInt64Int32Dictionary alloc] init]; - break; - case GPBTypeFixed64: - case GPBTypeUInt64: - dict = [[GPBInt64UInt64Dictionary alloc] init]; - break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - dict = [[GPBInt64Int64Dictionary alloc] init]; - break; - case GPBTypeFloat: - dict = [[GPBInt64FloatDictionary alloc] init]; - break; - case GPBTypeDouble: - dict = [[GPBInt64DoubleDictionary alloc] init]; - break; - case GPBTypeEnum: - dict = [[GPBInt64EnumDictionary alloc] - initWithValidationFunction:field.enumDescriptor.enumVerifier]; - break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: - dict = [[GPBInt64ObjectDictionary alloc] init]; - break; - case GPBTypeGroup: - NSCAssert(NO, @"shouldn't happen"); - return nil; - } - break; - case GPBTypeString: - switch (valueType) { - case GPBTypeBool: - dict = [[GPBStringBoolDictionary alloc] init]; - break; - case GPBTypeFixed32: - case GPBTypeUInt32: - dict = [[GPBStringUInt32Dictionary alloc] init]; - break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - dict = [[GPBStringInt32Dictionary alloc] init]; - break; - case GPBTypeFixed64: - case GPBTypeUInt64: - dict = [[GPBStringUInt64Dictionary alloc] init]; - break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - dict = [[GPBStringInt64Dictionary alloc] init]; - break; - case GPBTypeFloat: - dict = [[GPBStringFloatDictionary alloc] init]; - break; - case GPBTypeDouble: - dict = [[GPBStringDoubleDictionary alloc] init]; - break; - case GPBTypeEnum: - dict = [[GPBStringEnumDictionary alloc] - initWithValidationFunction:field.enumDescriptor.enumVerifier]; - break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: - dict = [[NSMutableDictionary alloc] init]; - break; - case GPBTypeGroup: - NSCAssert(NO, @"shouldn't happen"); - return nil; - } - break; + // No lock needed, this is called from places expecting to mutate + // so no threading protection is needed. + dict = CreateMapForField(field, nil); + GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax); + } + return dict; +} - case GPBTypeFloat: - case GPBTypeDouble: - case GPBTypeEnum: - case GPBTypeData: - case GPBTypeGroup: - case GPBTypeMessage: - NSCAssert(NO, @"shouldn't happen"); - return nil; +// This is like GPBGetObjectIvarWithField(), but for maps, it should +// only be used to wire the method into the class. +static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { + id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!dict) { + // Check again after getting the lock. + OSSpinLockLock(&self->readOnlyMutex_); + dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (!dict) { + dict = CreateMapForField(field, self); + GPBSetAutocreatedRetainedObjectIvarWithField(self, field, dict); } - - GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax); + OSSpinLockUnlock(&self->readOnlyMutex_); } return dict; } @@ -595,7 +659,30 @@ void GPBAutocreatedArrayModified(GPBMessage *self, id array) { } } } - NSCAssert(NO, @"Unknown array."); + NSCAssert(NO, @"Unknown autocreated %@ for %@.", [array class], self); +} + +void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) { + // When one of our autocreated dicts adds elements, make it visible. + GPBDescriptor *descriptor = [[self class] descriptor]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (field.fieldType == GPBFieldTypeMap) { + id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); + if (curDict == dictionary) { + if ((field.mapKeyType == GPBTypeString) && + GPBFieldTypeIsObject(field)) { + GPBAutocreatedDictionary *autoDict = dictionary; + autoDict->_autocreator = nil; + } else { + GPBInt32Int32Dictionary *gpbDict = dictionary; + gpbDict->_autocreator = nil; + } + GPBBecomeVisibleToAutocreator(self); + return; + } + } + } + NSCAssert(NO, @"Unknown autocreated %@ for %@.", [dictionary class], self); } void GPBClearMessageAutocreator(GPBMessage *self) { @@ -617,7 +704,8 @@ void GPBClearMessageAutocreator(GPBMessage *self) { : [self->autocreator_->autocreatedExtensionMap_ objectForKey:self->autocreatorExtension_]); NSCAssert(autocreatorHas || autocreatorFieldValue != self, - @"Cannot clear autocreator because it still refers to self."); + @"Cannot clear autocreator because it still refers to self, self: %@.", + self); #endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS) @@ -636,26 +724,6 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { return self->unknownFields_; } -#ifdef DEBUG -static void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { - if (!message.initialized) { - NSString *reason = - [NSString stringWithFormat:@"Uninitialized Message %@", message]; - NSDictionary *userInfo = - message ? @{GPBExceptionMessageKey : message} : nil; - NSException *exception = - [NSException exceptionWithName:NSInternalInconsistencyException - reason:reason - userInfo:userInfo]; - [exception raise]; - } -} -#else -GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { -#pragma unused(message) -} -#endif // DEBUG - @implementation GPBMessage + (void)initialize { @@ -663,14 +731,20 @@ GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { if ([self class] == pbMessageClass) { // This is here to start up the "base" class descriptor. [self descriptor]; + // Message shares extension method resolving with GPBRootObject so insure + // it is started up at the same time. + (void)[GPBRootObject class]; } else if ([self superclass] == pbMessageClass) { // This is here to start up all the "message" subclasses. Just needs to be // done for the messages, not any of the subclasses. // This must be done in initialize to enforce thread safety of start up of - // the protocol buffer library. All of the extension registries must be - // created in either "+load" or "+initialize". + // the protocol buffer library. + // Note: The generated code for -descriptor calls + // +[GPBDescriptor allocDescriptorForClass:...], passing the GPBRootObject + // subclass for the file. That call chain is what ensures that *Root class + // is started up to support extension resolution off the message class + // (+resolveClassMethod: below) in a thread safe manner. [self descriptor]; - [self extensionRegistry]; } } @@ -728,25 +802,63 @@ GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { return self; } -- (instancetype)initWithData:(NSData *)data { - return [self initWithData:data extensionRegistry:nil]; +- (instancetype)initWithData:(NSData *)data error:(NSError **)errorPtr { + return [self initWithData:data extensionRegistry:nil error:errorPtr]; } - (instancetype)initWithData:(NSData *)data - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { if ((self = [self init])) { - [self mergeFromData:data extensionRegistry:extensionRegistry]; - DebugRaiseExceptionIfNotInitialized(self); + @try { + [self mergeFromData:data extensionRegistry:extensionRegistry]; + } + @catch (NSException *exception) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, + exception.reason); + } + } +#ifdef DEBUG + if (self && !self.initialized) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif } return self; } - (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input extensionRegistry: - (GPBExtensionRegistry *)extensionRegistry { + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { if ((self = [self init])) { - [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; - DebugRaiseExceptionIfNotInitialized(self); + @try { + [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + } + @catch (NSException *exception) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, + exception.reason); + } + } +#ifdef DEBUG + if (self && !self.initialized) { + [self release]; + self = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif } return self; } @@ -900,6 +1012,20 @@ GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { gpbArray->_autocreator = nil; } } + } else { + if ((field.mapKeyType == GPBTypeString) && + GPBFieldTypeIsObject(field)) { + GPBAutocreatedDictionary *autoDict = arrayOrMap; + if (autoDict->_autocreator == self) { + autoDict->_autocreator = nil; + } + } else { + // Type doesn't matter, it is a GPB*Dictionary. + GPBInt32Int32Dictionary *gpbDict = arrayOrMap; + if (gpbDict->_autocreator == self) { + gpbDict->_autocreator = nil; + } + } } [arrayOrMap release]; } @@ -960,7 +1086,8 @@ GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { } } else { NSAssert(field.isOptional, - @"If not required or optional, what was it?"); + @"%@: Single message field %@ not required or optional?", + [self class], field.name); if (GPBGetHasIvarField(self, field)) { GPBMessage *message = GPBGetMessageIvarWithField(self, field); if (!message.initialized) { @@ -1025,11 +1152,27 @@ GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { } - (NSData *)data { - DebugRaiseExceptionIfNotInitialized(self); +#ifdef DEBUG + if (!self.initialized) { + return nil; + } +#endif NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]]; GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data]; - [self writeToCodedOutputStream:stream]; + @try { + [self writeToCodedOutputStream:stream]; + } + @catch (NSException *exception) { + // This really shouldn't happen. The only way writeToCodedOutputStream: + // could throw is if something in the library has a bug and the + // serializedSize was wrong. +#ifdef DEBUG + NSLog(@"%@: Internal exception while building message data: %@", + [self class], exception); +#endif + data = nil; + } [stream release]; return data; } @@ -1041,7 +1184,19 @@ GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { [NSMutableData dataWithLength:(serializedSize + varintSize)]; GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data]; - [self writeDelimitedToCodedOutputStream:stream]; + @try { + [self writeDelimitedToCodedOutputStream:stream]; + } + @catch (NSException *exception) { + // This really shouldn't happen. The only way writeToCodedOutputStream: + // could throw is if something in the library has a bug and the + // serializedSize was wrong. +#ifdef DEBUG + NSLog(@"%@: Internal exception while building message delimitedData: %@", + [self class], exception); +#endif + data = nil; + } [stream release]; return data; } @@ -1717,32 +1872,55 @@ GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) { #pragma mark - Parse From Data Support -+ (instancetype)parseFromData:(NSData *)data { - return [self parseFromData:data extensionRegistry:nil]; ++ (instancetype)parseFromData:(NSData *)data error:(NSError **)errorPtr { + return [self parseFromData:data extensionRegistry:nil error:errorPtr]; } + (instancetype)parseFromData:(NSData *)data - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { return [[[self alloc] initWithData:data - extensionRegistry:extensionRegistry] autorelease]; + extensionRegistry:extensionRegistry + error:errorPtr] autorelease]; } + (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { + extensionRegistry:(GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { return [[[self alloc] initWithCodedInputStream:input - extensionRegistry:extensionRegistry] autorelease]; + extensionRegistry:extensionRegistry + error:errorPtr] autorelease]; } #pragma mark - Parse Delimited From Data Support + (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input extensionRegistry: - (GPBExtensionRegistry *)extensionRegistry { + (GPBExtensionRegistry *)extensionRegistry + error:(NSError **)errorPtr { GPBMessage *message = [[[self alloc] init] autorelease]; - [message mergeDelimitedFromCodedInputStream:input - extensionRegistry:extensionRegistry]; - DebugRaiseExceptionIfNotInitialized(message); + @try { + [message mergeDelimitedFromCodedInputStream:input + extensionRegistry:extensionRegistry]; + } + @catch (NSException *exception) { + [message release]; + message = nil; + if (errorPtr) { + *errorPtr = MessageErrorWithReason(GPBMessageErrorCodeMalformedData, + exception.reason); + } + } +#ifdef DEBUG + if (message && !message.initialized) { + [message release]; + message = nil; + if (errorPtr) { + *errorPtr = MessageError(GPBMessageErrorCodeMissingRequiredField, nil); + } + } +#endif return message; } @@ -4661,7 +4839,9 @@ static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) { context.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { if (value) { [NSException raise:NSInvalidArgumentException - format:@"has fields can only be set to NO"]; + format:@"%@: %@ can only be set to NO (to clear field).", + [obj class], + NSStringFromSelector(field->setHasSel_)]; } GPBClearMessageField(obj, field); }); @@ -4684,9 +4864,15 @@ static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) { } } else { if (sel == field->getSel_) { - context.impToAdd = imp_implementationWithBlock(^(id obj) { - return GetArrayIvarWithField(obj, field); - }); + if (field.fieldType == GPBFieldTypeRepeated) { + context.impToAdd = imp_implementationWithBlock(^(id obj) { + return GetArrayIvarWithField(obj, field); + }); + } else { + context.impToAdd = imp_implementationWithBlock(^(id obj) { + return GetMapIvarWithField(obj, field); + }); + } context.encodingSelector = @selector(getArray); break; } else if (sel == field->setSel_) { @@ -4711,18 +4897,37 @@ static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) { return [super resolveInstanceMethod:sel]; } ++ (BOOL)resolveClassMethod:(SEL)sel { + // Extensions scoped to a Message and looked up via class methods. + if (GPBResolveExtensionClassMethod(self, sel)) { + return YES; + } + return [super resolveClassMethod:sel]; +} + #pragma mark - NSCoding Support ++ (BOOL)supportsSecureCoding { + return YES; +} + - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [self init]; if (self) { - [self mergeFromData:[aDecoder decodeDataObject] extensionRegistry:nil]; + NSData *data = + [aDecoder decodeObjectOfClass:[NSData class] forKey:kGPBDataCoderKey]; + if (data.length) { + [self mergeFromData:data extensionRegistry:nil]; + } } return self; } - (void)encodeWithCoder:(NSCoder *)aCoder { - [aCoder encodeDataObject:[self data]]; + NSData *data = [self data]; + if (data.length) { + [aCoder encodeObject:data forKey:kGPBDataCoderKey]; + } } #pragma mark - KVC Support diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h index f2a3d5fa..c437c55b 100644 --- a/objectivec/GPBMessage_PackagePrivate.h +++ b/objectivec/GPBMessage_PackagePrivate.h @@ -82,6 +82,7 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; // -[CodedInputStream checkLastTagWas:] after calling this to // verify that the last tag seen was the appropriate end-group tag, // or zero for EOF. +// NOTE: This will throw if there is an error while parsing. - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input extensionRegistry:(GPBExtensionRegistry *)extensionRegistry; @@ -113,9 +114,10 @@ BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent); // visible to its autocreator. void GPBBecomeVisibleToAutocreator(GPBMessage *self); -// Call this when an array is mutabled so the parent message that autocreated -// it can react. +// Call this when an array/dictionary is mutated so the parent message that +// autocreated it can react. void GPBAutocreatedArrayModified(GPBMessage *self, id array); +void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary); // Clear the autocreator, if any. Asserts if the autocreator still has an // autocreated reference to this message. diff --git a/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/objectivec/GPBProtocolBuffers_RuntimeSupport.h index ac3226ef..7fd7b4c8 100644 --- a/objectivec/GPBProtocolBuffers_RuntimeSupport.h +++ b/objectivec/GPBProtocolBuffers_RuntimeSupport.h @@ -35,7 +35,7 @@ #import "GPBDescriptor_PackagePrivate.h" #import "GPBExtensionField_PackagePrivate.h" -#import "GPBExtensionRegistry_PackagePrivate.h" +#import "GPBExtensionRegistry.h" #import "GPBMessage_PackagePrivate.h" #import "GPBRootObject_PackagePrivate.h" #import "GPBUtilities_PackagePrivate.h" diff --git a/objectivec/GPBRootObject.m b/objectivec/GPBRootObject.m index b58f95ce..38dab665 100644 --- a/objectivec/GPBRootObject.m +++ b/objectivec/GPBRootObject.m @@ -31,6 +31,7 @@ #import "GPBRootObject_PackagePrivate.h" #import +#import #import @@ -95,9 +96,11 @@ static CFHashCode GPBRootExtensionKeyHash(const void *value) { return jenkins_one_at_a_time_hash(key); } +static OSSpinLock gExtensionSingletonDictionaryLock_ = OS_SPINLOCK_INIT; static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; + (void)initialize { + // Ensure the global is started up. if (!gExtensionSingletonDictionary) { CFDictionaryKeyCallBacks keyCallBacks = { // See description above for reason for using custom dictionary. @@ -112,6 +115,13 @@ static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks, &kCFTypeDictionaryValueCallBacks); } + + if ([self superclass] == [GPBRootObject class]) { + // This is here to start up all the per file "Root" subclasses. + // This must be done in initialize to enforce thread safety of start up of + // the protocol buffer library. + [self extensionRegistry]; + } } + (GPBExtensionRegistry *)extensionRegistry { @@ -122,39 +132,54 @@ static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; + (void)globallyRegisterExtension:(GPBExtensionField *)field { const char *key = [field.descriptor singletonNameC]; - // Register happens at startup, so there is no thread safety issue in - // modifying the dictionary. + OSSpinLockLock(&gExtensionSingletonDictionaryLock_); CFDictionarySetValue(gExtensionSingletonDictionary, key, field); + OSSpinLockUnlock(&gExtensionSingletonDictionaryLock_); } -static id ExtensionForName(id self, SEL _cmd) { +GPB_INLINE id ExtensionForName(id self, SEL _cmd) { // Really fast way of doing "classname_selName". // This came up as a hotspot (creation of NSString *) when accessing a // lot of extensions. - const char *className = class_getName(self); const char *selName = sel_getName(_cmd); + if (selName[0] == '_') { + return nil; // Apple internal selector. + } + size_t selNameLen = 0; + while (1) { + char c = selName[selNameLen]; + if (c == '\0') { // String end. + break; + } + if (c == ':') { + return nil; // Selector took an arg, not one of the runtime methods. + } + ++selNameLen; + } + + const char *className = class_getName(self); size_t classNameLen = strlen(className); - size_t selNameLen = strlen(selName); char key[classNameLen + selNameLen + 2]; memcpy(key, className, classNameLen); key[classNameLen] = '_'; memcpy(&key[classNameLen + 1], selName, selNameLen); key[classNameLen + 1 + selNameLen] = '\0'; + OSSpinLockLock(&gExtensionSingletonDictionaryLock_); id extension = (id)CFDictionaryGetValue(gExtensionSingletonDictionary, key); - // We can't remove the key from the dictionary here (as an optimization), - // because resolveClassMethod can happen on any thread and we'd then need - // a lock. + if (extension) { + // The method is getting wired in to the class, so no need to keep it in + // the dictionary. + CFDictionaryRemoveValue(gExtensionSingletonDictionary, key); + } + OSSpinLockUnlock(&gExtensionSingletonDictionaryLock_); return extension; } -+ (BOOL)resolveClassMethod:(SEL)sel { +BOOL GPBResolveExtensionClassMethod(Class self, SEL sel) { // Another option would be to register the extensions with the class at // globallyRegisterExtension: // Timing the two solutions, this solution turned out to be much faster // and reduced startup time, and runtime memory. - // On an iPhone 5s: - // ResolveClassMethod: 1515583 nanos - // globallyRegisterExtension: 2453083 nanos // The advantage to globallyRegisterExtension is that it would reduce the // size of the protos somewhat because the singletonNameC wouldn't need // to include the class name. For a class with a lot of extensions it @@ -169,7 +194,17 @@ static id ExtensionForName(id self, SEL _cmd) { #pragma unused(obj) return extension; }); - return class_addMethod(metaClass, sel, imp, encoding); + if (class_addMethod(metaClass, sel, imp, encoding)) { + return YES; + } + } + return NO; +} + + ++ (BOOL)resolveClassMethod:(SEL)sel { + if (GPBResolveExtensionClassMethod(self, sel)) { + return YES; } return [super resolveClassMethod:sel]; } diff --git a/objectivec/GPBRootObject_PackagePrivate.h b/objectivec/GPBRootObject_PackagePrivate.h index 4e1d3913..f1cfe990 100644 --- a/objectivec/GPBRootObject_PackagePrivate.h +++ b/objectivec/GPBRootObject_PackagePrivate.h @@ -40,3 +40,7 @@ + (void)globallyRegisterExtension:(GPBExtensionField *)field; @end + +// Returns YES if the selector was resolved and added to the class, +// NO otherwise. +BOOL GPBResolveExtensionClassMethod(Class self, SEL sel); diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index 09e34bfb..f912b979 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -93,7 +93,9 @@ void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) { } BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); if (idx < 0) { NSCAssert(fieldNumber != 0, @"Invalid field number."); BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber); @@ -109,7 +111,8 @@ BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) { } uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) { - NSCAssert(idx < 0, @"invalid index for oneof."); + NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.", + [self class], idx); uint32_t result = self->messageStorage_->_has_storage_[-idx]; return result; } @@ -145,7 +148,9 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, // Like GPBClearMessageField(), free the memory if an objecttype is set, // pod types don't need to do anything. GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet]; - NSCAssert(fieldSet, @"oneof set to something not in the oneof?"); + NSCAssert(fieldSet, + @"%@: oneof set to something (%u) not in the oneof?", + [self class], fieldNumberSet); if (fieldSet && GPBFieldStoresObject(fieldSet)) { uint8_t *storage = (uint8_t *)self->messageStorage_; id *typePtr = (id *)&storage[fieldSet->description_->offset]; @@ -189,7 +194,9 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% if (oneof) { //% GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field)); //% } -//% NSCAssert(self->messageStorage_ != NULL, @"How?"); +//% NSCAssert(self->messageStorage_ != NULL, +//% @"%@: All messages should have storage (from init)", +//% [self class]); //%#if defined(__clang_analyzer__) //% if (self->messageStorage_ == NULL) return; //%#endif @@ -263,7 +270,9 @@ void GPBSetObjectIvarWithFieldInternal(GPBMessage *self, void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, id value, GPBFileSyntax syntax) { - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif @@ -328,7 +337,7 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, if (oldValue) { if (isMapOrArray) { if (field.fieldType == GPBFieldTypeRepeated) { - // If the old message value was autocreated by us, then clear it. + // If the old array was autocreated by us, then clear it. if (GPBTypeIsObject(fieldType)) { GPBAutocreatedArray *autoArray = oldValue; if (autoArray->_autocreator == self) { @@ -341,6 +350,21 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, gpbArray->_autocreator = nil; } } + } else { // GPBFieldTypeMap + // If the old map was autocreated by us, then clear it. + if ((field.mapKeyType == GPBTypeString) && + GPBTypeIsObject(fieldType)) { + GPBAutocreatedDictionary *autoDict = oldValue; + if (autoDict->_autocreator == self) { + autoDict->_autocreator = nil; + } + } else { + // Type doesn't matter, it is a GPB*Dictionary. + GPBInt32Int32Dictionary *gpbDict = oldValue; + if (gpbDict->_autocreator == self) { + gpbDict->_autocreator = nil; + } + } } } else if (fieldIsMessage) { // If the old message value was autocreated by us, then clear it. @@ -461,7 +485,9 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, if (oneof) { GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field)); } - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif @@ -507,7 +533,9 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, if (oneof) { GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field)); } - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif @@ -553,7 +581,9 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, if (oneof) { GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field)); } - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif @@ -599,7 +629,9 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, if (oneof) { GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field)); } - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif @@ -645,7 +677,9 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, if (oneof) { GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field)); } - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif @@ -691,7 +725,9 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, if (oneof) { GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field)); } - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif @@ -737,7 +773,9 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, if (oneof) { GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field)); } - NSCAssert(self->messageStorage_ != NULL, @"How?"); + NSCAssert(self->messageStorage_ != NULL, + @"%@: All messages should have storage (from init)", + [self class]); #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif @@ -1152,30 +1190,32 @@ static void AppendTextFormatForMessageField(GPBMessage *message, GPBFieldDescriptor *field, NSMutableString *toStr, NSString *lineIndent) { - id array; - NSUInteger arrayCount; + id arrayOrMap; + NSUInteger count; GPBFieldType fieldType = field.fieldType; switch (fieldType) { case GPBFieldTypeSingle: - array = nil; - arrayCount = (GPBGetHasIvarField(message, field) ? 1 : 0); + arrayOrMap = nil; + count = (GPBGetHasIvarField(message, field) ? 1 : 0); break; case GPBFieldTypeRepeated: - array = GPBGetObjectIvarWithFieldNoAutocreate(message, field); - arrayCount = [(NSArray *)array count]; + // Will be NSArray or GPB*Array, type doesn't matter, they both + // implement count. + arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); + count = [(NSArray *)arrayOrMap count]; break; case GPBFieldTypeMap: { - // Could be a GPB*Dictionary or NSMutableDictionary, type doesn't matter, - // just want count. - array = GPBGetObjectIvarWithFieldNoAutocreate(message, field); - arrayCount = [(NSArray *)array count]; + // Will be GPB*Dictionary or NSMutableDictionary, type doesn't matter, + // they both implement count. + arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(message, field); + count = [(NSDictionary *)arrayOrMap count]; break; } } - if (arrayCount == 0) { + if (count == 0) { // Nothing to print, out of here. return; } @@ -1189,7 +1229,7 @@ static void AppendTextFormatForMessageField(GPBMessage *message, fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)]; // If there is only one entry, put the objc name as a comment, other wise // add it before the the repeated values. - if (arrayCount > 1) { + if (count > 1) { [toStr appendFormat:@"%@# %@\n", lineIndent, field.name]; } else { lineEnding = [NSString stringWithFormat:@" # %@", field.name]; @@ -1197,16 +1237,17 @@ static void AppendTextFormatForMessageField(GPBMessage *message, } if (fieldType == GPBFieldTypeMap) { - AppendTextFormatForMapMessageField(array, field, toStr, lineIndent, + AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent, fieldName, lineEnding); return; } + id array = arrayOrMap; const BOOL isRepeated = (array != nil); GPBType fieldDataType = GPBGetFieldType(field); BOOL isMessageField = GPBTypeIsMessage(fieldDataType); - for (NSUInteger j = 0; j < arrayCount; ++j) { + for (NSUInteger j = 0; j < count; ++j) { // Start the line. [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, (isMessageField ? "" : ":")]; @@ -1291,7 +1332,7 @@ static void AppendTextFormatForMessageField(GPBMessage *message, // End the line. [toStr appendFormat:@"%@\n", lineEnding]; - } // for(arrayCount) + } // for(count) } static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index 46416043..f18ba2f8 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -200,7 +200,6 @@ F4B6B8AF1A9CC98000892426 /* GPBField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBField_PackagePrivate.h; sourceTree = ""; }; F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = ""; }; F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField_PackagePrivate.h; sourceTree = ""; }; - F4B6B8B71A9CD1DE00892426 /* GPBExtensionRegistry_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry_PackagePrivate.h; sourceTree = ""; }; F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = ""; }; F4B6B8B91A9D338B00892426 /* unittest_name_mangling.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_name_mangling.proto; sourceTree = ""; }; /* End PBXFileReference section */ @@ -301,7 +300,6 @@ F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */, 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */, F45C69CB16DFD08D0081955B /* GPBExtensionField.m */, - F4B6B8B71A9CD1DE00892426 /* GPBExtensionRegistry_PackagePrivate.h */, 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */, 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */, F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */, @@ -595,7 +593,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "set -eu\nmkdir -p \"${PROJECT_DERIVED_FILE_DIR}/protos\"\nexport PATH=\"${PATH}:.\"\ncd \"${SRCROOT}\"/../src\n\nPROTOC=./protoc\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_custom_options.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_enormous_descriptor.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_embed_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_empty.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_mset.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_no_generic_services.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_drop_unknown_fields.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_preserve_unknown_enum.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_lite_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_proto2_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_unittest.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_objc.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_cycle.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_name_mangling.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto2.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto3.proto\n\nexport GPB_CLASSLIST_PATH=\"${PROJECT_DERIVED_FILE_DIR}/ClassList.txt\"\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\n\nif [ -e ${GPB_CLASSLIST_PATH} ]; then\nrm ${GPB_CLASSLIST_PATH}\nfi\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_filter.proto\n\n"; + shellScript = "set -eu\nmkdir -p \"${PROJECT_DERIVED_FILE_DIR}/protos\"\nexport PATH=\"${PATH}:.\"\ncd \"${SRCROOT}\"/../src\n\nPROTOC=./protoc\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_custom_options.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_enormous_descriptor.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_embed_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_empty.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_mset.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_no_generic_services.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_drop_unknown_fields.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_preserve_unknown_enum.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_lite_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_proto2_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_unittest.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_objc.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_cycle.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_name_mangling.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto2.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto3.proto\n\n# Use the filter\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_filter.proto\n\n"; showEnvVarsInLog = 0; }; F4B62A781AF91F6000AFCEDC /* Script: Check Runtime Stamps */ = { @@ -819,6 +817,7 @@ CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES; CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = c99; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index f6f6e12b..617fb47f 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -34,6 +34,20 @@ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj"> + + + + + + + + ** (no default) + +Since Objective C uses a global namespace for all of its classes, there can +be collisions. This option provides a prefix that will be added to the Enums +and Objects (for messages) generated from the proto. Convention is to base +the prefix on the package the proto is in. + +Contributing +------------ + +Please make updates to the tests along with changes. If just changing the +runtime, the Xcode projects can be used to build and run tests. If change also +require changes to the generated code, `objectivec/DevTools/full_mac_build.sh` +can be used to easily rebuild and test changes. Passing `-h` to the script will +show the addition options that could be useful. + +Documentation +------------- + +The complete documentation for Protocol Buffers is available via the +web at: + + https://developers.google.com/protocol-buffers/ diff --git a/objectivec/Tests/GPBArrayTests.m b/objectivec/Tests/GPBArrayTests.m index 37724c59..0fb15e40 100644 --- a/objectivec/Tests/GPBArrayTests.m +++ b/objectivec/Tests/GPBArrayTests.m @@ -29,14 +29,11 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #import - #import #import "GPBArray.h" -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE +#import "GPBTestUtilities.h" // To let the testing macros work, add some extra methods to simplify things. @interface GPBEnumArray (TestingTweak) @@ -233,6 +230,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { //% // Should be new object but equal. //% XCTAssertNotEqual(array, array2); //% XCTAssertEqualObjects(array, array2); +//% [array2 release]; +//% [array release]; //%} //% //%- (void)testArrayFromArray { @@ -248,6 +247,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { //% // Should be new pointer, but equal objects. //% XCTAssertNotEqual(array, array2); //% XCTAssertEqualObjects(array, array2); +//% [array release]; //%} //% //%- (void)testAdds { @@ -275,6 +275,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { //% XCTAssertEqual([array valueAtIndex:2], VAL3); //% XCTAssertEqual([array valueAtIndex:3], VAL4); //% XCTAssertEqual([array valueAtIndex:4], VAL1); +//% [array2 release]; //%} //% //%- (void)testInsert { @@ -307,6 +308,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { //% XCTAssertEqual([array valueAtIndex:3], VAL2); //% XCTAssertEqual([array valueAtIndex:4], VAL3); //% XCTAssertEqual([array valueAtIndex:5], VAL4); +//% [array release]; //%} //% //%- (void)testRemove { @@ -343,6 +345,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { //% XCTAssertEqual(array.count, 0U); //% XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], //% NSException, NSRangeException); +//% [array release]; //%} //% //%- (void)testInplaceMutation { @@ -381,6 +384,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { //% NSException, NSRangeException); //% XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], //% NSException, NSRangeException); +//% [array release]; //%} //% //%- (void)testInternalResizing { @@ -405,6 +409,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { //% XCTAssertEqual(array.count, 404U); //% [array removeAll]; //% XCTAssertEqual(array.count, 0U); +//% [array release]; //%} //% //%@end @@ -558,6 +563,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new object but equal. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -573,6 +580,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new pointer, but equal objects. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array release]; } - (void)testAdds { @@ -600,6 +608,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], 3); XCTAssertEqual([array valueAtIndex:3], 4); XCTAssertEqual([array valueAtIndex:4], 1); + [array2 release]; } - (void)testInsert { @@ -632,6 +641,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:3], 2); XCTAssertEqual([array valueAtIndex:4], 3); XCTAssertEqual([array valueAtIndex:5], 4); + [array release]; } - (void)testRemove { @@ -668,6 +678,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 0U); XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], NSException, NSRangeException); + [array release]; } - (void)testInplaceMutation { @@ -706,6 +717,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { NSException, NSRangeException); XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], NSException, NSRangeException); + [array release]; } - (void)testInternalResizing { @@ -730,6 +742,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end @@ -883,6 +896,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new object but equal. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -898,6 +913,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new pointer, but equal objects. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array release]; } - (void)testAdds { @@ -925,6 +941,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], 13U); XCTAssertEqual([array valueAtIndex:3], 14U); XCTAssertEqual([array valueAtIndex:4], 11U); + [array2 release]; } - (void)testInsert { @@ -957,6 +974,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:3], 12U); XCTAssertEqual([array valueAtIndex:4], 13U); XCTAssertEqual([array valueAtIndex:5], 14U); + [array release]; } - (void)testRemove { @@ -993,6 +1011,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 0U); XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], NSException, NSRangeException); + [array release]; } - (void)testInplaceMutation { @@ -1031,6 +1050,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { NSException, NSRangeException); XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], NSException, NSRangeException); + [array release]; } - (void)testInternalResizing { @@ -1055,6 +1075,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end @@ -1208,6 +1229,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new object but equal. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -1223,6 +1246,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new pointer, but equal objects. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array release]; } - (void)testAdds { @@ -1250,6 +1274,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], 33LL); XCTAssertEqual([array valueAtIndex:3], 34LL); XCTAssertEqual([array valueAtIndex:4], 31LL); + [array2 release]; } - (void)testInsert { @@ -1282,6 +1307,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:3], 32LL); XCTAssertEqual([array valueAtIndex:4], 33LL); XCTAssertEqual([array valueAtIndex:5], 34LL); + [array release]; } - (void)testRemove { @@ -1318,6 +1344,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 0U); XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], NSException, NSRangeException); + [array release]; } - (void)testInplaceMutation { @@ -1356,6 +1383,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { NSException, NSRangeException); XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], NSException, NSRangeException); + [array release]; } - (void)testInternalResizing { @@ -1380,6 +1408,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end @@ -1533,6 +1562,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new object but equal. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -1548,6 +1579,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new pointer, but equal objects. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array release]; } - (void)testAdds { @@ -1575,6 +1607,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], 43ULL); XCTAssertEqual([array valueAtIndex:3], 44ULL); XCTAssertEqual([array valueAtIndex:4], 41ULL); + [array2 release]; } - (void)testInsert { @@ -1607,6 +1640,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:3], 42ULL); XCTAssertEqual([array valueAtIndex:4], 43ULL); XCTAssertEqual([array valueAtIndex:5], 44ULL); + [array release]; } - (void)testRemove { @@ -1643,6 +1677,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 0U); XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], NSException, NSRangeException); + [array release]; } - (void)testInplaceMutation { @@ -1681,6 +1716,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { NSException, NSRangeException); XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], NSException, NSRangeException); + [array release]; } - (void)testInternalResizing { @@ -1705,6 +1741,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end @@ -1858,6 +1895,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new object but equal. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -1873,6 +1912,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new pointer, but equal objects. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array release]; } - (void)testAdds { @@ -1900,6 +1940,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], 53.f); XCTAssertEqual([array valueAtIndex:3], 54.f); XCTAssertEqual([array valueAtIndex:4], 51.f); + [array2 release]; } - (void)testInsert { @@ -1932,6 +1973,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:3], 52.f); XCTAssertEqual([array valueAtIndex:4], 53.f); XCTAssertEqual([array valueAtIndex:5], 54.f); + [array release]; } - (void)testRemove { @@ -1968,6 +2010,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 0U); XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], NSException, NSRangeException); + [array release]; } - (void)testInplaceMutation { @@ -2006,6 +2049,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { NSException, NSRangeException); XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], NSException, NSRangeException); + [array release]; } - (void)testInternalResizing { @@ -2030,6 +2074,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end @@ -2183,6 +2228,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new object but equal. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -2198,6 +2245,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new pointer, but equal objects. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array release]; } - (void)testAdds { @@ -2225,6 +2273,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], 63.); XCTAssertEqual([array valueAtIndex:3], 64.); XCTAssertEqual([array valueAtIndex:4], 61.); + [array2 release]; } - (void)testInsert { @@ -2257,6 +2306,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:3], 62.); XCTAssertEqual([array valueAtIndex:4], 63.); XCTAssertEqual([array valueAtIndex:5], 64.); + [array release]; } - (void)testRemove { @@ -2293,6 +2343,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 0U); XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], NSException, NSRangeException); + [array release]; } - (void)testInplaceMutation { @@ -2331,6 +2382,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { NSException, NSRangeException); XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], NSException, NSRangeException); + [array release]; } - (void)testInternalResizing { @@ -2355,6 +2407,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end @@ -2508,6 +2561,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new object but equal. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -2523,6 +2578,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new pointer, but equal objects. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array release]; } - (void)testAdds { @@ -2550,6 +2606,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], FALSE); XCTAssertEqual([array valueAtIndex:3], FALSE); XCTAssertEqual([array valueAtIndex:4], TRUE); + [array2 release]; } - (void)testInsert { @@ -2582,6 +2639,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:3], TRUE); XCTAssertEqual([array valueAtIndex:4], FALSE); XCTAssertEqual([array valueAtIndex:5], FALSE); + [array release]; } - (void)testRemove { @@ -2618,6 +2676,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 0U); XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], NSException, NSRangeException); + [array release]; } - (void)testInplaceMutation { @@ -2656,6 +2715,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { NSException, NSRangeException); XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], NSException, NSRangeException); + [array release]; } - (void)testInternalResizing { @@ -2680,6 +2740,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end @@ -2833,6 +2894,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new object but equal. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -2848,6 +2911,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { // Should be new pointer, but equal objects. XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); + [array release]; } - (void)testAdds { @@ -2875,6 +2939,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], 73); XCTAssertEqual([array valueAtIndex:3], 74); XCTAssertEqual([array valueAtIndex:4], 71); + [array2 release]; } - (void)testInsert { @@ -2907,6 +2972,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:3], 72); XCTAssertEqual([array valueAtIndex:4], 73); XCTAssertEqual([array valueAtIndex:5], 74); + [array release]; } - (void)testRemove { @@ -2943,6 +3009,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 0U); XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0], NSException, NSRangeException); + [array release]; } - (void)testInplaceMutation { @@ -2981,6 +3048,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { NSException, NSRangeException); XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4], NSException, NSRangeException); + [array release]; } - (void)testInternalResizing { @@ -3005,6 +3073,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end @@ -3165,6 +3234,8 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array2 rawValueAtIndex:1], 72); XCTAssertEqual([array2 rawValueAtIndex:2], 1000); XCTAssertEqual([array2 valueAtIndex:2], kGPBUnrecognizedEnumeratorValue); + [array2 release]; + [array release]; } - (void)testArrayFromArray { @@ -3182,6 +3253,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertNotEqual(array, array2); XCTAssertEqualObjects(array, array2); XCTAssertEqual(array.validationFunc, array2.validationFunc); + [array release]; } - (void)testUnknownAdds { @@ -3197,7 +3269,6 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertThrowsSpecificNamed([array addValues:kValues1 count:GPBARRAYSIZE(kValues1)], NSException, NSInvalidArgumentException); XCTAssertEqual(array.count, 0U); - [array release]; } @@ -3229,7 +3300,6 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue); XCTAssertEqual([array rawValueAtIndex:3], 74); XCTAssertEqual([array rawValueAtIndex:4], 71); - [array release]; } @@ -3256,6 +3326,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertThrowsSpecificNamed([array insertValue:374 atIndex:3], NSException, NSInvalidArgumentException); XCTAssertEqual(array.count, 3U); + [array release]; } - (void)testRawInsert { @@ -3292,7 +3363,6 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array rawValueAtIndex:4], 73); XCTAssertEqual([array rawValueAtIndex:5], 374); XCTAssertEqual([array valueAtIndex:5], kGPBUnrecognizedEnumeratorValue); - [array release]; } @@ -3313,6 +3383,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual([array valueAtIndex:1], 72); XCTAssertEqual([array valueAtIndex:2], 73); XCTAssertEqual([array valueAtIndex:3], 74); + [array release]; } @@ -3336,6 +3407,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withRawValue:74], NSException, NSRangeException); + [array release]; } - (void)testRawInternalResizing { @@ -3360,6 +3432,7 @@ static BOOL TestingEnum_IsValidValue2(int32_t value) { XCTAssertEqual(array.count, 404U); [array removeAll]; XCTAssertEqual(array.count, 0U); + [array release]; } @end diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m index 0a709cbe..5f29d7c8 100644 --- a/objectivec/Tests/GPBCodedInputStreamTests.m +++ b/objectivec/Tests/GPBCodedInputStreamTests.m @@ -184,7 +184,7 @@ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length); TestAllTypes* message2 = - [TestAllTypes parseFromData:rawBytes extensionRegistry:nil]; + [TestAllTypes parseFromData:rawBytes extensionRegistry:nil error:NULL]; [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; } @@ -227,8 +227,9 @@ // reading. GPBCodedInputStream* stream = [GPBCodedInputStream streamWithData:message.data]; - TestAllTypes* message2 = - [TestAllTypes parseFromCodedInputStream:stream extensionRegistry:nil]; + TestAllTypes* message2 = [TestAllTypes parseFromCodedInputStream:stream + extensionRegistry:nil + error:NULL]; XCTAssertEqualObjects(message.optionalBytes, message2.optionalBytes); @@ -280,8 +281,9 @@ NSData* data = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey]; GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data]; - TestAllTypes* message = - [TestAllTypes parseFromCodedInputStream:input extensionRegistry:nil]; + TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input + extensionRegistry:nil + error:NULL]; // Make sure we can read string properties twice without crashing. XCTAssertEqual([message.defaultString length], (NSUInteger)0); XCTAssertEqualObjects(@"", message.defaultString); diff --git a/objectivec/Tests/GPBConcurrencyTests.m b/objectivec/Tests/GPBConcurrencyTests.m index 3749fc34..e500ad77 100644 --- a/objectivec/Tests/GPBConcurrencyTests.m +++ b/objectivec/Tests/GPBConcurrencyTests.m @@ -31,10 +31,16 @@ #import "GPBTestUtilities.h" #import "google/protobuf/Unittest.pbobjc.h" +#import "google/protobuf/UnittestObjc.pbobjc.h" static const int kNumThreads = 100; static const int kNumMessages = 100; +// NOTE: Most of these tests don't "fail" in the sense that the XCTAsserts +// trip. Rather, the asserts simply exercise the apis, and if there is +// a concurancy issue, the NSAsserts in the runtime code fire and/or the +// code just crashes outright. + @interface ConcurrencyTests : GPBTestCase @end @@ -132,6 +138,48 @@ static const int kNumMessages = 100; } } +- (void)readInt32Int32Map:(NSArray *)messages { + for (int i = 0; i < 10; i++) { + for (TestRecursiveMessageWithRepeatedField *message in messages) { + XCTAssertEqual([message.iToI count], (NSUInteger)0); + } + } +} + +- (void)testConcurrentReadOfUnsetInt32Int32MapField { + NSArray *messages = + [self createMessagesWithType:[TestRecursiveMessageWithRepeatedField class]]; + NSArray *threads = + [self createThreadsWithSelector:@selector(readInt32Int32Map:) + object:messages]; + [self startThreads:threads]; + [self joinThreads:threads]; + for (TestRecursiveMessageWithRepeatedField *message in messages) { + XCTAssertEqual([message.iToI count], (NSUInteger)0); + } +} + +- (void)readStringStringMap:(NSArray *)messages { + for (int i = 0; i < 10; i++) { + for (TestRecursiveMessageWithRepeatedField *message in messages) { + XCTAssertEqual([message.strToStr count], (NSUInteger)0); + } + } +} + +- (void)testConcurrentReadOfUnsetStringStringMapField { + NSArray *messages = + [self createMessagesWithType:[TestRecursiveMessageWithRepeatedField class]]; + NSArray *threads = + [self createThreadsWithSelector:@selector(readStringStringMap:) + object:messages]; + [self startThreads:threads]; + [self joinThreads:threads]; + for (TestRecursiveMessageWithRepeatedField *message in messages) { + XCTAssertEqual([message.strToStr count], (NSUInteger)0); + } +} + - (void)readOptionalForeignMessageExtension:(NSArray *)messages { for (int i = 0; i < 10; i++) { for (TestAllExtensions *message in messages) { diff --git a/objectivec/Tests/GPBDictionaryTests+Bool.m b/objectivec/Tests/GPBDictionaryTests+Bool.m index bc4998be..43650f51 100644 --- a/objectivec/Tests/GPBDictionaryTests+Bool.m +++ b/objectivec/Tests/GPBDictionaryTests+Bool.m @@ -33,12 +33,9 @@ #import "GPBDictionary.h" +#import "GPBTestUtilities.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE - // Pull in the macros (using an external file because expanding all tests // in a single file makes a file that is failing to work with within Xcode. //%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm diff --git a/objectivec/Tests/GPBDictionaryTests+Int32.m b/objectivec/Tests/GPBDictionaryTests+Int32.m index 5e25799c..1ee099ee 100644 --- a/objectivec/Tests/GPBDictionaryTests+Int32.m +++ b/objectivec/Tests/GPBDictionaryTests+Int32.m @@ -33,6 +33,7 @@ #import "GPBDictionary.h" +#import "GPBTestUtilities.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" // Pull in the macros (using an external file because expanding all tests @@ -42,10 +43,6 @@ //%PDDM-EXPAND TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14) // This block of code is generated, do not edit it directly. -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE - // To let the testing macros work, add some extra methods to simplify things. @interface GPBInt32EnumDictionary (TestingTweak) + (instancetype)dictionaryWithValue:(int32_t)value forKey:(int32_t)key; diff --git a/objectivec/Tests/GPBDictionaryTests+Int64.m b/objectivec/Tests/GPBDictionaryTests+Int64.m index 6e794d38..4a94e033 100644 --- a/objectivec/Tests/GPBDictionaryTests+Int64.m +++ b/objectivec/Tests/GPBDictionaryTests+Int64.m @@ -33,6 +33,7 @@ #import "GPBDictionary.h" +#import "GPBTestUtilities.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" // Pull in the macros (using an external file because expanding all tests @@ -42,10 +43,6 @@ //%PDDM-EXPAND TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL) // This block of code is generated, do not edit it directly. -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE - // To let the testing macros work, add some extra methods to simplify things. @interface GPBInt64EnumDictionary (TestingTweak) + (instancetype)dictionaryWithValue:(int32_t)value forKey:(int64_t)key; diff --git a/objectivec/Tests/GPBDictionaryTests+String.m b/objectivec/Tests/GPBDictionaryTests+String.m index 95bf2d06..09fbc608 100644 --- a/objectivec/Tests/GPBDictionaryTests+String.m +++ b/objectivec/Tests/GPBDictionaryTests+String.m @@ -33,6 +33,7 @@ #import "GPBDictionary.h" +#import "GPBTestUtilities.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" // Pull in the macros (using an external file because expanding all tests @@ -42,10 +43,6 @@ //%PDDM-EXPAND TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble") // This block of code is generated, do not edit it directly. -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE - // To let the testing macros work, add some extra methods to simplify things. @interface GPBStringEnumDictionary (TestingTweak) + (instancetype)dictionaryWithValue:(int32_t)value forKey:(NSString *)key; diff --git a/objectivec/Tests/GPBDictionaryTests+UInt32.m b/objectivec/Tests/GPBDictionaryTests+UInt32.m index a89ded3d..f8d280fa 100644 --- a/objectivec/Tests/GPBDictionaryTests+UInt32.m +++ b/objectivec/Tests/GPBDictionaryTests+UInt32.m @@ -33,6 +33,7 @@ #import "GPBDictionary.h" +#import "GPBTestUtilities.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" // Pull in the macros (using an external file because expanding all tests @@ -42,10 +43,6 @@ //%PDDM-EXPAND TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U) // This block of code is generated, do not edit it directly. -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE - // To let the testing macros work, add some extra methods to simplify things. @interface GPBUInt32EnumDictionary (TestingTweak) + (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint32_t)key; diff --git a/objectivec/Tests/GPBDictionaryTests+UInt64.m b/objectivec/Tests/GPBDictionaryTests+UInt64.m index 355639c6..cebd6df2 100644 --- a/objectivec/Tests/GPBDictionaryTests+UInt64.m +++ b/objectivec/Tests/GPBDictionaryTests+UInt64.m @@ -33,6 +33,7 @@ #import "GPBDictionary.h" +#import "GPBTestUtilities.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" // Pull in the macros (using an external file because expanding all tests @@ -42,10 +43,6 @@ //%PDDM-EXPAND TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL) // This block of code is generated, do not edit it directly. -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE - // To let the testing macros work, add some extra methods to simplify things. @interface GPBUInt64EnumDictionary (TestingTweak) + (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint64_t)key; diff --git a/objectivec/Tests/GPBDictionaryTests.pddm b/objectivec/Tests/GPBDictionaryTests.pddm index 39793e03..ee26fac8 100644 --- a/objectivec/Tests/GPBDictionaryTests.pddm +++ b/objectivec/Tests/GPBDictionaryTests.pddm @@ -720,10 +720,6 @@ // //%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP) -//%#ifndef GPBARRAYSIZE -//%#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -//%#endif // GPBARRAYSIZE -//% //%// To let the testing macros work, add some extra methods to simplify things. //%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak) //%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key; diff --git a/objectivec/Tests/GPBMessageTests+Merge.m b/objectivec/Tests/GPBMessageTests+Merge.m index 599ad055..3b6fdbd4 100644 --- a/objectivec/Tests/GPBMessageTests+Merge.m +++ b/objectivec/Tests/GPBMessageTests+Merge.m @@ -35,6 +35,7 @@ #import "GPBMessage.h" #import "google/protobuf/MapUnittest.pbobjc.h" +#import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto3.pbobjc.h" @@ -431,7 +432,7 @@ XCTAssertNotNil(dst.oneofGroup); XCTAssertNotEqual(dst.oneofGroup, mergedGroup); // Pointer comparision. - // Back to something else ot make sure message clears out ok. + // Back to something else to make sure message clears out ok. src.oneofInt32 = 10; [dst mergeFrom:src]; @@ -640,7 +641,7 @@ XCTAssertEqualObjects(mergedSubMessage, subMessage); XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault); - // Back to something else ot make sure message clears out ok. + // Back to something else to make sure message clears out ok. src.oneofInt32 = 10; [dst mergeFrom:src]; diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m index 6ad29ca5..4621f90f 100644 --- a/objectivec/Tests/GPBMessageTests+Runtime.m +++ b/objectivec/Tests/GPBMessageTests+Runtime.m @@ -35,6 +35,7 @@ #import "GPBMessage.h" #import "google/protobuf/MapUnittest.pbobjc.h" +#import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto3.pbobjc.h" @@ -772,6 +773,8 @@ XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException, NSInvalidArgumentException); XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar); + + [msg release]; } - (void)testAccessingProto3UnknownEnumValues { @@ -1261,7 +1264,7 @@ Message2_O_OneOfCase_OneofEnum, }; - for (size_t i = 0; i < (sizeof(values) / sizeof((values[0]))); ++i) { + for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) { switch (values[i]) { case Message2_O_OneOfCase_OneofInt32: msg.oneofInt32 = 1; @@ -1318,7 +1321,7 @@ msg.oneofEnum = Message2_Enum_Bar; break; default: - XCTFail(@"shouldn't happen, loop: %zd", i); + XCTFail(@"shouldn't happen, loop: %zd, value: %d", i, values[i]); break; } @@ -1770,7 +1773,7 @@ Message3_O_OneOfCase_OneofEnum, }; - for (size_t i = 0; i < (sizeof(values) / sizeof((values[0]))); ++i) { + for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) { switch (values[i]) { case Message3_O_OneOfCase_OneofInt32: msg.oneofInt32 = 1; @@ -1824,7 +1827,7 @@ msg.oneofEnum = Message3_Enum_Baz; break; default: - XCTFail(@"shouldn't happen, loop: %zd", i); + XCTFail(@"shouldn't happen, loop: %zd, value: %d", i, values[i]); break; } diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m index ddc2ae19..8867f56d 100644 --- a/objectivec/Tests/GPBMessageTests+Serialization.m +++ b/objectivec/Tests/GPBMessageTests+Serialization.m @@ -41,10 +41,6 @@ #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto3.pbobjc.h" -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE - static NSData *DataFromCStr(const char *str) { return [NSData dataWithBytes:str length:strlen(str)]; } @@ -124,7 +120,8 @@ static NSData *DataFromCStr(const char *str) { fooWithExtras.enumValue = DropUnknownsFooWithExtraFields_NestedEnum_Baz; fooWithExtras.extraInt32Value = 2; - DropUnknownsFoo *foo = [DropUnknownsFoo parseFromData:[fooWithExtras data]]; + DropUnknownsFoo *foo = + [DropUnknownsFoo parseFromData:[fooWithExtras data] error:NULL]; XCTAssertEqual(foo.int32Value, 1); XCTAssertEqual(foo.enumValue, DropUnknownsFoo_NestedEnum_Baz); @@ -132,7 +129,8 @@ static NSData *DataFromCStr(const char *str) { XCTAssertEqual([foo.unknownFields countOfFields], 0U); [fooWithExtras release]; - fooWithExtras = [DropUnknownsFooWithExtraFields parseFromData:[foo data]]; + fooWithExtras = + [DropUnknownsFooWithExtraFields parseFromData:[foo data] error:NULL]; XCTAssertEqual(fooWithExtras.int32Value, 1); XCTAssertEqual(fooWithExtras.enumValue, DropUnknownsFooWithExtraFields_NestedEnum_Baz); @@ -153,7 +151,7 @@ static NSData *DataFromCStr(const char *str) { rawValue:Message3_Enum_Extra3]; orig.oneofEnum = Message3_Enum_Extra3; - Message2 *msg = [[Message2 alloc] initWithData:[orig data]]; + Message2 *msg = [[Message2 alloc] initWithData:[orig data] error:NULL]; // None of the fields should be set. @@ -214,7 +212,7 @@ static NSData *DataFromCStr(const char *str) { // Everything should be there via raw values. UnknownEnumsMyMessage *msg = - [UnknownEnumsMyMessage parseFromData:[orig data]]; + [UnknownEnumsMyMessage parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue); XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(msg), @@ -236,7 +234,7 @@ static NSData *DataFromCStr(const char *str) { // Everything should go out and come back. - orig = [UnknownEnumsMyMessagePlusExtra parseFromData:[msg data]]; + orig = [UnknownEnumsMyMessagePlusExtra parseFromData:[msg data] error:NULL]; XCTAssertEqual(orig.e, UnknownEnumsMyEnumPlusExtra_EExtra); XCTAssertEqual(orig.repeatedEArray.count, 1U); @@ -255,7 +253,7 @@ static NSData *DataFromCStr(const char *str) { //% MESSAGE *orig = [[MESSAGE alloc] init]; //% orig.oneof##FIELD = VALUE; //% XCTAssertEqual(orig.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD); -//% MESSAGE *msg = [MESSAGE parseFromData:[orig data]]; +//% MESSAGE *msg = [MESSAGE parseFromData:[orig data] error:NULL]; //% XCTAssertEqual(msg.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD); //% XCTAssertEqual##EQ_SUFFIX(msg.oneof##FIELD, VALUE); //% [orig release]; @@ -323,7 +321,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofInt32 = 1; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt32); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32); XCTAssertEqual(msg.oneofInt32, 1); [orig release]; @@ -333,7 +331,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofInt64 = 2; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt64); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64); XCTAssertEqual(msg.oneofInt64, 2); [orig release]; @@ -343,7 +341,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofUint32 = 3U; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint32); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32); XCTAssertEqual(msg.oneofUint32, 3U); [orig release]; @@ -353,7 +351,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofUint64 = 4U; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint64); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64); XCTAssertEqual(msg.oneofUint64, 4U); [orig release]; @@ -363,7 +361,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofSint32 = 5; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint32); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32); XCTAssertEqual(msg.oneofSint32, 5); [orig release]; @@ -373,7 +371,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofSint64 = 6; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint64); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64); XCTAssertEqual(msg.oneofSint64, 6); [orig release]; @@ -383,7 +381,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofFixed32 = 7U; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed32); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32); XCTAssertEqual(msg.oneofFixed32, 7U); [orig release]; @@ -393,7 +391,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofFixed64 = 8U; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed64); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64); XCTAssertEqual(msg.oneofFixed64, 8U); [orig release]; @@ -403,7 +401,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofSfixed32 = 9; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32); XCTAssertEqual(msg.oneofSfixed32, 9); [orig release]; @@ -413,7 +411,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofSfixed64 = 10; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64); XCTAssertEqual(msg.oneofSfixed64, 10); [orig release]; @@ -423,7 +421,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofFloat = 11.0f; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFloat); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat); XCTAssertEqual(msg.oneofFloat, 11.0f); [orig release]; @@ -433,7 +431,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofDouble = 12.0; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofDouble); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble); XCTAssertEqual(msg.oneofDouble, 12.0); [orig release]; @@ -443,7 +441,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofBool = NO; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBool); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool); XCTAssertEqual(msg.oneofBool, NO); [orig release]; @@ -453,7 +451,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofString = @"foo"; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofString); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString); XCTAssertEqualObjects(msg.oneofString, @"foo"); [orig release]; @@ -463,7 +461,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding]; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBytes); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes); XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]); [orig release]; @@ -473,7 +471,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofGroup = group; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofGroup); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup); XCTAssertEqualObjects(msg.oneofGroup, group); [orig release]; @@ -483,7 +481,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofMessage = subMessage; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofMessage); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage); XCTAssertEqualObjects(msg.oneofMessage, subMessage); [orig release]; @@ -493,7 +491,7 @@ static NSData *DataFromCStr(const char *str) { Message2 *orig = [[Message2 alloc] init]; orig.oneofEnum = Message2_Enum_Bar; XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofEnum); - Message2 *msg = [Message2 parseFromData:[orig data]]; + Message2 *msg = [Message2 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum); XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar); [orig release]; @@ -516,7 +514,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofInt32 = 1; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt32); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32); XCTAssertEqual(msg.oneofInt32, 1); [orig release]; @@ -526,7 +524,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofInt64 = 2; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt64); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64); XCTAssertEqual(msg.oneofInt64, 2); [orig release]; @@ -536,7 +534,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofUint32 = 3U; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint32); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32); XCTAssertEqual(msg.oneofUint32, 3U); [orig release]; @@ -546,7 +544,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofUint64 = 4U; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint64); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64); XCTAssertEqual(msg.oneofUint64, 4U); [orig release]; @@ -556,7 +554,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofSint32 = 5; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint32); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32); XCTAssertEqual(msg.oneofSint32, 5); [orig release]; @@ -566,7 +564,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofSint64 = 6; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint64); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64); XCTAssertEqual(msg.oneofSint64, 6); [orig release]; @@ -576,7 +574,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofFixed32 = 7U; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed32); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32); XCTAssertEqual(msg.oneofFixed32, 7U); [orig release]; @@ -586,7 +584,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofFixed64 = 8U; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed64); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64); XCTAssertEqual(msg.oneofFixed64, 8U); [orig release]; @@ -596,7 +594,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofSfixed32 = 9; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32); XCTAssertEqual(msg.oneofSfixed32, 9); [orig release]; @@ -606,7 +604,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofSfixed64 = 10; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64); XCTAssertEqual(msg.oneofSfixed64, 10); [orig release]; @@ -616,7 +614,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofFloat = 11.0f; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFloat); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat); XCTAssertEqual(msg.oneofFloat, 11.0f); [orig release]; @@ -626,7 +624,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofDouble = 12.0; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofDouble); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble); XCTAssertEqual(msg.oneofDouble, 12.0); [orig release]; @@ -636,7 +634,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofBool = YES; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBool); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool); XCTAssertEqual(msg.oneofBool, YES); [orig release]; @@ -646,7 +644,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofString = @"foo"; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofString); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString); XCTAssertEqualObjects(msg.oneofString, @"foo"); [orig release]; @@ -656,7 +654,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding]; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBytes); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes); XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]); [orig release]; @@ -668,7 +666,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofMessage = subMessage; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofMessage); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage); XCTAssertEqualObjects(msg.oneofMessage, subMessage); [orig release]; @@ -678,7 +676,7 @@ static NSData *DataFromCStr(const char *str) { Message3 *orig = [[Message3 alloc] init]; orig.oneofEnum = Message2_Enum_Bar; XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofEnum); - Message3 *msg = [Message3 parseFromData:[orig data]]; + Message3 *msg = [Message3 parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum); XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar); [orig release]; @@ -695,7 +693,7 @@ static NSData *DataFromCStr(const char *str) { - (void)testMap_StandardWireFormat { NSData *data = DataFromCStr("\x0A\x04\x08\x01\x10\x01"); - TestMap *msg = [[TestMap alloc] initWithData:data]; + TestMap *msg = [[TestMap alloc] initWithData:data error:NULL]; XCTAssertEqual(msg.mapInt32Int32.count, 1U); int32_t val = 666; XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]); @@ -709,7 +707,7 @@ static NSData *DataFromCStr(const char *str) { // put value before key in wire format NSData *data = DataFromCStr("\x0A\x04\x10\x01\x08\x02"); - TestMap *msg = [[TestMap alloc] initWithData:data]; + TestMap *msg = [[TestMap alloc] initWithData:data error:NULL]; XCTAssertEqual(msg.mapInt32Int32.count, 1U); int32_t val = 666; XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]); @@ -723,7 +721,7 @@ static NSData *DataFromCStr(const char *str) { // Two key fields in wire format NSData *data = DataFromCStr("\x0A\x06\x08\x01\x08\x02\x10\x01"); - TestMap *msg = [[TestMap alloc] initWithData:data]; + TestMap *msg = [[TestMap alloc] initWithData:data error:NULL]; XCTAssertEqual(msg.mapInt32Int32.count, 1U); int32_t val = 666; XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]); @@ -737,7 +735,7 @@ static NSData *DataFromCStr(const char *str) { // Two value fields in wire format NSData *data = DataFromCStr("\x0A\x06\x08\x01\x10\x01\x10\x02"); - TestMap *msg = [[TestMap alloc] initWithData:data]; + TestMap *msg = [[TestMap alloc] initWithData:data error:NULL]; XCTAssertEqual(msg.mapInt32Int32.count, 1U); int32_t val = 666; XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]); @@ -751,7 +749,7 @@ static NSData *DataFromCStr(const char *str) { // No key field in wire format NSData *data = DataFromCStr("\x0A\x02\x10\x01"); - TestMap *msg = [[TestMap alloc] initWithData:data]; + TestMap *msg = [[TestMap alloc] initWithData:data error:NULL]; XCTAssertEqual(msg.mapInt32Int32.count, 1U); int32_t val = 666; XCTAssertTrue([msg.mapInt32Int32 valueForKey:0 value:&val]); @@ -765,7 +763,7 @@ static NSData *DataFromCStr(const char *str) { // No value field in wire format NSData *data = DataFromCStr("\x0A\x02\x08\x01"); - TestMap *msg = [[TestMap alloc] initWithData:data]; + TestMap *msg = [[TestMap alloc] initWithData:data error:NULL]; XCTAssertEqual(msg.mapInt32Int32.count, 1U); int32_t val = 666; XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]); @@ -779,7 +777,7 @@ static NSData *DataFromCStr(const char *str) { // Unknown field in wire format NSData *data = DataFromCStr("\x0A\x06\x08\x02\x10\x03\x18\x01"); - TestMap *msg = [[TestMap alloc] initWithData:data]; + TestMap *msg = [[TestMap alloc] initWithData:data error:NULL]; XCTAssertEqual(msg.mapInt32Int32.count, 1U); int32_t val = 666; XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]); @@ -793,8 +791,12 @@ static NSData *DataFromCStr(const char *str) { // corrupted data in wire format NSData *data = DataFromCStr("\x0A\x06\x08\x02\x11\x03"); - XCTAssertThrowsSpecificNamed([TestMap parseFromData:data], NSException, - NSParseErrorException); + NSError *error = nil; + TestMap *msg = [TestMap parseFromData:data error:&error]; + XCTAssertNil(msg); + XCTAssertNotNil(error); + XCTAssertEqualObjects(error.domain, GPBMessageErrorDomain); + XCTAssertEqual(error.code, GPBMessageErrorCodeMalformedData); } // TEST(GeneratedMapFieldTest, Proto2UnknownEnum) @@ -810,14 +812,15 @@ static NSData *DataFromCStr(const char *str) { [orig.unknownMapField setValue:Proto2MapEnumPlusExtra_EProto2MapEnumExtra forKey:0]; - TestEnumMap *msg1 = [TestEnumMap parseFromData:[orig data]]; + TestEnumMap *msg1 = [TestEnumMap parseFromData:[orig data] error:NULL]; XCTAssertEqual(msg1.knownMapField.count, 1U); int32_t val = -1; XCTAssertTrue([msg1.knownMapField valueForKey:0 value:&val]); XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo); XCTAssertEqual(msg1.unknownFields.countOfFields, 1U); - TestEnumMapPlusExtra *msg2 = [TestEnumMapPlusExtra parseFromData:[msg1 data]]; + TestEnumMapPlusExtra *msg2 = + [TestEnumMapPlusExtra parseFromData:[msg1 data] error:NULL]; val = -1; XCTAssertEqual(msg2.knownMapField.count, 1U); XCTAssertTrue([msg2.knownMapField valueForKey:0 value:&val]); @@ -833,6 +836,72 @@ static NSData *DataFromCStr(const char *str) { [orig release]; } -#pragma mark - +#pragma mark - Map Round Tripping + +- (void)testProto2MapRoundTripping { + Message2 *msg = [[Message2 alloc] init]; + + // Key/Value data should result in different byte lengths on wire to ensure + // everything is right. + [msg.mapInt32Int32 setValue:1000 forKey:200]; + [msg.mapInt32Int32 setValue:101 forKey:2001]; + [msg.mapInt64Int64 setValue:1002 forKey:202]; + [msg.mapInt64Int64 setValue:103 forKey:2003]; + [msg.mapUint32Uint32 setValue:1004 forKey:204]; + [msg.mapUint32Uint32 setValue:105 forKey:2005]; + [msg.mapUint64Uint64 setValue:1006 forKey:206]; + [msg.mapUint64Uint64 setValue:107 forKey:2007]; + [msg.mapSint32Sint32 setValue:1008 forKey:208]; + [msg.mapSint32Sint32 setValue:109 forKey:2009]; + [msg.mapSint64Sint64 setValue:1010 forKey:210]; + [msg.mapSint64Sint64 setValue:111 forKey:2011]; + [msg.mapFixed32Fixed32 setValue:1012 forKey:212]; + [msg.mapFixed32Fixed32 setValue:113 forKey:2013]; + [msg.mapFixed64Fixed64 setValue:1014 forKey:214]; + [msg.mapFixed64Fixed64 setValue:115 forKey:2015]; + [msg.mapSfixed32Sfixed32 setValue:1016 forKey:216]; + [msg.mapSfixed32Sfixed32 setValue:117 forKey:2017]; + [msg.mapSfixed64Sfixed64 setValue:1018 forKey:218]; + [msg.mapSfixed64Sfixed64 setValue:119 forKey:2019]; + [msg.mapInt32Float setValue:1020.f forKey:220]; + [msg.mapInt32Float setValue:121.f forKey:2021]; + [msg.mapInt32Double setValue:1022. forKey:222]; + [msg.mapInt32Double setValue:123. forKey:2023]; + [msg.mapBoolBool setValue:false forKey:true]; + [msg.mapBoolBool setValue:true forKey:false]; + msg.mapStringString[@"224"] = @"1024"; + msg.mapStringString[@"2025"] = @"125"; + msg.mapStringBytes[@"226"] = DataFromCStr("1026"); + msg.mapStringBytes[@"2027"] = DataFromCStr("127"); + Message2 *val1 = [[Message2 alloc] init]; + val1.optionalInt32 = 1028; + Message2 *val2 = [[Message2 alloc] init]; + val2.optionalInt32 = 129; + [msg.mapStringMessage setValue:val1 forKey:@"228"]; + [msg.mapStringMessage setValue:val2 forKey:@"2029"]; + [msg.mapInt32Bytes setValue:DataFromCStr("1030 bytes") forKey:230]; + [msg.mapInt32Bytes setValue:DataFromCStr("131") forKey:2031]; + [msg.mapInt32Enum setValue:Message2_Enum_Bar forKey:232]; + [msg.mapInt32Enum setValue:Message2_Enum_Baz forKey:2033]; + Message2 *val3 = [[Message2 alloc] init]; + val3.optionalInt32 = 1034; + Message2 *val4 = [[Message2 alloc] init]; + val4.optionalInt32 = 135; + [msg.mapInt32Message setValue:val3 forKey:234]; + [msg.mapInt32Message setValue:val4 forKey:2035]; + + NSData *data = [msg data]; + Message2 *msg2 = [[Message2 alloc] initWithData:data error:NULL]; + + XCTAssertNotEqual(msg2, msg); // Pointer comparison + XCTAssertEqualObjects(msg2, msg); + + [val4 release]; + [val3 release]; + [val2 release]; + [val1 release]; + [msg2 release]; + [msg release]; +} @end diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index 5ec67cd9..e0154c1a 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -34,6 +34,7 @@ #import "GPBArray_PackagePrivate.h" #import "GPBDescriptor.h" +#import "GPBDictionary_PackagePrivate.h" #import "GPBField_PackagePrivate.h" #import "GPBMessage_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h" @@ -47,23 +48,9 @@ @implementation MessageTests // TODO(thomasvl): this should get split into a few files of logic junks, it is -// a jumble -// of things at the moment (and the testutils have a bunch of the real +// a jumble of things at the moment (and the testutils have a bunch of the real // assertions). -#ifdef DEBUG -- (void)assertBlock:(void (^)())block - throwsWithMessageInUserInfo:(GPBMessage *)message { - @try { - block(); - XCTAssertTrue(NO); - } - @catch (NSException *e) { - XCTAssertEqualObjects([e userInfo][GPBExceptionMessageKey], message); - } -} -#endif // DEBUG - - (TestAllTypes *)mergeSource { TestAllTypes *message = [TestAllTypes message]; [message setOptionalInt32:1]; @@ -290,14 +277,18 @@ XCTAssertTrue(message.initialized); } -#ifdef DEBUG -- (void)testUninitializedException { +- (void)testDataFromUninitialized { TestRequired *message = [TestRequired message]; - [self assertBlock:^{ - [message data]; - } throwsWithMessageInUserInfo:message]; -} + NSData *data = [message data]; + // In DEBUG, the data generation will fail, but in non DEBUG, it passes + // because the check isn't done (for speed). +#ifdef DEBUG + XCTAssertNil(data); +#else + XCTAssertNotNil(data); + XCTAssertFalse(message.initialized); #endif // DEBUG +} - (void)testInitialized { // We're mostly testing that no exception is thrown. @@ -305,18 +296,22 @@ XCTAssertFalse(message.initialized); } -#ifdef DEBUG -- (void)testNestedUninitializedException { +- (void)testDataFromNestedUninitialized { TestRequiredForeign *message = [TestRequiredForeign message]; [message setOptionalMessage:[TestRequired message]]; message.repeatedMessageArray = [NSMutableArray array]; [message.repeatedMessageArray addObject:[TestRequired message]]; [message.repeatedMessageArray addObject:[TestRequired message]]; - [self assertBlock:^{ - [message data]; - } throwsWithMessageInUserInfo:message]; -} + NSData *data = [message data]; + // In DEBUG, the data generation will fail, but in non DEBUG, it passes + // because the check isn't done (for speed). +#ifdef DEBUG + XCTAssertNil(data); +#else + XCTAssertNotNil(data); + XCTAssertFalse(message.initialized); #endif // DEBUG +} - (void)testNestedInitialized { // We're mostly testing that no exception is thrown. @@ -330,13 +325,23 @@ XCTAssertFalse(message.initialized); } -#ifdef DEBUG - (void)testParseUninitialized { - [self assertBlock:^{ - [TestRequired parseFromData:GPBEmptyNSData()]; - } throwsWithMessageInUserInfo:[TestRequired message]]; -} + NSError *error = nil; + TestRequired *msg = + [TestRequired parseFromData:GPBEmptyNSData() error:&error]; + // In DEBUG, the parse will fail, but in non DEBUG, it passes because + // the check isn't done (for speed). +#ifdef DEBUG + XCTAssertNil(msg); + XCTAssertNotNil(error); + XCTAssertEqualObjects(error.domain, GPBMessageErrorDomain); + XCTAssertEqual(error.code, GPBMessageErrorCodeMissingRequiredField); +#else + XCTAssertNotNil(msg); + XCTAssertNil(error); + XCTAssertFalse(msg.initialized); #endif // DEBUG +} - (void)testCoding { NSData *data = @@ -1033,7 +1038,7 @@ message3.repeatedStringArray = [NSMutableArray arrayWithObject:@"wee"]; XCTAssertNotNil(message.repeatedInt32Array); XCTAssertNotNil(message.repeatedStringArray); - TestAllTypes *message4 = [message3 copy]; + TestAllTypes *message4 = [[message3 copy] autorelease]; XCTAssertNotEqual(message3.repeatedInt32Array, message4.repeatedInt32Array); XCTAssertEqualObjects(message3.repeatedInt32Array, message4.repeatedInt32Array); @@ -1156,6 +1161,205 @@ XCTAssertFalse([message hasA]); } +- (void)testDefaultingMaps { + // Basic tests for default creation of maps in a message. + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + TestRecursiveMessageWithRepeatedField *message2 = + [TestRecursiveMessageWithRepeatedField message]; + + // Simply accessing the map should not make any fields visible. + XCTAssertNotNil(message.a.a.iToI); + XCTAssertFalse([message hasA]); + XCTAssertFalse([message.a hasA]); + XCTAssertNotNil(message2.a.a.strToStr); + XCTAssertFalse([message2 hasA]); + XCTAssertFalse([message2.a hasA]); + + // But adding an element to the map should. + [message.a.a.iToI setValue:100 forKey:200]; + XCTAssertTrue([message hasA]); + XCTAssertTrue([message.a hasA]); + XCTAssertEqual([message.a.a.iToI count], (NSUInteger)1); + [message2.a.a.strToStr setObject:@"foo" forKey:@"bar"]; + XCTAssertTrue([message2 hasA]); + XCTAssertTrue([message2.a hasA]); + XCTAssertEqual([message2.a.a.strToStr count], (NSUInteger)1); +} + +- (void)testAutocreatedMapShared { + // Multiple objects pointing to the same map. + TestRecursiveMessageWithRepeatedField *message1a = + [TestRecursiveMessageWithRepeatedField message]; + TestRecursiveMessageWithRepeatedField *message1b = + [TestRecursiveMessageWithRepeatedField message]; + message1a.a.iToI = message1b.a.iToI; + XCTAssertTrue([message1a hasA]); + XCTAssertFalse([message1b hasA]); + [message1a.a.iToI setValue:1 forKey:2]; + XCTAssertTrue([message1a hasA]); + XCTAssertTrue([message1b hasA]); + XCTAssertEqual(message1a.a.iToI, message1b.a.iToI); + + TestRecursiveMessageWithRepeatedField *message2a = + [TestRecursiveMessageWithRepeatedField message]; + TestRecursiveMessageWithRepeatedField *message2b = + [TestRecursiveMessageWithRepeatedField message]; + message2a.a.strToStr = message2b.a.strToStr; + XCTAssertTrue([message2a hasA]); + XCTAssertFalse([message2b hasA]); + [message2a.a.strToStr setObject:@"bar" forKey:@"foo"]; + XCTAssertTrue([message2a hasA]); + XCTAssertTrue([message2b hasA]); + XCTAssertEqual(message2a.a.strToStr, message2b.a.strToStr); +} + +- (void)testAutocreatedMapCopy { + // Copy should not copy autocreated maps. + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + XCTAssertNotNil(message.strToStr); + XCTAssertNotNil(message.iToI); + TestRecursiveMessageWithRepeatedField *message2 = + [[message copy] autorelease]; + // Pointer conparisions. + XCTAssertNotEqual(message.strToStr, message2.strToStr); + XCTAssertNotEqual(message.iToI, message2.iToI); + + // Mutable copy should copy empty arrays that were explicitly set (end up + // with different objects that are equal). + TestRecursiveMessageWithRepeatedField *message3 = + [TestRecursiveMessageWithRepeatedField message]; + message3.iToI = [GPBInt32Int32Dictionary dictionaryWithValue:10 forKey:20]; + message3.strToStr = + [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"123"]; + XCTAssertNotNil(message.iToI); + XCTAssertNotNil(message.iToI); + TestRecursiveMessageWithRepeatedField *message4 = + [[message3 copy] autorelease]; + XCTAssertNotEqual(message3.iToI, message4.iToI); + XCTAssertEqualObjects(message3.iToI, message4.iToI); + XCTAssertNotEqual(message3.strToStr, message4.strToStr); + XCTAssertEqualObjects(message3.strToStr, message4.strToStr); +} + +- (void)testAutocreatedMapRetain { + // Should be able to retain autocreated map while the creator is dealloced. + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + + @autoreleasepool { + TestRecursiveMessageWithRepeatedField *message2 = + [TestRecursiveMessageWithRepeatedField message]; + message.iToI = message2.iToI; + message.strToStr = message2.strToStr; + // Pointer conparision + XCTAssertEqual(message.iToI->_autocreator, message2); + XCTAssertTrue([message.strToStr + isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual( + ((GPBAutocreatedDictionary *)message.strToStr)->_autocreator, + message2); + } + + XCTAssertNil(message.iToI->_autocreator); + XCTAssertTrue( + [message.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertNil( + ((GPBAutocreatedDictionary *)message.strToStr)->_autocreator); +} + +- (void)testSetNilAutocreatedMap { + // Setting map to nil should cause it to lose its delegate. + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + GPBInt32Int32Dictionary *iToI = [message.iToI retain]; + GPBAutocreatedDictionary *strToStr = + (GPBAutocreatedDictionary *)[message.strToStr retain]; + XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(iToI->_autocreator, message); + XCTAssertEqual(strToStr->_autocreator, message); + message.iToI = nil; + message.strToStr = nil; + XCTAssertNil(iToI->_autocreator); + XCTAssertNil(strToStr->_autocreator); + [iToI release]; + [strToStr release]; +} + +- (void)testReplaceAutocreatedMap { + // Replacing map should orphan the old one and cause its creator to become + // visible. + { + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + XCTAssertNotNil(message.a); + XCTAssertNotNil(message.a.iToI); + XCTAssertFalse([message hasA]); + GPBInt32Int32Dictionary *iToI = [message.a.iToI retain]; + XCTAssertEqual(iToI->_autocreator, message.a); // Pointer comparision + message.a.iToI = [GPBInt32Int32Dictionary dictionaryWithValue:6 forKey:7]; + XCTAssertTrue([message hasA]); + XCTAssertNotEqual(message.a.iToI, iToI); // Pointer comparision + XCTAssertNil(iToI->_autocreator); + [iToI release]; + } + + { + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + XCTAssertNotNil(message.a); + XCTAssertNotNil(message.a.strToStr); + XCTAssertFalse([message hasA]); + GPBAutocreatedDictionary *strToStr = + (GPBAutocreatedDictionary *)[message.a.strToStr retain]; + XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertEqual(strToStr->_autocreator, message.a); // Pointer comparision + message.a.strToStr = + [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"def"]; + XCTAssertTrue([message hasA]); + XCTAssertNotEqual(message.a.strToStr, strToStr); // Pointer comparision + XCTAssertNil(strToStr->_autocreator); + [strToStr release]; + } +} + +- (void)testSetAutocreatedMapToSelf { + // Setting map to itself should cause it to become visible. + { + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + XCTAssertNotNil(message.a); + XCTAssertNotNil(message.a.iToI); + XCTAssertFalse([message hasA]); + message.a.iToI = message.a.iToI; + XCTAssertTrue([message hasA]); + XCTAssertNil(message.a.iToI->_autocreator); + } + + { + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + XCTAssertNotNil(message.a); + XCTAssertNotNil(message.a.strToStr); + XCTAssertFalse([message hasA]); + message.a.strToStr = message.a.strToStr; + XCTAssertTrue([message hasA]); + XCTAssertTrue([message.a.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]); + XCTAssertNil(((GPBAutocreatedDictionary *)message.a.strToStr)->_autocreator); + } +} + +- (void)testAutocreatedMapRemoveAllValues { + // Calling removeAll on autocreated map should not cause it to be visible. + TestRecursiveMessageWithRepeatedField *message = + [TestRecursiveMessageWithRepeatedField message]; + [message.a.iToI removeAll]; + XCTAssertFalse([message hasA]); + [message.a.strToStr removeAllObjects]; + XCTAssertFalse([message hasA]); +} + - (void)testExtensionAccessors { TestAllExtensions *message = [TestAllExtensions message]; [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount]; @@ -1555,7 +1759,8 @@ GPBMessage *message = [GPBMessage message]; [message setUnknownFields:unknowns]; NSData *data = [message data]; - GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil]; + GPBMessage *message2 = + [GPBMessage parseFromData:data extensionRegistry:nil error:NULL]; XCTAssertEqualObjects(message, message2); } @@ -1579,9 +1784,11 @@ GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:delimitedData]; GPBMessage *message3 = [GPBMessage parseDelimitedFromCodedInputStream:input - extensionRegistry:nil]; + extensionRegistry:nil + error:NULL]; GPBMessage *message4 = [GPBMessage parseDelimitedFromCodedInputStream:input - extensionRegistry:nil]; + extensionRegistry:nil + error:NULL]; XCTAssertEqualObjects(message1, message3); XCTAssertEqualObjects(message2, message4); } @@ -1673,7 +1880,7 @@ XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_One); XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegOne); // Bounce to wire and back. - EnumTestMsg *msgPrime = [EnumTestMsg parseFromData:[msg data]]; + EnumTestMsg *msgPrime = [EnumTestMsg parseFromData:[msg data] error:NULL]; XCTAssertEqualObjects(msgPrime, msg); XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero); XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_One); @@ -1685,7 +1892,7 @@ XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_Two); XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegTwo); // Bounce to wire and back. - msgPrime = [EnumTestMsg parseFromData:[msg data]]; + msgPrime = [EnumTestMsg parseFromData:[msg data] error:NULL]; XCTAssertEqualObjects(msgPrime, msg); XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero); XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_Two); @@ -1706,7 +1913,7 @@ XCTAssertEqual([msg.mumbleArray valueAtIndex:3], EnumTestMsg_MyEnum_NegOne); XCTAssertEqual([msg.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo); // Bounce to wire and back. - msgPrime = [EnumTestMsg parseFromData:[msg data]]; + msgPrime = [EnumTestMsg parseFromData:[msg data] error:NULL]; XCTAssertEqualObjects(msgPrime, msg); XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:0], EnumTestMsg_MyEnum_Zero); diff --git a/objectivec/Tests/GPBPerfTests.m b/objectivec/Tests/GPBPerfTests.m index d09021af..1259d146 100644 --- a/objectivec/Tests/GPBPerfTests.m +++ b/objectivec/Tests/GPBPerfTests.m @@ -30,6 +30,7 @@ #import "GPBTestUtilities.h" #import "google/protobuf/Unittest.pbobjc.h" +#import "google/protobuf/UnittestImport.pbobjc.h" #import "google/protobuf/UnittestObjc.pbobjc.h" // @@ -57,7 +58,7 @@ static const uint32_t kRepeatedCount = 100; [self setAllFields:message repeatedCount:kRepeatedCount]; NSData* rawBytes = [message data]; [message release]; - message = [[TestAllTypes alloc] initWithData:rawBytes]; + message = [[TestAllTypes alloc] initWithData:rawBytes error:NULL]; [message release]; } }]; @@ -71,7 +72,7 @@ static const uint32_t kRepeatedCount = 100; NSData* rawBytes = [message data]; [message release]; TestAllExtensions* message2 = - [[TestAllExtensions alloc] initWithData:rawBytes]; + [[TestAllExtensions alloc] initWithData:rawBytes error:NULL]; [message2 release]; } }]; @@ -84,7 +85,7 @@ static const uint32_t kRepeatedCount = 100; [self setPackedFields:message repeatedCount:kRepeatedCount]; NSData* rawBytes = [message data]; [message release]; - message = [[TestPackedTypes alloc] initWithData:rawBytes]; + message = [[TestPackedTypes alloc] initWithData:rawBytes error:NULL]; [message release]; } }]; @@ -98,7 +99,7 @@ static const uint32_t kRepeatedCount = 100; NSData* rawBytes = [message data]; [message release]; TestPackedExtensions* message2 = - [[TestPackedExtensions alloc] initWithData:rawBytes]; + [[TestPackedExtensions alloc] initWithData:rawBytes error:NULL]; [message2 release]; } }]; diff --git a/objectivec/Tests/GPBStringTests.m b/objectivec/Tests/GPBStringTests.m index 30f13775..802afa7d 100644 --- a/objectivec/Tests/GPBStringTests.m +++ b/objectivec/Tests/GPBStringTests.m @@ -31,10 +31,7 @@ #import #import "GPBCodedInputStream_PackagePrivate.h" - -#ifndef GPBARRAYSIZE -#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) -#endif // GPBARRAYSIZE +#import "GPBTestUtilities.h" @interface TestClass : NSObject @property(nonatomic, retain) NSString *foo; diff --git a/objectivec/Tests/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift index e7b6f94c..30b9cbd4 100644 --- a/objectivec/Tests/GPBSwiftTests.swift +++ b/objectivec/Tests/GPBSwiftTests.swift @@ -53,6 +53,12 @@ class GPBBridgeTests: XCTestCase { msg.repeatedStringArray.addObject("pqr") msg.repeatedEnumArray.addValue(Message2_Enum.Bar.rawValue) msg.repeatedEnumArray.addValue(Message2_Enum.Baz.rawValue) + msg.mapInt32Int32.setValue(400, forKey:500) + msg.mapInt32Int32.setValue(401, forKey:501) + msg.mapStringString.setObject("foo", forKey:"bar") + msg.mapStringString.setObject("abc", forKey:"xyz") + msg.mapInt32Enum.setValue(Message2_Enum.Bar.rawValue, forKey:600) + msg.mapInt32Enum.setValue(Message2_Enum.Baz.rawValue, forKey:601) // Check has*. XCTAssertTrue(msg.hasOptionalInt32) @@ -83,6 +89,20 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message2_Enum.Bar.rawValue) XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message2_Enum.Baz.rawValue) XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0)) + XCTAssertEqual(msg.mapInt32Int32.count, UInt(2)) + var intValue: Int32 = 0; + XCTAssertTrue(msg.mapInt32Int32.valueForKey(500, value:&intValue)) + XCTAssertEqual(intValue, Int32(400)) + XCTAssertTrue(msg.mapInt32Int32.valueForKey(501, value:&intValue)) + XCTAssertEqual(intValue, Int32(401)) + XCTAssertEqual(msg.mapStringString.count, Int(2)) + XCTAssertEqual(msg.mapStringString.objectForKey("bar") as! String, "foo") + XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as! String, "abc") + XCTAssertEqual(msg.mapInt32Enum.count, UInt(2)) + XCTAssertTrue(msg.mapInt32Enum.valueForKey(600, value:&intValue)) + XCTAssertEqual(intValue, Message2_Enum.Bar.rawValue) + XCTAssertTrue(msg.mapInt32Enum.valueForKey(601, value:&intValue)) + XCTAssertEqual(intValue, Message2_Enum.Baz.rawValue) // Clearing a string with nil. msg2.optionalString = nil @@ -109,6 +129,9 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0)) XCTAssertEqual(msg.repeatedStringArray.count, Int(0)) XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0)) + XCTAssertEqual(msg.mapInt32Int32.count, UInt(0)) + XCTAssertEqual(msg.mapStringString.count, Int(0)) + XCTAssertEqual(msg.mapInt32Enum.count, UInt(0)) } func testProto3Basics() { @@ -128,6 +151,13 @@ class GPBBridgeTests: XCTestCase { msg.repeatedEnumArray.addValue(Message3_Enum.Bar.rawValue) msg.repeatedEnumArray.addRawValue(666) SetMessage3_OptionalEnum_RawValue(msg2, 666) + msg.mapInt32Int32.setValue(400, forKey:500) + msg.mapInt32Int32.setValue(401, forKey:501) + msg.mapStringString.setObject("foo", forKey:"bar") + msg.mapStringString.setObject("abc", forKey:"xyz") + msg.mapInt32Enum.setValue(Message2_Enum.Bar.rawValue, forKey:600) + // "proto3" syntax lets enum get unknown values. + msg.mapInt32Enum.setRawValue(666, forKey:601) // Has only exists on for message fields. XCTAssertTrue(msg.hasOptionalMessage) @@ -152,6 +182,22 @@ class GPBBridgeTests: XCTestCase { XCTAssertEqual(msg.repeatedEnumArray.rawValueAtIndex(1), 666) XCTAssertEqual(msg2.optionalEnum, Message3_Enum.GPBUnrecognizedEnumeratorValue) XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Int32(666)) + XCTAssertEqual(msg.mapInt32Int32.count, UInt(2)) + var intValue: Int32 = 0; + XCTAssertTrue(msg.mapInt32Int32.valueForKey(500, value:&intValue)) + XCTAssertEqual(intValue, Int32(400)) + XCTAssertTrue(msg.mapInt32Int32.valueForKey(501, value:&intValue)) + XCTAssertEqual(intValue, Int32(401)) + XCTAssertEqual(msg.mapStringString.count, Int(2)) + XCTAssertEqual(msg.mapStringString.objectForKey("bar") as! String, "foo") + XCTAssertEqual(msg.mapStringString.objectForKey("xyz") as! String, "abc") + XCTAssertEqual(msg.mapInt32Enum.count, UInt(2)) + XCTAssertTrue(msg.mapInt32Enum.valueForKey(600, value:&intValue)) + XCTAssertEqual(intValue, Message2_Enum.Bar.rawValue) + XCTAssertTrue(msg.mapInt32Enum.valueForKey(601, value:&intValue)) + XCTAssertEqual(intValue, Message3_Enum.GPBUnrecognizedEnumeratorValue.rawValue) + XCTAssertTrue(msg.mapInt32Enum.valueForKey(601, rawValue:&intValue)) + XCTAssertEqual(intValue, 666) // Clearing a string with nil. msg2.optionalString = nil @@ -175,6 +221,9 @@ class GPBBridgeTests: XCTestCase { msg2.clear() XCTAssertEqual(msg2.optionalEnum, Message3_Enum.Foo) // Default XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Message3_Enum.Foo.rawValue) + XCTAssertEqual(msg.mapInt32Int32.count, UInt(0)) + XCTAssertEqual(msg.mapStringString.count, Int(0)) + XCTAssertEqual(msg.mapInt32Enum.count, UInt(0)) } func testAutoCreation() { @@ -390,15 +439,21 @@ class GPBBridgeTests: XCTestCase { msg.optionalGroup.a = 102 msg.repeatedStringArray.addObject("abc") msg.repeatedStringArray.addObject("def") + msg.mapInt32Int32.setValue(200, forKey:300) + msg.mapInt32Int32.setValue(201, forKey:201) + msg.mapStringString.setObject("foo", forKey:"bar") + msg.mapStringString.setObject("abc", forKey:"xyz") let data = msg.data() - let msg2 = Message2(data: data) + let msg2 = Message2(data: data, error:nil) XCTAssertTrue(msg2 !== msg) // New instance XCTAssertEqual(msg.optionalInt32, Int32(100)) XCTAssertEqual(msg.optionalInt64, Int64(101)) XCTAssertEqual(msg.optionalGroup.a, Int32(102)) XCTAssertEqual(msg.repeatedStringArray.count, Int(2)) + XCTAssertEqual(msg.mapInt32Int32.count, UInt(2)) + XCTAssertEqual(msg.mapStringString.count, Int(2)) XCTAssertEqual(msg2, msg) } diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h index 37e30f96..6ae68c3a 100644 --- a/objectivec/Tests/GPBTestUtilities.h +++ b/objectivec/Tests/GPBTestUtilities.h @@ -37,6 +37,13 @@ @class TestPackedExtensions; @class GPBExtensionRegistry; + +// Helper for uses of C arrays in tests cases. +#ifndef GPBARRAYSIZE +#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0])))) +#endif // GPBARRAYSIZE + + // The number of repetitions of any repeated objects inside of test messages. extern const uint32_t kGPBDefaultRepeatCount; diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m index d664a88a..6058dfc1 100644 --- a/objectivec/Tests/GPBTestUtilities.m +++ b/objectivec/Tests/GPBTestUtilities.m @@ -32,6 +32,7 @@ #import "google/protobuf/MapUnittest.pbobjc.h" #import "google/protobuf/Unittest.pbobjc.h" +#import "google/protobuf/UnittestImport.pbobjc.h" const uint32_t kGPBDefaultRepeatCount = 2; @@ -1060,25 +1061,6 @@ const uint32_t kGPBDefaultRepeatCount = 2; } - (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count { - message.mapInt32Int32 = [GPBInt32Int32Dictionary dictionary]; - message.mapInt64Int64 = [GPBInt64Int64Dictionary dictionary]; - message.mapUint32Uint32 = [GPBUInt32UInt32Dictionary dictionary]; - message.mapUint64Uint64 = [GPBUInt64UInt64Dictionary dictionary]; - message.mapSint32Sint32 = [GPBInt32Int32Dictionary dictionary]; - message.mapSint64Sint64 = [GPBInt64Int64Dictionary dictionary]; - message.mapFixed32Fixed32 = [GPBUInt32UInt32Dictionary dictionary]; - message.mapFixed64Fixed64 = [GPBUInt64UInt64Dictionary dictionary]; - message.mapSfixed32Sfixed32 = [GPBInt32Int32Dictionary dictionary]; - message.mapSfixed64Sfixed64 = [GPBInt64Int64Dictionary dictionary]; - message.mapInt32Float = [GPBInt32FloatDictionary dictionary]; - message.mapInt32Double = [GPBInt32DoubleDictionary dictionary]; - message.mapBoolBool = [GPBBoolBoolDictionary dictionary]; - message.mapStringString = [NSMutableDictionary dictionary]; - message.mapInt32Bytes = [GPBInt32ObjectDictionary dictionary]; - message.mapInt32Enum = [GPBInt32EnumDictionary - dictionaryWithValidationFunction:MapEnum_IsValidValue]; - message.mapInt32ForeignMessage = [GPBInt32ObjectDictionary dictionary]; - for (uint32_t i = 0; i < count; i++) { [message.mapInt32Int32 setValue:(i + 1) forKey:100 + i * 100]; [message.mapInt64Int64 setValue:(i + 1) forKey:101 + i * 100]; diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m index 80186088..491bba9e 100644 --- a/objectivec/Tests/GPBUnknownFieldSetTest.m +++ b/objectivec/Tests/GPBUnknownFieldSetTest.m @@ -56,7 +56,7 @@ - (void)setUp { allFields_ = [self allSetRepeatedCount:kGPBDefaultRepeatCount]; allFieldsData_ = [allFields_ data]; - emptyMessage_ = [TestEmptyMessage parseFromData:allFieldsData_]; + emptyMessage_ = [TestEmptyMessage parseFromData:allFieldsData_ error:NULL]; unknownFields_ = emptyMessage_.unknownFields; } @@ -176,7 +176,7 @@ [fields addField:field]; NSData* data = fields.data; - TestAllTypes* destination = [TestAllTypes parseFromData:data]; + TestAllTypes* destination = [TestAllTypes parseFromData:data error:NULL]; [self assertAllFieldsSet:destination repeatedCount:kGPBDefaultRepeatCount]; XCTAssertEqual(destination.unknownFields.countOfFields, (NSUInteger)1); @@ -191,8 +191,10 @@ // when parsing. NSData* bizarroData = [self getBizarroData]; - TestAllTypes* allTypesMessage = [TestAllTypes parseFromData:bizarroData]; - TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData]; + TestAllTypes* allTypesMessage = + [TestAllTypes parseFromData:bizarroData error:NULL]; + TestEmptyMessage* emptyMessage = + [TestEmptyMessage parseFromData:bizarroData error:NULL]; // All fields should have been interpreted as unknown, so the debug strings // should be the same. @@ -204,7 +206,7 @@ // they are declared as extension numbers. TestEmptyMessageWithExtensions* message = - [TestEmptyMessageWithExtensions parseFromData:allFieldsData_]; + [TestEmptyMessageWithExtensions parseFromData:allFieldsData_ error:NULL]; XCTAssertEqual(unknownFields_.countOfFields, message.unknownFields.countOfFields); @@ -217,8 +219,9 @@ NSData* bizarroData = [self getBizarroData]; TestAllExtensions* allExtensionsMessage = - [TestAllExtensions parseFromData:bizarroData]; - TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData]; + [TestAllExtensions parseFromData:bizarroData error:NULL]; + TestEmptyMessage* emptyMessage = + [TestEmptyMessage parseFromData:bizarroData error:NULL]; // All fields should have been interpreted as unknown, so the debug strings // should be the same. diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m index 1344af08..fc5c4bda 100644 --- a/objectivec/Tests/GPBWireFormatTests.m +++ b/objectivec/Tests/GPBWireFormatTests.m @@ -47,7 +47,7 @@ NSData* rawBytes = message.data; XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length); - TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes]; + TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes error:NULL]; [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; } @@ -59,7 +59,8 @@ NSData* rawBytes = message.data; XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length); - TestPackedTypes* message2 = [TestPackedTypes parseFromData:rawBytes]; + TestPackedTypes* message2 = + [TestPackedTypes parseFromData:rawBytes error:NULL]; [self assertPackedFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; } @@ -74,7 +75,7 @@ NSData* rawBytes = message.data; XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length); - TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes]; + TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes error:NULL]; [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; } @@ -103,8 +104,9 @@ GPBExtensionRegistry* registry = [self extensionRegistry]; - TestAllExtensions* message2 = - [TestAllExtensions parseFromData:rawBytes extensionRegistry:registry]; + TestAllExtensions* message2 = [TestAllExtensions parseFromData:rawBytes + extensionRegistry:registry + error:NULL]; [self assertAllExtensionsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; } @@ -124,8 +126,9 @@ GPBExtensionRegistry* registry = [self extensionRegistry]; - TestPackedExtensions* message2 = - [TestPackedExtensions parseFromData:rawBytes extensionRegistry:registry]; + TestPackedExtensions* message2 = [TestPackedExtensions parseFromData:rawBytes + extensionRegistry:registry + error:NULL]; [self assertPackedExtensionsSet:message2 repeatedCount:kGPBDefaultRepeatCount]; @@ -151,7 +154,7 @@ const int kUnknownTypeId = 1550055; NSData* data = [message_set data]; // Parse back using RawMessageSet and check the contents. - RawMessageSet* raw = [RawMessageSet parseFromData:data]; + RawMessageSet* raw = [RawMessageSet parseFromData:data error:NULL]; XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0); @@ -163,11 +166,13 @@ const int kUnknownTypeId = 1550055; XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId); TestMessageSetExtension1* message1 = - [TestMessageSetExtension1 parseFromData:[raw.itemArray[0] message]]; + [TestMessageSetExtension1 parseFromData:[raw.itemArray[0] message] + error:NULL]; XCTAssertEqual(message1.i, 123); TestMessageSetExtension2* message2 = - [TestMessageSetExtension2 parseFromData:[raw.itemArray[1] message]]; + [TestMessageSetExtension2 parseFromData:[raw.itemArray[1] message] + error:NULL]; XCTAssertEqualObjects(message2.str, @"foo"); XCTAssertEqualObjects([raw.itemArray[2] message], @@ -209,7 +214,8 @@ const int kUnknownTypeId = 1550055; // Parse as a TestMessageSet and check the contents. TestMessageSet* messageSet = [TestMessageSet parseFromData:data - extensionRegistry:[UnittestMsetRoot extensionRegistry]]; + extensionRegistry:[UnittestMsetRoot extensionRegistry] + error:NULL]; XCTAssertEqual( [[messageSet diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto index d288a30d..3bb92761 100644 --- a/objectivec/Tests/unittest_objc.proto +++ b/objectivec/Tests/unittest_objc.proto @@ -44,6 +44,8 @@ message TestRecursiveMessageWithRepeatedField { optional TestRecursiveMessageWithRepeatedField a = 1; repeated int32 i = 2; repeated string str = 3; + map i_to_i = 4; + map str_to_str = 5; } // Recursive message and extension to for testing autocreators at different diff --git a/objectivec/Tests/unittest_runtime_proto2.proto b/objectivec/Tests/unittest_runtime_proto2.proto index f9fd3c35..12a2da68 100644 --- a/objectivec/Tests/unittest_runtime_proto2.proto +++ b/objectivec/Tests/unittest_runtime_proto2.proto @@ -105,4 +105,25 @@ message Message2 { Message2 oneof_message = 68; Enum oneof_enum = 69 [default = BAZ]; } + + // Some token map cases, too many combinations to list them all. + map map_int32_int32 = 70; + map map_int64_int64 = 71; + map map_uint32_uint32 = 72; + map map_uint64_uint64 = 73; + map map_sint32_sint32 = 74; + map map_sint64_sint64 = 75; + map map_fixed32_fixed32 = 76; + map map_fixed64_fixed64 = 77; + map map_sfixed32_sfixed32 = 78; + map map_sfixed64_sfixed64 = 79; + map map_int32_float = 80; + map map_int32_double = 81; + map map_bool_bool = 82; + map map_string_string = 83; + map map_string_bytes = 84; + map map_string_message = 85; + map map_int32_bytes = 86; + map map_int32_enum = 87; + map map_int32_message = 88; } diff --git a/objectivec/Tests/unittest_runtime_proto3.proto b/objectivec/Tests/unittest_runtime_proto3.proto index b6a2f4dc..feb7029d 100644 --- a/objectivec/Tests/unittest_runtime_proto3.proto +++ b/objectivec/Tests/unittest_runtime_proto3.proto @@ -98,4 +98,25 @@ message Message3 { Message3 oneof_message = 68; Enum oneof_enum = 69; } + + // Some token map cases, too many combinations to list them all. + map map_int32_int32 = 70; + map map_int64_int64 = 71; + map map_uint32_uint32 = 72; + map map_uint64_uint64 = 73; + map map_sint32_sint32 = 74; + map map_sint64_sint64 = 75; + map map_fixed32_fixed32 = 76; + map map_fixed64_fixed64 = 77; + map map_sfixed32_sfixed32 = 78; + map map_sfixed64_sfixed64 = 79; + map map_int32_float = 80; + map map_int32_double = 81; + map map_bool_bool = 82; + map map_string_string = 83; + map map_string_bytes = 84; + map map_string_message = 85; + map map_int32_bytes = 86; + map map_int32_enum = 87; + map map_int32_message = 88; } diff --git a/objectivec/generate_descriptors_proto.sh b/objectivec/generate_descriptors_proto.sh new file mode 100755 index 00000000..f2ed00b7 --- /dev/null +++ b/objectivec/generate_descriptors_proto.sh @@ -0,0 +1,54 @@ +#!/bin/bash + +# Run this script to regenerate descriptor.pbobjc.{h,m} after the protocol +# compiler changes. + +# HINT: Flags passed to generate_descriptor_proto.sh will be passed directly +# to make when building protoc. This is particularly useful for passing +# -j4 to run 4 jobs simultaneously. + +set -eu + +readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")") +readonly ProtoRootDir="${ScriptDir}/.." +readonly ProtoC="${ProtoRootDir}/src/protoc" + +pushd "${ProtoRootDir}" > /dev/null + +if test ! -e src/google/protobuf/stubs/common.h; then + cat >&2 << __EOF__ +Could not find source code. Make sure you are running this script from the +root of the distribution tree. +__EOF__ + exit 1 +fi + +if test ! -e src/Makefile; then + cat >&2 << __EOF__ +Could not find src/Makefile. You must run ./configure (and perhaps +./autogen.sh) first. +__EOF__ + exit 1 +fi + +# Make sure the compiler is current. +cd src +make $@ google/protobuf/stubs/pbconfig.h +make $@ protoc + +declare -a RUNTIME_PROTO_FILES=(\ + google/protobuf/any.proto \ + google/protobuf/api.proto \ + google/protobuf/descriptor.proto \ + google/protobuf/duration.proto \ + google/protobuf/empty.proto \ + google/protobuf/field_mask.proto \ + google/protobuf/source_context.proto \ + google/protobuf/struct.proto \ + google/protobuf/timestamp.proto \ + google/protobuf/type.proto \ + google/protobuf/wrappers.proto) + +./protoc --objc_out="${ProtoRootDir}/objectivec" ${RUNTIME_PROTO_FILES[@]} + +popd > /dev/null diff --git a/objectivec/google/protobuf/Any.pbobjc.h b/objectivec/google/protobuf/Any.pbobjc.h new file mode 100644 index 00000000..8154318e --- /dev/null +++ b/objectivec/google/protobuf/Any.pbobjc.h @@ -0,0 +1,100 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +#import "GPBProtocolBuffers.h" + +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 +#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#endif + +// @@protoc_insertion_point(imports) + +CF_EXTERN_C_BEGIN + + +#pragma mark - GPBAnyRoot + +@interface GPBAnyRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + +@end + +#pragma mark - GPBAny + +typedef GPB_ENUM(GPBAny_FieldNumber) { + GPBAny_FieldNumber_TypeURL = 1, + GPBAny_FieldNumber_Value = 2, +}; + +// `Any` contains an arbitrary serialized message along with a URL +// that describes the type of the serialized message. +// +// The proto runtimes and/or compiler will eventually +// provide utilities to pack/unpack Any values (projected Q1/15). +// +// # JSON +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the the `@type` +// field. Example (for message [google.protobuf.Duration][google.protobuf.Duration]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +@interface GPBAny : GPBMessage + +// A URL/resource name whose content describes the type of the +// serialized message. +// +// For URLs which use the schema `http`, `https`, or no schema, the +// following restrictions and interpretations apply: +// +// * If no schema is provided, `https` is assumed. +// * The last segment of the URL's path must represent the fully +// qualified name of the type (as in `path/google.protobuf.Duration`). +// * An HTTP GET on the URL must yield a [google.protobuf.Type][google.protobuf.Type] +// value in binary format, or produce an error. +// * Applications are allowed to cache lookup results based on the +// URL, or have them precompiled into a binary to avoid any +// lookup. Therefore, binary compatibility needs to be preserved +// on changes to types. (Use versioned type names to manage +// breaking changes.) +// +// Schemas other than `http`, `https` (or the empty schema) might be +// used with implementation specific semantics. +// +// Types originating from the `google.*` package +// namespace should use `type.googleapis.com/full.type.name` (without +// schema and path). A type service will eventually become available which +// serves those URLs (projected Q2/15). +@property(nonatomic, readwrite, copy) NSString *typeURL; + +// Must be valid serialized data of the above specified type. +@property(nonatomic, readwrite, copy) NSData *value; + +@end + +CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m new file mode 100644 index 00000000..4db73cb9 --- /dev/null +++ b/objectivec/google/protobuf/Any.pbobjc.m @@ -0,0 +1,93 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/any.proto + +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "google/protobuf/Any.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma mark - GPBAnyRoot + +@implementation GPBAnyRoot + +@end + +static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBAny + +@implementation GPBAny + +@dynamic typeURL; +@dynamic value; + +typedef struct GPBAny_Storage { + uint32_t _has_storage_[1]; + NSString *typeURL; + NSData *value; +} GPBAny_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "typeURL", + .number = GPBAny_FieldNumber_TypeURL, + .hasIndex = 0, + .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, + .type = GPBTypeString, + .offset = offsetof(GPBAny_Storage, typeURL), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "value", + .number = GPBAny_FieldNumber_Value, + .hasIndex = 1, + .flags = GPBFieldOptional, + .type = GPBTypeData, + .offset = offsetof(GPBAny_Storage, value), + .defaultValue.valueData = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; +#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + const char *extraTextFormatInfo = NULL; +#else + static const char *extraTextFormatInfo = "\001\001\004\241!!\000"; +#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBAny class] + rootClass:[GPBAnyRoot class] + file:GPBAnyRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBAny_Storage) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + } + return descriptor; +} + +@end + + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h new file mode 100644 index 00000000..9e6fc850 --- /dev/null +++ b/objectivec/google/protobuf/Api.pbobjc.h @@ -0,0 +1,121 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +#import "GPBProtocolBuffers.h" + +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 +#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#endif + +// @@protoc_insertion_point(imports) + +CF_EXTERN_C_BEGIN + +@class GPBSourceContext; + + +#pragma mark - GPBApiRoot + +@interface GPBApiRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + +@end + +#pragma mark - GPBApi + +typedef GPB_ENUM(GPBApi_FieldNumber) { + GPBApi_FieldNumber_Name = 1, + GPBApi_FieldNumber_MethodsArray = 2, + GPBApi_FieldNumber_OptionsArray = 3, + GPBApi_FieldNumber_Version = 4, + GPBApi_FieldNumber_SourceContext = 5, +}; + +// Api is a light-weight descriptor for a protocol buffer service. +@interface GPBApi : GPBMessage + +// The fully qualified name of this api, including package name +// followed by the api's simple name. +@property(nonatomic, readwrite, copy) NSString *name; + +// The methods of this api, in unspecified order. +// |methodsArray| contains |GPBMethod| +@property(nonatomic, readwrite, strong) NSMutableArray *methodsArray; + +// Any metadata attached to the API. +// |optionsArray| contains |GPBOption| +@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; + +// A version string for this api. If specified, must have the form +// `major-version.minor-version`, as in `1.10`. If the minor version +// is omitted, it defaults to zero. If the entire version field is +// empty, the major version is derived from the package name, as +// outlined below. If the field is not empty, the version in the +// package name will be verified to be consistent with what is +// provided here. +// +// The versioning schema uses [semantic +// versioning](http://semver.org) where the major version number +// indicates a breaking change and the minor version an additive, +// non-breaking change. Both version numbers are signals to users +// what to expect from different versions, and should be carefully +// chosen based on the product plan. +// +// The major version is also reflected in the package name of the +// API, which must end in `v`, as in +// `google.feature.v1`. For major versions 0 and 1, the suffix can +// be omitted. Zero major versions must only be used for +// experimental, none-GA apis. +// +// See also: [design doc](http://go/api-versioning). +@property(nonatomic, readwrite, copy) NSString *version; + +// Source context for the protocol buffer service represented by this +// message. +@property(nonatomic, readwrite) BOOL hasSourceContext; +@property(nonatomic, readwrite, strong) GPBSourceContext *sourceContext; + +@end + +#pragma mark - GPBMethod + +typedef GPB_ENUM(GPBMethod_FieldNumber) { + GPBMethod_FieldNumber_Name = 1, + GPBMethod_FieldNumber_RequestTypeURL = 2, + GPBMethod_FieldNumber_RequestStreaming = 3, + GPBMethod_FieldNumber_ResponseTypeURL = 4, + GPBMethod_FieldNumber_ResponseStreaming = 5, + GPBMethod_FieldNumber_OptionsArray = 6, +}; + +// Method represents a method of an api. +@interface GPBMethod : GPBMessage + +// The simple name of this method. +@property(nonatomic, readwrite, copy) NSString *name; + +// A URL of the input message type. +@property(nonatomic, readwrite, copy) NSString *requestTypeURL; + +// If true, the request is streamed. +@property(nonatomic, readwrite) BOOL requestStreaming; + +// The URL of the output message type. +@property(nonatomic, readwrite, copy) NSString *responseTypeURL; + +// If true, the response is streamed. +@property(nonatomic, readwrite) BOOL responseStreaming; + +// Any metadata attached to the method. +// |optionsArray| contains |GPBOption| +@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; + +@end + +CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m new file mode 100644 index 00000000..9416860a --- /dev/null +++ b/objectivec/google/protobuf/Api.pbobjc.m @@ -0,0 +1,262 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/api.proto + +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "google/protobuf/Api.pbobjc.h" +#import "google/protobuf/SourceContext.pbobjc.h" +#import "google/protobuf/Type.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma mark - GPBApiRoot + +@implementation GPBApiRoot + ++ (GPBExtensionRegistry*)extensionRegistry { + // This is called by +initialize so there is no need to worry + // about thread safety and initialization of registry. + static GPBExtensionRegistry* registry = nil; + if (!registry) { + registry = [[GPBExtensionRegistry alloc] init]; + static GPBExtensionDescription descriptions[] = { + }; + #pragma unused (descriptions) + [registry addExtensions:[GPBSourceContextRoot extensionRegistry]]; + [registry addExtensions:[GPBTypeRoot extensionRegistry]]; + } + return registry; +} + +@end + +static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBApi + +@implementation GPBApi + +@dynamic name; +@dynamic methodsArray; +@dynamic optionsArray; +@dynamic version; +@dynamic hasSourceContext, sourceContext; + +typedef struct GPBApi_Storage { + uint32_t _has_storage_[1]; + NSString *name; + NSMutableArray *methodsArray; + NSMutableArray *optionsArray; + NSString *version; + GPBSourceContext *sourceContext; +} GPBApi_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .number = GPBApi_FieldNumber_Name, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBApi_Storage, name), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "methodsArray", + .number = GPBApi_FieldNumber_MethodsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBApi_Storage, methodsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBMethod), + .fieldOptions = NULL, + }, + { + .name = "optionsArray", + .number = GPBApi_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBApi_Storage, optionsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBOption), + .fieldOptions = NULL, + }, + { + .name = "version", + .number = GPBApi_FieldNumber_Version, + .hasIndex = 3, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBApi_Storage, version), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "sourceContext", + .number = GPBApi_FieldNumber_SourceContext, + .hasIndex = 4, + .flags = GPBFieldOptional, + .type = GPBTypeMessage, + .offset = offsetof(GPBApi_Storage, sourceContext), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBApi class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBApi_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBMethod + +@implementation GPBMethod + +@dynamic name; +@dynamic requestTypeURL; +@dynamic requestStreaming; +@dynamic responseTypeURL; +@dynamic responseStreaming; +@dynamic optionsArray; + +typedef struct GPBMethod_Storage { + uint32_t _has_storage_[1]; + BOOL requestStreaming; + BOOL responseStreaming; + NSString *name; + NSString *requestTypeURL; + NSString *responseTypeURL; + NSMutableArray *optionsArray; +} GPBMethod_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .number = GPBMethod_FieldNumber_Name, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBMethod_Storage, name), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "requestTypeURL", + .number = GPBMethod_FieldNumber_RequestTypeURL, + .hasIndex = 1, + .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, + .type = GPBTypeString, + .offset = offsetof(GPBMethod_Storage, requestTypeURL), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "requestStreaming", + .number = GPBMethod_FieldNumber_RequestStreaming, + .hasIndex = 2, + .flags = GPBFieldOptional, + .type = GPBTypeBool, + .offset = offsetof(GPBMethod_Storage, requestStreaming), + .defaultValue.valueBool = NO, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "responseTypeURL", + .number = GPBMethod_FieldNumber_ResponseTypeURL, + .hasIndex = 3, + .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, + .type = GPBTypeString, + .offset = offsetof(GPBMethod_Storage, responseTypeURL), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "responseStreaming", + .number = GPBMethod_FieldNumber_ResponseStreaming, + .hasIndex = 4, + .flags = GPBFieldOptional, + .type = GPBTypeBool, + .offset = offsetof(GPBMethod_Storage, responseStreaming), + .defaultValue.valueBool = NO, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "optionsArray", + .number = GPBMethod_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBMethod_Storage, optionsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBOption), + .fieldOptions = NULL, + }, + }; +#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + const char *extraTextFormatInfo = NULL; +#else + static const char *extraTextFormatInfo = "\002\002\007\244\241!!\000\004\010\244\241!!\000"; +#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethod class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBMethod_Storage) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + } + return descriptor; +} + +@end + + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.h b/objectivec/google/protobuf/Descriptor.pbobjc.h index e3dacf25..19a82fd1 100644 --- a/objectivec/google/protobuf/Descriptor.pbobjc.h +++ b/objectivec/google/protobuf/Descriptor.pbobjc.h @@ -7,29 +7,18 @@ #error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. #endif +// @@protoc_insertion_point(imports) + CF_EXTERN_C_BEGIN -@class GPBDescriptorProto; -@class GPBDescriptorProto_ExtensionRange; -@class GPBEnumDescriptorProto; @class GPBEnumOptions; -@class GPBEnumValueDescriptorProto; @class GPBEnumValueOptions; -@class GPBFieldDescriptorProto; @class GPBFieldOptions; -@class GPBFileDescriptorProto; -@class GPBFileDescriptorSet; @class GPBFileOptions; @class GPBMessageOptions; -@class GPBMethodDescriptorProto; @class GPBMethodOptions; -@class GPBOneofDescriptorProto; -@class GPBServiceDescriptorProto; @class GPBServiceOptions; @class GPBSourceCodeInfo; -@class GPBSourceCodeInfo_Location; -@class GPBUninterpretedOption; -@class GPBUninterpretedOption_NamePart; #pragma mark - Enum GPBFieldDescriptorProto_Type @@ -126,6 +115,12 @@ BOOL GPBFieldOptions_CType_IsValidValue(int32_t value); #pragma mark - GPBDescriptorRoot @interface GPBDescriptorRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + @end #pragma mark - GPBFileDescriptorSet @@ -1049,3 +1044,5 @@ typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) { @end CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.m b/objectivec/google/protobuf/Descriptor.pbobjc.m index 25e4cc73..2fc1953c 100644 --- a/objectivec/google/protobuf/Descriptor.pbobjc.m +++ b/objectivec/google/protobuf/Descriptor.pbobjc.m @@ -2,8 +2,8 @@ // source: google/protobuf/descriptor.proto #import "GPBProtocolBuffers_RuntimeSupport.h" - #import "google/protobuf/Descriptor.pbobjc.h" +// @@protoc_insertion_point(imports) #pragma mark - GPBDescriptorRoot @@ -2216,3 +2216,5 @@ typedef struct GPBSourceCodeInfo_Location_Storage { @end + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h index c452d0bb..f65df6c9 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.h +++ b/objectivec/google/protobuf/Duration.pbobjc.h @@ -7,14 +7,20 @@ #error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. #endif -CF_EXTERN_C_BEGIN +// @@protoc_insertion_point(imports) -@class GPBDuration; +CF_EXTERN_C_BEGIN #pragma mark - GPBDurationRoot @interface GPBDurationRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + @end #pragma mark - GPBDuration @@ -81,3 +87,5 @@ typedef GPB_ENUM(GPBDuration_FieldNumber) { @end CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m index cf0a3064..4db030f4 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.m +++ b/objectivec/google/protobuf/Duration.pbobjc.m @@ -2,8 +2,8 @@ // source: google/protobuf/duration.proto #import "GPBProtocolBuffers_RuntimeSupport.h" - #import "google/protobuf/Duration.pbobjc.h" +// @@protoc_insertion_point(imports) #pragma mark - GPBDurationRoot @@ -83,3 +83,5 @@ typedef struct GPBDuration_Storage { @end + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Empty.pbobjc.h b/objectivec/google/protobuf/Empty.pbobjc.h new file mode 100644 index 00000000..1356c3a7 --- /dev/null +++ b/objectivec/google/protobuf/Empty.pbobjc.h @@ -0,0 +1,41 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +#import "GPBProtocolBuffers.h" + +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 +#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#endif + +// @@protoc_insertion_point(imports) + +CF_EXTERN_C_BEGIN + + +#pragma mark - GPBEmptyRoot + +@interface GPBEmptyRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + +@end + +#pragma mark - GPBEmpty + +// A generic empty message that you can re-use to avoid defining duplicated +// empty messages in your APIs. A typical example is to use it as the request +// or the response type of an API method. For instance: +// +// service Foo { +// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); +// } +@interface GPBEmpty : GPBMessage + +@end + +CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m new file mode 100644 index 00000000..619fe905 --- /dev/null +++ b/objectivec/google/protobuf/Empty.pbobjc.m @@ -0,0 +1,61 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/empty.proto + +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "google/protobuf/Empty.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma mark - GPBEmptyRoot + +@implementation GPBEmptyRoot + +@end + +static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBEmpty + +@implementation GPBEmpty + + +typedef struct GPBEmpty_Storage { + uint32_t _has_storage_[0]; +} GPBEmpty_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] + rootClass:[GPBEmptyRoot class] + file:GPBEmptyRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEmpty_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h new file mode 100644 index 00000000..ac6f03d2 --- /dev/null +++ b/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -0,0 +1,160 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +#import "GPBProtocolBuffers.h" + +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 +#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#endif + +// @@protoc_insertion_point(imports) + +CF_EXTERN_C_BEGIN + + +#pragma mark - GPBFieldMaskRoot + +@interface GPBFieldMaskRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + +@end + +#pragma mark - GPBFieldMask + +typedef GPB_ENUM(GPBFieldMask_FieldNumber) { + GPBFieldMask_FieldNumber_PathsArray = 1, +}; + +// `FieldMask` represents a set of symbolic field paths, for example: +// +// paths: "f.a" +// paths: "f.b.d" +// +// Here `f` represents a field in some root message, `a` and `b` +// fields in the message found in `f`, and `d` a field found in the +// message in `f.b`. +// +// Field masks are used to specify a subset of fields that should be +// returned by a get operation or modified by an update operation. +// Field masks also have a custom JSON encoding (see below). +// +// # Field Masks in Projections +// When used in the context of a projection, a response message or +// sub-message is filtered by the API to only contain those fields as +// specified in the mask. For example, if the mask in the previous +// example is applied to a response message as follows: +// +// f { +// a : 22 +// b { +// d : 1 +// x : 2 +// } +// y : 13 +// } +// z: 8 +// +// The result will not contain specific values for fields x,y and z +// (there value will be set to the default, and omitted in proto text +// output): +// +// +// f { +// a : 22 +// b { +// d : 1 +// } +// } +// +// A repeated field is not allowed except at the last position of a +// field mask. +// +// If a FieldMask object is not present in a get operation, the +// operation applies to all fields (as if a FieldMask of all fields +// had been specified). +// +// Note that a field mask does not necessarily applies to the +// top-level response message. In case of a REST get operation, the +// field mask applies directly to the response, but in case of a REST +// list operation, the mask instead applies to each individual message +// in the returned resource list. In case of a REST custom method, +// other definitions may be used. Where the mask applies will be +// clearly documented together with its declaration in the API. In +// any case, the effect on the returned resource/resources is required +// behavior for APIs. +// +// # Field Masks in Update Operations +// A field mask in update operations specifies which fields of the +// targeted resource are going to be updated. The API is required +// to only change the values of the fields as specified in the mask +// and leave the others untouched. If a resource is passed in to +// describe the updated values, the API ignores the values of all +// fields not covered by the mask. +// +// In order to reset a field's value to the default, the field must +// be in the mask and set to the default value in the provided resource. +// Hence, in order to reset all fields of a resource, provide a default +// instance of the resource and set all fields in the mask, or do +// not provide a mask as described below. +// +// If a field mask is not present on update, the operation applies to +// all fields (as if a field mask of all fields has been specified). +// Note that in the presence of schema evolution, this may mean that +// fields the client does not know and has therefore not filled into +// the request will be reset to their default. If this is unwanted +// behavior, a specific service may require a client to always specify +// a field mask, producing an error if not. +// +// As with get operations, the location of the resource which +// describes the updated values in the request message depends on the +// operation kind. In any case, the effect of the field mask is +// required to be honored by the API. +// +// ## Considerations for HTTP REST +// The HTTP kind of an update operation which uses a field mask must +// be set to PATCH instead of PUT in order to satisfy HTTP semantics +// (PUT must only be used for full updates). +// +// # JSON Encoding of Field Masks +// In JSON, a field mask is encoded as a single string where paths are +// separated by a comma. Fields name in each path are converted +// to/from lower-camel naming conventions. +// +// As an example, consider the following message declarations: +// +// message Profile { +// User user = 1; +// Photo photo = 2; +// } +// message User { +// string display_name = 1; +// string address = 2; +// } +// +// In proto a field mask for `Profile` may look as such: +// +// mask { +// paths: "user.display_name" +// paths: "photo" +// } +// +// In JSON, the same mask is represented as below: +// +// { +// mask: "user.displayName,photo" +// } +@interface GPBFieldMask : GPBMessage + +// The set of field mask paths. +// |pathsArray| contains |NSString| +@property(nonatomic, readwrite, strong) NSMutableArray *pathsArray; + +@end + +CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m new file mode 100644 index 00000000..e37ac6c2 --- /dev/null +++ b/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -0,0 +1,74 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/field_mask.proto + +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "google/protobuf/FieldMask.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma mark - GPBFieldMaskRoot + +@implementation GPBFieldMaskRoot + +@end + +static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBFieldMask + +@implementation GPBFieldMask + +@dynamic pathsArray; + +typedef struct GPBFieldMask_Storage { + uint32_t _has_storage_[1]; + NSMutableArray *pathsArray; +} GPBFieldMask_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "pathsArray", + .number = GPBFieldMask_FieldNumber_PathsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeString, + .offset = offsetof(GPBFieldMask_Storage, pathsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] + rootClass:[GPBFieldMaskRoot class] + file:GPBFieldMaskRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFieldMask_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.h b/objectivec/google/protobuf/SourceContext.pbobjc.h new file mode 100644 index 00000000..bcbf1e3d --- /dev/null +++ b/objectivec/google/protobuf/SourceContext.pbobjc.h @@ -0,0 +1,44 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +#import "GPBProtocolBuffers.h" + +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 +#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#endif + +// @@protoc_insertion_point(imports) + +CF_EXTERN_C_BEGIN + + +#pragma mark - GPBSourceContextRoot + +@interface GPBSourceContextRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + +@end + +#pragma mark - GPBSourceContext + +typedef GPB_ENUM(GPBSourceContext_FieldNumber) { + GPBSourceContext_FieldNumber_FileName = 1, +}; + +// `SourceContext` represents information about the source of a +// protobuf element, like the file in which it is defined. +@interface GPBSourceContext : GPBMessage + +// The path-qualified name of the .proto file that contained the associated +// protobuf element. For example: `"google/protobuf/source.proto"`. +@property(nonatomic, readwrite, copy) NSString *fileName; + +@end + +CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m new file mode 100644 index 00000000..271f9243 --- /dev/null +++ b/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -0,0 +1,74 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "google/protobuf/SourceContext.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma mark - GPBSourceContextRoot + +@implementation GPBSourceContextRoot + +@end + +static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBSourceContext + +@implementation GPBSourceContext + +@dynamic fileName; + +typedef struct GPBSourceContext_Storage { + uint32_t _has_storage_[1]; + NSString *fileName; +} GPBSourceContext_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "fileName", + .number = GPBSourceContext_FieldNumber_FileName, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBSourceContext_Storage, fileName), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] + rootClass:[GPBSourceContextRoot class] + file:GPBSourceContextRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBSourceContext_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h new file mode 100644 index 00000000..f55af82b --- /dev/null +++ b/objectivec/google/protobuf/Struct.pbobjc.h @@ -0,0 +1,134 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +#import "GPBProtocolBuffers.h" + +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 +#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#endif + +// @@protoc_insertion_point(imports) + +CF_EXTERN_C_BEGIN + +@class GPBListValue; +@class GPBStruct; + +#pragma mark - Enum GPBNullValue + +// `NullValue` is a singleton enumeration to represent the null +// value for the `Value` type union. +typedef GPB_ENUM(GPBNullValue) { + GPBNullValue_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + // Null value. + GPBNullValue_NullValue = 0, +}; + +GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void); + +BOOL GPBNullValue_IsValidValue(int32_t value); + + +#pragma mark - GPBStructRoot + +@interface GPBStructRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + +@end + +#pragma mark - GPBStruct + +typedef GPB_ENUM(GPBStruct_FieldNumber) { + GPBStruct_FieldNumber_Fields = 1, +}; + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +@interface GPBStruct : GPBMessage + +// Map of dynamically typed values. +// |fields| values are |GPBValue| +@property(nonatomic, readwrite, strong) NSMutableDictionary *fields; + +@end + +#pragma mark - GPBValue + +typedef GPB_ENUM(GPBValue_FieldNumber) { + GPBValue_FieldNumber_NullValue = 1, + GPBValue_FieldNumber_NumberValue = 2, + GPBValue_FieldNumber_StringValue = 3, + GPBValue_FieldNumber_BoolValue = 4, + GPBValue_FieldNumber_StructValue = 5, + GPBValue_FieldNumber_ListValue = 6, +}; + +typedef GPB_ENUM(GPBValue_Kind_OneOfCase) { + GPBValue_Kind_OneOfCase_GPBUnsetOneOfCase = 0, + GPBValue_Kind_OneOfCase_NullValue = 1, + GPBValue_Kind_OneOfCase_NumberValue = 2, + GPBValue_Kind_OneOfCase_StringValue = 3, + GPBValue_Kind_OneOfCase_BoolValue = 4, + GPBValue_Kind_OneOfCase_StructValue = 5, + GPBValue_Kind_OneOfCase_ListValue = 6, +}; + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of that +// variants, absence of any variant indicates an error. +@interface GPBValue : GPBMessage + +@property(nonatomic, readonly) GPBValue_Kind_OneOfCase kindOneOfCase; + +// Represents a null value. +@property(nonatomic, readwrite) GPBNullValue nullValue; + +// Represents a double value. +@property(nonatomic, readwrite) double numberValue; + +// Represents a string value. +@property(nonatomic, readwrite, copy) NSString *stringValue; + +// Represents a boolean value. +@property(nonatomic, readwrite) BOOL boolValue; + +// Represents a structured value. +@property(nonatomic, readwrite, strong) GPBStruct *structValue; + +// Represents a repeated `Value`. +@property(nonatomic, readwrite, strong) GPBListValue *listValue; + +@end + +int32_t GPBValue_NullValue_RawValue(GPBValue *message); +void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value); + +void GPBValue_ClearKindOneOfCase(GPBValue *message); + +#pragma mark - GPBListValue + +typedef GPB_ENUM(GPBListValue_FieldNumber) { + GPBListValue_FieldNumber_ValuesArray = 1, +}; + +// `ListValue` is a wrapper around a repeated field of values. +@interface GPBListValue : GPBMessage + +// Repeated field of dynamically typed values. +// |valuesArray| contains |GPBValue| +@property(nonatomic, readwrite, strong) NSMutableArray *valuesArray; + +@end + +CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m new file mode 100644 index 00000000..e5a8b547 --- /dev/null +++ b/objectivec/google/protobuf/Struct.pbobjc.m @@ -0,0 +1,284 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "google/protobuf/Struct.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma mark - GPBStructRoot + +@implementation GPBStructRoot + +@end + +static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - Enum GPBNullValue + +GPBEnumDescriptor *GPBNullValue_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageEnumValueDescription values[] = { + { .name = "NullValue", .number = GPBNullValue_NullValue }, + }; + descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBNullValue) + values:values + valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription) + enumVerifier:GPBNullValue_IsValidValue]; + } + return descriptor; +} + +BOOL GPBNullValue_IsValidValue(int32_t value__) { + switch (value__) { + case GPBNullValue_NullValue: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBStruct + +@implementation GPBStruct + +@dynamic fields; + +typedef struct GPBStruct_Storage { + uint32_t _has_storage_[1]; + NSMutableDictionary *fields; +} GPBStruct_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "fields", + .number = GPBStruct_FieldNumber_Fields, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldMapKeyString, + .type = GPBTypeMessage, + .offset = offsetof(GPBStruct_Storage, fields), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBValue), + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBStruct class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBStruct_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBValue + +@implementation GPBValue + +@dynamic kindOneOfCase; +@dynamic nullValue; +@dynamic numberValue; +@dynamic stringValue; +@dynamic boolValue; +@dynamic structValue; +@dynamic listValue; + +typedef struct GPBValue_Storage { + uint32_t _has_storage_[2]; + BOOL boolValue; + GPBNullValue nullValue; + NSString *stringValue; + GPBStruct *structValue; + GPBListValue *listValue; + double numberValue; +} GPBValue_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageOneofDescription oneofs[] = { + { + .name = "kind", + .index = -1, + }, + }; + static GPBMessageFieldDescription fields[] = { + { + .name = "nullValue", + .number = GPBValue_FieldNumber_NullValue, + .hasIndex = -1, + .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .type = GPBTypeEnum, + .offset = offsetof(GPBValue_Storage, nullValue), + .defaultValue.valueEnum = GPBNullValue_NullValue, + .typeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, + .fieldOptions = NULL, + }, + { + .name = "numberValue", + .number = GPBValue_FieldNumber_NumberValue, + .hasIndex = -1, + .flags = GPBFieldOptional, + .type = GPBTypeDouble, + .offset = offsetof(GPBValue_Storage, numberValue), + .defaultValue.valueDouble = 0, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "stringValue", + .number = GPBValue_FieldNumber_StringValue, + .hasIndex = -1, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBValue_Storage, stringValue), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "boolValue", + .number = GPBValue_FieldNumber_BoolValue, + .hasIndex = -1, + .flags = GPBFieldOptional, + .type = GPBTypeBool, + .offset = offsetof(GPBValue_Storage, boolValue), + .defaultValue.valueBool = NO, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "structValue", + .number = GPBValue_FieldNumber_StructValue, + .hasIndex = -1, + .flags = GPBFieldOptional, + .type = GPBTypeMessage, + .offset = offsetof(GPBValue_Storage, structValue), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBStruct), + .fieldOptions = NULL, + }, + { + .name = "listValue", + .number = GPBValue_FieldNumber_ListValue, + .hasIndex = -1, + .flags = GPBFieldOptional, + .type = GPBTypeMessage, + .offset = offsetof(GPBValue_Storage, listValue), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBListValue), + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:oneofs + oneofCount:sizeof(oneofs) / sizeof(GPBMessageOneofDescription) + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBValue_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +int32_t GPBValue_NullValue_RawValue(GPBValue *message) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; + return GPBGetInt32IvarWithField(message, field); +} + +void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { + GPBDescriptor *descriptor = [GPBValue descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +void GPBValue_ClearKindOneOfCase(GPBValue *message) { + GPBDescriptor *descriptor = [message descriptor]; + GPBOneofDescriptor *oneof = descriptor->oneofs_[0]; + GPBMaybeClearOneof(message, oneof, 0); +} +#pragma mark - GPBListValue + +@implementation GPBListValue + +@dynamic valuesArray; + +typedef struct GPBListValue_Storage { + uint32_t _has_storage_[1]; + NSMutableArray *valuesArray; +} GPBListValue_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "valuesArray", + .number = GPBListValue_FieldNumber_ValuesArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBListValue_Storage, valuesArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBValue), + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBListValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBListValue_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h index c9fc9175..a81321b4 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.h +++ b/objectivec/google/protobuf/Timestamp.pbobjc.h @@ -7,14 +7,20 @@ #error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. #endif -CF_EXTERN_C_BEGIN +// @@protoc_insertion_point(imports) -@class GPBTimestamp; +CF_EXTERN_C_BEGIN #pragma mark - GPBTimestampRoot @interface GPBTimestampRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + @end #pragma mark - GPBTimestamp @@ -92,3 +98,5 @@ typedef GPB_ENUM(GPBTimestamp_FieldNumber) { @end CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m index 1c8d3c76..197dff48 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.m +++ b/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -2,8 +2,8 @@ // source: google/protobuf/timestamp.proto #import "GPBProtocolBuffers_RuntimeSupport.h" - #import "google/protobuf/Timestamp.pbobjc.h" +// @@protoc_insertion_point(imports) #pragma mark - GPBTimestampRoot @@ -83,3 +83,5 @@ typedef struct GPBTimestamp_Storage { @end + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h new file mode 100644 index 00000000..652a33a7 --- /dev/null +++ b/objectivec/google/protobuf/Type.pbobjc.h @@ -0,0 +1,274 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +#import "GPBProtocolBuffers.h" + +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 +#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#endif + +// @@protoc_insertion_point(imports) + +CF_EXTERN_C_BEGIN + +@class GPBAny; +@class GPBSourceContext; + +#pragma mark - Enum GPBField_Kind + +// Kind represents a basic field type. +typedef GPB_ENUM(GPBField_Kind) { + GPBField_Kind_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + // Field type unknown. + GPBField_Kind_TypeUnknown = 0, + + // Field type double. + GPBField_Kind_TypeDouble = 1, + + // Field type float. + GPBField_Kind_TypeFloat = 2, + + // Field type int64. + GPBField_Kind_TypeInt64 = 3, + + // Field type uint64. + GPBField_Kind_TypeUint64 = 4, + + // Field type int32. + GPBField_Kind_TypeInt32 = 5, + + // Field type fixed64. + GPBField_Kind_TypeFixed64 = 6, + + // Field type fixed32. + GPBField_Kind_TypeFixed32 = 7, + + // Field type bool. + GPBField_Kind_TypeBool = 8, + + // Field type string. + GPBField_Kind_TypeString = 9, + + // Field type message. + GPBField_Kind_TypeMessage = 11, + + // Field type bytes. + GPBField_Kind_TypeBytes = 12, + + // Field type uint32. + GPBField_Kind_TypeUint32 = 13, + + // Field type enum. + GPBField_Kind_TypeEnum = 14, + + // Field type sfixed32. + GPBField_Kind_TypeSfixed32 = 15, + + // Field type sfixed64. + GPBField_Kind_TypeSfixed64 = 16, + + // Field type sint32. + GPBField_Kind_TypeSint32 = 17, + + // Field type sint64. + GPBField_Kind_TypeSint64 = 18, +}; + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void); + +BOOL GPBField_Kind_IsValidValue(int32_t value); + +#pragma mark - Enum GPBField_Cardinality + +// Cardinality represents whether a field is optional, required, or +// repeated. +typedef GPB_ENUM(GPBField_Cardinality) { + GPBField_Cardinality_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue, + // The field cardinality is unknown. Typically an error condition. + GPBField_Cardinality_CardinalityUnknown = 0, + + // For optional fields. + GPBField_Cardinality_CardinalityOptional = 1, + + // For required fields. Not used for proto3. + GPBField_Cardinality_CardinalityRequired = 2, + + // For repeated fields. + GPBField_Cardinality_CardinalityRepeated = 3, +}; + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void); + +BOOL GPBField_Cardinality_IsValidValue(int32_t value); + + +#pragma mark - GPBTypeRoot + +@interface GPBTypeRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + +@end + +#pragma mark - GPBType + +typedef GPB_ENUM(GPBType_FieldNumber) { + GPBType_FieldNumber_Name = 1, + GPBType_FieldNumber_FieldsArray = 2, + GPBType_FieldNumber_OneofsArray = 3, + GPBType_FieldNumber_OptionsArray = 4, + GPBType_FieldNumber_SourceContext = 5, +}; + +// A light-weight descriptor for a proto message type. +@interface GPBType : GPBMessage + +// The fully qualified message name. +@property(nonatomic, readwrite, copy) NSString *name; + +// The list of fields. +// |fieldsArray| contains |GPBField| +@property(nonatomic, readwrite, strong) NSMutableArray *fieldsArray; + +// The list of oneof definitions. +// The list of oneofs declared in this Type +// |oneofsArray| contains |NSString| +@property(nonatomic, readwrite, strong) NSMutableArray *oneofsArray; + +// The proto options. +// |optionsArray| contains |GPBOption| +@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; + +// The source context. +@property(nonatomic, readwrite) BOOL hasSourceContext; +@property(nonatomic, readwrite, strong) GPBSourceContext *sourceContext; + +@end + +#pragma mark - GPBField + +typedef GPB_ENUM(GPBField_FieldNumber) { + GPBField_FieldNumber_Kind = 1, + GPBField_FieldNumber_Cardinality = 2, + GPBField_FieldNumber_Number = 3, + GPBField_FieldNumber_Name = 4, + GPBField_FieldNumber_TypeURL = 6, + GPBField_FieldNumber_OneofIndex = 7, + GPBField_FieldNumber_Packed = 8, + GPBField_FieldNumber_OptionsArray = 9, +}; + +// Field represents a single field of a message type. +@interface GPBField : GPBMessage + +// The field kind. +@property(nonatomic, readwrite) GPBField_Kind kind; + +// The field cardinality, i.e. optional/required/repeated. +@property(nonatomic, readwrite) GPBField_Cardinality cardinality; + +// The proto field number. +@property(nonatomic, readwrite) int32_t number; + +// The field name. +@property(nonatomic, readwrite, copy) NSString *name; + +// The type URL (without the scheme) when the type is MESSAGE or ENUM, +// such as `type.googleapis.com/google.protobuf.Empty`. +@property(nonatomic, readwrite, copy) NSString *typeURL; + +// Index in Type.oneofs. Starts at 1. Zero means no oneof mapping. +@property(nonatomic, readwrite) int32_t oneofIndex; + +// Whether to use alternative packed wire representation. +@property(nonatomic, readwrite) BOOL packed; + +// The proto options. +// |optionsArray| contains |GPBOption| +@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; + +@end + +int32_t GPBField_Kind_RawValue(GPBField *message); +void SetGPBField_Kind_RawValue(GPBField *message, int32_t value); + +int32_t GPBField_Cardinality_RawValue(GPBField *message); +void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value); + +#pragma mark - GPBEnum + +typedef GPB_ENUM(GPBEnum_FieldNumber) { + GPBEnum_FieldNumber_Name = 1, + GPBEnum_FieldNumber_EnumvalueArray = 2, + GPBEnum_FieldNumber_OptionsArray = 3, + GPBEnum_FieldNumber_SourceContext = 4, +}; + +// Enum type definition. +@interface GPBEnum : GPBMessage + +// Enum type name. +@property(nonatomic, readwrite, copy) NSString *name; + +// Enum value definitions. +// |enumvalueArray| contains |GPBEnumValue| +@property(nonatomic, readwrite, strong) NSMutableArray *enumvalueArray; + +// Proto options for the enum type. +// |optionsArray| contains |GPBOption| +@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; + +// The source context. +@property(nonatomic, readwrite) BOOL hasSourceContext; +@property(nonatomic, readwrite, strong) GPBSourceContext *sourceContext; + +@end + +#pragma mark - GPBEnumValue + +typedef GPB_ENUM(GPBEnumValue_FieldNumber) { + GPBEnumValue_FieldNumber_Name = 1, + GPBEnumValue_FieldNumber_Number = 2, + GPBEnumValue_FieldNumber_OptionsArray = 3, +}; + +// Enum value definition. +@interface GPBEnumValue : GPBMessage + +// Enum value name. +@property(nonatomic, readwrite, copy) NSString *name; + +// Enum value number. +@property(nonatomic, readwrite) int32_t number; + +// Proto options for the enum value. +// |optionsArray| contains |GPBOption| +@property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; + +@end + +#pragma mark - GPBOption + +typedef GPB_ENUM(GPBOption_FieldNumber) { + GPBOption_FieldNumber_Name = 1, + GPBOption_FieldNumber_Value = 2, +}; + +// Proto option attached to messages/fields/enums etc. +@interface GPBOption : GPBMessage + +// Proto option name. +@property(nonatomic, readwrite, copy) NSString *name; + +// Proto option value. +@property(nonatomic, readwrite) BOOL hasValue; +@property(nonatomic, readwrite, strong) GPBAny *value; + +@end + +CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m new file mode 100644 index 00000000..182370c8 --- /dev/null +++ b/objectivec/google/protobuf/Type.pbobjc.m @@ -0,0 +1,628 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "google/protobuf/Type.pbobjc.h" +#import "google/protobuf/Any.pbobjc.h" +#import "google/protobuf/SourceContext.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma mark - GPBTypeRoot + +@implementation GPBTypeRoot + ++ (GPBExtensionRegistry*)extensionRegistry { + // This is called by +initialize so there is no need to worry + // about thread safety and initialization of registry. + static GPBExtensionRegistry* registry = nil; + if (!registry) { + registry = [[GPBExtensionRegistry alloc] init]; + static GPBExtensionDescription descriptions[] = { + }; + #pragma unused (descriptions) + [registry addExtensions:[GPBAnyRoot extensionRegistry]]; + [registry addExtensions:[GPBSourceContextRoot extensionRegistry]]; + } + return registry; +} + +@end + +static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBType + +@implementation GPBType + +@dynamic name; +@dynamic fieldsArray; +@dynamic oneofsArray; +@dynamic optionsArray; +@dynamic hasSourceContext, sourceContext; + +typedef struct GPBType_Storage { + uint32_t _has_storage_[1]; + NSString *name; + NSMutableArray *fieldsArray; + NSMutableArray *oneofsArray; + NSMutableArray *optionsArray; + GPBSourceContext *sourceContext; +} GPBType_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .number = GPBType_FieldNumber_Name, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBType_Storage, name), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "fieldsArray", + .number = GPBType_FieldNumber_FieldsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBType_Storage, fieldsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBField), + .fieldOptions = NULL, + }, + { + .name = "oneofsArray", + .number = GPBType_FieldNumber_OneofsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeString, + .offset = offsetof(GPBType_Storage, oneofsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "optionsArray", + .number = GPBType_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBType_Storage, optionsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBOption), + .fieldOptions = NULL, + }, + { + .name = "sourceContext", + .number = GPBType_FieldNumber_SourceContext, + .hasIndex = 4, + .flags = GPBFieldOptional, + .type = GPBTypeMessage, + .offset = offsetof(GPBType_Storage, sourceContext), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBType class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBType_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBField + +@implementation GPBField + +@dynamic kind; +@dynamic cardinality; +@dynamic number; +@dynamic name; +@dynamic typeURL; +@dynamic oneofIndex; +@dynamic packed; +@dynamic optionsArray; + +typedef struct GPBField_Storage { + uint32_t _has_storage_[1]; + BOOL packed; + GPBField_Kind kind; + GPBField_Cardinality cardinality; + int32_t number; + int32_t oneofIndex; + NSString *name; + NSString *typeURL; + NSMutableArray *optionsArray; +} GPBField_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "kind", + .number = GPBField_FieldNumber_Kind, + .hasIndex = 0, + .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .type = GPBTypeEnum, + .offset = offsetof(GPBField_Storage, kind), + .defaultValue.valueEnum = GPBField_Kind_TypeUnknown, + .typeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, + .fieldOptions = NULL, + }, + { + .name = "cardinality", + .number = GPBField_FieldNumber_Cardinality, + .hasIndex = 1, + .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, + .type = GPBTypeEnum, + .offset = offsetof(GPBField_Storage, cardinality), + .defaultValue.valueEnum = GPBField_Cardinality_CardinalityUnknown, + .typeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, + .fieldOptions = NULL, + }, + { + .name = "number", + .number = GPBField_FieldNumber_Number, + .hasIndex = 2, + .flags = GPBFieldOptional, + .type = GPBTypeInt32, + .offset = offsetof(GPBField_Storage, number), + .defaultValue.valueInt32 = 0, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "name", + .number = GPBField_FieldNumber_Name, + .hasIndex = 3, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBField_Storage, name), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "typeURL", + .number = GPBField_FieldNumber_TypeURL, + .hasIndex = 4, + .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, + .type = GPBTypeString, + .offset = offsetof(GPBField_Storage, typeURL), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "oneofIndex", + .number = GPBField_FieldNumber_OneofIndex, + .hasIndex = 5, + .flags = GPBFieldOptional, + .type = GPBTypeInt32, + .offset = offsetof(GPBField_Storage, oneofIndex), + .defaultValue.valueInt32 = 0, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "packed", + .number = GPBField_FieldNumber_Packed, + .hasIndex = 6, + .flags = GPBFieldOptional, + .type = GPBTypeBool, + .offset = offsetof(GPBField_Storage, packed), + .defaultValue.valueBool = NO, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "optionsArray", + .number = GPBField_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBField_Storage, optionsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBOption), + .fieldOptions = NULL, + }, + }; + static GPBMessageEnumDescription enums[] = { + { .enumDescriptorFunc = GPBField_Kind_EnumDescriptor }, + { .enumDescriptorFunc = GPBField_Cardinality_EnumDescriptor }, + }; +#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + const char *extraTextFormatInfo = NULL; +#else + static const char *extraTextFormatInfo = "\001\006\004\241!!\000"; +#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBField class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:enums + enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBField_Storage) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + } + return descriptor; +} + +@end + +int32_t GPBField_Kind_RawValue(GPBField *message) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; + return GPBGetInt32IvarWithField(message, field); +} + +void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +int32_t GPBField_Cardinality_RawValue(GPBField *message) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; + return GPBGetInt32IvarWithField(message, field); +} + +void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { + GPBDescriptor *descriptor = [GPBField descriptor]; + GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; + GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax); +} + +#pragma mark - Enum GPBField_Kind + +GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageEnumValueDescription values[] = { + { .name = "TypeUnknown", .number = GPBField_Kind_TypeUnknown }, + { .name = "TypeDouble", .number = GPBField_Kind_TypeDouble }, + { .name = "TypeFloat", .number = GPBField_Kind_TypeFloat }, + { .name = "TypeInt64", .number = GPBField_Kind_TypeInt64 }, + { .name = "TypeUint64", .number = GPBField_Kind_TypeUint64 }, + { .name = "TypeInt32", .number = GPBField_Kind_TypeInt32 }, + { .name = "TypeFixed64", .number = GPBField_Kind_TypeFixed64 }, + { .name = "TypeFixed32", .number = GPBField_Kind_TypeFixed32 }, + { .name = "TypeBool", .number = GPBField_Kind_TypeBool }, + { .name = "TypeString", .number = GPBField_Kind_TypeString }, + { .name = "TypeMessage", .number = GPBField_Kind_TypeMessage }, + { .name = "TypeBytes", .number = GPBField_Kind_TypeBytes }, + { .name = "TypeUint32", .number = GPBField_Kind_TypeUint32 }, + { .name = "TypeEnum", .number = GPBField_Kind_TypeEnum }, + { .name = "TypeSfixed32", .number = GPBField_Kind_TypeSfixed32 }, + { .name = "TypeSfixed64", .number = GPBField_Kind_TypeSfixed64 }, + { .name = "TypeSint32", .number = GPBField_Kind_TypeSint32 }, + { .name = "TypeSint64", .number = GPBField_Kind_TypeSint64 }, + }; + descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind) + values:values + valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription) + enumVerifier:GPBField_Kind_IsValidValue]; + } + return descriptor; +} + +BOOL GPBField_Kind_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Kind_TypeUnknown: + case GPBField_Kind_TypeDouble: + case GPBField_Kind_TypeFloat: + case GPBField_Kind_TypeInt64: + case GPBField_Kind_TypeUint64: + case GPBField_Kind_TypeInt32: + case GPBField_Kind_TypeFixed64: + case GPBField_Kind_TypeFixed32: + case GPBField_Kind_TypeBool: + case GPBField_Kind_TypeString: + case GPBField_Kind_TypeMessage: + case GPBField_Kind_TypeBytes: + case GPBField_Kind_TypeUint32: + case GPBField_Kind_TypeEnum: + case GPBField_Kind_TypeSfixed32: + case GPBField_Kind_TypeSfixed64: + case GPBField_Kind_TypeSint32: + case GPBField_Kind_TypeSint64: + return YES; + default: + return NO; + } +} + +#pragma mark - Enum GPBField_Cardinality + +GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) { + static GPBEnumDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageEnumValueDescription values[] = { + { .name = "CardinalityUnknown", .number = GPBField_Cardinality_CardinalityUnknown }, + { .name = "CardinalityOptional", .number = GPBField_Cardinality_CardinalityOptional }, + { .name = "CardinalityRequired", .number = GPBField_Cardinality_CardinalityRequired }, + { .name = "CardinalityRepeated", .number = GPBField_Cardinality_CardinalityRepeated }, + }; + descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality) + values:values + valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription) + enumVerifier:GPBField_Cardinality_IsValidValue]; + } + return descriptor; +} + +BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { + switch (value__) { + case GPBField_Cardinality_CardinalityUnknown: + case GPBField_Cardinality_CardinalityOptional: + case GPBField_Cardinality_CardinalityRequired: + case GPBField_Cardinality_CardinalityRepeated: + return YES; + default: + return NO; + } +} + +#pragma mark - GPBEnum + +@implementation GPBEnum + +@dynamic name; +@dynamic enumvalueArray; +@dynamic optionsArray; +@dynamic hasSourceContext, sourceContext; + +typedef struct GPBEnum_Storage { + uint32_t _has_storage_[1]; + NSString *name; + NSMutableArray *enumvalueArray; + NSMutableArray *optionsArray; + GPBSourceContext *sourceContext; +} GPBEnum_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .number = GPBEnum_FieldNumber_Name, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBEnum_Storage, name), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "enumvalueArray", + .number = GPBEnum_FieldNumber_EnumvalueArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBEnum_Storage, enumvalueArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBEnumValue), + .fieldOptions = NULL, + }, + { + .name = "optionsArray", + .number = GPBEnum_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBEnum_Storage, optionsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBOption), + .fieldOptions = NULL, + }, + { + .name = "sourceContext", + .number = GPBEnum_FieldNumber_SourceContext, + .hasIndex = 3, + .flags = GPBFieldOptional, + .type = GPBTypeMessage, + .offset = offsetof(GPBEnum_Storage, sourceContext), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnum class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEnum_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBEnumValue + +@implementation GPBEnumValue + +@dynamic name; +@dynamic number; +@dynamic optionsArray; + +typedef struct GPBEnumValue_Storage { + uint32_t _has_storage_[1]; + int32_t number; + NSString *name; + NSMutableArray *optionsArray; +} GPBEnumValue_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .number = GPBEnumValue_FieldNumber_Name, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBEnumValue_Storage, name), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "number", + .number = GPBEnumValue_FieldNumber_Number, + .hasIndex = 1, + .flags = GPBFieldOptional, + .type = GPBTypeInt32, + .offset = offsetof(GPBEnumValue_Storage, number), + .defaultValue.valueInt32 = 0, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "optionsArray", + .number = GPBEnumValue_FieldNumber_OptionsArray, + .hasIndex = GPBNoHasBit, + .flags = GPBFieldRepeated, + .type = GPBTypeMessage, + .offset = offsetof(GPBEnumValue_Storage, optionsArray), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBOption), + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEnumValue_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBOption + +@implementation GPBOption + +@dynamic name; +@dynamic hasValue, value; + +typedef struct GPBOption_Storage { + uint32_t _has_storage_[1]; + NSString *name; + GPBAny *value; +} GPBOption_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "name", + .number = GPBOption_FieldNumber_Name, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBOption_Storage, name), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + { + .name = "value", + .number = GPBOption_FieldNumber_Value, + .hasIndex = 1, + .flags = GPBFieldOptional, + .type = GPBTypeMessage, + .offset = offsetof(GPBOption_Storage, value), + .defaultValue.valueMessage = nil, + .typeSpecific.className = GPBStringifySymbol(GPBAny), + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBOption class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBOption_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.h b/objectivec/google/protobuf/Wrappers.pbobjc.h new file mode 100644 index 00000000..227d958e --- /dev/null +++ b/objectivec/google/protobuf/Wrappers.pbobjc.h @@ -0,0 +1,154 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +#import "GPBProtocolBuffers.h" + +#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000 +#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources. +#endif + +// @@protoc_insertion_point(imports) + +CF_EXTERN_C_BEGIN + + +#pragma mark - GPBWrappersRoot + +@interface GPBWrappersRoot : GPBRootObject + +// The base class provides: +// + (GPBExtensionRegistry *)extensionRegistry; +// which is an GPBExtensionRegistry that includes all the extensions defined by +// this file and all files that it depends on. + +@end + +#pragma mark - GPBDoubleValue + +typedef GPB_ENUM(GPBDoubleValue_FieldNumber) { + GPBDoubleValue_FieldNumber_Value = 1, +}; + +// Wrapper message for double. +@interface GPBDoubleValue : GPBMessage + +// The double value. +@property(nonatomic, readwrite) double value; + +@end + +#pragma mark - GPBFloatValue + +typedef GPB_ENUM(GPBFloatValue_FieldNumber) { + GPBFloatValue_FieldNumber_Value = 1, +}; + +// Wrapper message for float. +@interface GPBFloatValue : GPBMessage + +// The float value. +@property(nonatomic, readwrite) float value; + +@end + +#pragma mark - GPBInt64Value + +typedef GPB_ENUM(GPBInt64Value_FieldNumber) { + GPBInt64Value_FieldNumber_Value = 1, +}; + +// Wrapper message for int64. +@interface GPBInt64Value : GPBMessage + +// The int64 value. +@property(nonatomic, readwrite) int64_t value; + +@end + +#pragma mark - GPBUInt64Value + +typedef GPB_ENUM(GPBUInt64Value_FieldNumber) { + GPBUInt64Value_FieldNumber_Value = 1, +}; + +// Wrapper message for uint64. +@interface GPBUInt64Value : GPBMessage + +// The uint64 value. +@property(nonatomic, readwrite) uint64_t value; + +@end + +#pragma mark - GPBInt32Value + +typedef GPB_ENUM(GPBInt32Value_FieldNumber) { + GPBInt32Value_FieldNumber_Value = 1, +}; + +// Wrapper message for int32. +@interface GPBInt32Value : GPBMessage + +// The int32 value. +@property(nonatomic, readwrite) int32_t value; + +@end + +#pragma mark - GPBUInt32Value + +typedef GPB_ENUM(GPBUInt32Value_FieldNumber) { + GPBUInt32Value_FieldNumber_Value = 1, +}; + +// Wrapper message for uint32. +@interface GPBUInt32Value : GPBMessage + +// The uint32 value. +@property(nonatomic, readwrite) uint32_t value; + +@end + +#pragma mark - GPBBoolValue + +typedef GPB_ENUM(GPBBoolValue_FieldNumber) { + GPBBoolValue_FieldNumber_Value = 1, +}; + +// Wrapper message for bool. +@interface GPBBoolValue : GPBMessage + +// The bool value. +@property(nonatomic, readwrite) BOOL value; + +@end + +#pragma mark - GPBStringValue + +typedef GPB_ENUM(GPBStringValue_FieldNumber) { + GPBStringValue_FieldNumber_Value = 1, +}; + +// Wrapper message for string. +@interface GPBStringValue : GPBMessage + +// The string value. +@property(nonatomic, readwrite, copy) NSString *value; + +@end + +#pragma mark - GPBBytesValue + +typedef GPB_ENUM(GPBBytesValue_FieldNumber) { + GPBBytesValue_FieldNumber_Value = 1, +}; + +// Wrapper message for bytes. +@interface GPBBytesValue : GPBMessage + +// The bytes value. +@property(nonatomic, readwrite, copy) NSData *value; + +@end + +CF_EXTERN_C_END + +// @@protoc_insertion_point(global_scope) diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m new file mode 100644 index 00000000..6c342850 --- /dev/null +++ b/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -0,0 +1,458 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/wrappers.proto + +#import "GPBProtocolBuffers_RuntimeSupport.h" +#import "google/protobuf/Wrappers.pbobjc.h" +// @@protoc_insertion_point(imports) + +#pragma mark - GPBWrappersRoot + +@implementation GPBWrappersRoot + +@end + +static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { + // This is called by +initialize so there is no need to worry + // about thread safety of the singleton. + static GPBFileDescriptor *descriptor = NULL; + if (!descriptor) { + descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" + syntax:GPBFileSyntaxProto3]; + } + return descriptor; +} + +#pragma mark - GPBDoubleValue + +@implementation GPBDoubleValue + +@dynamic value; + +typedef struct GPBDoubleValue_Storage { + uint32_t _has_storage_[1]; + double value; +} GPBDoubleValue_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBDoubleValue_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeDouble, + .offset = offsetof(GPBDoubleValue_Storage, value), + .defaultValue.valueDouble = 0, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBDoubleValue_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBFloatValue + +@implementation GPBFloatValue + +@dynamic value; + +typedef struct GPBFloatValue_Storage { + uint32_t _has_storage_[1]; + float value; +} GPBFloatValue_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBFloatValue_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeFloat, + .offset = offsetof(GPBFloatValue_Storage, value), + .defaultValue.valueFloat = 0, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFloatValue_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBInt64Value + +@implementation GPBInt64Value + +@dynamic value; + +typedef struct GPBInt64Value_Storage { + uint32_t _has_storage_[1]; + int64_t value; +} GPBInt64Value_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBInt64Value_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeInt64, + .offset = offsetof(GPBInt64Value_Storage, value), + .defaultValue.valueInt64 = 0LL, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBInt64Value_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBUInt64Value + +@implementation GPBUInt64Value + +@dynamic value; + +typedef struct GPBUInt64Value_Storage { + uint32_t _has_storage_[1]; + uint64_t value; +} GPBUInt64Value_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBUInt64Value_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeUInt64, + .offset = offsetof(GPBUInt64Value_Storage, value), + .defaultValue.valueUInt64 = 0ULL, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBUInt64Value_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBInt32Value + +@implementation GPBInt32Value + +@dynamic value; + +typedef struct GPBInt32Value_Storage { + uint32_t _has_storage_[1]; + int32_t value; +} GPBInt32Value_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBInt32Value_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeInt32, + .offset = offsetof(GPBInt32Value_Storage, value), + .defaultValue.valueInt32 = 0, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBInt32Value_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBUInt32Value + +@implementation GPBUInt32Value + +@dynamic value; + +typedef struct GPBUInt32Value_Storage { + uint32_t _has_storage_[1]; + uint32_t value; +} GPBUInt32Value_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBUInt32Value_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeUInt32, + .offset = offsetof(GPBUInt32Value_Storage, value), + .defaultValue.valueUInt32 = 0U, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBUInt32Value_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBBoolValue + +@implementation GPBBoolValue + +@dynamic value; + +typedef struct GPBBoolValue_Storage { + uint32_t _has_storage_[1]; + BOOL value; +} GPBBoolValue_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBBoolValue_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeBool, + .offset = offsetof(GPBBoolValue_Storage, value), + .defaultValue.valueBool = NO, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBBoolValue_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBStringValue + +@implementation GPBStringValue + +@dynamic value; + +typedef struct GPBStringValue_Storage { + uint32_t _has_storage_[1]; + NSString *value; +} GPBStringValue_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBStringValue_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeString, + .offset = offsetof(GPBStringValue_Storage, value), + .defaultValue.valueString = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBStringValue_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + +#pragma mark - GPBBytesValue + +@implementation GPBBytesValue + +@dynamic value; + +typedef struct GPBBytesValue_Storage { + uint32_t _has_storage_[1]; + NSData *value; +} GPBBytesValue_Storage; + +// This method is threadsafe because it is initially called +// in +initialize for each subclass. ++ (GPBDescriptor *)descriptor { + static GPBDescriptor *descriptor = NULL; + if (!descriptor) { + static GPBMessageFieldDescription fields[] = { + { + .name = "value", + .number = GPBBytesValue_FieldNumber_Value, + .hasIndex = 0, + .flags = GPBFieldOptional, + .type = GPBTypeData, + .offset = offsetof(GPBBytesValue_Storage, value), + .defaultValue.valueData = nil, + .typeSpecific.className = NULL, + .fieldOptions = NULL, + }, + }; + descriptor = [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBBytesValue_Storage) + wireFormat:NO]; + } + return descriptor; +} + +@end + + +// @@protoc_insertion_point(global_scope) diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h index 2dc5547b..0b41cf73 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.h @@ -49,7 +49,7 @@ namespace objectivec { class EnumGenerator { public: - EnumGenerator(const EnumDescriptor* descriptor); + explicit EnumGenerator(const EnumDescriptor* descriptor); ~EnumGenerator(); void GenerateHeader(io::Printer* printer); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index 739282b2..d6609692 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -48,6 +48,13 @@ void SetEnumVariables(const FieldDescriptor* descriptor, map* variables) { string type = EnumName(descriptor->enum_type()); (*variables)["storage_type"] = type; + // For non repeated fields, if it was defined in a different file, the + // property decls need to use "enum NAME" rather than just "NAME" to support + // the forward declaration of the enums. + if (!descriptor->is_repeated() && + (descriptor->file() != descriptor->enum_type()->file())) { + (*variables)["property_type"] = "enum " + type; + } // TODO(thomasvl): Make inclusion of descriptor compile time and output // both of these. Note: Extensions currently have to have the EnumDescription. (*variables)["enum_verifier"] = type + "_IsValidValue"; @@ -76,7 +83,9 @@ void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific( void EnumFieldGenerator::GenerateCFunctionDeclarations( io::Printer* printer) const { - if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return; + if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) { + return; + } printer->Print( variables_, @@ -105,6 +114,18 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( "\n"); } +void EnumFieldGenerator::DetermineForwardDeclarations( + set* fwd_decls) const { + // If it is an enum defined in a different file, then we'll need a forward + // declaration for it. When it is in our file, all the enums are output + // before the message, so it will be declared before it is needed. + if (descriptor_->file() != descriptor_->enum_type()->file()) { + // Enum name is already in "storage_type". + const string& name = variable("storage_type"); + fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")"); + } +} + RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( const FieldDescriptor* descriptor) : RepeatedFieldGenerator(descriptor) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h index 2d5822bb..b629eae8 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h @@ -47,9 +47,10 @@ class EnumFieldGenerator : public SingleFieldGenerator { virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; virtual void GenerateCFunctionDeclarations(io::Printer* printer) const; virtual void GenerateCFunctionImplementations(io::Printer* printer) const; + virtual void DetermineForwardDeclarations(set* fwd_decls) const; protected: - EnumFieldGenerator(const FieldDescriptor* descriptor); + explicit EnumFieldGenerator(const FieldDescriptor* descriptor); virtual ~EnumFieldGenerator(); private: diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index 0574cca2..76137c80 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -66,7 +66,7 @@ ExtensionGenerator::ExtensionGenerator(const string& root_class_name, } if (descriptor->is_map()) { // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some - // error case, so it seem to be ok to use as a back door for errors. + // error cases, so it seems to be ok to use as a back door for errors. cerr << "error: Extension is a map<>!" << " That used to be blocked by the compiler." << endl; cerr.flush(); @@ -107,7 +107,7 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( std::vector options; if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated"); - if (descriptor_->options().packed()) options.push_back("GPBExtensionPacked"); + if (descriptor_->is_packed()) options.push_back("GPBExtensionPacked"); if (descriptor_->containing_type()->options().message_set_wire_format()) options.push_back("GPBExtensionSetWireFormat"); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h index d17f5be9..553f0887 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h @@ -47,8 +47,8 @@ namespace objectivec { class ExtensionGenerator { public: - explicit ExtensionGenerator(const string& root_class_name, - const FieldDescriptor* descriptor); + ExtensionGenerator(const string& root_class_name, + const FieldDescriptor* descriptor); ~ExtensionGenerator(); void GenerateMembersHeader(io::Printer* printer); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index 93fffe0e..ee5253a5 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -80,7 +80,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated"); if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired"); if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional"); - if (descriptor->options().packed()) field_flags.push_back("GPBFieldPacked"); + if (descriptor->is_packed()) field_flags.push_back("GPBFieldPacked"); // ObjC custom flags. if (descriptor->has_default_value()) @@ -235,6 +235,11 @@ void FieldGenerator::GenerateCFunctionImplementations( // Nothing } +void FieldGenerator::DetermineForwardDeclarations( + set* fwd_decls) const { + // Nothing +} + void FieldGenerator::GenerateFieldDescription( io::Printer* printer) const { printer->Print( @@ -282,12 +287,16 @@ void FieldGenerator::SetOneofIndexBase(int index_base) { if (descriptor_->containing_oneof() != NULL) { int index = descriptor_->containing_oneof()->index() + index_base; // Flip the sign to mark it as a oneof. - variables_["has_index"] = SimpleItoa(-index);; + variables_["has_index"] = SimpleItoa(-index); } } void FieldGenerator::FinishInitialization(void) { - // Nothing + // If "property_type" wasn't set, make it "storage_type". + if ((variables_.find("property_type") == variables_.end()) && + (variables_.find("storage_type") != variables_.end())) { + variables_["property_type"] = variable("storage_type"); + } } SingleFieldGenerator::SingleFieldGenerator( @@ -313,7 +322,7 @@ void SingleFieldGenerator::GeneratePropertyDeclaration( } printer->Print( variables_, - "@property(nonatomic, readwrite) $storage_type$ $name$;\n" + "@property(nonatomic, readwrite) $property_type$ $name$;\n" "\n"); } @@ -369,12 +378,12 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration( } printer->Print( variables_, - "@property(nonatomic, readwrite, $property_storage_attribute$) $storage_type$ *$name$$storage_attribute$;\n"); + "@property(nonatomic, readwrite, $property_storage_attribute$) $property_type$ *$name$$storage_attribute$;\n"); if (IsInitName(variables_.at("name"))) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 printer->Print(variables_, - "- ($storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n"); + "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n"); } printer->Print("\n"); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h index c65e73b2..130a52dd 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h @@ -65,6 +65,8 @@ class FieldGenerator { virtual void GenerateCFunctionDeclarations(io::Printer* printer) const; virtual void GenerateCFunctionImplementations(io::Printer* printer) const; + virtual void DetermineForwardDeclarations(set* fwd_decls) const; + void SetOneofIndexBase(int index_base); string variable(const char* key) const { @@ -79,7 +81,7 @@ class FieldGenerator { string raw_field_name() const { return variable("raw_field_name"); } protected: - FieldGenerator(const FieldDescriptor* descriptor); + explicit FieldGenerator(const FieldDescriptor* descriptor); virtual void FinishInitialization(void); virtual bool WantsHasProperty(void) const = 0; @@ -101,7 +103,7 @@ class SingleFieldGenerator : public FieldGenerator { virtual void GeneratePropertyImplementation(io::Printer* printer) const; protected: - SingleFieldGenerator(const FieldDescriptor* descriptor); + explicit SingleFieldGenerator(const FieldDescriptor* descriptor); virtual bool WantsHasProperty(void) const; private: @@ -117,7 +119,7 @@ class ObjCObjFieldGenerator : public SingleFieldGenerator { virtual void GeneratePropertyDeclaration(io::Printer* printer) const; protected: - ObjCObjFieldGenerator(const FieldDescriptor* descriptor); + explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator); @@ -133,7 +135,7 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator { virtual void GeneratePropertyImplementation(io::Printer* printer) const; protected: - RepeatedFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor); virtual void FinishInitialization(void); virtual bool WantsHasProperty(void) const; @@ -144,7 +146,7 @@ class RepeatedFieldGenerator : public ObjCObjFieldGenerator { // Convenience class which constructs FieldGenerators for a Descriptor. class FieldGeneratorMap { public: - FieldGeneratorMap(const Descriptor* descriptor); + explicit FieldGeneratorMap(const Descriptor* descriptor); ~FieldGeneratorMap(); const FieldGenerator& get(const FieldDescriptor* field) const; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index b3ad448e..d04eee85 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -50,11 +50,17 @@ const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30000; namespace compiler { namespace objectivec { + FileGenerator::FileGenerator(const FileDescriptor *file) : file_(file), root_class_name_(FileClassName(file)), is_filtered_(true), - all_extensions_filtered_(true) { + all_extensions_filtered_(true), + is_public_dep_(false) { + // Validate the objc prefix, do this even if the file's contents are filtered + // to catch a bad prefix as soon as it is found. + ValidateObjCClassPrefix(file_); + for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); // The enums are exposed via C functions, so they will dead strip if @@ -96,7 +102,9 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "\n", "filename", file_->name()); - printer->Print("#import \"GPBProtocolBuffers.h\"\n\n"); + printer->Print( + "#import \"GPBProtocolBuffers.h\"\n" + "\n"); // Add some verification that the generated code matches the source the // code is being compiled with. @@ -108,31 +116,34 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "protoc_gen_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION)); - if (!IsFiltered()) { - const vector &dependency_generators = - DependencyGenerators(); - if (dependency_generators.size() > 0) { - for (vector::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { - printer->Print("#import \"$header$.pbobjc.h\"\n", - "header", (*iter)->Path()); - } - printer->Print("\n"); + const vector &dependency_generators = + DependencyGenerators(); + for (vector::const_iterator iter = + dependency_generators.begin(); + iter != dependency_generators.end(); ++iter) { + if ((*iter)->IsPublicDependency()) { + printer->Print("#import \"$header$.pbobjc.h\"\n", + "header", (*iter)->Path()); } } + printer->Print( + "// @@protoc_insertion_point(imports)\n" + "\n"); + printer->Print("CF_EXTERN_C_BEGIN\n\n"); if (!IsFiltered()) { - set dependencies; - DetermineDependencies(&dependencies); - for (set::const_iterator i(dependencies.begin()); - i != dependencies.end(); ++i) { + set fwd_decls; + for (vector::iterator iter = message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->DetermineForwardDeclarations(&fwd_decls); + } + for (set::const_iterator i(fwd_decls.begin()); + i != fwd_decls.end(); ++i) { printer->Print("$value$;\n", "value", *i); } - - if (dependencies.begin() != dependencies.end()) { + if (fwd_decls.begin() != fwd_decls.end()) { printer->Print("\n"); } } @@ -156,7 +167,14 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "#pragma mark - $root_class_name$\n" "\n" "@interface $root_class_name$ : GPBRootObject\n" - "@end\n\n", + "\n" + "// The base class provides:\n" + "// + (GPBExtensionRegistry *)extensionRegistry;\n" + "// which is an GPBExtensionRegistry that includes all the extensions defined by\n" + "// this file and all files that it depends on.\n" + "\n" + "@end\n" + "\n", "root_class_name", root_class_name_); } @@ -189,33 +207,10 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { } printer->Print("CF_EXTERN_C_END\n"); -} - -void DetermineDependenciesWorker(set *dependencies, - set *seen_files, - const string &classname, - const FileDescriptor *file) { - if (seen_files->find(file->name()) != seen_files->end()) { - // don't infinitely recurse - return; - } - - seen_files->insert(file->name()); - - for (int i = 0; i < file->dependency_count(); i++) { - DetermineDependenciesWorker(dependencies, seen_files, classname, - file->dependency(i)); - } - for (int i = 0; i < file->message_type_count(); i++) { - MessageGenerator(classname, file->message_type(i)) - .DetermineDependencies(dependencies); - } -} -void FileGenerator::DetermineDependencies(set *dependencies) { - set seen_files; - DetermineDependenciesWorker(dependencies, &seen_files, root_class_name_, - file_); + printer->Print( + "\n" + "// @@protoc_insertion_point(global_scope)\n"); } void FileGenerator::GenerateSource(io::Printer *printer) { @@ -225,6 +220,25 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "\n", "filename", file_->name()); + string header_file = Path() + ".pbobjc.h"; + printer->Print( + "#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n" + "#import \"$header_file$\"\n", + "header_file", header_file); + const vector &dependency_generators = + DependencyGenerators(); + for (vector::const_iterator iter = + dependency_generators.begin(); + iter != dependency_generators.end(); ++iter) { + if (!(*iter)->IsPublicDependency()) { + printer->Print("#import \"$header$.pbobjc.h\"\n", + "header", (*iter)->Path()); + } + } + printer->Print( + "// @@protoc_insertion_point(imports)\n" + "\n"); + if (IsFiltered()) { printer->Print( "// File empty because all messages, extensions and enum have been filtered.\n" @@ -232,22 +246,17 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "\n" "// Dummy symbol that will be stripped but will avoid linker warnings about\n" "// no symbols in the .o form compiling this file.\n" - "static int $root_class_name$_dummy __attribute__((unused,used)) = 0;\n", + "static int $root_class_name$_dummy __attribute__((unused,used)) = 0;\n" + "\n" + "// @@protoc_insertion_point(global_scope)\n", "root_class_name", root_class_name_); return; } - printer->Print("#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n\n"); - - string header_file = Path() + ".pbobjc.h"; - printer->Print( - "#import \"$header_file$\"\n" - "\n" "#pragma mark - $root_class_name$\n" "\n" "@implementation $root_class_name$\n\n", - "header_file", header_file, "root_class_name", root_class_name_); bool generated_extensions = false; @@ -326,12 +335,7 @@ void FileGenerator::GenerateSource(io::Printer *printer) { " }\n" " return registry;\n" "}\n" - "\n" - "+ (void)load {\n" - " @autoreleasepool {\n" - " [self extensionRegistry]; // Construct extension registry.\n" - " }\n" - "}\n\n"); + "\n"); } } @@ -374,19 +378,31 @@ void FileGenerator::GenerateSource(io::Printer *printer) { iter != message_generators_.end(); ++iter) { (*iter)->GenerateSource(printer); } + + printer->Print( + "\n" + "// @@protoc_insertion_point(global_scope)\n"); } const string FileGenerator::Path() const { return FilePath(file_); } const vector &FileGenerator::DependencyGenerators() { if (file_->dependency_count() != dependency_generators_.size()) { + set public_import_names; + for (int i = 0; i < file_->public_dependency_count(); i++) { + public_import_names.insert(file_->public_dependency(i)->name()); + } for (int i = 0; i < file_->dependency_count(); i++) { FileGenerator *generator = new FileGenerator(file_->dependency(i)); + const string& name = file_->dependency(i)->name(); + bool public_import = (public_import_names.count(name) != 0); + generator->SetIsPublicDependency(public_import); dependency_generators_.push_back(generator); } } return dependency_generators_; } + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index fbd08eae..95d17bfd 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -66,6 +66,12 @@ class FileGenerator { bool IsFiltered() const { return is_filtered_; } bool AreAllExtensionsFiltered() const { return all_extensions_filtered_; } + bool IsPublicDependency() const { return is_public_dep_; } + + protected: + void SetIsPublicDependency(bool is_public_dep) { + is_public_dep_ = is_public_dep; + } private: const FileDescriptor* file_; @@ -80,15 +86,16 @@ class FileGenerator { vector extension_generators_; bool is_filtered_; bool all_extensions_filtered_; - - void DetermineDependencies(set* dependencies); + bool is_public_dep_; const vector& DependencyGenerators(); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; + } // namespace objectivec } // namespace compiler } // namespace protobuf } // namespace google + #endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__ diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index d4675f02..6d6e5959 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -41,7 +41,7 @@ #include // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some -// error case, so it seem to be ok to use as a back door for errors. +// error cases, so it seems to be ok to use as a back door for errors. namespace google { namespace protobuf { @@ -53,6 +53,11 @@ namespace { hash_set gClassWhitelist; // islower()/isupper()/tolower()/toupper() change based on locale. +// +// src/google/protobuf/stubs/strutil.h:150 has the same pattern. For the +// Objective C plugin, test failures were seen on TravisCI because isupper('A') +// was coming back false for some server's locale. This approach avoids any +// such issues. bool IsLower(const char c) { return ('a' <= c && c <= 'z'); @@ -205,10 +210,9 @@ const char* const kReservedWordList[] = { // Only need to add instance methods that may conflict with // method declared in protos. The main cases are methods // that take no arguments, or setFoo:/hasFoo: type methods. - // These are currently in the same order as in GPBMessage.h. - "unknownFields", "extensionRegistry", "isInitialized", - "data", "delimitedData", "serializedSize", - "descriptor", "extensionsCurrentlySet", "clear", "sortedExtensionsInUse", + "clear", "data", "delimitedData", "descriptor", "extensionRegistry", + "extensionsCurrentlySet", "isInitialized", "serializedSize", + "sortedExtensionsInUse", "unknownFields", // MacTypes.h names "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount", @@ -335,7 +339,32 @@ string FilePath(const FileDescriptor* file) { string FileClassPrefix(const FileDescriptor* file) { // Default is empty string, no need to check has_objc_class_prefix. - return file->options().objc_class_prefix(); + string result = file->options().objc_class_prefix(); + return result; +} + +void ValidateObjCClassPrefix(const FileDescriptor* file) { + string prefix = file->options().objc_class_prefix(); + if (prefix.length() > 0) { + // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some + // error cases, so it seems to be ok to use as a back door for errors. + if (!IsUpper(prefix[0])) { + cerr << endl + << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " it should start with a capital letter." + << endl; + cerr.flush(); + } + if (prefix.length() < 3) { + cerr << endl + << "protoc:0: warning: Invalid 'option objc_class_prefix = \"" + << prefix << "\";' in '" << file->name() << "';" + << " Apple recommends they should be at least 3 characters long." + << endl; + cerr.flush(); + } + } } string FileClassName(const FileDescriptor* file) { @@ -468,7 +497,7 @@ string OneofEnumName(const OneofDescriptor* descriptor) { const Descriptor* fieldDescriptor = descriptor->containing_type(); string name = ClassName(fieldDescriptor); name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase"; - // No sanitize needed because it the OS never has names that end in OneOfCase. + // No sanitize needed because the OS never has names that end in _OneOfCase. return name; } @@ -560,6 +589,8 @@ string GetCapitalizedType(const FieldDescriptor* field) { return "Message"; } + // 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 NULL; } @@ -607,6 +638,8 @@ ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) { return OBJECTIVECTYPE_MESSAGE; } + // 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 OBJECTIVECTYPE_INT32; } @@ -683,6 +716,8 @@ string GPBValueFieldName(const FieldDescriptor* field) { return "valueMessage"; } + // 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 NULL; } @@ -753,6 +788,8 @@ string DefaultValue(const FieldDescriptor* field) { return "nil"; } + // 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 NULL; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index ab030d15..29168937 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -62,6 +62,9 @@ string FileName(const FileDescriptor* file); // declared in the proto package. string FilePath(const FileDescriptor* file); +// Checks the prefix for a given file and outputs any warnings/errors needed. +void ValidateObjCClassPrefix(const FileDescriptor* file); + // Gets the name of the root class we'll generate in the file. This class // is not meant for external consumption, but instead contains helpers that // the rest of the the classes need diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc index cafdf39d..2987f3db 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc @@ -76,6 +76,8 @@ const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) { return "Object"; } + // 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 NULL; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h index 8862dc35..173541f2 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h @@ -48,7 +48,7 @@ class MapFieldGenerator : public RepeatedFieldGenerator { virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const; protected: - MapFieldGenerator(const FieldDescriptor* descriptor); + explicit MapFieldGenerator(const FieldDescriptor* descriptor); virtual ~MapFieldGenerator(); private: diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index f6a5852d..52e583bf 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -120,6 +120,8 @@ int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) { 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; } @@ -188,7 +190,7 @@ MessageGenerator::MessageGenerator(const string& root_classname, extension_generators_.push_back( new ExtensionGenerator(class_name_, descriptor_->extension(i))); } - // No need to oneofs if this message is filtered + // No need to generate oneofs if this message is filtered. for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); oneof_generators_.push_back(generator); @@ -253,15 +255,24 @@ void MessageGenerator::GenerateStaticVariablesInitialization( } } -void MessageGenerator::DetermineDependencies(set* dependencies) { +void MessageGenerator::DetermineForwardDeclarations(set* fwd_decls) { if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { - dependencies->insert("@class " + class_name_); + 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::iterator iter = nested_message_generators_.begin(); iter != nested_message_generators_.end(); ++iter) { - (*iter)->DetermineDependencies(dependencies); + (*iter)->DetermineForwardDeclarations(fwd_decls); } } @@ -361,13 +372,13 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { "classname", class_name_, "comments", message_comments); - vector seen_oneofs(descriptor_->oneof_decl_count(), false); + vector 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] = true; + seen_oneofs[oneof_index] = 1; oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration( printer); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h index 5992d0cf..8d03c0b8 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h @@ -63,7 +63,7 @@ class MessageGenerator { void GenerateMessageHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); void GenerateExtensionRegistrationSource(io::Printer* printer); - void DetermineDependencies(set* dependencies); + void DetermineForwardDeclarations(set* fwd_decls); // This only speaks for this message, not sub message/enums. bool IsFiltered() const { return filter_reason_.length() > 0; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc index 9c4a4e44..2e3bdfdb 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -65,6 +65,12 @@ MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor) MessageFieldGenerator::~MessageFieldGenerator() {} +void MessageFieldGenerator::DetermineForwardDeclarations( + set* fwd_decls) const { + // Class name is already in "storage_type". + fwd_decls->insert("@class " + variable("storage_type")); +} + bool MessageFieldGenerator::WantsHasProperty(void) const { if (descriptor_->containing_oneof() != NULL) { // If in a oneof, it uses the oneofcase instead of a has bit. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h index a1ac2d39..708ea566 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h @@ -44,10 +44,13 @@ class MessageFieldGenerator : public ObjCObjFieldGenerator { friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); protected: - MessageFieldGenerator(const FieldDescriptor* descriptor); + explicit MessageFieldGenerator(const FieldDescriptor* descriptor); virtual ~MessageFieldGenerator(); virtual bool WantsHasProperty(void) const; + public: + virtual void DetermineForwardDeclarations(set* fwd_decls) const; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; @@ -56,7 +59,7 @@ class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator { friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); protected: - RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor); virtual ~RepeatedMessageFieldGenerator(); private: diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h index 77b7f800..bcba82da 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h @@ -49,7 +49,7 @@ namespace objectivec { class OneofGenerator { public: - OneofGenerator(const OneofDescriptor* descriptor); + explicit OneofGenerator(const OneofDescriptor* descriptor); ~OneofGenerator(); void SetOneofIndexBase(int index_base); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc index 54f94284..c185b66d 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc @@ -77,6 +77,8 @@ const char* PrimitiveTypeName(const FieldDescriptor* descriptor) { return NULL; } + // 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 NULL; } @@ -108,6 +110,8 @@ const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) { return ""; // Want NSArray } + // 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 NULL; } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h index b3599297..9bb79343 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h @@ -44,7 +44,7 @@ class PrimitiveFieldGenerator : public SingleFieldGenerator { friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); protected: - PrimitiveFieldGenerator(const FieldDescriptor* descriptor); + explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor); virtual ~PrimitiveFieldGenerator(); private: @@ -55,7 +55,7 @@ class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator { friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); protected: - PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor); + explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor); virtual ~PrimitiveObjFieldGenerator(); private: @@ -66,7 +66,7 @@ class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator { friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field); protected: - RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); + explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor); virtual ~RepeatedPrimitiveFieldGenerator(); virtual void FinishInitialization(void); -- cgit v1.2.3 From cf603a9dfac6447f2fe62822fa7c235a50a92de7 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Sun, 24 May 2015 22:28:04 -0700 Subject: Fix bugs on windows. --- src/google/protobuf/any.h | 2 +- src/google/protobuf/arena_unittest.cc | 5 +- .../compiler/command_line_interface_unittest.cc | 4 ++ .../compiler/objectivec/objectivec_helpers.h | 2 +- .../objectivec/objectivec_helpers_unittest.cc | 7 +++ src/google/protobuf/map.h | 6 +-- src/google/protobuf/map_entry.h | 6 +-- src/google/protobuf/map_entry_lite.h | 12 ++--- src/google/protobuf/map_field.h | 2 +- src/google/protobuf/map_field_lite.h | 2 +- src/google/protobuf/stubs/strutil.h | 57 +++++++++++++--------- 11 files changed, 64 insertions(+), 41 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h index 757b45aa..f681eceb 100644 --- a/src/google/protobuf/any.h +++ b/src/google/protobuf/any.h @@ -43,7 +43,7 @@ namespace protobuf { namespace internal { // Helper class used to implement google::protobuf::Any. -class AnyMetadata { +class LIBPROTOBUF_EXPORT AnyMetadata { typedef ArenaStringPtr UrlType; typedef ArenaStringPtr ValueType; public: diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 873e85ae..b9dd8b98 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -1232,8 +1232,11 @@ TEST(ArenaTest, ArenaHooksSanity) { EXPECT_EQ(1, ArenaHooksTestUtil::num_init); EXPECT_EQ(0, ArenaHooksTestUtil::num_allocations); ::google::protobuf::Arena::Create(&arena); +#ifdef _WIN32 + EXPECT_EQ(2, ArenaHooksTestUtil::num_allocations); +#else EXPECT_EQ(1, ArenaHooksTestUtil::num_allocations); - +#endif arena.Reset(); arena.Reset(); EXPECT_EQ(2, ArenaHooksTestUtil::num_reset); diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 23d67e2b..e5b77c33 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -973,6 +973,9 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { EXPECT_TRUE(descriptor_set.file(1).has_source_code_info()); } +#ifdef _WIN32 +// TODO(teboring): Figure out how to write test on windows. +#else TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileGivenTwoInputs) { CreateTempFile("foo.proto", "syntax = \"proto2\";\n" @@ -1042,6 +1045,7 @@ TEST_F(CommandLineInterfaceTest, WriteDependencyManifestFileForAbsolutePath) { "$tmpdir/bar.proto.MockCodeGenerator.test_generator: " "$tmpdir/foo.proto\\\n $tmpdir/bar.proto"); } +#endif // !_WIN32 // ------------------------------------------------------------------- diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 29168937..19317698 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -150,7 +150,7 @@ bool FilterClass(const string& name); // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the the expected output. -class TextFormatDecodeData { +class LIBPROTOC_EXPORT TextFormatDecodeData { public: TextFormatDecodeData() {} diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc index 01e937c3..b091b77a 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc @@ -111,6 +111,8 @@ TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) { EXPECT_EQ(expected, result); } +// Death tests do not work on Windows as of yet. +#ifdef PROTOBUF_HAS_DEATH_TEST TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) { // Empty inputs. @@ -136,6 +138,7 @@ TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) { ::testing::KilledBySignal(SIGABRT), "error: got a null char in a string for making TextFormat data, input:"); } +#endif // PROTOBUF_HAS_DEATH_TEST TEST(ObjCHelper, TextFormatDecodeData_RawStrings) { TextFormatDecodeData decode_data; @@ -198,6 +201,9 @@ TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) { EXPECT_EQ(expected, decode_data.Data()); } + +// Death tests do not work on Windows as of yet. +#ifdef PROTOBUF_HAS_DEATH_TEST TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) { TextFormatDecodeData decode_data; @@ -234,6 +240,7 @@ TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) { ::testing::KilledBySignal(SIGABRT), "error: duplicate key \\(2\\) making TextFormat data, input:"); } +#endif // PROTOBUF_HAS_DEATH_TEST } // namespace } // namespace objectivec diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 1858e2f9..f246dd10 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -199,7 +199,7 @@ class Map { typedef MapAllocator*> > Allocator; // Iterators - class LIBPROTOBUF_EXPORT const_iterator + class const_iterator : public std::iterator { typedef typename hash_map, equal_to, @@ -229,7 +229,7 @@ class Map { InnerIt it_; }; - class LIBPROTOBUF_EXPORT iterator : public std::iterator { + class iterator : public std::iterator { typedef typename hash_map, Allocator>::iterator InnerIt; @@ -428,7 +428,7 @@ class Map { internal::WireFormatLite::FieldType key_wire_type, internal::WireFormatLite::FieldType value_wire_type, int default_enum_value> - friend class LIBPROTOBUF_EXPORT internal::MapFieldLite; + friend class internal::MapFieldLite; }; } // namespace protobuf diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h index f78a4f40..e93d0348 100644 --- a/src/google/protobuf/map_entry.h +++ b/src/google/protobuf/map_entry.h @@ -97,7 +97,7 @@ template -class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase { +class MapEntry : public MapEntryBase { // Handlers for key/value wire type. Provide utilities to parse/serialize // key/value. typedef MapWireFieldTypeHandler KeyWireHandler; @@ -274,8 +274,8 @@ class LIBPROTOBUF_EXPORT MapEntry : public MapEntryBase { typedef void DestructorSkippable_; template - friend class LIBPROTOBUF_EXPORT internal::MapField; - friend class LIBPROTOBUF_EXPORT internal::GeneratedMessageReflection; + friend class internal::MapField; + friend class internal::GeneratedMessageReflection; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry); }; diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h index 2d11bea8..52746da5 100644 --- a/src/google/protobuf/map_entry_lite.h +++ b/src/google/protobuf/map_entry_lite.h @@ -60,7 +60,7 @@ template -class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { +class MapEntryLite : public MessageLite { // Handlers for key/value wire type. Provide utilities to parse/serialize // key/value. typedef MapWireFieldTypeHandler KeyWireHandler; @@ -302,7 +302,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { // only takes references of given key and value. template - class LIBPROTOBUF_EXPORT MapEntryWrapper + class MapEntryWrapper : public MapEntryLite { typedef MapEntryLite Base; typedef typename Base::KeyCppType KeyCppType; @@ -336,7 +336,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { // the temporary. template - class LIBPROTOBUF_EXPORT MapEnumEntryWrapper + class MapEnumEntryWrapper : public MapEntryLite { typedef MapEntryLite Base; typedef typename Base::KeyCppType KeyCppType; @@ -357,7 +357,7 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { const KeyCppType& key_; const ValCppType value_; - friend class LIBPROTOBUF_EXPORT google::protobuf::Arena; + friend class google::protobuf::Arena; typedef void DestructorSkippable_; }; @@ -396,10 +396,10 @@ class LIBPROTOBUF_EXPORT MapEntryLite : public MessageLite { typedef void DestructorSkippable_; template - friend class LIBPROTOBUF_EXPORT internal::MapEntry; + friend class internal::MapEntry; template - friend class LIBPROTOBUF_EXPORT internal::MapFieldLite; + friend class internal::MapFieldLite; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite); }; diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h index f3504f1b..902aefce 100644 --- a/src/google/protobuf/map_field.h +++ b/src/google/protobuf/map_field.h @@ -146,7 +146,7 @@ template -class LIBPROTOBUF_EXPORT MapField : public MapFieldBase, +class MapField : public MapFieldBase, public MapFieldLite { // Handlers for key/value wire type. Provide utilities to parse/serialize diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h index 40322851..860dae55 100644 --- a/src/google/protobuf/map_field_lite.h +++ b/src/google/protobuf/map_field_lite.h @@ -45,7 +45,7 @@ template -class LIBPROTOBUF_EXPORT MapFieldLite { +class MapFieldLite { // Define message type for internal repeated field. typedef MapEntryLite EntryType; diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index 5faa81e0..397122ef 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -534,7 +534,7 @@ struct Hex { } }; -struct AlphaNum { +struct LIBPROTOBUF_EXPORT AlphaNum { const char *piece_data_; // move these to string_ref eventually size_t piece_size_; // move these to string_ref eventually @@ -610,23 +610,30 @@ using strings::AlphaNum; // be a reference into str. // ---------------------------------------------------------------------- -string StrCat(const AlphaNum &a, const AlphaNum &b); -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c); -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d); -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e); -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f); -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g); -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g, const AlphaNum &h); -string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, - const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, - const AlphaNum &g, const AlphaNum &h, const AlphaNum &i); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h, + const AlphaNum& i); inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } @@ -651,12 +658,14 @@ inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } // worked around as consecutive calls to StrAppend are quite efficient. // ---------------------------------------------------------------------- -void StrAppend(string* dest, const AlphaNum& a); -void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b); -void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c); -void StrAppend(string* dest, const AlphaNum& a, const AlphaNum& b, - const AlphaNum& c, const AlphaNum& d); +LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a); +LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, + const AlphaNum& b); +LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c); +LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c, + const AlphaNum& d); // ---------------------------------------------------------------------- // Join() -- cgit v1.2.3 From a9332e201d246c0f6076a6821893b141967a056b Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Mon, 25 May 2015 16:04:36 -0700 Subject: Copy two data files from ruby/tests to src/google/compiler/ruby. Tests in src/google/compiler/ruby depend on these two files, but they were missed in language distributions other than ruby --- src/Makefile.am | 2 + .../compiler/ruby/ruby_generated_code.proto | 67 ++++++++++++++++++++ .../protobuf/compiler/ruby/ruby_generated_code.rb | 74 ++++++++++++++++++++++ .../compiler/ruby/ruby_generator_unittest.cc | 14 ++-- 4 files changed, 150 insertions(+), 7 deletions(-) create mode 100644 src/google/protobuf/compiler/ruby/ruby_generated_code.proto create mode 100644 src/google/protobuf/compiler/ruby/ruby_generated_code.rb (limited to 'src/google/protobuf/compiler') diff --git a/src/Makefile.am b/src/Makefile.am index 2ecf6028..a394a13a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -449,6 +449,8 @@ EXTRA_DIST = \ google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt \ google/protobuf/package_info.h \ google/protobuf/io/package_info.h \ + google/protobuf/compiler/ruby/ruby_generated_code.proto \ + google/protobuf/compiler/ruby/ruby_generated_code.rb \ google/protobuf/compiler/package_info.h \ google/protobuf/compiler/zip_output_unittest.sh \ google/protobuf/unittest_enormous_descriptor.proto diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.proto b/src/google/protobuf/compiler/ruby/ruby_generated_code.proto new file mode 100644 index 00000000..42d82a6b --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_code.proto @@ -0,0 +1,67 @@ +syntax = "proto3"; + +package A.B.C; + +message TestMessage { + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + bool optional_bool = 5; + double optional_double = 6; + float optional_float = 7; + string optional_string = 8; + bytes optional_bytes = 9; + TestEnum optional_enum = 10; + TestMessage optional_msg = 11; + + repeated int32 repeated_int32 = 21; + repeated int64 repeated_int64 = 22; + repeated uint32 repeated_uint32 = 23; + repeated uint64 repeated_uint64 = 24; + repeated bool repeated_bool = 25; + repeated double repeated_double = 26; + repeated float repeated_float = 27; + repeated string repeated_string = 28; + repeated bytes repeated_bytes = 29; + repeated TestEnum repeated_enum = 30; + repeated TestMessage repeated_msg = 31; + + oneof my_oneof { + int32 oneof_int32 = 41; + int64 oneof_int64 = 42; + uint32 oneof_uint32 = 43; + uint64 oneof_uint64 = 44; + bool oneof_bool = 45; + double oneof_double = 46; + float oneof_float = 47; + string oneof_string = 48; + bytes oneof_bytes = 49; + TestEnum oneof_enum = 50; + TestMessage oneof_msg = 51; + } + + map map_int32_string = 61; + map map_int64_string = 62; + map map_uint32_string = 63; + map map_uint64_string = 64; + map map_bool_string = 65; + map map_string_string = 66; + map map_string_msg = 67; + map map_string_enum = 68; + map map_string_int32 = 69; + map map_string_bool = 70; + + message NestedMessage { + int32 foo = 1; + } + + NestedMessage nested_message = 80; +} + +enum TestEnum { + Default = 0; + A = 1; + B = 2; + C = 3; +} diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code.rb new file mode 100644 index 00000000..100d6fa7 --- /dev/null +++ b/src/google/protobuf/compiler/ruby/ruby_generated_code.rb @@ -0,0 +1,74 @@ +# Generated by the protocol buffer compiler. DO NOT EDIT! +# source: ruby_generated_code.proto + +require 'google/protobuf' + +Google::Protobuf::DescriptorPool.generated_pool.build do + add_message "A.B.C.TestMessage" do + optional :optional_int32, :int32, 1 + optional :optional_int64, :int64, 2 + optional :optional_uint32, :uint32, 3 + optional :optional_uint64, :uint64, 4 + optional :optional_bool, :bool, 5 + optional :optional_double, :double, 6 + optional :optional_float, :float, 7 + optional :optional_string, :string, 8 + optional :optional_bytes, :string, 9 + optional :optional_enum, :enum, 10, "A.B.C.TestEnum" + optional :optional_msg, :message, 11, "A.B.C.TestMessage" + repeated :repeated_int32, :int32, 21 + repeated :repeated_int64, :int64, 22 + repeated :repeated_uint32, :uint32, 23 + repeated :repeated_uint64, :uint64, 24 + repeated :repeated_bool, :bool, 25 + repeated :repeated_double, :double, 26 + repeated :repeated_float, :float, 27 + repeated :repeated_string, :string, 28 + repeated :repeated_bytes, :string, 29 + repeated :repeated_enum, :enum, 30, "A.B.C.TestEnum" + repeated :repeated_msg, :message, 31, "A.B.C.TestMessage" + map :map_int32_string, :int32, :string, 61 + map :map_int64_string, :int64, :string, 62 + map :map_uint32_string, :uint32, :string, 63 + map :map_uint64_string, :uint64, :string, 64 + map :map_bool_string, :bool, :string, 65 + map :map_string_string, :string, :string, 66 + map :map_string_msg, :string, :message, 67, "A.B.C.TestMessage" + map :map_string_enum, :string, :enum, 68, "A.B.C.TestEnum" + map :map_string_int32, :string, :int32, 69 + map :map_string_bool, :string, :bool, 70 + optional :nested_message, :message, 80, "A.B.C.TestMessage.NestedMessage" + oneof :my_oneof do + optional :oneof_int32, :int32, 41 + optional :oneof_int64, :int64, 42 + optional :oneof_uint32, :uint32, 43 + optional :oneof_uint64, :uint64, 44 + optional :oneof_bool, :bool, 45 + optional :oneof_double, :double, 46 + optional :oneof_float, :float, 47 + optional :oneof_string, :string, 48 + optional :oneof_bytes, :string, 49 + optional :oneof_enum, :enum, 50, "A.B.C.TestEnum" + optional :oneof_msg, :message, 51, "A.B.C.TestMessage" + end + end + add_message "A.B.C.TestMessage.NestedMessage" do + optional :foo, :int32, 1 + end + add_enum "A.B.C.TestEnum" do + value :Default, 0 + value :A, 1 + value :B, 2 + value :C, 3 + end +end + +module A + module B + module C + TestMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage").msgclass + TestMessage::NestedMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestMessage.NestedMessage").msgclass + TestEnum = Google::Protobuf::DescriptorPool.generated_pool.lookup("A.B.C.TestEnum").enummodule + end + end +end diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index e35ca695..0247e95f 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -48,7 +48,7 @@ namespace { string FindRubyTestDir() { // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc. string prefix = "."; - while (!File::Exists(prefix + "/ruby/tests")) { + while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby")) { if (!File::Exists(prefix)) { GOOGLE_LOG(FATAL) << "Could not find Ruby test directory. Please run tests from " @@ -56,7 +56,7 @@ string FindRubyTestDir() { } prefix += "/.."; } - return prefix + "/ruby/tests"; + return prefix + "/src/google/protobuf/compiler/ruby"; } // This test is a simple golden-file test over the output of the Ruby code @@ -78,11 +78,11 @@ TEST(RubyGeneratorTest, GeneratorTest) { // Copy generated_code.proto to the temporary test directory. string test_input; GOOGLE_CHECK_OK(File::GetContents( - ruby_tests + "/generated_code.proto", + ruby_tests + "/ruby_generated_code.proto", &test_input, true)); GOOGLE_CHECK_OK(File::SetContents( - TestTempDir() + "/generated_code.proto", + TestTempDir() + "/ruby_generated_code.proto", test_input, true)); @@ -93,7 +93,7 @@ TEST(RubyGeneratorTest, GeneratorTest) { "protoc", ruby_out.c_str(), proto_path.c_str(), - "generated_code.proto", + "ruby_generated_code.proto", }; EXPECT_EQ(0, cli.Run(4, argv)); @@ -101,12 +101,12 @@ TEST(RubyGeneratorTest, GeneratorTest) { // Load the generated output and compare to the expected result. string output; GOOGLE_CHECK_OK(File::GetContents( - TestTempDir() + "/generated_code.rb", + TestTempDir() + "/ruby_generated_code.rb", &output, true)); string expected_output; GOOGLE_CHECK_OK(File::GetContents( - ruby_tests + "/generated_code.rb", + ruby_tests + "/ruby_generated_code.rb", &expected_output, true)); EXPECT_EQ(expected_output, output); -- cgit v1.2.3 From 83d334f713b814dfff2d76e189a8245c8e296792 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Tue, 26 May 2015 14:13:53 -0700 Subject: When doing make distcheck, a src/google/protobuf/compiler/ruby is created to put built libraries. This directory hides the one that contains ruby_generated_code.proto and ruby_generated_code.rb. --- src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index 0247e95f..6c203ab6 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -45,10 +45,10 @@ namespace compiler { namespace ruby { namespace { -string FindRubyTestDir() { +string FindRubyTestDir(const string& file) { // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc. string prefix = "."; - while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby")) { + while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby" + file)) { if (!File::Exists(prefix)) { GOOGLE_LOG(FATAL) << "Could not find Ruby test directory. Please run tests from " @@ -67,7 +67,7 @@ string FindRubyTestDir() { // extensions to the point where we can do this test in a more automated way. TEST(RubyGeneratorTest, GeneratorTest) { - string ruby_tests = FindRubyTestDir(); + string ruby_tests = FindRubyTestDir("/ruby_generated_code.proto"); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); -- cgit v1.2.3 From ca1c252923021306b7fbc488d33f6a6a89df59cf Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 May 2015 11:45:32 -0700 Subject: Fixes on visual studio 2008 --- src/google/protobuf/arena_unittest.cc | 2 -- src/google/protobuf/compiler/objectivec/objectivec_field.cc | 6 +++--- src/google/protobuf/lite_unittest.cc | 2 +- src/google/protobuf/map.h | 6 ++++++ src/google/protobuf/map_field_test.cc | 2 +- src/google/protobuf/map_test.cc | 2 +- src/google/protobuf/stubs/hash.h | 5 ++--- vsprojects/google/protobuf/stubs/pbconfig.h | 12 +++++++++++- 8 files changed, 25 insertions(+), 12 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc index 307c0905..6c185695 100644 --- a/src/google/protobuf/arena_unittest.cc +++ b/src/google/protobuf/arena_unittest.cc @@ -30,8 +30,6 @@ #include -#include - #include #include #include diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index ee5253a5..c5f05653 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -256,7 +256,7 @@ void FieldGenerator::GenerateFieldDescription( // " .typeSpecific.value* = [something]," GenerateFieldDescriptionTypeSpecific(printer); - const string& field_options(variables_.at("fieldoptions")); + const string& field_options(variables_.find("fieldoptions")->second); if (field_options.empty()) { printer->Print(" .fieldOptions = NULL,\n"); } else { @@ -379,7 +379,7 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration( printer->Print( variables_, "@property(nonatomic, readwrite, $property_storage_attribute$) $property_type$ *$name$$storage_attribute$;\n"); - if (IsInitName(variables_.at("name"))) { + if (IsInitName(variables_.find("name")->second)) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 printer->Print(variables_, @@ -426,7 +426,7 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration( "$comments$" "$array_comment$" "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n"); - if (IsInitName(variables_.at("name"))) { + if (IsInitName(variables_.find("name")->second)) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 printer->Print(variables_, diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index 1995cf08..5af8b24d 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -700,7 +700,7 @@ int main(int argc, char* argv[]) { // Allocate a large initial block to avoid mallocs during hooked test. std::vector arena_block(128 * 1024); google::protobuf::ArenaOptions options; - options.initial_block = arena_block.data(); + options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); google::protobuf::Arena arena(options); string data; diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 58a1817a..c16fbed2 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -33,6 +33,7 @@ #include #include +#include // To support Visual Studio 2008 #include #include @@ -200,6 +201,11 @@ class Map { return arena_ != other.arena_; } + // To support Visual Studio 2008 + size_type max_size() const { + return std::numeric_limits::max(); + } + private: Arena* arena_; diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc index f4681866..e3a64079 100644 --- a/src/google/protobuf/map_field_test.cc +++ b/src/google/protobuf/map_field_test.cc @@ -145,7 +145,7 @@ TEST_F(MapFieldBasePrimitiveTest, Arena) { // Allocate a large initial block to avoid mallocs during hooked test. std::vector arena_block(128 * 1024); ArenaOptions options; - options.initial_block = arena_block.data(); + options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index 447f52d9..d62ec85f 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -2285,7 +2285,7 @@ TEST(ArenaTest, ParsingAndSerializingNoHeapAllocation) { // Allocate a large initial block to avoid mallocs during hooked test. std::vector arena_block(128 * 1024); ArenaOptions options; - options.initial_block = arena_block.data(); + options.initial_block = &arena_block[0]; options.initial_block_size = arena_block.size(); Arena arena(options); string data; diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h index ee3c63fe..4da8a5d8 100755 --- a/src/google/protobuf/stubs/hash.h +++ b/src/google/protobuf/stubs/hash.h @@ -112,7 +112,7 @@ class hash_set : public std::set { #elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) template -struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare { +struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE { }; // MSVC's hash_compare hashes based on the string contents but @@ -126,8 +126,7 @@ class CstringLess { template <> struct hash - : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash_compare< - const char*, CstringLess> {}; + : public GOOGLE_PROTOBUF_HASH_COMPARE {}; template , diff --git a/vsprojects/google/protobuf/stubs/pbconfig.h b/vsprojects/google/protobuf/stubs/pbconfig.h index 18250a22..9629f2e4 100755 --- a/vsprojects/google/protobuf/stubs/pbconfig.h +++ b/vsprojects/google/protobuf/stubs/pbconfig.h @@ -10,24 +10,34 @@ // http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx // And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That // said, use unordered_map for MSVC 2010 and beyond is our safest bet. -#if _MSC_VER >= 1600 +#if _MSC_VER >= 1600 // Since Visual Studio 2010 #define GOOGLE_PROTOBUF_HASH_NAMESPACE std #define GOOGLE_PROTOBUF_HASH_MAP_H #define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map #define GOOGLE_PROTOBUF_HASH_SET_H #define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare +#elif _MSC_VER >= 1500 // Since Visual Studio 2008 +#define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 +#define GOOGLE_PROTOBUF_HASH_MAP_H +#define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +#define GOOGLE_PROTOBUF_HASH_SET_H +#define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare #elif _MSC_VER >= 1310 #define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext #define GOOGLE_PROTOBUF_HASH_MAP_H #define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map #define GOOGLE_PROTOBUF_HASH_SET_H #define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +#define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare #else #define GOOGLE_PROTOBUF_HASH_NAMESPACE std #define GOOGLE_PROTOBUF_HASH_MAP_H #define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map #define GOOGLE_PROTOBUF_HASH_SET_H #define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +#define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare #endif /* the location of */ -- cgit v1.2.3 From f7b417ddfe63cb4d39775e5fd4560894cc547d65 Mon Sep 17 00:00:00 2001 From: Jie Luo Date: Fri, 29 May 2015 12:48:25 -0700 Subject: Add oneof support for C# --- .../ProtocolBuffers.Test/AbstractMessageTest.cs | 26 + .../src/ProtocolBuffers.Test/DynamicMessageTest.cs | 49 + .../src/ProtocolBuffers.Test/FieldPresenceTest.cs | 33 +- .../ProtocolBuffers.Test/GeneratedMessageTest.cs | 262 ++ .../src/ProtocolBuffers.Test/ReflectionTester.cs | 31 +- .../ProtocolBuffers.Test/TestProtos/Unittest.cs | 2689 ++++++++++++-------- .../TestProtos/UnittestNoFieldPresence.cs | 284 ++- .../TestProtos/UnittestOptimizeFor.cs | 61 +- csharp/src/ProtocolBuffers.Test/TestResources.cs | 9 +- csharp/src/ProtocolBuffers.Test/TestUtil.cs | 107 + csharp/src/ProtocolBuffers.Test/WireFormatTest.cs | 2 +- csharp/src/ProtocolBuffers/AbstractBuilder.cs | 8 + csharp/src/ProtocolBuffers/AbstractMessage.cs | 2 + .../ProtocolBuffers/Descriptors/FieldDescriptor.cs | 18 +- .../Descriptors/MessageDescriptor.cs | 28 + .../ProtocolBuffers/Descriptors/OneofDescriptor.cs | 78 + csharp/src/ProtocolBuffers/DynamicMessage.cs | 122 +- .../FieldAccess/FieldAccessorTable.cs | 46 +- .../ProtocolBuffers/FieldAccess/OneofAccessor.cs | 91 + .../FieldAccess/SingleEnumAccessor.cs | 3 +- .../FieldAccess/SingleMessageAccessor.cs | 4 +- .../FieldAccess/SinglePrimitiveAccessor.cs | 22 +- csharp/src/ProtocolBuffers/GeneratedBuilder.cs | 16 + csharp/src/ProtocolBuffers/GeneratedMessage.cs | 10 + csharp/src/ProtocolBuffers/IBuilder.cs | 14 + csharp/src/ProtocolBuffers/IMessage.cs | 4 + csharp/src/ProtocolBuffers/ProtocolBuffers.csproj | 4 +- .../TestProtos/Unittest.cs | 2689 ++++++++++++-------- .../TestProtos/UnittestLite.cs | 211 +- .../protobuf/compiler/csharp/csharp_enum_field.cc | 117 +- .../protobuf/compiler/csharp/csharp_enum_field.h | 18 + .../protobuf/compiler/csharp/csharp_field_base.cc | 8 + .../protobuf/compiler/csharp/csharp_field_base.h | 2 + .../protobuf/compiler/csharp/csharp_helpers.cc | 18 +- .../protobuf/compiler/csharp/csharp_message.cc | 95 +- .../compiler/csharp/csharp_message_field.cc | 118 +- .../compiler/csharp/csharp_message_field.h | 18 + .../compiler/csharp/csharp_primitive_field.cc | 104 +- .../compiler/csharp/csharp_primitive_field.h | 18 + 39 files changed, 4998 insertions(+), 2441 deletions(-) create mode 100644 csharp/src/ProtocolBuffers/Descriptors/OneofDescriptor.cs create mode 100644 csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs (limited to 'src/google/protobuf/compiler') diff --git a/csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs b/csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs index 595fb3ae..8118808b 100644 --- a/csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs +++ b/csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs @@ -374,6 +374,16 @@ namespace Google.ProtocolBuffers return wrappedMessage.HasField(field); } + public override bool HasOneof(OneofDescriptor oneof) + { + return wrappedMessage.HasOneof(oneof); + } + + public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof) + { + return wrappedMessage.OneofFieldDescriptor(oneof); + } + public override object this[FieldDescriptor field] { get { return wrappedMessage[field]; } @@ -461,6 +471,16 @@ namespace Google.ProtocolBuffers return wrappedBuilder.HasField(field); } + public override bool HasOneof(OneofDescriptor oneof) + { + return wrappedBuilder.HasOneof(oneof); + } + + public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof) + { + return wrappedBuilder.OneofFieldDescriptor(oneof); + } + public override UnknownFieldSet UnknownFields { get { return wrappedBuilder.UnknownFields; } @@ -493,6 +513,12 @@ namespace Google.ProtocolBuffers return this; } + public override Builder ClearOneof(OneofDescriptor oneof) + { + wrappedBuilder.WeakClearOneof(oneof); + return this; + } + public override Builder AddRepeatedField(FieldDescriptor field, object value) { wrappedBuilder.WeakAddRepeatedField(field, value); diff --git a/csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs b/csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs index d38d66d7..f60db213 100644 --- a/csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs +++ b/csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs @@ -36,6 +36,7 @@ using System; using System.Collections.Generic; +using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.TestProtos; using NUnit.Framework; @@ -200,6 +201,21 @@ namespace Google.ProtocolBuffers DynamicMessage copy = DynamicMessage.CreateBuilder(message).Build(); reflectionTester.AssertAllFieldsSetViaReflection(copy); + + // Oneof + FieldDescriptor bytesField = + TestAllTypes.Descriptor.FindFieldByName("oneof_bytes"); + FieldDescriptor uint32Field = + TestAllTypes.Descriptor.FindFieldByName("oneof_uint32"); + Assert.True(copy.HasField(bytesField)); + Assert.False(copy.HasField(uint32Field)); + + DynamicMessage.Builder dynamicBuilder = DynamicMessage.CreateBuilder(message); + dynamicBuilder[uint32Field] = 123U; + DynamicMessage copy2 = dynamicBuilder.Build(); + Assert.IsFalse(copy2.HasField(bytesField)); + Assert.IsTrue(copy2.HasField(uint32Field)); + Assert.AreEqual(123U, copy2[uint32Field]); } [Test] @@ -223,5 +239,38 @@ namespace Google.ProtocolBuffers Assert.AreEqual(1, values.Count); Assert.AreEqual(unknownFieldVal, values[0]); } + + [Test] + public void DynamicOneofMessage() + { + DynamicMessage.Builder builder = + DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); + OneofDescriptor oneof = TestAllTypes.Descriptor.Oneofs[0]; + Assert.False(builder.HasOneof(oneof)); + Assert.AreSame(null, builder.OneofFieldDescriptor(oneof)); + + reflectionTester.SetAllFieldsViaReflection(builder); + Assert.True(builder.HasOneof(oneof)); + FieldDescriptor field = oneof.Field(3); + Assert.AreSame(field, builder.OneofFieldDescriptor(oneof)); + Assert.AreEqual(TestUtil.ToBytes("604"), builder[field]); + + DynamicMessage message = builder.BuildPartial(); + Assert.IsTrue(message.HasOneof(oneof)); + + DynamicMessage.Builder mergedBuilder = + DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); + FieldDescriptor mergedField = oneof.Field(0); + mergedBuilder[mergedField] = 123U; + Assert.IsTrue(mergedBuilder.HasField(mergedField)); + mergedBuilder.MergeFrom(message); + Assert.IsTrue(mergedBuilder.HasField(field)); + Assert.IsFalse(mergedBuilder.HasField(mergedField)); + + mergedBuilder.ClearOneof(oneof); + Assert.AreSame(null, mergedBuilder.OneofFieldDescriptor(oneof)); + message = mergedBuilder.Build(); + Assert.AreSame(null, message.OneofFieldDescriptor(oneof)); + } } } \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs b/csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs index 8f59334e..66214221 100644 --- a/csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs +++ b/csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs @@ -59,16 +59,25 @@ namespace Google.ProtocolBuffers CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalBytes"); CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalNestedEnum"); - proto2Type = typeof(Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder); - proto3Type = typeof(TestAllTypes.Builder); - CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalInt32"); - CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalString"); - CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalBytes"); - CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalNestedEnum"); + Type proto2BuilderType = typeof(Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder); + Type proto3BuilderType = typeof(TestAllTypes.Builder); + CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OptionalInt32"); + CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OptionalString"); + CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OptionalBytes"); + CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OptionalNestedEnum"); // message fields still have the HasFoo method generated Assert.IsFalse(TestAllTypes.CreateBuilder().Build().HasOptionalNestedMessage); Assert.IsFalse(TestAllTypes.CreateBuilder().HasOptionalNestedMessage); + + // oneof fields don't have the HasFoo method (even for message types) + CheckHasMethodRemoved(proto2Type, proto3Type, "OneofUint32"); + CheckHasMethodRemoved(proto2Type, proto3Type, "OneofString"); + CheckHasMethodRemoved(proto2Type, proto3Type, "OneofNestedMessage"); + + CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OneofUint32"); + CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OneofString"); + CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OneofNestedMessage"); } [Test] @@ -114,6 +123,7 @@ namespace Google.ProtocolBuffers FieldDescriptor optionalStringField = descriptor.FindFieldByName("optional_string"); FieldDescriptor optionalBytesField = descriptor.FindFieldByName("optional_bytes"); FieldDescriptor optionalNestedEnumField = descriptor.FindFieldByName("optional_nested_enum"); + FieldDescriptor oneofUint32Field = descriptor.FindFieldByName("oneof_uint32"); TestAllTypes message = TestAllTypes.CreateBuilder().Build(); Assert.IsFalse(message.HasField(optionalInt32Field)); @@ -121,20 +131,23 @@ namespace Google.ProtocolBuffers Assert.IsFalse(message.HasField(optionalBytesField)); Assert.IsFalse(message.HasField(optionalNestedEnumField)); - // Set to default value is seen as not present + // Set to default value is seen as not present for optional fields. + // Set to default value is seen as present for oneof fields. message = TestAllTypes.CreateBuilder() .SetOptionalInt32(0) .SetOptionalString("") .SetOptionalBytes(ByteString.Empty) .SetOptionalNestedEnum(TestAllTypes.Types.NestedEnum.FOO) + .SetOneofUint32(0U) .Build(); Assert.IsFalse(message.HasField(optionalInt32Field)); Assert.IsFalse(message.HasField(optionalStringField)); Assert.IsFalse(message.HasField(optionalBytesField)); Assert.IsFalse(message.HasField(optionalNestedEnumField)); - Assert.AreEqual(0, message.AllFields.Count); + Assert.IsTrue(message.HasField(oneofUint32Field)); + Assert.AreEqual(1, message.AllFields.Count); - // Set t0 non-defalut value is seen as present + // Set to non-defalut value is seen as present message = TestAllTypes.CreateBuilder() .SetOptionalInt32(1) .SetOptionalString("x") @@ -169,6 +182,7 @@ namespace Google.ProtocolBuffers builder.SetOptionalInt32(1234); builder.SetOptionalString("hello"); builder.SetOptionalNestedMessage(TestAllTypes.Types.NestedMessage.DefaultInstance); + builder.SetOneofUint32(0U); ByteString data = builder.Build().ToByteString(); TestAllTypes message = TestAllTypes.ParseFrom(data); @@ -178,6 +192,7 @@ namespace Google.ProtocolBuffers Assert.AreEqual(TestAllTypes.Types.NestedEnum.FOO, message.OptionalNestedEnum); Assert.IsTrue(message.HasOptionalNestedMessage); Assert.AreEqual(0, message.OptionalNestedMessage.Bb); + Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase); } } } diff --git a/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs b/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs index 984c36e6..4f669449 100644 --- a/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs +++ b/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs @@ -36,6 +36,7 @@ using System; using System.Collections.Generic; +using Google.ProtocolBuffers.Descriptors; using Google.ProtocolBuffers.Collections; using Google.ProtocolBuffers.TestProtos; using NUnit.Framework; @@ -292,6 +293,31 @@ namespace Google.ProtocolBuffers }); } + [Test] + public void ReflectionGetOneof() + { + TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); + reflectionTester.SetAllFieldsViaReflection(builder); + Descriptors.OneofDescriptor oneof = TestAllTypes.Descriptor.Oneofs[0]; + Descriptors.FieldDescriptor field = TestAllTypes.Descriptor.FindFieldByName("oneof_bytes"); + Assert.AreSame(field, builder.OneofFieldDescriptor(oneof)); + } + + [Test] + public void ReflectionClearOneof() + { + TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); + reflectionTester.SetAllFieldsViaReflection(builder); + OneofDescriptor oneof = TestAllTypes.Descriptor.Oneofs[0]; + FieldDescriptor field = TestAllTypes.Descriptor.FindFieldByName("oneof_bytes"); + + Assert.IsTrue(builder.HasOneof(oneof)); + Assert.IsTrue(builder.HasField(field)); + builder.ClearOneof(oneof); + Assert.IsFalse(builder.HasOneof(oneof)); + Assert.IsFalse(builder.HasField(field)); + } + // ================================================================= // Extensions. @@ -510,5 +536,241 @@ namespace Google.ProtocolBuffers TestPackedTypes empty = new TestPackedTypes.Builder().Build(); Assert.AreEqual(0, empty.SerializedSize); } + + // oneof tests + [Test] + public void TestOneofEnumCase() + { + TestOneof2 message = TestOneof2.CreateBuilder() + .SetFooInt(123).SetFooString("foo").SetFooCord("bar").Build(); + TestUtil.AssertAtMostOneFieldSetOneof(message); + } + + [Test] + public void TestClearOneof() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder().SetFooInt(123); + Assert.AreEqual(TestOneof2.FooOneofCase.FooInt, builder.FooCase); + builder.ClearFoo(); + Assert.AreEqual(TestOneof2.FooOneofCase.None, builder.FooCase); + } + + [Test] + public void TestSetOneofClearsOthers() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = + builder.SetFooInt(123).SetFooString("foo").Build(); + Assert.IsTrue(message.HasFooString); + TestUtil.AssertAtMostOneFieldSetOneof(message); + + message = builder.SetFooCord("bar").Build(); + Assert.IsTrue(message.HasFooCord); + TestUtil.AssertAtMostOneFieldSetOneof(message); + + message = builder.SetFooStringPiece("baz").Build(); + Assert.IsTrue(message.HasFooStringPiece); + TestUtil.AssertAtMostOneFieldSetOneof(message); + + message = builder.SetFooBytes(TestUtil.ToBytes("qux")).Build(); + Assert.IsTrue(message.HasFooBytes); + TestUtil.AssertAtMostOneFieldSetOneof(message); + + message = builder.SetFooEnum(TestOneof2.Types.NestedEnum.FOO).Build(); + Assert.IsTrue(message.HasFooEnum); + TestUtil.AssertAtMostOneFieldSetOneof(message); + + message = builder.SetFooMessage( + TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(234).Build()).Build(); + Assert.IsTrue(message.HasFooMessage); + TestUtil.AssertAtMostOneFieldSetOneof(message); + + message = builder.SetFooInt(123).Build(); + Assert.IsTrue(message.HasFooInt); + TestUtil.AssertAtMostOneFieldSetOneof(message); + } + + [Test] + public void TestOneofTypes_Primitive() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + Assert.AreEqual(builder.FooInt, 0); + Assert.IsFalse(builder.HasFooInt); + Assert.IsTrue(builder.SetFooInt(123).HasFooInt); + Assert.AreEqual(builder.FooInt, 123); + TestOneof2 message = builder.BuildPartial(); + Assert.IsTrue(message.HasFooInt); + Assert.AreEqual(message.FooInt, 123); + + Assert.IsFalse(builder.ClearFooInt().HasFooInt); + TestOneof2 message2 = builder.Build(); + Assert.IsFalse(message2.HasFooInt); + Assert.AreEqual(message2.FooInt, 0); + } + + [Test] + public void TestOneofTypes_Enum() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + Assert.AreEqual(builder.FooEnum, TestOneof2.Types.NestedEnum.FOO); + Assert.IsTrue(builder.SetFooEnum(TestOneof2.Types.NestedEnum.BAR).HasFooEnum); + Assert.AreEqual(builder.FooEnum, TestOneof2.Types.NestedEnum.BAR); + TestOneof2 message = builder.BuildPartial(); + Assert.IsTrue(message.HasFooEnum); + Assert.AreEqual(message.FooEnum, TestOneof2.Types.NestedEnum.BAR); + + Assert.IsFalse(builder.ClearFooEnum().HasFooEnum); + TestOneof2 message2 = builder.Build(); + Assert.IsFalse(message2.HasFooEnum); + Assert.AreEqual(message2.FooEnum, TestOneof2.Types.NestedEnum.FOO); + } + + [Test] + public void TestOneofTypes_String() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + Assert.AreEqual(builder.FooString, ""); + Assert.IsTrue(builder.SetFooString("foo").HasFooString); + Assert.AreEqual(builder.FooString, "foo"); + TestOneof2 message = builder.BuildPartial(); + Assert.IsTrue(message.HasFooString); + Assert.AreEqual(message.FooString, "foo"); + + Assert.IsFalse(builder.ClearFooString().HasFooString); + TestOneof2 message2 = builder.Build(); + Assert.IsFalse(message2.HasFooString); + Assert.AreEqual(message2.FooString, ""); + + builder.SetFooInt(123); + Assert.AreEqual(builder.FooString, ""); + Assert.AreEqual(builder.FooInt, 123); + message = builder.Build(); + Assert.AreEqual(message.FooString, ""); + Assert.AreEqual(message.FooInt, 123); + } + + [Test] + public void TestOneofTypes_Message() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + Assert.AreEqual(builder.FooMessage.QuxInt, 0); + builder.SetFooMessage(TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(234).Build()); + Assert.IsTrue(builder.HasFooMessage); + Assert.AreEqual(builder.FooMessage.QuxInt, 234); + TestOneof2 message = builder.BuildPartial(); + Assert.IsTrue(message.HasFooMessage); + Assert.AreEqual(message.FooMessage.QuxInt, 234); + + Assert.IsFalse(builder.ClearFooMessage().HasFooMessage); + message = builder.Build(); + Assert.IsFalse(message.HasFooMessage); + Assert.AreEqual(message.FooMessage.QuxInt, 0); + + builder = TestOneof2.CreateBuilder(); + Assert.IsFalse(builder.HasFooMessage); + builder.SetFooMessage(TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(123)); + Assert.IsTrue(builder.HasFooMessage); + Assert.AreEqual(builder.FooMessage.QuxInt, 123); + message = builder.Build(); + Assert.IsTrue(message.HasFooMessage); + Assert.AreEqual(message.FooMessage.QuxInt, 123); + } + + [Test] + public void TestOneofMerge_Primitive() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooInt(123).Build(); + TestOneof2 message2 = TestOneof2.CreateBuilder().MergeFrom(message).Build(); + Assert.IsTrue(message2.HasFooInt); + Assert.AreEqual(message2.FooInt, 123); + } + + [Test] + public void TestOneofMerge_String() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooString("foo").Build(); + TestOneof2 message2 = TestOneof2.CreateBuilder().MergeFrom(message).Build(); + Assert.IsTrue(message2.HasFooString); + Assert.AreEqual(message2.FooString, "foo"); + } + + [Test] + public void TestOneofMerge_Enum() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooEnum(TestOneof2.Types.NestedEnum.BAR).Build(); + TestOneof2 message2 = TestOneof2.CreateBuilder().MergeFrom(message).Build(); + Assert.IsTrue(message2.HasFooEnum); + Assert.AreEqual(message2.FooEnum, TestOneof2.Types.NestedEnum.BAR); + } + + public void TestOneofMerge_message() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooMessage( + TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(234).Build()).Build(); + TestOneof2 message2 = TestOneof2.CreateBuilder().MergeFrom(message).Build(); + Assert.IsTrue(message2.HasFooMessage); + Assert.AreEqual(message2.FooMessage.QuxInt, 234); + } + + [Test] + public void TestOneofMergeMixed() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooEnum(TestOneof2.Types.NestedEnum.BAR).Build(); + TestOneof2 message2 = + TestOneof2.CreateBuilder().SetFooString("foo").MergeFrom(message).Build(); + Assert.IsFalse(message2.HasFooString); + Assert.IsTrue(message2.HasFooEnum); + Assert.AreEqual(message2.FooEnum, TestOneof2.Types.NestedEnum.BAR); + } + + [Test] + public void TestOneofSerialization_Primitive() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooInt(123).Build(); + ByteString serialized = message.ToByteString(); + TestOneof2 message2 = TestOneof2.ParseFrom(serialized); + Assert.IsTrue(message2.HasFooInt); + Assert.AreEqual(message2.FooInt, 123); + } + + [Test] + public void TestOneofSerialization_String() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooString("foo").Build(); + ByteString serialized = message.ToByteString(); + TestOneof2 message2 = TestOneof2.ParseFrom(serialized); + Assert.IsTrue(message2.HasFooString); + Assert.AreEqual(message2.FooString, "foo"); + } + + [Test] + public void TestOneofSerialization_Enum() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooEnum(TestOneof2.Types.NestedEnum.BAR).Build(); + ByteString serialized = message.ToByteString(); + TestOneof2 message2 = TestOneof2.ParseFrom(serialized); + Assert.IsTrue(message2.HasFooEnum); + Assert.AreEqual(message2.FooEnum, TestOneof2.Types.NestedEnum.BAR); + } + + [Test] + public void TestOneofSerialization_Message() + { + TestOneof2.Builder builder = TestOneof2.CreateBuilder(); + TestOneof2 message = builder.SetFooMessage( + TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(234).Build()).Build(); + ByteString serialized = message.ToByteString(); + TestOneof2 message2 = TestOneof2.ParseFrom(serialized); + Assert.IsTrue(message2.HasFooMessage); + Assert.AreEqual(message2.FooMessage.QuxInt, 234); + } } } \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/ReflectionTester.cs b/csharp/src/ProtocolBuffers.Test/ReflectionTester.cs index bd1d2c65..22795b3f 100644 --- a/csharp/src/ProtocolBuffers.Test/ReflectionTester.cs +++ b/csharp/src/ProtocolBuffers.Test/ReflectionTester.cs @@ -380,6 +380,12 @@ namespace Google.ProtocolBuffers message[f("default_string_piece")] = "424"; message[f("default_cord")] = "425"; + + message[f("oneof_uint32")] = 601U; + message[f("oneof_nested_message")] = + CreateBuilderForField(message, f("optional_nested_message")).SetField(nestedB, 602).WeakBuild(); + message[f("oneof_string")] = "603"; + message[f("oneof_bytes")] = TestUtil.ToBytes("604"); } /// @@ -642,6 +648,20 @@ namespace Google.ProtocolBuffers Assert.AreEqual("424", message[f("default_string_piece")]); Assert.AreEqual("425", message[f("default_cord")]); + if (extensionRegistry == null) + { + Assert.IsFalse(message.HasField(f("oneof_uint32"))); + Assert.IsFalse(message.HasField(f("oneof_nested_message"))); + Assert.IsFalse(message.HasField(f("oneof_string"))); + } else + { + Assert.IsTrue(message.HasField(f("oneof_uint32"))); + Assert.IsTrue(message.HasField(f("oneof_nested_message"))); + Assert.IsTrue(message.HasField(f("oneof_string"))); + Assert.AreEqual(601U, message[f("oneof_uint32")]); + Assert.AreEqual(602, ((IMessage)message[f("oneof_nested_message")])[nestedB]); + Assert.AreEqual("603", message[f("oneof_string")]); + } } /// @@ -793,6 +813,15 @@ namespace Google.ProtocolBuffers Assert.AreEqual("abc", message[f("default_string_piece")]); Assert.AreEqual("123", message[f("default_cord")]); + + Assert.IsFalse(message.HasField(f("oneof_uint32"))); + Assert.IsFalse(message.HasField(f("oneof_nested_message"))); + Assert.IsFalse(message.HasField(f("oneof_string"))); + Assert.IsFalse(message.HasField(f("oneof_bytes"))); + + Assert.AreEqual(0U, message[f("oneof_uint32")]); + Assert.AreEqual("", message[f("oneof_string")]); + Assert.AreEqual(TestUtil.ToBytes(""), message[f("oneof_bytes")]); } // --------------------------------------------------------------- @@ -1001,4 +1030,4 @@ namespace Google.ProtocolBuffers Assert.AreEqual(foreignBaz, message[f("packed_enum"), 1]); } } -} \ No newline at end of file +} diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs index 083523c0..67898644 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs @@ -355,6 +355,8 @@ namespace Google.ProtocolBuffers.TestProtos { internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ForeignMessage__Descriptor; internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable; + internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestReservedFields__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestAllExtensions__Descriptor; internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestAllExtensions__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor; @@ -565,426 +567,429 @@ namespace Google.ProtocolBuffers.TestProtos { "ZXMYciABKAxIABobCg1OZXN0ZWRNZXNzYWdlEgoKAmJiGAEgASgFGhoKDU9w", "dGlvbmFsR3JvdXASCQoBYRgRIAEoBRoaCg1SZXBlYXRlZEdyb3VwEgkKAWEY", "LyABKAUiOQoKTmVzdGVkRW51bRIHCgNGT08QARIHCgNCQVIQAhIHCgNCQVoQ", - "AxIQCgNORUcQ////////////AUINCgtvbmVvZl9maWVsZCJ8ChJOZXN0ZWRU", - "ZXN0QWxsVHlwZXMSNAoFY2hpbGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVz", - "dC5OZXN0ZWRUZXN0QWxsVHlwZXMSMAoHcGF5bG9hZBgCIAEoCzIfLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcyI0ChRUZXN0RGVwcmVjYXRlZEZp", - "ZWxkcxIcChBkZXByZWNhdGVkX2ludDMyGAEgASgFQgIYASIbCg5Gb3JlaWdu", - "TWVzc2FnZRIJCgFjGAEgASgFIh0KEVRlc3RBbGxFeHRlbnNpb25zKggIARCA", - "gICAAiIkChdPcHRpb25hbEdyb3VwX2V4dGVuc2lvbhIJCgFhGBEgASgFIiQK", - "F1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uEgkKAWEYLyABKAUimAEKE1Rlc3RO", - "ZXN0ZWRFeHRlbnNpb24yOQoEdGVzdBIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGOoHIAEoCToEdGVzdDJGChduZXN0ZWRfc3RyaW5n", - "X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNp", - "b25zGOsHIAEoCSLVBQoMVGVzdFJlcXVpcmVkEgkKAWEYASACKAUSDgoGZHVt", - "bXkyGAIgASgFEgkKAWIYAyACKAUSDgoGZHVtbXk0GAQgASgFEg4KBmR1bW15", - "NRgFIAEoBRIOCgZkdW1teTYYBiABKAUSDgoGZHVtbXk3GAcgASgFEg4KBmR1", - "bW15OBgIIAEoBRIOCgZkdW1teTkYCSABKAUSDwoHZHVtbXkxMBgKIAEoBRIP", - "CgdkdW1teTExGAsgASgFEg8KB2R1bW15MTIYDCABKAUSDwoHZHVtbXkxMxgN", - "IAEoBRIPCgdkdW1teTE0GA4gASgFEg8KB2R1bW15MTUYDyABKAUSDwoHZHVt", - "bXkxNhgQIAEoBRIPCgdkdW1teTE3GBEgASgFEg8KB2R1bW15MTgYEiABKAUS", - "DwoHZHVtbXkxORgTIAEoBRIPCgdkdW1teTIwGBQgASgFEg8KB2R1bW15MjEY", - "FSABKAUSDwoHZHVtbXkyMhgWIAEoBRIPCgdkdW1teTIzGBcgASgFEg8KB2R1", - "bW15MjQYGCABKAUSDwoHZHVtbXkyNRgZIAEoBRIPCgdkdW1teTI2GBogASgF", - "Eg8KB2R1bW15MjcYGyABKAUSDwoHZHVtbXkyOBgcIAEoBRIPCgdkdW1teTI5", - "GB0gASgFEg8KB2R1bW15MzAYHiABKAUSDwoHZHVtbXkzMRgfIAEoBRIPCgdk", - "dW1teTMyGCAgASgFEgkKAWMYISACKAUyVgoGc2luZ2xlEiQucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMY6AcgASgLMh8ucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdFJlcXVpcmVkMlUKBW11bHRpEiQucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMY6QcgAygLMh8ucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdFJlcXVpcmVkIpoBChNUZXN0UmVxdWlyZWRGb3JlaWduEjkK", - "EG9wdGlvbmFsX21lc3NhZ2UYASABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5U", - "ZXN0UmVxdWlyZWQSOQoQcmVwZWF0ZWRfbWVzc2FnZRgCIAMoCzIfLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZBINCgVkdW1teRgDIAEoBSJaChFU", - "ZXN0Rm9yZWlnbk5lc3RlZBJFCg5mb3JlaWduX25lc3RlZBgBIAEoCzItLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlIhIK", - "EFRlc3RFbXB0eU1lc3NhZ2UiKgoeVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRl", - "bnNpb25zKggIARCAgICAAiI3ChtUZXN0TXVsdGlwbGVFeHRlbnNpb25SYW5n", - "ZXMqBAgqECsqBgivIBCUISoKCICABBCAgICAAiI0ChhUZXN0UmVhbGx5TGFy", - "Z2VUYWdOdW1iZXISCQoBYRgBIAEoBRINCgJiYhj///9/IAEoBSJVChRUZXN0", - "UmVjdXJzaXZlTWVzc2FnZRIyCgFhGAEgASgLMicucHJvdG9idWZfdW5pdHRl", - "c3QuVGVzdFJlY3Vyc2l2ZU1lc3NhZ2USCQoBaRgCIAEoBSJLChRUZXN0TXV0", - "dWFsUmVjdXJzaW9uQRIzCgJiYhgBIAEoCzInLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RNdXR1YWxSZWN1cnNpb25CImIKFFRlc3RNdXR1YWxSZWN1cnNpb25C", - "EjIKAWEYASABKAsyJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TXV0dWFsUmVj", - "dXJzaW9uQRIWCg5vcHRpb25hbF9pbnQzMhgCIAEoBSKzAQoSVGVzdER1cEZp", - "ZWxkTnVtYmVyEgkKAWEYASABKAUSNgoDZm9vGAIgASgKMikucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdER1cEZpZWxkTnVtYmVyLkZvbxI2CgNiYXIYAyABKAoy", - "KS5wcm90b2J1Zl91bml0dGVzdC5UZXN0RHVwRmllbGROdW1iZXIuQmFyGhAK", - "A0ZvbxIJCgFhGAEgASgFGhAKA0JhchIJCgFhGAEgASgFIkwKEFRlc3RFYWdl", - "ck1lc3NhZ2USOAoLc3ViX21lc3NhZ2UYASABKAsyHy5wcm90b2J1Zl91bml0", - "dGVzdC5UZXN0QWxsVHlwZXNCAigAIksKD1Rlc3RMYXp5TWVzc2FnZRI4Cgtz", - "dWJfbWVzc2FnZRgBIAEoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxU", - "eXBlc0ICKAEigAIKGFRlc3ROZXN0ZWRNZXNzYWdlSGFzQml0cxJaChdvcHRp", - "b25hbF9uZXN0ZWRfbWVzc2FnZRgBIAEoCzI5LnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3ROZXN0ZWRNZXNzYWdlSGFzQml0cy5OZXN0ZWRNZXNzYWdlGocBCg1O", - "ZXN0ZWRNZXNzYWdlEiQKHG5lc3RlZG1lc3NhZ2VfcmVwZWF0ZWRfaW50MzIY", - "ASADKAUSUAolbmVzdGVkbWVzc2FnZV9yZXBlYXRlZF9mb3JlaWdubWVzc2Fn", - "ZRgCIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlIuUD", - "ChdUZXN0Q2FtZWxDYXNlRmllbGROYW1lcxIWCg5QcmltaXRpdmVGaWVsZBgB", - "IAEoBRITCgtTdHJpbmdGaWVsZBgCIAEoCRIxCglFbnVtRmllbGQYAyABKA4y", - "Hi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bRI3CgxNZXNzYWdlRmll", - "bGQYBCABKAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZRIc", - "ChBTdHJpbmdQaWVjZUZpZWxkGAUgASgJQgIIAhIVCglDb3JkRmllbGQYBiAB", - "KAlCAggBEh4KFlJlcGVhdGVkUHJpbWl0aXZlRmllbGQYByADKAUSGwoTUmVw", - "ZWF0ZWRTdHJpbmdGaWVsZBgIIAMoCRI5ChFSZXBlYXRlZEVudW1GaWVsZBgJ", - "IAMoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtEj8KFFJlcGVh", - "dGVkTWVzc2FnZUZpZWxkGAogAygLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9y", - "ZWlnbk1lc3NhZ2USJAoYUmVwZWF0ZWRTdHJpbmdQaWVjZUZpZWxkGAsgAygJ", - "QgIIAhIdChFSZXBlYXRlZENvcmRGaWVsZBgMIAMoCUICCAEi1QEKElRlc3RG", - "aWVsZE9yZGVyaW5ncxIRCglteV9zdHJpbmcYCyABKAkSDgoGbXlfaW50GAEg", - "ASgDEhAKCG15X2Zsb2F0GGUgASgCElUKF29wdGlvbmFsX25lc3RlZF9tZXNz", - "YWdlGMgBIAEoCzIzLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RGaWVsZE9yZGVy", - "aW5ncy5OZXN0ZWRNZXNzYWdlGicKDU5lc3RlZE1lc3NhZ2USCgoCb28YAiAB", - "KAMSCgoCYmIYASABKAUqBAgCEAsqBAgMEGUitgcKGFRlc3RFeHRyZW1lRGVm", - "YXVsdFZhbHVlcxI/Cg1lc2NhcGVkX2J5dGVzGAEgASgMOihcMDAwXDAwMVww", - "MDdcMDEwXDAxNFxuXHJcdFwwMTNcXFwnXCJcMzc2EiAKDGxhcmdlX3VpbnQz", - "MhgCIAEoDToKNDI5NDk2NzI5NRIqCgxsYXJnZV91aW50NjQYAyABKAQ6FDE4", - "NDQ2NzQ0MDczNzA5NTUxNjE1EiAKC3NtYWxsX2ludDMyGAQgASgFOgstMjE0", - "NzQ4MzY0NxIpCgtzbWFsbF9pbnQ2NBgFIAEoAzoULTkyMjMzNzIwMzY4NTQ3", - "NzU4MDcSJwoScmVhbGx5X3NtYWxsX2ludDMyGBUgASgFOgstMjE0NzQ4MzY0", - "OBIwChJyZWFsbHlfc21hbGxfaW50NjQYFiABKAM6FC05MjIzMzcyMDM2ODU0", - "Nzc1ODA4EhgKC3V0Zjhfc3RyaW5nGAYgASgJOgPhiLQSFQoKemVyb19mbG9h", - "dBgHIAEoAjoBMBIUCglvbmVfZmxvYXQYCCABKAI6ATESGAoLc21hbGxfZmxv", - "YXQYCSABKAI6AzEuNRIeChJuZWdhdGl2ZV9vbmVfZmxvYXQYCiABKAI6Ai0x", - "EhwKDm5lZ2F0aXZlX2Zsb2F0GAsgASgCOgQtMS41EhoKC2xhcmdlX2Zsb2F0", - "GAwgASgCOgUyZSswOBIkChRzbWFsbF9uZWdhdGl2ZV9mbG9hdBgNIAEoAjoG", - "LThlLTI4EhcKCmluZl9kb3VibGUYDiABKAE6A2luZhIcCg5uZWdfaW5mX2Rv", - "dWJsZRgPIAEoAToELWluZhIXCgpuYW5fZG91YmxlGBAgASgBOgNuYW4SFgoJ", - "aW5mX2Zsb2F0GBEgASgCOgNpbmYSGwoNbmVnX2luZl9mbG9hdBgSIAEoAjoE", - "LWluZhIWCgluYW5fZmxvYXQYEyABKAI6A25hbhIrCgxjcHBfdHJpZ3JhcGgY", - "FCABKAk6FT8gPyA/PyA/PyA/Pz8gPz8vID8/LRIgChBzdHJpbmdfd2l0aF96", - "ZXJvGBcgASgJOgZoZWwAbG8SIgoPYnl0ZXNfd2l0aF96ZXJvGBggASgMOgl3", - "b3JcMDAwbGQSKAoWc3RyaW5nX3BpZWNlX3dpdGhfemVybxgZIAEoCToEYWIA", - "Y0ICCAISIAoOY29yZF93aXRoX3plcm8YGiABKAk6BDEyADNCAggBEiYKEnJl", - "cGxhY2VtZW50X3N0cmluZxgbIAEoCToKJHt1bmtub3dufSJLChFTcGFyc2VF", - "bnVtTWVzc2FnZRI2CgtzcGFyc2VfZW51bRgBIAEoDjIhLnByb3RvYnVmX3Vu", - "aXR0ZXN0LlRlc3RTcGFyc2VFbnVtIhkKCU9uZVN0cmluZxIMCgRkYXRhGAEg", - "ASgJIhoKCk1vcmVTdHJpbmcSDAoEZGF0YRgBIAMoCSIYCghPbmVCeXRlcxIM", - "CgRkYXRhGAEgASgMIhkKCU1vcmVCeXRlcxIMCgRkYXRhGAEgAygMIhwKDElu", - "dDMyTWVzc2FnZRIMCgRkYXRhGAEgASgFIh0KDVVpbnQzMk1lc3NhZ2USDAoE", - "ZGF0YRgBIAEoDSIcCgxJbnQ2NE1lc3NhZ2USDAoEZGF0YRgBIAEoAyIdCg1V", - "aW50NjRNZXNzYWdlEgwKBGRhdGEYASABKAQiGwoLQm9vbE1lc3NhZ2USDAoE", - "ZGF0YRgBIAEoCCLQAQoJVGVzdE9uZW9mEhEKB2Zvb19pbnQYASABKAVIABIU", - "Cgpmb29fc3RyaW5nGAIgASgJSAASNgoLZm9vX21lc3NhZ2UYAyABKAsyHy5w", - "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNIABI5Cghmb29ncm91cBgE", - "IAEoCjIlLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVvZi5Gb29Hcm91cEgA", - "GiAKCEZvb0dyb3VwEgkKAWEYBSABKAUSCQoBYhgGIAEoCUIFCgNmb28i5wEK", - "HFRlc3RPbmVvZkJhY2t3YXJkc0NvbXBhdGlibGUSDwoHZm9vX2ludBgBIAEo", - "BRISCgpmb29fc3RyaW5nGAIgASgJEjQKC2Zvb19tZXNzYWdlGAMgASgLMh8u", - "cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzEkoKCGZvb2dyb3VwGAQg", - "ASgKMjgucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mQmFja3dhcmRzQ29t", - "cGF0aWJsZS5Gb29Hcm91cBogCghGb29Hcm91cBIJCgFhGAUgASgFEgkKAWIY", - "BiABKAkingYKClRlc3RPbmVvZjISEQoHZm9vX2ludBgBIAEoBUgAEhQKCmZv", - "b19zdHJpbmcYAiABKAlIABIWCghmb29fY29yZBgDIAEoCUICCAFIABIeChBm", - "b29fc3RyaW5nX3BpZWNlGAQgASgJQgIIAkgAEhMKCWZvb19ieXRlcxgFIAEo", - "DEgAEjwKCGZvb19lbnVtGAYgASgOMigucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dE9uZW9mMi5OZXN0ZWRFbnVtSAASQgoLZm9vX21lc3NhZ2UYByABKAsyKy5w", - "cm90b2J1Zl91bml0dGVzdC5UZXN0T25lb2YyLk5lc3RlZE1lc3NhZ2VIABI6", - "Cghmb29ncm91cBgIIAEoCjImLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVv", - "ZjIuRm9vR3JvdXBIABJLChBmb29fbGF6eV9tZXNzYWdlGAsgASgLMisucHJv", - "dG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mMi5OZXN0ZWRNZXNzYWdlQgIoAUgA", - "EhQKB2Jhcl9pbnQYDCABKAU6ATVIARIcCgpiYXJfc3RyaW5nGA0gASgJOgZT", - "VFJJTkdIARIcCghiYXJfY29yZBgOIAEoCToEQ09SREICCAFIARImChBiYXJf", - "c3RyaW5nX3BpZWNlGA8gASgJOgZTUElFQ0VCAggCSAESGgoJYmFyX2J5dGVz", - "GBAgASgMOgVCWVRFU0gBEkEKCGJhcl9lbnVtGBEgASgOMigucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdE9uZW9mMi5OZXN0ZWRFbnVtOgNCQVJIARIPCgdiYXpf", - "aW50GBIgASgFEhcKCmJhel9zdHJpbmcYEyABKAk6A0JBWhogCghGb29Hcm91", - "cBIJCgFhGAkgASgFEgkKAWIYCiABKAkaMwoNTmVzdGVkTWVzc2FnZRIPCgdx", - "dXhfaW50GAEgASgDEhEKCWNvcmdlX2ludBgCIAMoBSInCgpOZXN0ZWRFbnVt", - "EgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADQgUKA2Zvb0IFCgNiYXIiuAEK", - "EVRlc3RSZXF1aXJlZE9uZW9mEhEKB2Zvb19pbnQYASABKAVIABIUCgpmb29f", - "c3RyaW5nGAIgASgJSAASSQoLZm9vX21lc3NhZ2UYAyABKAsyMi5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRPbmVvZi5OZXN0ZWRNZXNzYWdlSAAa", - "KAoNTmVzdGVkTWVzc2FnZRIXCg9yZXF1aXJlZF9kb3VibGUYASACKAFCBQoD", - "Zm9vIqoDCg9UZXN0UGFja2VkVHlwZXMSGAoMcGFja2VkX2ludDMyGFogAygF", - "QgIQARIYCgxwYWNrZWRfaW50NjQYWyADKANCAhABEhkKDXBhY2tlZF91aW50", - "MzIYXCADKA1CAhABEhkKDXBhY2tlZF91aW50NjQYXSADKARCAhABEhkKDXBh", - "Y2tlZF9zaW50MzIYXiADKBFCAhABEhkKDXBhY2tlZF9zaW50NjQYXyADKBJC", - "AhABEhoKDnBhY2tlZF9maXhlZDMyGGAgAygHQgIQARIaCg5wYWNrZWRfZml4", - "ZWQ2NBhhIAMoBkICEAESGwoPcGFja2VkX3NmaXhlZDMyGGIgAygPQgIQARIb", - "Cg9wYWNrZWRfc2ZpeGVkNjQYYyADKBBCAhABEhgKDHBhY2tlZF9mbG9hdBhk", - "IAMoAkICEAESGQoNcGFja2VkX2RvdWJsZRhlIAMoAUICEAESFwoLcGFja2Vk", - "X2Jvb2wYZiADKAhCAhABEjcKC3BhY2tlZF9lbnVtGGcgAygOMh4ucHJvdG9i", - "dWZfdW5pdHRlc3QuRm9yZWlnbkVudW1CAhABIsgDChFUZXN0VW5wYWNrZWRU", - "eXBlcxIaCg51bnBhY2tlZF9pbnQzMhhaIAMoBUICEAASGgoOdW5wYWNrZWRf", - "aW50NjQYWyADKANCAhAAEhsKD3VucGFja2VkX3VpbnQzMhhcIAMoDUICEAAS", - "GwoPdW5wYWNrZWRfdWludDY0GF0gAygEQgIQABIbCg91bnBhY2tlZF9zaW50", - "MzIYXiADKBFCAhAAEhsKD3VucGFja2VkX3NpbnQ2NBhfIAMoEkICEAASHAoQ", - "dW5wYWNrZWRfZml4ZWQzMhhgIAMoB0ICEAASHAoQdW5wYWNrZWRfZml4ZWQ2", - "NBhhIAMoBkICEAASHQoRdW5wYWNrZWRfc2ZpeGVkMzIYYiADKA9CAhAAEh0K", - "EXVucGFja2VkX3NmaXhlZDY0GGMgAygQQgIQABIaCg51bnBhY2tlZF9mbG9h", - "dBhkIAMoAkICEAASGwoPdW5wYWNrZWRfZG91YmxlGGUgAygBQgIQABIZCg11", - "bnBhY2tlZF9ib29sGGYgAygIQgIQABI5Cg11bnBhY2tlZF9lbnVtGGcgAygO", - "Mh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1CAhAAIiAKFFRlc3RQ", - "YWNrZWRFeHRlbnNpb25zKggIARCAgICAAiIiChZUZXN0VW5wYWNrZWRFeHRl", - "bnNpb25zKggIARCAgICAAiKZBAoVVGVzdER5bmFtaWNFeHRlbnNpb25zEhkK", - "EHNjYWxhcl9leHRlbnNpb24Y0A8gASgHEjcKDmVudW1fZXh0ZW5zaW9uGNEP", - "IAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtElkKFmR5bmFt", - "aWNfZW51bV9leHRlbnNpb24Y0g8gASgOMjgucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdER5bmFtaWNFeHRlbnNpb25zLkR5bmFtaWNFbnVtVHlwZRI9ChFtZXNz", - "YWdlX2V4dGVuc2lvbhjTDyABKAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3Jl", - "aWduTWVzc2FnZRJfChlkeW5hbWljX21lc3NhZ2VfZXh0ZW5zaW9uGNQPIAEo", - "CzI7LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REeW5hbWljRXh0ZW5zaW9ucy5E", - "eW5hbWljTWVzc2FnZVR5cGUSGwoScmVwZWF0ZWRfZXh0ZW5zaW9uGNUPIAMo", - "CRIdChBwYWNrZWRfZXh0ZW5zaW9uGNYPIAMoEUICEAEaLAoSRHluYW1pY01l", - "c3NhZ2VUeXBlEhYKDWR5bmFtaWNfZmllbGQYtBAgASgFIkcKD0R5bmFtaWNF", - "bnVtVHlwZRIQCgtEWU5BTUlDX0ZPTxCYERIQCgtEWU5BTUlDX0JBUhCZERIQ", - "CgtEWU5BTUlDX0JBWhCaESLAAQojVGVzdFJlcGVhdGVkU2NhbGFyRGlmZmVy", - "ZW50VGFnU2l6ZXMSGAoQcmVwZWF0ZWRfZml4ZWQzMhgMIAMoBxIWCg5yZXBl", - "YXRlZF9pbnQzMhgNIAMoBRIZChByZXBlYXRlZF9maXhlZDY0GP4PIAMoBhIX", - "Cg5yZXBlYXRlZF9pbnQ2NBj/DyADKAMSGAoOcmVwZWF0ZWRfZmxvYXQY/v8P", - "IAMoAhIZCg9yZXBlYXRlZF91aW50NjQY//8PIAMoBCL3CQoQVGVzdFBhcnNp", - "bmdNZXJnZRI7ChJyZXF1aXJlZF9hbGxfdHlwZXMYASACKAsyHy5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMSOwoSb3B0aW9uYWxfYWxsX3R5cGVz", - "GAIgASgLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzEjsKEnJl", - "cGVhdGVkX2FsbF90eXBlcxgDIAMoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxUeXBlcxJICg1vcHRpb25hbGdyb3VwGAogASgKMjEucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZS5PcHRpb25hbEdyb3VwEkgKDXJl", - "cGVhdGVkZ3JvdXAYFCADKAoyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFy", - "c2luZ01lcmdlLlJlcGVhdGVkR3JvdXAaqgQKF1JlcGVhdGVkRmllbGRzR2Vu", - "ZXJhdG9yEi8KBmZpZWxkMRgBIAMoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxUeXBlcxIvCgZmaWVsZDIYAiADKAsyHy5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsVHlwZXMSLwoGZmllbGQzGAMgAygLMh8ucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdEFsbFR5cGVzElIKBmdyb3VwMRgKIAMoCjJCLnByb3RvYnVm", - "X3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2UuUmVwZWF0ZWRGaWVsZHNHZW5l", - "cmF0b3IuR3JvdXAxElIKBmdyb3VwMhgUIAMoCjJCLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RQYXJzaW5nTWVyZ2UuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3Iu", - "R3JvdXAyEi4KBGV4dDEY6AcgAygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dEFsbFR5cGVzEi4KBGV4dDIY6QcgAygLMh8ucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdEFsbFR5cGVzGjkKBkdyb3VwMRIvCgZmaWVsZDEYCyABKAsyHy5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMaOQoGR3JvdXAyEi8KBmZpZWxk", - "MRgVIAEoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcxpSCg1P", - "cHRpb25hbEdyb3VwEkEKGG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcxgLIAEo", - "CzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcxpSCg1SZXBlYXRl", - "ZEdyb3VwEkEKGHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcxgVIAEoCzIfLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcyoJCOgHEICAgIACMlsKDG9w", - "dGlvbmFsX2V4dBIjLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVy", - "Z2UY6AcgASgLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzMlsK", - "DHJlcGVhdGVkX2V4dBIjLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5n", - "TWVyZ2UY6QcgAygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVz", - "IkQKG1Rlc3RDb21tZW50SW5qZWN0aW9uTWVzc2FnZRIlCgFhGAEgASgJOhoq", - "LyA8LSBOZWl0aGVyIHNob3VsZCB0aGlzLiIMCgpGb29SZXF1ZXN0Ig0KC0Zv", - "b1Jlc3BvbnNlIhIKEEZvb0NsaWVudE1lc3NhZ2UiEgoQRm9vU2VydmVyTWVz", - "c2FnZSIMCgpCYXJSZXF1ZXN0Ig0KC0JhclJlc3BvbnNlKkAKC0ZvcmVpZ25F", - "bnVtEg8KC0ZPUkVJR05fRk9PEAQSDwoLRk9SRUlHTl9CQVIQBRIPCgtGT1JF", - "SUdOX0JBWhAGKksKFFRlc3RFbnVtV2l0aER1cFZhbHVlEggKBEZPTzEQARII", - "CgRCQVIxEAISBwoDQkFaEAMSCAoERk9PMhABEggKBEJBUjIQAhoCEAEqiQEK", - "DlRlc3RTcGFyc2VFbnVtEgwKCFNQQVJTRV9BEHsSDgoIU1BBUlNFX0IQpucD", - "Eg8KCFNQQVJTRV9DELKxgAYSFQoIU1BBUlNFX0QQ8f//////////ARIVCghT", - "UEFSU0VfRRC03vz///////8BEgwKCFNQQVJTRV9GEAASDAoIU1BBUlNFX0cQ", - "AjKZAQoLVGVzdFNlcnZpY2USRAoDRm9vEh0ucHJvdG9idWZfdW5pdHRlc3Qu", - "Rm9vUmVxdWVzdBoeLnByb3RvYnVmX3VuaXR0ZXN0LkZvb1Jlc3BvbnNlEkQK", - "A0JhchIdLnByb3RvYnVmX3VuaXR0ZXN0LkJhclJlcXVlc3QaHi5wcm90b2J1", - "Zl91bml0dGVzdC5CYXJSZXNwb25zZTpGChhvcHRpb25hbF9pbnQzMl9leHRl", - "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgB", - "IAEoBTpGChhvcHRpb25hbF9pbnQ2NF9leHRlbnNpb24SJC5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgCIAEoAzpHChlvcHRpb25hbF91", - "aW50MzJfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4", - "dGVuc2lvbnMYAyABKA06RwoZb3B0aW9uYWxfdWludDY0X2V4dGVuc2lvbhIk", - "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAQgASgEOkcK", - "GW9wdGlvbmFsX3NpbnQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsRXh0ZW5zaW9ucxgFIAEoETpHChlvcHRpb25hbF9zaW50NjRf", - "ZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lv", - "bnMYBiABKBI6SAoab3B0aW9uYWxfZml4ZWQzMl9leHRlbnNpb24SJC5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgHIAEoBzpIChpvcHRp", - "b25hbF9maXhlZDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGAggASgGOkkKG29wdGlvbmFsX3NmaXhlZDMyX2V4", + "AxIQCgNORUcQ////////////AUINCgtvbmVvZl9maWVsZCK7AQoSTmVzdGVk", + "VGVzdEFsbFR5cGVzEjQKBWNoaWxkGAEgASgLMiUucHJvdG9idWZfdW5pdHRl", + "c3QuTmVzdGVkVGVzdEFsbFR5cGVzEjAKB3BheWxvYWQYAiABKAsyHy5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMSPQoOcmVwZWF0ZWRfY2hpbGQY", + "AyADKAsyJS5wcm90b2J1Zl91bml0dGVzdC5OZXN0ZWRUZXN0QWxsVHlwZXMi", + "NAoUVGVzdERlcHJlY2F0ZWRGaWVsZHMSHAoQZGVwcmVjYXRlZF9pbnQzMhgB", + "IAEoBUICGAEiGwoORm9yZWlnbk1lc3NhZ2USCQoBYxgBIAEoBSIwChJUZXN0", + "UmVzZXJ2ZWRGaWVsZHNKBAgCEANKBAgPEBBKBAgJEAxSA2JhclIDYmF6Ih0K", + "EVRlc3RBbGxFeHRlbnNpb25zKggIARCAgICAAiIkChdPcHRpb25hbEdyb3Vw", + "X2V4dGVuc2lvbhIJCgFhGBEgASgFIiQKF1JlcGVhdGVkR3JvdXBfZXh0ZW5z", + "aW9uEgkKAWEYLyABKAUimAEKE1Rlc3ROZXN0ZWRFeHRlbnNpb24yOQoEdGVz", + "dBIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGOoHIAEo", + "CToEdGVzdDJGChduZXN0ZWRfc3RyaW5nX2V4dGVuc2lvbhIkLnByb3RvYnVm", + "X3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGOsHIAEoCSLVBQoMVGVzdFJl", + "cXVpcmVkEgkKAWEYASACKAUSDgoGZHVtbXkyGAIgASgFEgkKAWIYAyACKAUS", + "DgoGZHVtbXk0GAQgASgFEg4KBmR1bW15NRgFIAEoBRIOCgZkdW1teTYYBiAB", + "KAUSDgoGZHVtbXk3GAcgASgFEg4KBmR1bW15OBgIIAEoBRIOCgZkdW1teTkY", + "CSABKAUSDwoHZHVtbXkxMBgKIAEoBRIPCgdkdW1teTExGAsgASgFEg8KB2R1", + "bW15MTIYDCABKAUSDwoHZHVtbXkxMxgNIAEoBRIPCgdkdW1teTE0GA4gASgF", + "Eg8KB2R1bW15MTUYDyABKAUSDwoHZHVtbXkxNhgQIAEoBRIPCgdkdW1teTE3", + "GBEgASgFEg8KB2R1bW15MTgYEiABKAUSDwoHZHVtbXkxORgTIAEoBRIPCgdk", + "dW1teTIwGBQgASgFEg8KB2R1bW15MjEYFSABKAUSDwoHZHVtbXkyMhgWIAEo", + "BRIPCgdkdW1teTIzGBcgASgFEg8KB2R1bW15MjQYGCABKAUSDwoHZHVtbXky", + "NRgZIAEoBRIPCgdkdW1teTI2GBogASgFEg8KB2R1bW15MjcYGyABKAUSDwoH", + "ZHVtbXkyOBgcIAEoBRIPCgdkdW1teTI5GB0gASgFEg8KB2R1bW15MzAYHiAB", + "KAUSDwoHZHVtbXkzMRgfIAEoBRIPCgdkdW1teTMyGCAgASgFEgkKAWMYISAC", + "KAUyVgoGc2luZ2xlEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", + "c2lvbnMY6AcgASgLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVk", + "MlUKBW11bHRpEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lv", + "bnMY6QcgAygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkIpoB", + "ChNUZXN0UmVxdWlyZWRGb3JlaWduEjkKEG9wdGlvbmFsX21lc3NhZ2UYASAB", + "KAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWQSOQoQcmVwZWF0", + "ZWRfbWVzc2FnZRgCIAMoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1", + "aXJlZBINCgVkdW1teRgDIAEoBSJaChFUZXN0Rm9yZWlnbk5lc3RlZBJFCg5m", + "b3JlaWduX25lc3RlZBgBIAEoCzItLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxUeXBlcy5OZXN0ZWRNZXNzYWdlIhIKEFRlc3RFbXB0eU1lc3NhZ2UiKgoe", + "VGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zKggIARCAgICAAiI3ChtU", + "ZXN0TXVsdGlwbGVFeHRlbnNpb25SYW5nZXMqBAgqECsqBgivIBCUISoKCICA", + "BBCAgICAAiI0ChhUZXN0UmVhbGx5TGFyZ2VUYWdOdW1iZXISCQoBYRgBIAEo", + "BRINCgJiYhj///9/IAEoBSJVChRUZXN0UmVjdXJzaXZlTWVzc2FnZRIyCgFh", + "GAEgASgLMicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlY3Vyc2l2ZU1lc3Nh", + "Z2USCQoBaRgCIAEoBSJLChRUZXN0TXV0dWFsUmVjdXJzaW9uQRIzCgJiYhgB", + "IAEoCzInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNdXR1YWxSZWN1cnNpb25C", + "ImIKFFRlc3RNdXR1YWxSZWN1cnNpb25CEjIKAWEYASABKAsyJy5wcm90b2J1", + "Zl91bml0dGVzdC5UZXN0TXV0dWFsUmVjdXJzaW9uQRIWCg5vcHRpb25hbF9p", + "bnQzMhgCIAEoBSKzAQoSVGVzdER1cEZpZWxkTnVtYmVyEgkKAWEYASABKAUS", + "NgoDZm9vGAIgASgKMikucHJvdG9idWZfdW5pdHRlc3QuVGVzdER1cEZpZWxk", + "TnVtYmVyLkZvbxI2CgNiYXIYAyABKAoyKS5wcm90b2J1Zl91bml0dGVzdC5U", + "ZXN0RHVwRmllbGROdW1iZXIuQmFyGhAKA0ZvbxIJCgFhGAEgASgFGhAKA0Jh", + "chIJCgFhGAEgASgFIkwKEFRlc3RFYWdlck1lc3NhZ2USOAoLc3ViX21lc3Nh", + "Z2UYASABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNCAigA", + "IksKD1Rlc3RMYXp5TWVzc2FnZRI4CgtzdWJfbWVzc2FnZRgBIAEoCzIfLnBy", + "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0ICKAEigAIKGFRlc3ROZXN0", + "ZWRNZXNzYWdlSGFzQml0cxJaChdvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZRgB", + "IAEoCzI5LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3ROZXN0ZWRNZXNzYWdlSGFz", + "Qml0cy5OZXN0ZWRNZXNzYWdlGocBCg1OZXN0ZWRNZXNzYWdlEiQKHG5lc3Rl", + "ZG1lc3NhZ2VfcmVwZWF0ZWRfaW50MzIYASADKAUSUAolbmVzdGVkbWVzc2Fn", + "ZV9yZXBlYXRlZF9mb3JlaWdubWVzc2FnZRgCIAMoCzIhLnByb3RvYnVmX3Vu", + "aXR0ZXN0LkZvcmVpZ25NZXNzYWdlIuUDChdUZXN0Q2FtZWxDYXNlRmllbGRO", + "YW1lcxIWCg5QcmltaXRpdmVGaWVsZBgBIAEoBRITCgtTdHJpbmdGaWVsZBgC", + "IAEoCRIxCglFbnVtRmllbGQYAyABKA4yHi5wcm90b2J1Zl91bml0dGVzdC5G", + "b3JlaWduRW51bRI3CgxNZXNzYWdlRmllbGQYBCABKAsyIS5wcm90b2J1Zl91", + "bml0dGVzdC5Gb3JlaWduTWVzc2FnZRIcChBTdHJpbmdQaWVjZUZpZWxkGAUg", + "ASgJQgIIAhIVCglDb3JkRmllbGQYBiABKAlCAggBEh4KFlJlcGVhdGVkUHJp", + "bWl0aXZlRmllbGQYByADKAUSGwoTUmVwZWF0ZWRTdHJpbmdGaWVsZBgIIAMo", + "CRI5ChFSZXBlYXRlZEVudW1GaWVsZBgJIAMoDjIeLnByb3RvYnVmX3VuaXR0", + "ZXN0LkZvcmVpZ25FbnVtEj8KFFJlcGVhdGVkTWVzc2FnZUZpZWxkGAogAygL", + "MiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USJAoYUmVwZWF0", + "ZWRTdHJpbmdQaWVjZUZpZWxkGAsgAygJQgIIAhIdChFSZXBlYXRlZENvcmRG", + "aWVsZBgMIAMoCUICCAEi1QEKElRlc3RGaWVsZE9yZGVyaW5ncxIRCglteV9z", + "dHJpbmcYCyABKAkSDgoGbXlfaW50GAEgASgDEhAKCG15X2Zsb2F0GGUgASgC", + "ElUKF29wdGlvbmFsX25lc3RlZF9tZXNzYWdlGMgBIAEoCzIzLnByb3RvYnVm", + "X3VuaXR0ZXN0LlRlc3RGaWVsZE9yZGVyaW5ncy5OZXN0ZWRNZXNzYWdlGicK", + "DU5lc3RlZE1lc3NhZ2USCgoCb28YAiABKAMSCgoCYmIYASABKAUqBAgCEAsq", + "BAgMEGUitgcKGFRlc3RFeHRyZW1lRGVmYXVsdFZhbHVlcxI/Cg1lc2NhcGVk", + "X2J5dGVzGAEgASgMOihcMDAwXDAwMVwwMDdcMDEwXDAxNFxuXHJcdFwwMTNc", + "XFwnXCJcMzc2EiAKDGxhcmdlX3VpbnQzMhgCIAEoDToKNDI5NDk2NzI5NRIq", + "CgxsYXJnZV91aW50NjQYAyABKAQ6FDE4NDQ2NzQ0MDczNzA5NTUxNjE1EiAK", + "C3NtYWxsX2ludDMyGAQgASgFOgstMjE0NzQ4MzY0NxIpCgtzbWFsbF9pbnQ2", + "NBgFIAEoAzoULTkyMjMzNzIwMzY4NTQ3NzU4MDcSJwoScmVhbGx5X3NtYWxs", + "X2ludDMyGBUgASgFOgstMjE0NzQ4MzY0OBIwChJyZWFsbHlfc21hbGxfaW50", + "NjQYFiABKAM6FC05MjIzMzcyMDM2ODU0Nzc1ODA4EhgKC3V0Zjhfc3RyaW5n", + "GAYgASgJOgPhiLQSFQoKemVyb19mbG9hdBgHIAEoAjoBMBIUCglvbmVfZmxv", + "YXQYCCABKAI6ATESGAoLc21hbGxfZmxvYXQYCSABKAI6AzEuNRIeChJuZWdh", + "dGl2ZV9vbmVfZmxvYXQYCiABKAI6Ai0xEhwKDm5lZ2F0aXZlX2Zsb2F0GAsg", + "ASgCOgQtMS41EhoKC2xhcmdlX2Zsb2F0GAwgASgCOgUyZSswOBIkChRzbWFs", + "bF9uZWdhdGl2ZV9mbG9hdBgNIAEoAjoGLThlLTI4EhcKCmluZl9kb3VibGUY", + "DiABKAE6A2luZhIcCg5uZWdfaW5mX2RvdWJsZRgPIAEoAToELWluZhIXCgpu", + "YW5fZG91YmxlGBAgASgBOgNuYW4SFgoJaW5mX2Zsb2F0GBEgASgCOgNpbmYS", + "GwoNbmVnX2luZl9mbG9hdBgSIAEoAjoELWluZhIWCgluYW5fZmxvYXQYEyAB", + "KAI6A25hbhIrCgxjcHBfdHJpZ3JhcGgYFCABKAk6FT8gPyA/PyA/PyA/Pz8g", + "Pz8vID8/LRIgChBzdHJpbmdfd2l0aF96ZXJvGBcgASgJOgZoZWwAbG8SIgoP", + "Ynl0ZXNfd2l0aF96ZXJvGBggASgMOgl3b3JcMDAwbGQSKAoWc3RyaW5nX3Bp", + "ZWNlX3dpdGhfemVybxgZIAEoCToEYWIAY0ICCAISIAoOY29yZF93aXRoX3pl", + "cm8YGiABKAk6BDEyADNCAggBEiYKEnJlcGxhY2VtZW50X3N0cmluZxgbIAEo", + "CToKJHt1bmtub3dufSJLChFTcGFyc2VFbnVtTWVzc2FnZRI2CgtzcGFyc2Vf", + "ZW51bRgBIAEoDjIhLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RTcGFyc2VFbnVt", + "IhkKCU9uZVN0cmluZxIMCgRkYXRhGAEgASgJIhoKCk1vcmVTdHJpbmcSDAoE", + "ZGF0YRgBIAMoCSIYCghPbmVCeXRlcxIMCgRkYXRhGAEgASgMIhkKCU1vcmVC", + "eXRlcxIMCgRkYXRhGAEgAygMIhwKDEludDMyTWVzc2FnZRIMCgRkYXRhGAEg", + "ASgFIh0KDVVpbnQzMk1lc3NhZ2USDAoEZGF0YRgBIAEoDSIcCgxJbnQ2NE1l", + "c3NhZ2USDAoEZGF0YRgBIAEoAyIdCg1VaW50NjRNZXNzYWdlEgwKBGRhdGEY", + "ASABKAQiGwoLQm9vbE1lc3NhZ2USDAoEZGF0YRgBIAEoCCLQAQoJVGVzdE9u", + "ZW9mEhEKB2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIgASgJSAAS", + "NgoLZm9vX21lc3NhZ2UYAyABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0", + "QWxsVHlwZXNIABI5Cghmb29ncm91cBgEIAEoCjIlLnByb3RvYnVmX3VuaXR0", + "ZXN0LlRlc3RPbmVvZi5Gb29Hcm91cEgAGiAKCEZvb0dyb3VwEgkKAWEYBSAB", + "KAUSCQoBYhgGIAEoCUIFCgNmb28i5wEKHFRlc3RPbmVvZkJhY2t3YXJkc0Nv", + "bXBhdGlibGUSDwoHZm9vX2ludBgBIAEoBRISCgpmb29fc3RyaW5nGAIgASgJ", + "EjQKC2Zvb19tZXNzYWdlGAMgASgLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVz", + "dEFsbFR5cGVzEkoKCGZvb2dyb3VwGAQgASgKMjgucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdE9uZW9mQmFja3dhcmRzQ29tcGF0aWJsZS5Gb29Hcm91cBogCghG", + "b29Hcm91cBIJCgFhGAUgASgFEgkKAWIYBiABKAkingYKClRlc3RPbmVvZjIS", + "EQoHZm9vX2ludBgBIAEoBUgAEhQKCmZvb19zdHJpbmcYAiABKAlIABIWCghm", + "b29fY29yZBgDIAEoCUICCAFIABIeChBmb29fc3RyaW5nX3BpZWNlGAQgASgJ", + "QgIIAkgAEhMKCWZvb19ieXRlcxgFIAEoDEgAEjwKCGZvb19lbnVtGAYgASgO", + "MigucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mMi5OZXN0ZWRFbnVtSAAS", + "QgoLZm9vX21lc3NhZ2UYByABKAsyKy5wcm90b2J1Zl91bml0dGVzdC5UZXN0", + "T25lb2YyLk5lc3RlZE1lc3NhZ2VIABI6Cghmb29ncm91cBgIIAEoCjImLnBy", + "b3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVvZjIuRm9vR3JvdXBIABJLChBmb29f", + "bGF6eV9tZXNzYWdlGAsgASgLMisucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9u", + "ZW9mMi5OZXN0ZWRNZXNzYWdlQgIoAUgAEhQKB2Jhcl9pbnQYDCABKAU6ATVI", + "ARIcCgpiYXJfc3RyaW5nGA0gASgJOgZTVFJJTkdIARIcCghiYXJfY29yZBgO", + "IAEoCToEQ09SREICCAFIARImChBiYXJfc3RyaW5nX3BpZWNlGA8gASgJOgZT", + "UElFQ0VCAggCSAESGgoJYmFyX2J5dGVzGBAgASgMOgVCWVRFU0gBEkEKCGJh", + "cl9lbnVtGBEgASgOMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mMi5O", + "ZXN0ZWRFbnVtOgNCQVJIARIPCgdiYXpfaW50GBIgASgFEhcKCmJhel9zdHJp", + "bmcYEyABKAk6A0JBWhogCghGb29Hcm91cBIJCgFhGAkgASgFEgkKAWIYCiAB", + "KAkaMwoNTmVzdGVkTWVzc2FnZRIPCgdxdXhfaW50GAEgASgDEhEKCWNvcmdl", + "X2ludBgCIAMoBSInCgpOZXN0ZWRFbnVtEgcKA0ZPTxABEgcKA0JBUhACEgcK", + "A0JBWhADQgUKA2Zvb0IFCgNiYXIiuAEKEVRlc3RSZXF1aXJlZE9uZW9mEhEK", + "B2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIgASgJSAASSQoLZm9v", + "X21lc3NhZ2UYAyABKAsyMi5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWly", + "ZWRPbmVvZi5OZXN0ZWRNZXNzYWdlSAAaKAoNTmVzdGVkTWVzc2FnZRIXCg9y", + "ZXF1aXJlZF9kb3VibGUYASACKAFCBQoDZm9vIqoDCg9UZXN0UGFja2VkVHlw", + "ZXMSGAoMcGFja2VkX2ludDMyGFogAygFQgIQARIYCgxwYWNrZWRfaW50NjQY", + "WyADKANCAhABEhkKDXBhY2tlZF91aW50MzIYXCADKA1CAhABEhkKDXBhY2tl", + "ZF91aW50NjQYXSADKARCAhABEhkKDXBhY2tlZF9zaW50MzIYXiADKBFCAhAB", + "EhkKDXBhY2tlZF9zaW50NjQYXyADKBJCAhABEhoKDnBhY2tlZF9maXhlZDMy", + "GGAgAygHQgIQARIaCg5wYWNrZWRfZml4ZWQ2NBhhIAMoBkICEAESGwoPcGFj", + "a2VkX3NmaXhlZDMyGGIgAygPQgIQARIbCg9wYWNrZWRfc2ZpeGVkNjQYYyAD", + "KBBCAhABEhgKDHBhY2tlZF9mbG9hdBhkIAMoAkICEAESGQoNcGFja2VkX2Rv", + "dWJsZRhlIAMoAUICEAESFwoLcGFja2VkX2Jvb2wYZiADKAhCAhABEjcKC3Bh", + "Y2tlZF9lbnVtGGcgAygOMh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVu", + "dW1CAhABIsgDChFUZXN0VW5wYWNrZWRUeXBlcxIaCg51bnBhY2tlZF9pbnQz", + "MhhaIAMoBUICEAASGgoOdW5wYWNrZWRfaW50NjQYWyADKANCAhAAEhsKD3Vu", + "cGFja2VkX3VpbnQzMhhcIAMoDUICEAASGwoPdW5wYWNrZWRfdWludDY0GF0g", + "AygEQgIQABIbCg91bnBhY2tlZF9zaW50MzIYXiADKBFCAhAAEhsKD3VucGFj", + "a2VkX3NpbnQ2NBhfIAMoEkICEAASHAoQdW5wYWNrZWRfZml4ZWQzMhhgIAMo", + "B0ICEAASHAoQdW5wYWNrZWRfZml4ZWQ2NBhhIAMoBkICEAASHQoRdW5wYWNr", + "ZWRfc2ZpeGVkMzIYYiADKA9CAhAAEh0KEXVucGFja2VkX3NmaXhlZDY0GGMg", + "AygQQgIQABIaCg51bnBhY2tlZF9mbG9hdBhkIAMoAkICEAASGwoPdW5wYWNr", + "ZWRfZG91YmxlGGUgAygBQgIQABIZCg11bnBhY2tlZF9ib29sGGYgAygIQgIQ", + "ABI5Cg11bnBhY2tlZF9lbnVtGGcgAygOMh4ucHJvdG9idWZfdW5pdHRlc3Qu", + "Rm9yZWlnbkVudW1CAhAAIiAKFFRlc3RQYWNrZWRFeHRlbnNpb25zKggIARCA", + "gICAAiIiChZUZXN0VW5wYWNrZWRFeHRlbnNpb25zKggIARCAgICAAiKZBAoV", + "VGVzdER5bmFtaWNFeHRlbnNpb25zEhkKEHNjYWxhcl9leHRlbnNpb24Y0A8g", + "ASgHEjcKDmVudW1fZXh0ZW5zaW9uGNEPIAEoDjIeLnByb3RvYnVmX3VuaXR0", + "ZXN0LkZvcmVpZ25FbnVtElkKFmR5bmFtaWNfZW51bV9leHRlbnNpb24Y0g8g", + "ASgOMjgucHJvdG9idWZfdW5pdHRlc3QuVGVzdER5bmFtaWNFeHRlbnNpb25z", + "LkR5bmFtaWNFbnVtVHlwZRI9ChFtZXNzYWdlX2V4dGVuc2lvbhjTDyABKAsy", + "IS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZRJfChlkeW5hbWlj", + "X21lc3NhZ2VfZXh0ZW5zaW9uGNQPIAEoCzI7LnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3REeW5hbWljRXh0ZW5zaW9ucy5EeW5hbWljTWVzc2FnZVR5cGUSGwoS", + "cmVwZWF0ZWRfZXh0ZW5zaW9uGNUPIAMoCRIdChBwYWNrZWRfZXh0ZW5zaW9u", + "GNYPIAMoEUICEAEaLAoSRHluYW1pY01lc3NhZ2VUeXBlEhYKDWR5bmFtaWNf", + "ZmllbGQYtBAgASgFIkcKD0R5bmFtaWNFbnVtVHlwZRIQCgtEWU5BTUlDX0ZP", + "TxCYERIQCgtEWU5BTUlDX0JBUhCZERIQCgtEWU5BTUlDX0JBWhCaESLAAQoj", + "VGVzdFJlcGVhdGVkU2NhbGFyRGlmZmVyZW50VGFnU2l6ZXMSGAoQcmVwZWF0", + "ZWRfZml4ZWQzMhgMIAMoBxIWCg5yZXBlYXRlZF9pbnQzMhgNIAMoBRIZChBy", + "ZXBlYXRlZF9maXhlZDY0GP4PIAMoBhIXCg5yZXBlYXRlZF9pbnQ2NBj/DyAD", + "KAMSGAoOcmVwZWF0ZWRfZmxvYXQY/v8PIAMoAhIZCg9yZXBlYXRlZF91aW50", + "NjQY//8PIAMoBCL3CQoQVGVzdFBhcnNpbmdNZXJnZRI7ChJyZXF1aXJlZF9h", + "bGxfdHlwZXMYASACKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlw", + "ZXMSOwoSb3B0aW9uYWxfYWxsX3R5cGVzGAIgASgLMh8ucHJvdG9idWZfdW5p", + "dHRlc3QuVGVzdEFsbFR5cGVzEjsKEnJlcGVhdGVkX2FsbF90eXBlcxgDIAMo", + "CzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcxJICg1vcHRpb25h", + "bGdyb3VwGAogASgKMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdN", + "ZXJnZS5PcHRpb25hbEdyb3VwEkgKDXJlcGVhdGVkZ3JvdXAYFCADKAoyMS5w", + "cm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlLlJlcGVhdGVkR3Jv", + "dXAaqgQKF1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yEi8KBmZpZWxkMRgBIAMo", + "CzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcxIvCgZmaWVsZDIY", + "AiADKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMSLwoGZmll", + "bGQzGAMgAygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzElIK", + "Bmdyb3VwMRgKIAMoCjJCLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5n", + "TWVyZ2UuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxElIKBmdyb3Vw", + "MhgUIAMoCjJCLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2Uu", + "UmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyEi4KBGV4dDEY6AcgAygL", + "Mh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzEi4KBGV4dDIY6Qcg", + "AygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzGjkKBkdyb3Vw", + "MRIvCgZmaWVsZDEYCyABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxs", + "VHlwZXMaOQoGR3JvdXAyEi8KBmZpZWxkMRgVIAEoCzIfLnByb3RvYnVmX3Vu", + "aXR0ZXN0LlRlc3RBbGxUeXBlcxpSCg1PcHRpb25hbEdyb3VwEkEKGG9wdGlv", + "bmFsX2dyb3VwX2FsbF90eXBlcxgLIAEoCzIfLnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3RBbGxUeXBlcxpSCg1SZXBlYXRlZEdyb3VwEkEKGHJlcGVhdGVkX2dy", + "b3VwX2FsbF90eXBlcxgVIAEoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxUeXBlcyoJCOgHEICAgIACMlsKDG9wdGlvbmFsX2V4dBIjLnByb3RvYnVm", + "X3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2UY6AcgASgLMh8ucHJvdG9idWZf", + "dW5pdHRlc3QuVGVzdEFsbFR5cGVzMlsKDHJlcGVhdGVkX2V4dBIjLnByb3Rv", + "YnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2UY6QcgAygLMh8ucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzIkQKG1Rlc3RDb21tZW50SW5qZWN0", + "aW9uTWVzc2FnZRIlCgFhGAEgASgJOhoqLyA8LSBOZWl0aGVyIHNob3VsZCB0", + "aGlzLiIMCgpGb29SZXF1ZXN0Ig0KC0Zvb1Jlc3BvbnNlIhIKEEZvb0NsaWVu", + "dE1lc3NhZ2UiEgoQRm9vU2VydmVyTWVzc2FnZSIMCgpCYXJSZXF1ZXN0Ig0K", + "C0JhclJlc3BvbnNlKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9PEAQS", + "DwoLRk9SRUlHTl9CQVIQBRIPCgtGT1JFSUdOX0JBWhAGKksKFFRlc3RFbnVt", + "V2l0aER1cFZhbHVlEggKBEZPTzEQARIICgRCQVIxEAISBwoDQkFaEAMSCAoE", + "Rk9PMhABEggKBEJBUjIQAhoCEAEqiQEKDlRlc3RTcGFyc2VFbnVtEgwKCFNQ", + "QVJTRV9BEHsSDgoIU1BBUlNFX0IQpucDEg8KCFNQQVJTRV9DELKxgAYSFQoI", + "U1BBUlNFX0QQ8f//////////ARIVCghTUEFSU0VfRRC03vz///////8BEgwK", + "CFNQQVJTRV9GEAASDAoIU1BBUlNFX0cQAjKZAQoLVGVzdFNlcnZpY2USRAoD", + "Rm9vEh0ucHJvdG9idWZfdW5pdHRlc3QuRm9vUmVxdWVzdBoeLnByb3RvYnVm", + "X3VuaXR0ZXN0LkZvb1Jlc3BvbnNlEkQKA0JhchIdLnByb3RvYnVmX3VuaXR0", + "ZXN0LkJhclJlcXVlc3QaHi5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXNwb25z", + "ZTpGChhvcHRpb25hbF9pbnQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0", + "dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgBIAEoBTpGChhvcHRpb25hbF9pbnQ2", + "NF9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", + "aW9ucxgCIAEoAzpHChlvcHRpb25hbF91aW50MzJfZXh0ZW5zaW9uEiQucHJv", + "dG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYAyABKA06RwoZb3B0", + "aW9uYWxfdWludDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", + "c3RBbGxFeHRlbnNpb25zGAQgASgEOkcKGW9wdGlvbmFsX3NpbnQzMl9leHRl", + "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgF", + "IAEoETpHChlvcHRpb25hbF9zaW50NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZf", + "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYBiABKBI6SAoab3B0aW9uYWxf", + "Zml4ZWQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxs", + "RXh0ZW5zaW9ucxgHIAEoBzpIChpvcHRpb25hbF9maXhlZDY0X2V4dGVuc2lv", + "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAggASgG", + "OkkKG29wdGlvbmFsX3NmaXhlZDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3Vu", + "aXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAkgASgPOkkKG29wdGlvbmFsX3Nm", + "aXhlZDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxF", + "eHRlbnNpb25zGAogASgQOkYKGG9wdGlvbmFsX2Zsb2F0X2V4dGVuc2lvbhIk", + "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAsgASgCOkcK", + "GW9wdGlvbmFsX2RvdWJsZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", + "dC5UZXN0QWxsRXh0ZW5zaW9ucxgMIAEoATpFChdvcHRpb25hbF9ib29sX2V4", + "dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25z", + "GA0gASgIOkcKGW9wdGlvbmFsX3N0cmluZ19leHRlbnNpb24SJC5wcm90b2J1", + "Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgOIAEoCTpGChhvcHRpb25h", + "bF9ieXRlc19leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxs", + "RXh0ZW5zaW9ucxgPIAEoDDpxChdvcHRpb25hbGdyb3VwX2V4dGVuc2lvbhIk", + "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGBAgASgKMiou", + "cHJvdG9idWZfdW5pdHRlc3QuT3B0aW9uYWxHcm91cF9leHRlbnNpb246fgoh", + "b3B0aW9uYWxfbmVzdGVkX21lc3NhZ2VfZXh0ZW5zaW9uEiQucHJvdG9idWZf", + "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYEiABKAsyLS5wcm90b2J1Zl91", + "bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZTpzCiJvcHRpb25h", + "bF9mb3JlaWduX21lc3NhZ2VfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdEFsbEV4dGVuc2lvbnMYEyABKAsyIS5wcm90b2J1Zl91bml0dGVz", + "dC5Gb3JlaWduTWVzc2FnZTp4CiFvcHRpb25hbF9pbXBvcnRfbWVzc2FnZV9l", + "eHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9u", + "cxgUIAEoCzInLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNz", + "YWdlOngKHm9wdGlvbmFsX25lc3RlZF9lbnVtX2V4dGVuc2lvbhIkLnByb3Rv", + "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGBUgASgOMioucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW06bQofb3B0aW9u", + "YWxfZm9yZWlnbl9lbnVtX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3RBbGxFeHRlbnNpb25zGBYgASgOMh4ucHJvdG9idWZfdW5pdHRlc3Qu", + "Rm9yZWlnbkVudW06cgoeb3B0aW9uYWxfaW1wb3J0X2VudW1fZXh0ZW5zaW9u", + "EiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYFyABKA4y", + "JC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bTpRCh9vcHRp", + "b25hbF9zdHJpbmdfcGllY2VfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdEFsbEV4dGVuc2lvbnMYGCABKAlCAggCOkkKF29wdGlvbmFsX2Nv", + "cmRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", + "c2lvbnMYGSABKAlCAggBOoUBCihvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21l", + "c3NhZ2VfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4", + "dGVuc2lvbnMYGiABKAsyLS5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVi", + "bGljSW1wb3J0TWVzc2FnZTqAAQofb3B0aW9uYWxfbGF6eV9tZXNzYWdlX2V4", "dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25z", - "GAkgASgPOkkKG29wdGlvbmFsX3NmaXhlZDY0X2V4dGVuc2lvbhIkLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAogASgQOkYKGG9wdGlv", - "bmFsX2Zsb2F0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", - "bGxFeHRlbnNpb25zGAsgASgCOkcKGW9wdGlvbmFsX2RvdWJsZV9leHRlbnNp", - "b24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgMIAEo", - "ATpFChdvcHRpb25hbF9ib29sX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RBbGxFeHRlbnNpb25zGA0gASgIOkcKGW9wdGlvbmFsX3N0cmlu", - "Z19leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", - "aW9ucxgOIAEoCTpGChhvcHRpb25hbF9ieXRlc19leHRlbnNpb24SJC5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgPIAEoDDpxChdvcHRp", - "b25hbGdyb3VwX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", - "bGxFeHRlbnNpb25zGBAgASgKMioucHJvdG9idWZfdW5pdHRlc3QuT3B0aW9u", - "YWxHcm91cF9leHRlbnNpb246fgohb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2Vf", + "GBsgASgLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3Rl", + "ZE1lc3NhZ2VCAigBOkYKGHJlcGVhdGVkX2ludDMyX2V4dGVuc2lvbhIkLnBy", + "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGB8gAygFOkYKGHJl", + "cGVhdGVkX2ludDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", + "c3RBbGxFeHRlbnNpb25zGCAgAygDOkcKGXJlcGVhdGVkX3VpbnQzMl9leHRl", + "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgh", + "IAMoDTpHChlyZXBlYXRlZF91aW50NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZf", + "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYIiADKAQ6RwoZcmVwZWF0ZWRf", + "c2ludDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxF", + "eHRlbnNpb25zGCMgAygROkcKGXJlcGVhdGVkX3NpbnQ2NF9leHRlbnNpb24S", + "JC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgkIAMoEjpI", + "ChpyZXBlYXRlZF9maXhlZDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0", + "ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCUgAygHOkgKGnJlcGVhdGVkX2ZpeGVk", + "NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", + "c2lvbnMYJiADKAY6SQobcmVwZWF0ZWRfc2ZpeGVkMzJfZXh0ZW5zaW9uEiQu", + "cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYJyADKA86SQob", + "cmVwZWF0ZWRfc2ZpeGVkNjRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdEFsbEV4dGVuc2lvbnMYKCADKBA6RgoYcmVwZWF0ZWRfZmxvYXRf", "ZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lv", - "bnMYEiABKAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVz", - "dGVkTWVzc2FnZTpzCiJvcHRpb25hbF9mb3JlaWduX21lc3NhZ2VfZXh0ZW5z", - "aW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYEyAB", - "KAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZTp4CiFvcHRp", - "b25hbF9pbXBvcnRfbWVzc2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0", - "dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgUIAEoCzInLnByb3RvYnVmX3VuaXR0", - "ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlOngKHm9wdGlvbmFsX25lc3RlZF9l", - "bnVtX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRl", - "bnNpb25zGBUgASgOMioucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVz", - "Lk5lc3RlZEVudW06bQofb3B0aW9uYWxfZm9yZWlnbl9lbnVtX2V4dGVuc2lv", - "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGBYgASgO", - "Mh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW06cgoeb3B0aW9uYWxf", - "aW1wb3J0X2VudW1fZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dEFsbEV4dGVuc2lvbnMYFyABKA4yJC5wcm90b2J1Zl91bml0dGVzdF9pbXBv", - "cnQuSW1wb3J0RW51bTpRCh9vcHRpb25hbF9zdHJpbmdfcGllY2VfZXh0ZW5z", - "aW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYGCAB", - "KAlCAggCOkkKF29wdGlvbmFsX2NvcmRfZXh0ZW5zaW9uEiQucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYGSABKAlCAggBOoUBCihvcHRp", - "b25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2VfZXh0ZW5zaW9uEiQucHJvdG9i", - "dWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYGiABKAsyLS5wcm90b2J1", - "Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZTqAAQofb3B0", - "aW9uYWxfbGF6eV9tZXNzYWdlX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RBbGxFeHRlbnNpb25zGBsgASgLMi0ucHJvdG9idWZfdW5pdHRl", - "c3QuVGVzdEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VCAigBOkYKGHJlcGVhdGVk", - "X2ludDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxF", - "eHRlbnNpb25zGB8gAygFOkYKGHJlcGVhdGVkX2ludDY0X2V4dGVuc2lvbhIk", - "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCAgAygDOkcK", - "GXJlcGVhdGVkX3VpbnQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsRXh0ZW5zaW9ucxghIAMoDTpHChlyZXBlYXRlZF91aW50NjRf", + "bnMYKSADKAI6RwoZcmVwZWF0ZWRfZG91YmxlX2V4dGVuc2lvbhIkLnByb3Rv", + "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCogAygBOkUKF3JlcGVh", + "dGVkX2Jvb2xfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFs", + "bEV4dGVuc2lvbnMYKyADKAg6RwoZcmVwZWF0ZWRfc3RyaW5nX2V4dGVuc2lv", + "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCwgAygJ", + "OkYKGHJlcGVhdGVkX2J5dGVzX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0", + "ZXN0LlRlc3RBbGxFeHRlbnNpb25zGC0gAygMOnEKF3JlcGVhdGVkZ3JvdXBf", "ZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lv", - "bnMYIiADKAQ6RwoZcmVwZWF0ZWRfc2ludDMyX2V4dGVuc2lvbhIkLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCMgAygROkcKGXJlcGVh", - "dGVkX3NpbnQ2NF9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0", - "QWxsRXh0ZW5zaW9ucxgkIAMoEjpIChpyZXBlYXRlZF9maXhlZDMyX2V4dGVu", - "c2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCUg", - "AygHOkgKGnJlcGVhdGVkX2ZpeGVkNjRfZXh0ZW5zaW9uEiQucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYJiADKAY6SQobcmVwZWF0ZWRf", - "c2ZpeGVkMzJfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFs", - "bEV4dGVuc2lvbnMYJyADKA86SQobcmVwZWF0ZWRfc2ZpeGVkNjRfZXh0ZW5z", - "aW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYKCAD", - "KBA6RgoYcmVwZWF0ZWRfZmxvYXRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYKSADKAI6RwoZcmVwZWF0ZWRfZG91", - "YmxlX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRl", - "bnNpb25zGCogAygBOkUKF3JlcGVhdGVkX2Jvb2xfZXh0ZW5zaW9uEiQucHJv", - "dG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYKyADKAg6RwoZcmVw", - "ZWF0ZWRfc3RyaW5nX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGCwgAygJOkYKGHJlcGVhdGVkX2J5dGVzX2V4dGVu", - "c2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGC0g", - "AygMOnEKF3JlcGVhdGVkZ3JvdXBfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYLiADKAoyKi5wcm90b2J1Zl91bml0", - "dGVzdC5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbjp+CiFyZXBlYXRlZF9uZXN0", - "ZWRfbWVzc2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0", - "QWxsRXh0ZW5zaW9ucxgwIAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", - "bGxUeXBlcy5OZXN0ZWRNZXNzYWdlOnMKInJlcGVhdGVkX2ZvcmVpZ25fbWVz", - "c2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0", - "ZW5zaW9ucxgxIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNz", - "YWdlOngKIXJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlX2V4dGVuc2lvbhIkLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGDIgAygLMicucHJv", - "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2U6eAoecmVwZWF0", - "ZWRfbmVzdGVkX2VudW1fZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdEFsbEV4dGVuc2lvbnMYMyADKA4yKi5wcm90b2J1Zl91bml0dGVzdC5U", - "ZXN0QWxsVHlwZXMuTmVzdGVkRW51bTptCh9yZXBlYXRlZF9mb3JlaWduX2Vu", - "dW1fZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", - "c2lvbnMYNCADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bTpy", - "Ch5yZXBlYXRlZF9pbXBvcnRfZW51bV9leHRlbnNpb24SJC5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg1IAMoDjIkLnByb3RvYnVmX3Vu", - "aXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtOlEKH3JlcGVhdGVkX3N0cmluZ19w", - "aWVjZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0", - "ZW5zaW9ucxg2IAMoCUICCAI6SQoXcmVwZWF0ZWRfY29yZF9leHRlbnNpb24S", - "JC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg3IAMoCUIC", - "CAE6gAEKH3JlcGVhdGVkX2xhenlfbWVzc2FnZV9leHRlbnNpb24SJC5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg5IAMoCzItLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlQgIoATpJ", - "ChdkZWZhdWx0X2ludDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RBbGxFeHRlbnNpb25zGD0gASgFOgI0MTpJChdkZWZhdWx0X2ludDY0", - "X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNp", - "b25zGD4gASgDOgI0MjpKChhkZWZhdWx0X3VpbnQzMl9leHRlbnNpb24SJC5w", - "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg/IAEoDToCNDM6", - "SgoYZGVmYXVsdF91aW50NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRl", - "c3QuVGVzdEFsbEV4dGVuc2lvbnMYQCABKAQ6AjQ0OksKGGRlZmF1bHRfc2lu", - "dDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRl", - "bnNpb25zGEEgASgROgMtNDU6SgoYZGVmYXVsdF9zaW50NjRfZXh0ZW5zaW9u", - "EiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYQiABKBI6", - "AjQ2OksKGWRlZmF1bHRfZml4ZWQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhDIAEoBzoCNDc6SwoZZGVmYXVs", - "dF9maXhlZDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", - "bGxFeHRlbnNpb25zGEQgASgGOgI0ODpMChpkZWZhdWx0X3NmaXhlZDMyX2V4", - "dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25z", - "GEUgASgPOgI0OTpNChpkZWZhdWx0X3NmaXhlZDY0X2V4dGVuc2lvbhIkLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEYgASgQOgMtNTA6", - "SwoXZGVmYXVsdF9mbG9hdF9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsRXh0ZW5zaW9ucxhHIAEoAjoENTEuNTpNChhkZWZhdWx0X2Rv", - "dWJsZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0", - "ZW5zaW9ucxhIIAEoAToFNTIwMDA6SgoWZGVmYXVsdF9ib29sX2V4dGVuc2lv", - "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEkgASgI", - "OgR0cnVlOk0KGGRlZmF1bHRfc3RyaW5nX2V4dGVuc2lvbhIkLnByb3RvYnVm", - "X3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEogASgJOgVoZWxsbzpMChdk", - "ZWZhdWx0X2J5dGVzX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGEsgASgMOgV3b3JsZDp8Ch1kZWZhdWx0X25lc3Rl", - "ZF9lbnVtX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxF", - "eHRlbnNpb25zGFEgASgOMioucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5", - "cGVzLk5lc3RlZEVudW06A0JBUjp5Ch5kZWZhdWx0X2ZvcmVpZ25fZW51bV9l", - "eHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9u", - "cxhSIAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtOgtGT1JF", - "SUdOX0JBUjp9Ch1kZWZhdWx0X2ltcG9ydF9lbnVtX2V4dGVuc2lvbhIkLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGFMgASgOMiQucHJv", - "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW06CklNUE9SVF9CQVI6", - "VQoeZGVmYXVsdF9zdHJpbmdfcGllY2VfZXh0ZW5zaW9uEiQucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYVCABKAk6A2FiY0ICCAI6TQoW", - "ZGVmYXVsdF9jb3JkX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGFUgASgJOgMxMjNCAggBOkQKFm9uZW9mX3VpbnQz", - "Ml9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", - "aW9ucxhvIAEoDTp7Ch5vbmVvZl9uZXN0ZWRfbWVzc2FnZV9leHRlbnNpb24S", - "JC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhwIAEoCzIt", + "bnMYLiADKAoyKi5wcm90b2J1Zl91bml0dGVzdC5SZXBlYXRlZEdyb3VwX2V4", + "dGVuc2lvbjp+CiFyZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZV9leHRlbnNpb24S", + "JC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgwIAMoCzIt", "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdl", - "OkQKFm9uZW9mX3N0cmluZ19leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsRXh0ZW5zaW9ucxhxIAEoCTpDChVvbmVvZl9ieXRlc19leHRl", - "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhy", - "IAEoDDpCChNteV9leHRlbnNpb25fc3RyaW5nEiUucHJvdG9idWZfdW5pdHRl", - "c3QuVGVzdEZpZWxkT3JkZXJpbmdzGDIgASgJOj8KEG15X2V4dGVuc2lvbl9p", - "bnQSJS5wcm90b2J1Zl91bml0dGVzdC5UZXN0RmllbGRPcmRlcmluZ3MYBSAB", - "KAU6SwoWcGFja2VkX2ludDMyX2V4dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zGFogAygFQgIQATpLChZwYWNrZWRf", + "OnMKInJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZV9leHRlbnNpb24SJC5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgxIAMoCzIhLnByb3Rv", + "YnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlOngKIXJlcGVhdGVkX2ltcG9y", + "dF9tZXNzYWdlX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxFeHRlbnNpb25zGDIgAygLMicucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0", + "LkltcG9ydE1lc3NhZ2U6eAoecmVwZWF0ZWRfbmVzdGVkX2VudW1fZXh0ZW5z", + "aW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYMyAD", + "KA4yKi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkRW51", + "bTptCh9yZXBlYXRlZF9mb3JlaWduX2VudW1fZXh0ZW5zaW9uEiQucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYNCADKA4yHi5wcm90b2J1", + "Zl91bml0dGVzdC5Gb3JlaWduRW51bTpyCh5yZXBlYXRlZF9pbXBvcnRfZW51", + "bV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", + "aW9ucxg1IAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRF", + "bnVtOlEKH3JlcGVhdGVkX3N0cmluZ19waWVjZV9leHRlbnNpb24SJC5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg2IAMoCUICCAI6SQoX", + "cmVwZWF0ZWRfY29yZF9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5U", + "ZXN0QWxsRXh0ZW5zaW9ucxg3IAMoCUICCAE6gAEKH3JlcGVhdGVkX2xhenlf", + "bWVzc2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxs", + "RXh0ZW5zaW9ucxg5IAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxU", + "eXBlcy5OZXN0ZWRNZXNzYWdlQgIoATpJChdkZWZhdWx0X2ludDMyX2V4dGVu", + "c2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGD0g", + "ASgFOgI0MTpJChdkZWZhdWx0X2ludDY0X2V4dGVuc2lvbhIkLnByb3RvYnVm", + "X3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGD4gASgDOgI0MjpKChhkZWZh", + "dWx0X3VpbnQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0", + "QWxsRXh0ZW5zaW9ucxg/IAEoDToCNDM6SgoYZGVmYXVsdF91aW50NjRfZXh0", + "ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMY", + "QCABKAQ6AjQ0OksKGGRlZmF1bHRfc2ludDMyX2V4dGVuc2lvbhIkLnByb3Rv", + "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEEgASgROgMtNDU6SgoY", + "ZGVmYXVsdF9zaW50NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3Qu", + "VGVzdEFsbEV4dGVuc2lvbnMYQiABKBI6AjQ2OksKGWRlZmF1bHRfZml4ZWQz", + "Ml9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", + "aW9ucxhDIAEoBzoCNDc6SwoZZGVmYXVsdF9maXhlZDY0X2V4dGVuc2lvbhIk", + "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEQgASgGOgI0", + "ODpMChpkZWZhdWx0X3NmaXhlZDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3Vu", + "aXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEUgASgPOgI0OTpNChpkZWZhdWx0", + "X3NmaXhlZDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxFeHRlbnNpb25zGEYgASgQOgMtNTA6SwoXZGVmYXVsdF9mbG9hdF9leHRl", + "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhH", + "IAEoAjoENTEuNTpNChhkZWZhdWx0X2RvdWJsZV9leHRlbnNpb24SJC5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhIIAEoAToFNTIwMDA6", + "SgoWZGVmYXVsdF9ib29sX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3RBbGxFeHRlbnNpb25zGEkgASgIOgR0cnVlOk0KGGRlZmF1bHRfc3Ry", + "aW5nX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRl", + "bnNpb25zGEogASgJOgVoZWxsbzpMChdkZWZhdWx0X2J5dGVzX2V4dGVuc2lv", + "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEsgASgM", + "OgV3b3JsZDp8Ch1kZWZhdWx0X25lc3RlZF9lbnVtX2V4dGVuc2lvbhIkLnBy", + "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGFEgASgOMioucHJv", + "dG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW06A0JBUjp5", + "Ch5kZWZhdWx0X2ZvcmVpZ25fZW51bV9leHRlbnNpb24SJC5wcm90b2J1Zl91", + "bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhSIAEoDjIeLnByb3RvYnVmX3Vu", + "aXR0ZXN0LkZvcmVpZ25FbnVtOgtGT1JFSUdOX0JBUjp9Ch1kZWZhdWx0X2lt", + "cG9ydF9lbnVtX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxFeHRlbnNpb25zGFMgASgOMiQucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0", + "LkltcG9ydEVudW06CklNUE9SVF9CQVI6VQoeZGVmYXVsdF9zdHJpbmdfcGll", + "Y2VfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", + "c2lvbnMYVCABKAk6A2FiY0ICCAI6TQoWZGVmYXVsdF9jb3JkX2V4dGVuc2lv", + "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGFUgASgJ", + "OgMxMjNCAggBOkQKFm9uZW9mX3VpbnQzMl9leHRlbnNpb24SJC5wcm90b2J1", + "Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhvIAEoDTp7Ch5vbmVvZl9u", + "ZXN0ZWRfbWVzc2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5U", + "ZXN0QWxsRXh0ZW5zaW9ucxhwIAEoCzItLnByb3RvYnVmX3VuaXR0ZXN0LlRl", + "c3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlOkQKFm9uZW9mX3N0cmluZ19leHRl", + "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhx", + "IAEoCTpDChVvbmVvZl9ieXRlc19leHRlbnNpb24SJC5wcm90b2J1Zl91bml0", + "dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhyIAEoDDpCChNteV9leHRlbnNpb25f", + "c3RyaW5nEiUucHJvdG9idWZfdW5pdHRlc3QuVGVzdEZpZWxkT3JkZXJpbmdz", + "GDIgASgJOj8KEG15X2V4dGVuc2lvbl9pbnQSJS5wcm90b2J1Zl91bml0dGVz", + "dC5UZXN0RmllbGRPcmRlcmluZ3MYBSABKAU6SwoWcGFja2VkX2ludDMyX2V4", + "dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNp", + "b25zGFogAygFQgIQATpLChZwYWNrZWRfaW50NjRfZXh0ZW5zaW9uEicucHJv", + "dG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYWyADKANCAhAB", + "OkwKF3BhY2tlZF91aW50MzJfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYXCADKA1CAhABOkwKF3BhY2tlZF91", "aW50NjRfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tl", - "ZEV4dGVuc2lvbnMYWyADKANCAhABOkwKF3BhY2tlZF91aW50MzJfZXh0ZW5z", + "ZEV4dGVuc2lvbnMYXSADKARCAhABOkwKF3BhY2tlZF9zaW50MzJfZXh0ZW5z", "aW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMY", - "XCADKA1CAhABOkwKF3BhY2tlZF91aW50NjRfZXh0ZW5zaW9uEicucHJvdG9i", - "dWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYXSADKARCAhABOkwK", - "F3BhY2tlZF9zaW50MzJfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdFBhY2tlZEV4dGVuc2lvbnMYXiADKBFCAhABOkwKF3BhY2tlZF9zaW50", - "NjRfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4", - "dGVuc2lvbnMYXyADKBJCAhABOk0KGHBhY2tlZF9maXhlZDMyX2V4dGVuc2lv", - "bhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zGGAg", - "AygHQgIQATpNChhwYWNrZWRfZml4ZWQ2NF9leHRlbnNpb24SJy5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9ucxhhIAMoBkICEAE6TgoZ", - "cGFja2VkX3NmaXhlZDMyX2V4dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RQYWNrZWRFeHRlbnNpb25zGGIgAygPQgIQATpOChlwYWNrZWRfc2Zp", - "eGVkNjRfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tl", - "ZEV4dGVuc2lvbnMYYyADKBBCAhABOksKFnBhY2tlZF9mbG9hdF9leHRlbnNp", - "b24SJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9ucxhk", - "IAMoAkICEAE6TAoXcGFja2VkX2RvdWJsZV9leHRlbnNpb24SJy5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9ucxhlIAMoAUICEAE6SgoV", - "cGFja2VkX2Jvb2xfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dFBhY2tlZEV4dGVuc2lvbnMYZiADKAhCAhABOmoKFXBhY2tlZF9lbnVtX2V4", - "dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNp", - "b25zGGcgAygOMh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1CAhAB", - "Ok8KGHVucGFja2VkX2ludDMyX2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYWiADKAVCAhAAOk8KGHVucGFj", - "a2VkX2ludDY0X2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RV", - "bnBhY2tlZEV4dGVuc2lvbnMYWyADKANCAhAAOlAKGXVucGFja2VkX3VpbnQz", - "Ml9leHRlbnNpb24SKS5wcm90b2J1Zl91bml0dGVzdC5UZXN0VW5wYWNrZWRF", - "eHRlbnNpb25zGFwgAygNQgIQADpQChl1bnBhY2tlZF91aW50NjRfZXh0ZW5z", + "XiADKBFCAhABOkwKF3BhY2tlZF9zaW50NjRfZXh0ZW5zaW9uEicucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYXyADKBJCAhABOk0K", + "GHBhY2tlZF9maXhlZDMyX2V4dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3RQYWNrZWRFeHRlbnNpb25zGGAgAygHQgIQATpNChhwYWNrZWRfZml4", + "ZWQ2NF9leHRlbnNpb24SJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2Vk", + "RXh0ZW5zaW9ucxhhIAMoBkICEAE6TgoZcGFja2VkX3NmaXhlZDMyX2V4dGVu", + "c2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25z", + "GGIgAygPQgIQATpOChlwYWNrZWRfc2ZpeGVkNjRfZXh0ZW5zaW9uEicucHJv", + "dG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYYyADKBBCAhAB", + "OksKFnBhY2tlZF9mbG9hdF9leHRlbnNpb24SJy5wcm90b2J1Zl91bml0dGVz", + "dC5UZXN0UGFja2VkRXh0ZW5zaW9ucxhkIAMoAkICEAE6TAoXcGFja2VkX2Rv", + "dWJsZV9leHRlbnNpb24SJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2Vk", + "RXh0ZW5zaW9ucxhlIAMoAUICEAE6SgoVcGFja2VkX2Jvb2xfZXh0ZW5zaW9u", + "EicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYZiAD", + "KAhCAhABOmoKFXBhY2tlZF9lbnVtX2V4dGVuc2lvbhInLnByb3RvYnVmX3Vu", + "aXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zGGcgAygOMh4ucHJvdG9idWZf", + "dW5pdHRlc3QuRm9yZWlnbkVudW1CAhABOk8KGHVucGFja2VkX2ludDMyX2V4", + "dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVu", + "c2lvbnMYWiADKAVCAhAAOk8KGHVucGFja2VkX2ludDY0X2V4dGVuc2lvbhIp", + "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYWyAD", + "KANCAhAAOlAKGXVucGFja2VkX3VpbnQzMl9leHRlbnNpb24SKS5wcm90b2J1", + "Zl91bml0dGVzdC5UZXN0VW5wYWNrZWRFeHRlbnNpb25zGFwgAygNQgIQADpQ", + "Chl1bnBhY2tlZF91aW50NjRfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhdIAMoBEICEAA6UAoZdW5wYWNr", + "ZWRfc2ludDMyX2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RV", + "bnBhY2tlZEV4dGVuc2lvbnMYXiADKBFCAhAAOlAKGXVucGFja2VkX3NpbnQ2", + "NF9leHRlbnNpb24SKS5wcm90b2J1Zl91bml0dGVzdC5UZXN0VW5wYWNrZWRF", + "eHRlbnNpb25zGF8gAygSQgIQADpRChp1bnBhY2tlZF9maXhlZDMyX2V4dGVu", + "c2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lv", + "bnMYYCADKAdCAhAAOlEKGnVucGFja2VkX2ZpeGVkNjRfZXh0ZW5zaW9uEiku", + "cHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhhIAMo", + "BkICEAA6UgobdW5wYWNrZWRfc2ZpeGVkMzJfZXh0ZW5zaW9uEikucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhiIAMoD0ICEAA6", + "UgobdW5wYWNrZWRfc2ZpeGVkNjRfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5p", + "dHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhjIAMoEEICEAA6TwoYdW5w", + "YWNrZWRfZmxvYXRfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVz", + "dFVucGFja2VkRXh0ZW5zaW9ucxhkIAMoAkICEAA6UAoZdW5wYWNrZWRfZG91", + "YmxlX2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tl", + "ZEV4dGVuc2lvbnMYZSADKAFCAhAAOk4KF3VucGFja2VkX2Jvb2xfZXh0ZW5z", "aW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9u", - "cxhdIAMoBEICEAA6UAoZdW5wYWNrZWRfc2ludDMyX2V4dGVuc2lvbhIpLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYXiADKBFC", - "AhAAOlAKGXVucGFja2VkX3NpbnQ2NF9leHRlbnNpb24SKS5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0VW5wYWNrZWRFeHRlbnNpb25zGF8gAygSQgIQADpRChp1", - "bnBhY2tlZF9maXhlZDMyX2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYYCADKAdCAhAAOlEKGnVucGFja2Vk", - "X2ZpeGVkNjRfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVzdFVu", - "cGFja2VkRXh0ZW5zaW9ucxhhIAMoBkICEAA6UgobdW5wYWNrZWRfc2ZpeGVk", - "MzJfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2Vk", - "RXh0ZW5zaW9ucxhiIAMoD0ICEAA6UgobdW5wYWNrZWRfc2ZpeGVkNjRfZXh0", - "ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5z", - "aW9ucxhjIAMoEEICEAA6TwoYdW5wYWNrZWRfZmxvYXRfZXh0ZW5zaW9uEiku", - "cHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhkIAMo", - "AkICEAA6UAoZdW5wYWNrZWRfZG91YmxlX2V4dGVuc2lvbhIpLnByb3RvYnVm", - "X3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYZSADKAFCAhAAOk4K", - "F3VucGFja2VkX2Jvb2xfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdFVucGFja2VkRXh0ZW5zaW9ucxhmIAMoCEICEAA6bgoXdW5wYWNrZWRf", - "ZW51bV9leHRlbnNpb24SKS5wcm90b2J1Zl91bml0dGVzdC5UZXN0VW5wYWNr", - "ZWRFeHRlbnNpb25zGGcgAygOMh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWln", - "bkVudW1CAhAAQkFCDVVuaXR0ZXN0UHJvdG9IAYABAYgBAZABAfgBAaoCIUdv", - "b2dsZS5Qcm90b2NvbEJ1ZmZlcnMuVGVzdFByb3Rvcw==")); + "cxhmIAMoCEICEAA6bgoXdW5wYWNrZWRfZW51bV9leHRlbnNpb24SKS5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0VW5wYWNrZWRFeHRlbnNpb25zGGcgAygOMh4u", + "cHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1CAhAAQkFCDVVuaXR0ZXN0", + "UHJvdG9IAYABAYgBAZABAfgBAaoCIUdvb2dsZS5Qcm90b2NvbEJ1ZmZlcnMu", + "VGVzdFByb3Rvcw==")); pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { descriptor = root; internal__static_protobuf_unittest_TestAllTypes__Descriptor = Descriptor.MessageTypes[0]; internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestAllTypes__Descriptor, - new string[] { "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalGroup", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalImportMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalImportEnum", "OptionalStringPiece", "OptionalCord", "OptionalPublicImportMessage", "OptionalLazyMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedGroup", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedStringPiece", "RepeatedCord", "RepeatedLazyMessage", "DefaultInt32", "DefaultInt64", "DefaultUint32", "DefaultUint64", "DefaultSint32", "DefaultSint64", "DefaultFixed32", "DefaultFixed64", "DefaultSfixed32", "DefaultSfixed64", "DefaultFloat", "DefaultDouble", "DefaultBool", "DefaultString", "DefaultBytes", "DefaultNestedEnum", "DefaultForeignEnum", "DefaultImportEnum", "DefaultStringPiece", "DefaultCord", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", }); + new string[] { "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalGroup", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalImportMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalImportEnum", "OptionalStringPiece", "OptionalCord", "OptionalPublicImportMessage", "OptionalLazyMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedGroup", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedStringPiece", "RepeatedCord", "RepeatedLazyMessage", "DefaultInt32", "DefaultInt64", "DefaultUint32", "DefaultUint64", "DefaultSint32", "DefaultSint64", "DefaultFixed32", "DefaultFixed64", "DefaultSfixed32", "DefaultSfixed64", "DefaultFloat", "DefaultDouble", "DefaultBool", "DefaultString", "DefaultBytes", "DefaultNestedEnum", "DefaultForeignEnum", "DefaultImportEnum", "DefaultStringPiece", "DefaultCord", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofField", }); internal__static_protobuf_unittest_TestAllTypes_NestedMessage__Descriptor = internal__static_protobuf_unittest_TestAllTypes__Descriptor.NestedTypes[0]; internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestAllTypes_NestedMessage__Descriptor, @@ -1000,7 +1005,7 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_NestedTestAllTypes__Descriptor = Descriptor.MessageTypes[1]; internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_NestedTestAllTypes__Descriptor, - new string[] { "Child", "Payload", }); + new string[] { "Child", "Payload", "RepeatedChild", }); internal__static_protobuf_unittest_TestDeprecatedFields__Descriptor = Descriptor.MessageTypes[2]; internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDeprecatedFields__Descriptor, @@ -1009,67 +1014,71 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_ForeignMessage__Descriptor, new string[] { "C", }); - internal__static_protobuf_unittest_TestAllExtensions__Descriptor = Descriptor.MessageTypes[4]; + internal__static_protobuf_unittest_TestReservedFields__Descriptor = Descriptor.MessageTypes[4]; + internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestReservedFields__Descriptor, + new string[] { }); + internal__static_protobuf_unittest_TestAllExtensions__Descriptor = Descriptor.MessageTypes[5]; internal__static_protobuf_unittest_TestAllExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestAllExtensions__Descriptor, new string[] { }); - internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor = Descriptor.MessageTypes[5]; + internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor = Descriptor.MessageTypes[6]; internal__static_protobuf_unittest_OptionalGroup_extension__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor, new string[] { "A", }); - internal__static_protobuf_unittest_RepeatedGroup_extension__Descriptor = Descriptor.MessageTypes[6]; + internal__static_protobuf_unittest_RepeatedGroup_extension__Descriptor = Descriptor.MessageTypes[7]; internal__static_protobuf_unittest_RepeatedGroup_extension__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_RepeatedGroup_extension__Descriptor, new string[] { "A", }); - internal__static_protobuf_unittest_TestNestedExtension__Descriptor = Descriptor.MessageTypes[7]; + internal__static_protobuf_unittest_TestNestedExtension__Descriptor = Descriptor.MessageTypes[8]; internal__static_protobuf_unittest_TestNestedExtension__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestNestedExtension__Descriptor, new string[] { }); global::Google.ProtocolBuffers.TestProtos.TestNestedExtension.Test = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestNestedExtension.Descriptor.Extensions[0]); global::Google.ProtocolBuffers.TestProtos.TestNestedExtension.NestedStringExtension = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestNestedExtension.Descriptor.Extensions[1]); - internal__static_protobuf_unittest_TestRequired__Descriptor = Descriptor.MessageTypes[8]; + internal__static_protobuf_unittest_TestRequired__Descriptor = Descriptor.MessageTypes[9]; internal__static_protobuf_unittest_TestRequired__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRequired__Descriptor, new string[] { "A", "Dummy2", "B", "Dummy4", "Dummy5", "Dummy6", "Dummy7", "Dummy8", "Dummy9", "Dummy10", "Dummy11", "Dummy12", "Dummy13", "Dummy14", "Dummy15", "Dummy16", "Dummy17", "Dummy18", "Dummy19", "Dummy20", "Dummy21", "Dummy22", "Dummy23", "Dummy24", "Dummy25", "Dummy26", "Dummy27", "Dummy28", "Dummy29", "Dummy30", "Dummy31", "Dummy32", "C", }); global::Google.ProtocolBuffers.TestProtos.TestRequired.Single = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestRequired.Descriptor.Extensions[0]); global::Google.ProtocolBuffers.TestProtos.TestRequired.Multi = pb::GeneratedRepeatExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestRequired.Descriptor.Extensions[1]); - internal__static_protobuf_unittest_TestRequiredForeign__Descriptor = Descriptor.MessageTypes[9]; + internal__static_protobuf_unittest_TestRequiredForeign__Descriptor = Descriptor.MessageTypes[10]; internal__static_protobuf_unittest_TestRequiredForeign__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRequiredForeign__Descriptor, new string[] { "OptionalMessage", "RepeatedMessage", "Dummy", }); - internal__static_protobuf_unittest_TestForeignNested__Descriptor = Descriptor.MessageTypes[10]; + internal__static_protobuf_unittest_TestForeignNested__Descriptor = Descriptor.MessageTypes[11]; internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestForeignNested__Descriptor, new string[] { "ForeignNested", }); - internal__static_protobuf_unittest_TestEmptyMessage__Descriptor = Descriptor.MessageTypes[11]; + internal__static_protobuf_unittest_TestEmptyMessage__Descriptor = Descriptor.MessageTypes[12]; internal__static_protobuf_unittest_TestEmptyMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestEmptyMessage__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestEmptyMessageWithExtensions__Descriptor = Descriptor.MessageTypes[12]; + internal__static_protobuf_unittest_TestEmptyMessageWithExtensions__Descriptor = Descriptor.MessageTypes[13]; internal__static_protobuf_unittest_TestEmptyMessageWithExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestEmptyMessageWithExtensions__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestMultipleExtensionRanges__Descriptor = Descriptor.MessageTypes[13]; + internal__static_protobuf_unittest_TestMultipleExtensionRanges__Descriptor = Descriptor.MessageTypes[14]; internal__static_protobuf_unittest_TestMultipleExtensionRanges__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestMultipleExtensionRanges__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor = Descriptor.MessageTypes[14]; + internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor = Descriptor.MessageTypes[15]; internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor, new string[] { "A", "Bb", }); - internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor = Descriptor.MessageTypes[15]; + internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor = Descriptor.MessageTypes[16]; internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor, new string[] { "A", "I", }); - internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor = Descriptor.MessageTypes[16]; + internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor = Descriptor.MessageTypes[17]; internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor, new string[] { "Bb", }); - internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor = Descriptor.MessageTypes[17]; + internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor = Descriptor.MessageTypes[18]; internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor, new string[] { "A", "OptionalInt32", }); - internal__static_protobuf_unittest_TestDupFieldNumber__Descriptor = Descriptor.MessageTypes[18]; + internal__static_protobuf_unittest_TestDupFieldNumber__Descriptor = Descriptor.MessageTypes[19]; internal__static_protobuf_unittest_TestDupFieldNumber__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDupFieldNumber__Descriptor, new string[] { "A", "Foo", "Bar", }); @@ -1081,15 +1090,15 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestDupFieldNumber_Bar__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDupFieldNumber_Bar__Descriptor, new string[] { "A", }); - internal__static_protobuf_unittest_TestEagerMessage__Descriptor = Descriptor.MessageTypes[19]; + internal__static_protobuf_unittest_TestEagerMessage__Descriptor = Descriptor.MessageTypes[20]; internal__static_protobuf_unittest_TestEagerMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestEagerMessage__Descriptor, new string[] { "SubMessage", }); - internal__static_protobuf_unittest_TestLazyMessage__Descriptor = Descriptor.MessageTypes[20]; + internal__static_protobuf_unittest_TestLazyMessage__Descriptor = Descriptor.MessageTypes[21]; internal__static_protobuf_unittest_TestLazyMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestLazyMessage__Descriptor, new string[] { "SubMessage", }); - internal__static_protobuf_unittest_TestNestedMessageHasBits__Descriptor = Descriptor.MessageTypes[21]; + internal__static_protobuf_unittest_TestNestedMessageHasBits__Descriptor = Descriptor.MessageTypes[22]; internal__static_protobuf_unittest_TestNestedMessageHasBits__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestNestedMessageHasBits__Descriptor, new string[] { "OptionalNestedMessage", }); @@ -1097,11 +1106,11 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestNestedMessageHasBits_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestNestedMessageHasBits_NestedMessage__Descriptor, new string[] { "NestedmessageRepeatedInt32", "NestedmessageRepeatedForeignmessage", }); - internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor = Descriptor.MessageTypes[22]; + internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor = Descriptor.MessageTypes[23]; internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor, new string[] { "PrimitiveField", "StringField", "EnumField", "MessageField", "StringPieceField", "CordField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField", "RepeatedStringPieceField", "RepeatedCordField", }); - internal__static_protobuf_unittest_TestFieldOrderings__Descriptor = Descriptor.MessageTypes[23]; + internal__static_protobuf_unittest_TestFieldOrderings__Descriptor = Descriptor.MessageTypes[24]; internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestFieldOrderings__Descriptor, new string[] { "MyString", "MyInt", "MyFloat", "OptionalNestedMessage", }); @@ -1109,59 +1118,59 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__Descriptor, new string[] { "Oo", "Bb", }); - internal__static_protobuf_unittest_TestExtremeDefaultValues__Descriptor = Descriptor.MessageTypes[24]; + internal__static_protobuf_unittest_TestExtremeDefaultValues__Descriptor = Descriptor.MessageTypes[25]; internal__static_protobuf_unittest_TestExtremeDefaultValues__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestExtremeDefaultValues__Descriptor, new string[] { "EscapedBytes", "LargeUint32", "LargeUint64", "SmallInt32", "SmallInt64", "ReallySmallInt32", "ReallySmallInt64", "Utf8String", "ZeroFloat", "OneFloat", "SmallFloat", "NegativeOneFloat", "NegativeFloat", "LargeFloat", "SmallNegativeFloat", "InfDouble", "NegInfDouble", "NanDouble", "InfFloat", "NegInfFloat", "NanFloat", "CppTrigraph", "StringWithZero", "BytesWithZero", "StringPieceWithZero", "CordWithZero", "ReplacementString", }); - internal__static_protobuf_unittest_SparseEnumMessage__Descriptor = Descriptor.MessageTypes[25]; + internal__static_protobuf_unittest_SparseEnumMessage__Descriptor = Descriptor.MessageTypes[26]; internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_SparseEnumMessage__Descriptor, new string[] { "SparseEnum", }); - internal__static_protobuf_unittest_OneString__Descriptor = Descriptor.MessageTypes[26]; + internal__static_protobuf_unittest_OneString__Descriptor = Descriptor.MessageTypes[27]; internal__static_protobuf_unittest_OneString__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_OneString__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_MoreString__Descriptor = Descriptor.MessageTypes[27]; + internal__static_protobuf_unittest_MoreString__Descriptor = Descriptor.MessageTypes[28]; internal__static_protobuf_unittest_MoreString__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_MoreString__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_OneBytes__Descriptor = Descriptor.MessageTypes[28]; + internal__static_protobuf_unittest_OneBytes__Descriptor = Descriptor.MessageTypes[29]; internal__static_protobuf_unittest_OneBytes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_OneBytes__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_MoreBytes__Descriptor = Descriptor.MessageTypes[29]; + internal__static_protobuf_unittest_MoreBytes__Descriptor = Descriptor.MessageTypes[30]; internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_MoreBytes__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_Int32Message__Descriptor = Descriptor.MessageTypes[30]; + internal__static_protobuf_unittest_Int32Message__Descriptor = Descriptor.MessageTypes[31]; internal__static_protobuf_unittest_Int32Message__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_Int32Message__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_Uint32Message__Descriptor = Descriptor.MessageTypes[31]; + internal__static_protobuf_unittest_Uint32Message__Descriptor = Descriptor.MessageTypes[32]; internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_Uint32Message__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_Int64Message__Descriptor = Descriptor.MessageTypes[32]; + internal__static_protobuf_unittest_Int64Message__Descriptor = Descriptor.MessageTypes[33]; internal__static_protobuf_unittest_Int64Message__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_Int64Message__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_Uint64Message__Descriptor = Descriptor.MessageTypes[33]; + internal__static_protobuf_unittest_Uint64Message__Descriptor = Descriptor.MessageTypes[34]; internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_Uint64Message__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_BoolMessage__Descriptor = Descriptor.MessageTypes[34]; + internal__static_protobuf_unittest_BoolMessage__Descriptor = Descriptor.MessageTypes[35]; internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_BoolMessage__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_TestOneof__Descriptor = Descriptor.MessageTypes[35]; + internal__static_protobuf_unittest_TestOneof__Descriptor = Descriptor.MessageTypes[36]; internal__static_protobuf_unittest_TestOneof__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof__Descriptor, - new string[] { "FooInt", "FooString", "FooMessage", "FooGroup", }); + new string[] { "FooInt", "FooString", "FooMessage", "FooGroup", "Foo", }); internal__static_protobuf_unittest_TestOneof_FooGroup__Descriptor = internal__static_protobuf_unittest_TestOneof__Descriptor.NestedTypes[0]; internal__static_protobuf_unittest_TestOneof_FooGroup__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof_FooGroup__Descriptor, new string[] { "A", "B", }); - internal__static_protobuf_unittest_TestOneofBackwardsCompatible__Descriptor = Descriptor.MessageTypes[36]; + internal__static_protobuf_unittest_TestOneofBackwardsCompatible__Descriptor = Descriptor.MessageTypes[37]; internal__static_protobuf_unittest_TestOneofBackwardsCompatible__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneofBackwardsCompatible__Descriptor, new string[] { "FooInt", "FooString", "FooMessage", "FooGroup", }); @@ -1169,10 +1178,10 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestOneofBackwardsCompatible_FooGroup__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneofBackwardsCompatible_FooGroup__Descriptor, new string[] { "A", "B", }); - internal__static_protobuf_unittest_TestOneof2__Descriptor = Descriptor.MessageTypes[37]; + internal__static_protobuf_unittest_TestOneof2__Descriptor = Descriptor.MessageTypes[38]; internal__static_protobuf_unittest_TestOneof2__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof2__Descriptor, - new string[] { "FooInt", "FooString", "FooCord", "FooStringPiece", "FooBytes", "FooEnum", "FooMessage", "FooGroup", "FooLazyMessage", "BarInt", "BarString", "BarCord", "BarStringPiece", "BarBytes", "BarEnum", "BazInt", "BazString", }); + new string[] { "FooInt", "FooString", "FooCord", "FooStringPiece", "FooBytes", "FooEnum", "FooMessage", "FooGroup", "FooLazyMessage", "BarInt", "BarString", "BarCord", "BarStringPiece", "BarBytes", "BarEnum", "BazInt", "BazString", "Foo", "Bar", }); internal__static_protobuf_unittest_TestOneof2_FooGroup__Descriptor = internal__static_protobuf_unittest_TestOneof2__Descriptor.NestedTypes[0]; internal__static_protobuf_unittest_TestOneof2_FooGroup__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof2_FooGroup__Descriptor, @@ -1181,31 +1190,31 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestOneof2_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof2_NestedMessage__Descriptor, new string[] { "QuxInt", "CorgeInt", }); - internal__static_protobuf_unittest_TestRequiredOneof__Descriptor = Descriptor.MessageTypes[38]; + internal__static_protobuf_unittest_TestRequiredOneof__Descriptor = Descriptor.MessageTypes[39]; internal__static_protobuf_unittest_TestRequiredOneof__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRequiredOneof__Descriptor, - new string[] { "FooInt", "FooString", "FooMessage", }); + new string[] { "FooInt", "FooString", "FooMessage", "Foo", }); internal__static_protobuf_unittest_TestRequiredOneof_NestedMessage__Descriptor = internal__static_protobuf_unittest_TestRequiredOneof__Descriptor.NestedTypes[0]; internal__static_protobuf_unittest_TestRequiredOneof_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRequiredOneof_NestedMessage__Descriptor, new string[] { "RequiredDouble", }); - internal__static_protobuf_unittest_TestPackedTypes__Descriptor = Descriptor.MessageTypes[39]; + internal__static_protobuf_unittest_TestPackedTypes__Descriptor = Descriptor.MessageTypes[40]; internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestPackedTypes__Descriptor, new string[] { "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum", }); - internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor = Descriptor.MessageTypes[40]; + internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor = Descriptor.MessageTypes[41]; internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor, new string[] { "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum", }); - internal__static_protobuf_unittest_TestPackedExtensions__Descriptor = Descriptor.MessageTypes[41]; + internal__static_protobuf_unittest_TestPackedExtensions__Descriptor = Descriptor.MessageTypes[42]; internal__static_protobuf_unittest_TestPackedExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestPackedExtensions__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestUnpackedExtensions__Descriptor = Descriptor.MessageTypes[42]; + internal__static_protobuf_unittest_TestUnpackedExtensions__Descriptor = Descriptor.MessageTypes[43]; internal__static_protobuf_unittest_TestUnpackedExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestUnpackedExtensions__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestDynamicExtensions__Descriptor = Descriptor.MessageTypes[43]; + internal__static_protobuf_unittest_TestDynamicExtensions__Descriptor = Descriptor.MessageTypes[44]; internal__static_protobuf_unittest_TestDynamicExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDynamicExtensions__Descriptor, new string[] { "ScalarExtension", "EnumExtension", "DynamicEnumExtension", "MessageExtension", "DynamicMessageExtension", "RepeatedExtension", "PackedExtension", }); @@ -1213,11 +1222,11 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestDynamicExtensions_DynamicMessageType__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDynamicExtensions_DynamicMessageType__Descriptor, new string[] { "DynamicField", }); - internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor = Descriptor.MessageTypes[44]; + internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor = Descriptor.MessageTypes[45]; internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor, new string[] { "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64", }); - internal__static_protobuf_unittest_TestParsingMerge__Descriptor = Descriptor.MessageTypes[45]; + internal__static_protobuf_unittest_TestParsingMerge__Descriptor = Descriptor.MessageTypes[46]; internal__static_protobuf_unittest_TestParsingMerge__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestParsingMerge__Descriptor, new string[] { "RequiredAllTypes", "OptionalAllTypes", "RepeatedAllTypes", "OptionalGroup", "RepeatedGroup", }); @@ -1243,31 +1252,31 @@ namespace Google.ProtocolBuffers.TestProtos { new string[] { "RepeatedGroupAllTypes", }); global::Google.ProtocolBuffers.TestProtos.TestParsingMerge.OptionalExt = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestParsingMerge.Descriptor.Extensions[0]); global::Google.ProtocolBuffers.TestProtos.TestParsingMerge.RepeatedExt = pb::GeneratedRepeatExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestParsingMerge.Descriptor.Extensions[1]); - internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor = Descriptor.MessageTypes[46]; + internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor = Descriptor.MessageTypes[47]; internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor, new string[] { "A", }); - internal__static_protobuf_unittest_FooRequest__Descriptor = Descriptor.MessageTypes[47]; + internal__static_protobuf_unittest_FooRequest__Descriptor = Descriptor.MessageTypes[48]; internal__static_protobuf_unittest_FooRequest__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_FooRequest__Descriptor, new string[] { }); - internal__static_protobuf_unittest_FooResponse__Descriptor = Descriptor.MessageTypes[48]; + internal__static_protobuf_unittest_FooResponse__Descriptor = Descriptor.MessageTypes[49]; internal__static_protobuf_unittest_FooResponse__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_FooResponse__Descriptor, new string[] { }); - internal__static_protobuf_unittest_FooClientMessage__Descriptor = Descriptor.MessageTypes[49]; + internal__static_protobuf_unittest_FooClientMessage__Descriptor = Descriptor.MessageTypes[50]; internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_FooClientMessage__Descriptor, new string[] { }); - internal__static_protobuf_unittest_FooServerMessage__Descriptor = Descriptor.MessageTypes[50]; + internal__static_protobuf_unittest_FooServerMessage__Descriptor = Descriptor.MessageTypes[51]; internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_FooServerMessage__Descriptor, new string[] { }); - internal__static_protobuf_unittest_BarRequest__Descriptor = Descriptor.MessageTypes[51]; + internal__static_protobuf_unittest_BarRequest__Descriptor = Descriptor.MessageTypes[52]; internal__static_protobuf_unittest_BarRequest__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_BarRequest__Descriptor, new string[] { }); - internal__static_protobuf_unittest_BarResponse__Descriptor = Descriptor.MessageTypes[52]; + internal__static_protobuf_unittest_BarResponse__Descriptor = Descriptor.MessageTypes[53]; internal__static_protobuf_unittest_BarResponse__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_BarResponse__Descriptor, new string[] { }); @@ -2281,6 +2290,19 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object oneofField_; + public enum OneofFieldOneofCase { + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofBytes = 114, + None = 0, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + public const int OptionalInt32FieldNumber = 1; private bool hasOptionalInt32; private int optionalInt32_; @@ -3042,43 +3064,35 @@ namespace Google.ProtocolBuffers.TestProtos { } public const int OneofUint32FieldNumber = 111; - private bool hasOneofUint32; - private uint oneofUint32_; public bool HasOneofUint32 { - get { return hasOneofUint32; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } } public uint OneofUint32 { - get { return oneofUint32_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } } public const int OneofNestedMessageFieldNumber = 112; - private bool hasOneofNestedMessage; - private global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage oneofNestedMessage_; public bool HasOneofNestedMessage { - get { return hasOneofNestedMessage; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { - get { return oneofNestedMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage) oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } } public const int OneofStringFieldNumber = 113; - private bool hasOneofString; - private string oneofString_ = ""; public bool HasOneofString { - get { return hasOneofString; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; } } public string OneofString { - get { return oneofString_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } } public const int OneofBytesFieldNumber = 114; - private bool hasOneofBytes; - private pb::ByteString oneofBytes_ = pb::ByteString.Empty; public bool HasOneofBytes { - get { return hasOneofBytes; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } } public pb::ByteString OneofBytes { - get { return oneofBytes_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } } public override bool IsInitialized { @@ -3303,16 +3317,16 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasDefaultCord) { output.WriteString(85, field_names[2], DefaultCord); } - if (hasOneofUint32) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { output.WriteUInt32(111, field_names[23], OneofUint32); } - if (hasOneofNestedMessage) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { output.WriteMessage(112, field_names[21], OneofNestedMessage); } - if (hasOneofString) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { output.WriteString(113, field_names[22], OneofString); } - if (hasOneofBytes) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { output.WriteBytes(114, field_names[20], OneofBytes); } UnknownFields.WriteTo(output); @@ -3637,16 +3651,16 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasDefaultCord) { size += pb::CodedOutputStream.ComputeStringSize(85, DefaultCord); } - if (hasOneofUint32) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { size += pb::CodedOutputStream.ComputeUInt32Size(111, OneofUint32); } - if (hasOneofNestedMessage) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { size += pb::CodedOutputStream.ComputeMessageSize(112, OneofNestedMessage); } - if (hasOneofString) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { size += pb::CodedOutputStream.ComputeStringSize(113, OneofString); } - if (hasOneofBytes) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { size += pb::CodedOutputStream.ComputeBytesSize(114, OneofBytes); } size += UnknownFields.SerializedSize; @@ -4009,17 +4023,24 @@ namespace Google.ProtocolBuffers.TestProtos { if (other.HasDefaultCord) { DefaultCord = other.DefaultCord; } - if (other.HasOneofUint32) { - OneofUint32 = other.OneofUint32; - } - if (other.HasOneofNestedMessage) { - MergeOneofNestedMessage(other.OneofNestedMessage); - } - if (other.HasOneofString) { - OneofString = other.OneofString; - } - if (other.HasOneofBytes) { - OneofBytes = other.OneofBytes; + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: { + SetOneofUint32(other.OneofUint32); + break; + } + case OneofFieldOneofCase.OneofNestedMessage: { + MergeOneofNestedMessage(other.OneofNestedMessage); + break; + } + case OneofFieldOneofCase.OneofString: { + SetOneofString(other.OneofString); + break; + } + case OneofFieldOneofCase.OneofBytes: { + SetOneofBytes(other.OneofBytes); + break; + } + case OneofFieldOneofCase.None: { break; } } this.MergeUnknownFields(other.UnknownFields); return this; @@ -4470,24 +4491,37 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 888: { - result.hasOneofUint32 = input.ReadUInt32(ref result.oneofUint32_); + uint value = 0; + if (input.ReadUInt32(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } break; } case 898: { global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.CreateBuilder(); - if (result.hasOneofNestedMessage) { + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { subBuilder.MergeFrom(OneofNestedMessage); } input.ReadMessage(subBuilder, extensionRegistry); - OneofNestedMessage = subBuilder.BuildPartial(); + result.oneofField_ = subBuilder.BuildPartial(); + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; break; } case 906: { - result.hasOneofString = input.ReadString(ref result.oneofString_); + string value = ""; + if (input.ReadString(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } break; } case 914: { - result.hasOneofBytes = input.ReadBytes(ref result.oneofBytes_); + pb::ByteString value = pb::ByteString.Empty; + if (input.ReadBytes(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } break; } } @@ -6377,104 +6411,119 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofUint32 { - get { return result.hasOneofUint32; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } } public uint OneofUint32 { - get { return result.OneofUint32; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) result.oneofField_ : 0; } set { SetOneofUint32(value); } } public Builder SetOneofUint32(uint value) { PrepareBuilder(); - result.hasOneofUint32 = true; - result.oneofUint32_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; return this; } public Builder ClearOneofUint32() { PrepareBuilder(); - result.hasOneofUint32 = false; - result.oneofUint32_ = 0; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } return this; } public bool HasOneofNestedMessage { - get { return result.hasOneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { - get { return result.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } set { SetOneofNestedMessage(value); } } public Builder SetOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofNestedMessage = true; - result.oneofNestedMessage_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; + result.oneofField_ = value; return this; } public Builder SetOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasOneofNestedMessage = true; - result.oneofNestedMessage_ = builderForValue.Build(); + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; + result.oneofField_ = builderForValue.Build(); return this; } public Builder MergeOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasOneofNestedMessage && - result.oneofNestedMessage_ != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance) { - result.oneofNestedMessage_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.CreateBuilder(result.oneofNestedMessage_).MergeFrom(value).BuildPartial(); + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage && + result.OneofNestedMessage != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance) { + result.oneofField_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.CreateBuilder(result.OneofNestedMessage).MergeFrom(value).BuildPartial(); } else { - result.oneofNestedMessage_ = value; + result.oneofField_ = value; } - result.hasOneofNestedMessage = true; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; return this; } public Builder ClearOneofNestedMessage() { - PrepareBuilder(); - result.hasOneofNestedMessage = false; - result.oneofNestedMessage_ = null; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + PrepareBuilder(); + result.oneofFieldCase_ = OneofFieldOneofCase.None; + result.oneofField_ = null; + } return this; } public bool HasOneofString { - get { return result.hasOneofString; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofString; } } public string OneofString { - get { return result.OneofString; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) result.oneofField_ : ""; } set { SetOneofString(value); } } public Builder SetOneofString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofString = true; - result.oneofString_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofString; return this; } public Builder ClearOneofString() { PrepareBuilder(); - result.hasOneofString = false; - result.oneofString_ = ""; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } return this; } public bool HasOneofBytes { - get { return result.hasOneofBytes; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } } public pb::ByteString OneofBytes { - get { return result.OneofBytes; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) result.oneofField_ : pb::ByteString.Empty; } set { SetOneofBytes(value); } } public Builder SetOneofBytes(pb::ByteString value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofBytes = true; - result.oneofBytes_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; return this; } public Builder ClearOneofBytes() { PrepareBuilder(); - result.hasOneofBytes = false; - result.oneofBytes_ = pb::ByteString.Empty; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } + return this; + } + + public OneofFieldOneofCase OneofFieldCase { + get { return result.oneofFieldCase_; } + } + public Builder ClearOneofField() { + PrepareBuilder(); + result.oneofField_ = null; + result.oneofFieldCase_ = OneofFieldOneofCase.None; return this; } } @@ -6487,8 +6536,8 @@ namespace Google.ProtocolBuffers.TestProtos { public sealed partial class NestedTestAllTypes : pb::GeneratedMessage { private NestedTestAllTypes() { } private static readonly NestedTestAllTypes defaultInstance = new NestedTestAllTypes().MakeReadOnly(); - private static readonly string[] _nestedTestAllTypesFieldNames = new string[] { "child", "payload" }; - private static readonly uint[] _nestedTestAllTypesFieldTags = new uint[] { 10, 18 }; + private static readonly string[] _nestedTestAllTypesFieldNames = new string[] { "child", "payload", "repeated_child" }; + private static readonly uint[] _nestedTestAllTypesFieldTags = new uint[] { 10, 18, 26 }; public static NestedTestAllTypes DefaultInstance { get { return defaultInstance; } } @@ -6529,6 +6578,18 @@ namespace Google.ProtocolBuffers.TestProtos { get { return payload_ ?? global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } } + public const int RepeatedChildFieldNumber = 3; + private pbc::PopsicleList repeatedChild_ = new pbc::PopsicleList(); + public scg::IList RepeatedChildList { + get { return repeatedChild_; } + } + public int RepeatedChildCount { + get { return repeatedChild_.Count; } + } + public global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes GetRepeatedChild(int index) { + return repeatedChild_[index]; + } + public override bool IsInitialized { get { return true; @@ -6544,6 +6605,9 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasPayload) { output.WriteMessage(2, field_names[1], Payload); } + if (repeatedChild_.Count > 0) { + output.WriteMessageArray(3, field_names[2], repeatedChild_); + } UnknownFields.WriteTo(output); } @@ -6567,6 +6631,9 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasPayload) { size += pb::CodedOutputStream.ComputeMessageSize(2, Payload); } + foreach (global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes element in RepeatedChildList) { + size += pb::CodedOutputStream.ComputeMessageSize(3, element); + } size += UnknownFields.SerializedSize; memoizedSerializedSize = size; return size; @@ -6602,6 +6669,7 @@ namespace Google.ProtocolBuffers.TestProtos { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } private NestedTestAllTypes MakeReadOnly() { + repeatedChild_.MakeReadOnly(); return this; } @@ -6695,6 +6763,9 @@ namespace Google.ProtocolBuffers.TestProtos { if (other.HasPayload) { MergePayload(other.Payload); } + if (other.repeatedChild_.Count != 0) { + result.repeatedChild_.Add(other.repeatedChild_); + } this.MergeUnknownFields(other.UnknownFields); return this; } @@ -6756,6 +6827,10 @@ namespace Google.ProtocolBuffers.TestProtos { Payload = subBuilder.BuildPartial(); break; } + case 26: { + input.ReadMessageArray(tag, field_name, result.repeatedChild_, global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes.DefaultInstance, extensionRegistry); + break; + } } } @@ -6845,6 +6920,50 @@ namespace Google.ProtocolBuffers.TestProtos { result.payload_ = null; return this; } + + public pbc::IPopsicleList RepeatedChildList { + get { return PrepareBuilder().repeatedChild_; } + } + public int RepeatedChildCount { + get { return result.RepeatedChildCount; } + } + public global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes GetRepeatedChild(int index) { + return result.GetRepeatedChild(index); + } + public Builder SetRepeatedChild(int index, global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.repeatedChild_[index] = value; + return this; + } + public Builder SetRepeatedChild(int index, global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.repeatedChild_[index] = builderForValue.Build(); + return this; + } + public Builder AddRepeatedChild(global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.repeatedChild_.Add(value); + return this; + } + public Builder AddRepeatedChild(global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.repeatedChild_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeRepeatedChild(scg::IEnumerable values) { + PrepareBuilder(); + result.repeatedChild_.Add(values); + return this; + } + public Builder ClearRepeatedChild() { + PrepareBuilder(); + result.repeatedChild_.Clear(); + return this; + } } static NestedTestAllTypes() { object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); @@ -7408,43 +7527,40 @@ namespace Google.ProtocolBuffers.TestProtos { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class TestAllExtensions : pb::ExtendableMessage { - private TestAllExtensions() { } - private static readonly TestAllExtensions defaultInstance = new TestAllExtensions().MakeReadOnly(); - private static readonly string[] _testAllExtensionsFieldNames = new string[] { }; - private static readonly uint[] _testAllExtensionsFieldTags = new uint[] { }; - public static TestAllExtensions DefaultInstance { + public sealed partial class TestReservedFields : pb::GeneratedMessage { + private TestReservedFields() { } + private static readonly TestReservedFields defaultInstance = new TestReservedFields().MakeReadOnly(); + private static readonly string[] _testReservedFieldsFieldNames = new string[] { }; + private static readonly uint[] _testReservedFieldsFieldTags = new uint[] { }; + public static TestReservedFields DefaultInstance { get { return defaultInstance; } } - public override TestAllExtensions DefaultInstanceForType { + public override TestReservedFields DefaultInstanceForType { get { return DefaultInstance; } } - protected override TestAllExtensions ThisMessage { + protected override TestReservedFields ThisMessage { get { return this; } } public static pbd::MessageDescriptor Descriptor { - get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestAllExtensions__Descriptor; } + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestReservedFields__Descriptor; } } - protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { - get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestAllExtensions__FieldAccessorTable; } + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable; } } public override bool IsInitialized { get { - if (!ExtensionsAreInitialized) return false; return true; } } public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); - string[] field_names = _testAllExtensionsFieldNames; - pb::ExtendableMessage.ExtensionWriter extensionWriter = CreateExtensionWriter(this); - extensionWriter.WriteUntil(536870912, output); + string[] field_names = _testReservedFieldsFieldNames; UnknownFields.WriteTo(output); } @@ -7462,54 +7578,53 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - size += ExtensionsSerializedSize; size += UnknownFields.SerializedSize; memoizedSerializedSize = size; return size; } - public static TestAllExtensions ParseFrom(pb::ByteString data) { + public static TestReservedFields ParseFrom(pb::ByteString data) { return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); } - public static TestAllExtensions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); } - public static TestAllExtensions ParseFrom(byte[] data) { + public static TestReservedFields ParseFrom(byte[] data) { return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); } - public static TestAllExtensions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); } - public static TestAllExtensions ParseFrom(global::System.IO.Stream input) { + public static TestReservedFields ParseFrom(global::System.IO.Stream input) { return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); } - public static TestAllExtensions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } - public static TestAllExtensions ParseDelimitedFrom(global::System.IO.Stream input) { + public static TestReservedFields ParseDelimitedFrom(global::System.IO.Stream input) { return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); } - public static TestAllExtensions ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); } - public static TestAllExtensions ParseFrom(pb::ICodedInputStream input) { + public static TestReservedFields ParseFrom(pb::ICodedInputStream input) { return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); } - public static TestAllExtensions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } - private TestAllExtensions MakeReadOnly() { + private TestReservedFields MakeReadOnly() { return this; } public static Builder CreateBuilder() { return new Builder(); } public override Builder ToBuilder() { return CreateBuilder(this); } public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(TestAllExtensions prototype) { + public static Builder CreateBuilder(TestReservedFields prototype) { return new Builder(prototype); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::ExtendableBuilder { + public sealed partial class Builder : pb::GeneratedBuilder { protected override Builder ThisBuilder { get { return this; } } @@ -7517,18 +7632,18 @@ namespace Google.ProtocolBuffers.TestProtos { result = DefaultInstance; resultIsReadOnly = true; } - internal Builder(TestAllExtensions cloneFrom) { + internal Builder(TestReservedFields cloneFrom) { result = cloneFrom; resultIsReadOnly = true; } private bool resultIsReadOnly; - private TestAllExtensions result; + private TestReservedFields result; - private TestAllExtensions PrepareBuilder() { + private TestReservedFields PrepareBuilder() { if (resultIsReadOnly) { - TestAllExtensions original = result; - result = new TestAllExtensions(); + TestReservedFields original = result; + result = new TestReservedFields(); resultIsReadOnly = false; MergeFrom(original); } @@ -7539,7 +7654,7 @@ namespace Google.ProtocolBuffers.TestProtos { get { return result.IsInitialized; } } - protected override TestAllExtensions MessageBeingBuilt { + protected override TestReservedFields MessageBeingBuilt { get { return PrepareBuilder(); } } @@ -7558,14 +7673,14 @@ namespace Google.ProtocolBuffers.TestProtos { } public override pbd::MessageDescriptor DescriptorForType { - get { return global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.Descriptor; } + get { return global::Google.ProtocolBuffers.TestProtos.TestReservedFields.Descriptor; } } - public override TestAllExtensions DefaultInstanceForType { - get { return global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.DefaultInstance; } + public override TestReservedFields DefaultInstanceForType { + get { return global::Google.ProtocolBuffers.TestProtos.TestReservedFields.DefaultInstance; } } - public override TestAllExtensions BuildPartial() { + public override TestReservedFields BuildPartial() { if (resultIsReadOnly) { return result; } @@ -7574,18 +7689,17 @@ namespace Google.ProtocolBuffers.TestProtos { } public override Builder MergeFrom(pb::IMessage other) { - if (other is TestAllExtensions) { - return MergeFrom((TestAllExtensions) other); + if (other is TestReservedFields) { + return MergeFrom((TestReservedFields) other); } else { base.MergeFrom(other); return this; } } - public override Builder MergeFrom(TestAllExtensions other) { - if (other == global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.DefaultInstance) return this; + public override Builder MergeFrom(TestReservedFields other) { + if (other == global::Google.ProtocolBuffers.TestProtos.TestReservedFields.DefaultInstance) return this; PrepareBuilder(); - this.MergeExtensionFields(other); this.MergeUnknownFields(other.UnknownFields); return this; } @@ -7601,9 +7715,9 @@ namespace Google.ProtocolBuffers.TestProtos { string field_name; while (input.ReadTag(out tag, out field_name)) { if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_testAllExtensionsFieldNames, field_name, global::System.StringComparer.Ordinal); + int field_ordinal = global::System.Array.BinarySearch(_testReservedFieldsFieldNames, field_name, global::System.StringComparer.Ordinal); if(field_ordinal >= 0) - tag = _testAllExtensionsFieldTags[field_ordinal]; + tag = _testReservedFieldsFieldTags[field_ordinal]; else { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -7639,59 +7753,49 @@ namespace Google.ProtocolBuffers.TestProtos { } } - static TestAllExtensions() { + static TestReservedFields() { object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class OptionalGroup_extension : pb::GeneratedMessage { - private OptionalGroup_extension() { } - private static readonly OptionalGroup_extension defaultInstance = new OptionalGroup_extension().MakeReadOnly(); - private static readonly string[] _optionalGroupExtensionFieldNames = new string[] { "a" }; - private static readonly uint[] _optionalGroupExtensionFieldTags = new uint[] { 136 }; - public static OptionalGroup_extension DefaultInstance { + public sealed partial class TestAllExtensions : pb::ExtendableMessage { + private TestAllExtensions() { } + private static readonly TestAllExtensions defaultInstance = new TestAllExtensions().MakeReadOnly(); + private static readonly string[] _testAllExtensionsFieldNames = new string[] { }; + private static readonly uint[] _testAllExtensionsFieldTags = new uint[] { }; + public static TestAllExtensions DefaultInstance { get { return defaultInstance; } } - public override OptionalGroup_extension DefaultInstanceForType { + public override TestAllExtensions DefaultInstanceForType { get { return DefaultInstance; } } - protected override OptionalGroup_extension ThisMessage { + protected override TestAllExtensions ThisMessage { get { return this; } } public static pbd::MessageDescriptor Descriptor { - get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor; } - } - - protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { - get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_OptionalGroup_extension__FieldAccessorTable; } + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestAllExtensions__Descriptor; } } - public const int AFieldNumber = 17; - private bool hasA; - private int a_; - public bool HasA { - get { return hasA; } - } - public int A { - get { return a_; } + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestAllExtensions__FieldAccessorTable; } } public override bool IsInitialized { get { + if (!ExtensionsAreInitialized) return false; return true; } } public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); - string[] field_names = _optionalGroupExtensionFieldNames; - if (hasA) { - output.WriteInt32(17, field_names[0], A); - } + string[] field_names = _testAllExtensionsFieldNames; + pb::ExtendableMessage.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + extensionWriter.WriteUntil(536870912, output); UnknownFields.WriteTo(output); } @@ -7709,56 +7813,54 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - if (hasA) { - size += pb::CodedOutputStream.ComputeInt32Size(17, A); - } + size += ExtensionsSerializedSize; size += UnknownFields.SerializedSize; memoizedSerializedSize = size; return size; } - public static OptionalGroup_extension ParseFrom(pb::ByteString data) { + public static TestAllExtensions ParseFrom(pb::ByteString data) { return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(byte[] data) { + public static TestAllExtensions ParseFrom(byte[] data) { return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(global::System.IO.Stream input) { + public static TestAllExtensions ParseFrom(global::System.IO.Stream input) { return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } - public static OptionalGroup_extension ParseDelimitedFrom(global::System.IO.Stream input) { + public static TestAllExtensions ParseDelimitedFrom(global::System.IO.Stream input) { return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); } - public static OptionalGroup_extension ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(pb::ICodedInputStream input) { + public static TestAllExtensions ParseFrom(pb::ICodedInputStream input) { return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } - private OptionalGroup_extension MakeReadOnly() { + private TestAllExtensions MakeReadOnly() { return this; } public static Builder CreateBuilder() { return new Builder(); } public override Builder ToBuilder() { return CreateBuilder(this); } public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(OptionalGroup_extension prototype) { + public static Builder CreateBuilder(TestAllExtensions prototype) { return new Builder(prototype); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder { + public sealed partial class Builder : pb::ExtendableBuilder { protected override Builder ThisBuilder { get { return this; } } @@ -7766,18 +7868,18 @@ namespace Google.ProtocolBuffers.TestProtos { result = DefaultInstance; resultIsReadOnly = true; } - internal Builder(OptionalGroup_extension cloneFrom) { + internal Builder(TestAllExtensions cloneFrom) { result = cloneFrom; resultIsReadOnly = true; } private bool resultIsReadOnly; - private OptionalGroup_extension result; + private TestAllExtensions result; - private OptionalGroup_extension PrepareBuilder() { + private TestAllExtensions PrepareBuilder() { if (resultIsReadOnly) { - OptionalGroup_extension original = result; - result = new OptionalGroup_extension(); + TestAllExtensions original = result; + result = new TestAllExtensions(); resultIsReadOnly = false; MergeFrom(original); } @@ -7788,7 +7890,7 @@ namespace Google.ProtocolBuffers.TestProtos { get { return result.IsInitialized; } } - protected override OptionalGroup_extension MessageBeingBuilt { + protected override TestAllExtensions MessageBeingBuilt { get { return PrepareBuilder(); } } @@ -7807,14 +7909,14 @@ namespace Google.ProtocolBuffers.TestProtos { } public override pbd::MessageDescriptor DescriptorForType { - get { return global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.Descriptor; } + get { return global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.Descriptor; } } - public override OptionalGroup_extension DefaultInstanceForType { - get { return global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.DefaultInstance; } + public override TestAllExtensions DefaultInstanceForType { + get { return global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.DefaultInstance; } } - public override OptionalGroup_extension BuildPartial() { + public override TestAllExtensions BuildPartial() { if (resultIsReadOnly) { return result; } @@ -7823,20 +7925,18 @@ namespace Google.ProtocolBuffers.TestProtos { } public override Builder MergeFrom(pb::IMessage other) { - if (other is OptionalGroup_extension) { - return MergeFrom((OptionalGroup_extension) other); + if (other is TestAllExtensions) { + return MergeFrom((TestAllExtensions) other); } else { base.MergeFrom(other); return this; } } - public override Builder MergeFrom(OptionalGroup_extension other) { - if (other == global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.DefaultInstance) return this; + public override Builder MergeFrom(TestAllExtensions other) { + if (other == global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.DefaultInstance) return this; PrepareBuilder(); - if (other.HasA) { - A = other.A; - } + this.MergeExtensionFields(other); this.MergeUnknownFields(other.UnknownFields); return this; } @@ -7852,9 +7952,9 @@ namespace Google.ProtocolBuffers.TestProtos { string field_name; while (input.ReadTag(out tag, out field_name)) { if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_optionalGroupExtensionFieldNames, field_name, global::System.StringComparer.Ordinal); + int field_ordinal = global::System.Array.BinarySearch(_testAllExtensionsFieldNames, field_name, global::System.StringComparer.Ordinal); if(field_ordinal >= 0) - tag = _optionalGroupExtensionFieldTags[field_ordinal]; + tag = _testAllExtensionsFieldTags[field_ordinal]; else { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -7880,10 +7980,6 @@ namespace Google.ProtocolBuffers.TestProtos { ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); break; } - case 136: { - result.hasA = input.ReadInt32(ref result.a_); - break; - } } } @@ -7893,39 +7989,294 @@ namespace Google.ProtocolBuffers.TestProtos { return this; } - - public bool HasA { - get { return result.hasA; } - } - public int A { - get { return result.A; } - set { SetA(value); } - } - public Builder SetA(int value) { - PrepareBuilder(); - result.hasA = true; - result.a_ = value; - return this; - } - public Builder ClearA() { - PrepareBuilder(); - result.hasA = false; - result.a_ = 0; - return this; - } } - static OptionalGroup_extension() { + static TestAllExtensions() { object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class RepeatedGroup_extension : pb::GeneratedMessage { - private RepeatedGroup_extension() { } - private static readonly RepeatedGroup_extension defaultInstance = new RepeatedGroup_extension().MakeReadOnly(); - private static readonly string[] _repeatedGroupExtensionFieldNames = new string[] { "a" }; - private static readonly uint[] _repeatedGroupExtensionFieldTags = new uint[] { 376 }; - public static RepeatedGroup_extension DefaultInstance { + public sealed partial class OptionalGroup_extension : pb::GeneratedMessage { + private OptionalGroup_extension() { } + private static readonly OptionalGroup_extension defaultInstance = new OptionalGroup_extension().MakeReadOnly(); + private static readonly string[] _optionalGroupExtensionFieldNames = new string[] { "a" }; + private static readonly uint[] _optionalGroupExtensionFieldTags = new uint[] { 136 }; + public static OptionalGroup_extension DefaultInstance { + get { return defaultInstance; } + } + + public override OptionalGroup_extension DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override OptionalGroup_extension ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_OptionalGroup_extension__FieldAccessorTable; } + } + + public const int AFieldNumber = 17; + private bool hasA; + private int a_; + public bool HasA { + get { return hasA; } + } + public int A { + get { return a_; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _optionalGroupExtensionFieldNames; + if (hasA) { + output.WriteInt32(17, field_names[0], A); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasA) { + size += pb::CodedOutputStream.ComputeInt32Size(17, A); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static OptionalGroup_extension ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static OptionalGroup_extension ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static OptionalGroup_extension ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private OptionalGroup_extension MakeReadOnly() { + return this; + } + + public static Builder CreateBuilder() { return new Builder(); } + public override Builder ToBuilder() { return CreateBuilder(this); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(OptionalGroup_extension prototype) { + return new Builder(prototype); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class Builder : pb::GeneratedBuilder { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() { + result = DefaultInstance; + resultIsReadOnly = true; + } + internal Builder(OptionalGroup_extension cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private OptionalGroup_extension result; + + private OptionalGroup_extension PrepareBuilder() { + if (resultIsReadOnly) { + OptionalGroup_extension original = result; + result = new OptionalGroup_extension(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override OptionalGroup_extension MessageBeingBuilt { + get { return PrepareBuilder(); } + } + + public override Builder Clear() { + result = DefaultInstance; + resultIsReadOnly = true; + return this; + } + + public override Builder Clone() { + if (resultIsReadOnly) { + return new Builder(result); + } else { + return new Builder().MergeFrom(result); + } + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.Descriptor; } + } + + public override OptionalGroup_extension DefaultInstanceForType { + get { return global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.DefaultInstance; } + } + + public override OptionalGroup_extension BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is OptionalGroup_extension) { + return MergeFrom((OptionalGroup_extension) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(OptionalGroup_extension other) { + if (other == global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.DefaultInstance) return this; + PrepareBuilder(); + if (other.HasA) { + A = other.A; + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::ICodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + PrepareBuilder(); + pb::UnknownFieldSet.Builder unknownFields = null; + uint tag; + string field_name; + while (input.ReadTag(out tag, out field_name)) { + if(tag == 0 && field_name != null) { + int field_ordinal = global::System.Array.BinarySearch(_optionalGroupExtensionFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _optionalGroupExtensionFieldTags[field_ordinal]; + else { + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + continue; + } + } + switch (tag) { + case 0: { + throw pb::InvalidProtocolBufferException.InvalidTag(); + } + default: { + if (pb::WireFormat.IsEndGroupTag(tag)) { + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + break; + } + case 136: { + result.hasA = input.ReadInt32(ref result.a_); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public bool HasA { + get { return result.hasA; } + } + public int A { + get { return result.A; } + set { SetA(value); } + } + public Builder SetA(int value) { + PrepareBuilder(); + result.hasA = true; + result.a_ = value; + return this; + } + public Builder ClearA() { + PrepareBuilder(); + result.hasA = false; + result.a_ = 0; + return this; + } + } + static OptionalGroup_extension() { + object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class RepeatedGroup_extension : pb::GeneratedMessage { + private RepeatedGroup_extension() { } + private static readonly RepeatedGroup_extension defaultInstance = new RepeatedGroup_extension().MakeReadOnly(); + private static readonly string[] _repeatedGroupExtensionFieldNames = new string[] { "a" }; + private static readonly uint[] _repeatedGroupExtensionFieldTags = new uint[] { 376 }; + public static RepeatedGroup_extension DefaultInstance { get { return defaultInstance; } } @@ -21288,44 +21639,49 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object foo_; + public enum FooOneofCase { + FooInt = 1, + FooString = 2, + FooMessage = 3, + FooGroup = 4, + None = 0, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + public FooOneofCase FooCase { + get { return fooCase_; } + } + public const int FooIntFieldNumber = 1; - private bool hasFooInt; - private int fooInt_; public bool HasFooInt { - get { return hasFooInt; } + get { return fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return fooInt_; } + get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } } public const int FooStringFieldNumber = 2; - private bool hasFooString; - private string fooString_ = ""; public bool HasFooString { - get { return hasFooString; } + get { return fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return fooString_; } + get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } } public const int FooMessageFieldNumber = 3; - private bool hasFooMessage; - private global::Google.ProtocolBuffers.TestProtos.TestAllTypes fooMessage_; public bool HasFooMessage { - get { return hasFooMessage; } + get { return fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes FooMessage { - get { return fooMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes) foo_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } } public const int FooGroupFieldNumber = 4; - private bool hasFooGroup; - private global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup fooGroup_; public bool HasFooGroup { - get { return hasFooGroup; } + get { return fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup FooGroup { - get { return fooGroup_ ?? global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } } public override bool IsInitialized { @@ -21337,16 +21693,16 @@ namespace Google.ProtocolBuffers.TestProtos { public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); string[] field_names = _testOneofFieldNames; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { output.WriteInt32(1, field_names[0], FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { output.WriteString(2, field_names[2], FooString); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { output.WriteMessage(3, field_names[1], FooMessage); } - if (hasFooGroup) { + if (fooCase_ == FooOneofCase.FooGroup) { output.WriteGroup(4, field_names[3], FooGroup); } UnknownFields.WriteTo(output); @@ -21366,16 +21722,16 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { size += pb::CodedOutputStream.ComputeInt32Size(1, FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { size += pb::CodedOutputStream.ComputeStringSize(2, FooString); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { size += pb::CodedOutputStream.ComputeMessageSize(3, FooMessage); } - if (hasFooGroup) { + if (fooCase_ == FooOneofCase.FooGroup) { size += pb::CodedOutputStream.ComputeGroupSize(4, FooGroup); } size += UnknownFields.SerializedSize; @@ -21500,17 +21856,24 @@ namespace Google.ProtocolBuffers.TestProtos { public override Builder MergeFrom(TestOneof other) { if (other == global::Google.ProtocolBuffers.TestProtos.TestOneof.DefaultInstance) return this; PrepareBuilder(); - if (other.HasFooInt) { - FooInt = other.FooInt; - } - if (other.HasFooString) { - FooString = other.FooString; - } - if (other.HasFooMessage) { - MergeFooMessage(other.FooMessage); - } - if (other.HasFooGroup) { - MergeFooGroup(other.FooGroup); + switch (other.FooCase) { + case FooOneofCase.FooInt: { + SetFooInt(other.FooInt); + break; + } + case FooOneofCase.FooString: { + SetFooString(other.FooString); + break; + } + case FooOneofCase.FooMessage: { + MergeFooMessage(other.FooMessage); + break; + } + case FooOneofCase.FooGroup: { + MergeFooGroup(other.FooGroup); + break; + } + case FooOneofCase.None: { break; } } this.MergeUnknownFields(other.UnknownFields); return this; @@ -21556,29 +21919,39 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 8: { - result.hasFooInt = input.ReadInt32(ref result.fooInt_); + int value = 0; + if (input.ReadInt32(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; + } break; } case 18: { - result.hasFooString = input.ReadString(ref result.fooString_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; + } break; } case 26: { global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.CreateBuilder(); - if (result.hasFooMessage) { + if (result.fooCase_ == FooOneofCase.FooMessage) { subBuilder.MergeFrom(FooMessage); } input.ReadMessage(subBuilder, extensionRegistry); - FooMessage = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooMessage; break; } case 35: { global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.CreateBuilder(); - if (result.hasFooGroup) { + if (result.fooCase_ == FooOneofCase.FooGroup) { subBuilder.MergeFrom(FooGroup); } input.ReadGroup(4, subBuilder, extensionRegistry); - FooGroup = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooGroup; break; } } @@ -21592,123 +21965,139 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasFooInt { - get { return result.hasFooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return result.FooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt ? (int) result.foo_ : 0; } set { SetFooInt(value); } } public Builder SetFooInt(int value) { PrepareBuilder(); - result.hasFooInt = true; - result.fooInt_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; return this; } public Builder ClearFooInt() { PrepareBuilder(); - result.hasFooInt = false; - result.fooInt_ = 0; + if (result.fooCase_ == FooOneofCase.FooInt) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooString { - get { return result.hasFooString; } + get { return result.fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return result.FooString; } + get { return result.fooCase_ == FooOneofCase.FooString ? (string) result.foo_ : ""; } set { SetFooString(value); } } public Builder SetFooString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooString = true; - result.fooString_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; return this; } public Builder ClearFooString() { PrepareBuilder(); - result.hasFooString = false; - result.fooString_ = ""; + if (result.fooCase_ == FooOneofCase.FooString) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooMessage { - get { return result.hasFooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes FooMessage { - get { return result.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } set { SetFooMessage(value); } } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = value; + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = value; return this; } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooMessage && - result.fooMessage_ != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance) { - result.fooMessage_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.CreateBuilder(result.fooMessage_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooMessage && + result.FooMessage != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.CreateBuilder(result.FooMessage).MergeFrom(value).BuildPartial(); } else { - result.fooMessage_ = value; + result.foo_ = value; } - result.hasFooMessage = true; + result.fooCase_ = FooOneofCase.FooMessage; return this; } public Builder ClearFooMessage() { - PrepareBuilder(); - result.hasFooMessage = false; - result.fooMessage_ = null; + if (result.fooCase_ == FooOneofCase.FooMessage) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } return this; } public bool HasFooGroup { - get { return result.hasFooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup FooGroup { - get { return result.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } set { SetFooGroup(value); } } public Builder SetFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup value) { pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasFooGroup = true; - result.fooGroup_ = value; + PrepareBuilder(); + result.fooCase_ = FooOneofCase.FooGroup; + result.foo_ = value; return this; } public Builder SetFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooGroup = true; - result.fooGroup_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooGroup; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooGroup && - result.fooGroup_ != global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance) { - result.fooGroup_ = global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.CreateBuilder(result.fooGroup_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooGroup && + result.FooGroup != global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.CreateBuilder(result.FooGroup).MergeFrom(value).BuildPartial(); } else { - result.fooGroup_ = value; + result.foo_ = value; } - result.hasFooGroup = true; + result.fooCase_ = FooOneofCase.FooGroup; return this; } public Builder ClearFooGroup() { + if (result.fooCase_ == FooOneofCase.FooGroup) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } + return this; + } + + public FooOneofCase FooCase { + get { return result.fooCase_; } + } + public Builder ClearFoo() { PrepareBuilder(); - result.hasFooGroup = false; - result.fooGroup_ = null; + result.foo_ = null; + result.fooCase_ = FooOneofCase.None; return this; } } @@ -23191,154 +23580,157 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object foo_; + public enum FooOneofCase { + FooInt = 1, + FooString = 2, + FooCord = 3, + FooStringPiece = 4, + FooBytes = 5, + FooEnum = 6, + FooMessage = 7, + FooGroup = 8, + FooLazyMessage = 11, + None = 0, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + public FooOneofCase FooCase { + get { return fooCase_; } + } + + private object bar_; + public enum BarOneofCase { + BarInt = 12, + BarString = 13, + BarCord = 14, + BarStringPiece = 15, + BarBytes = 16, + BarEnum = 17, + None = 0, + } + private BarOneofCase barCase_ = BarOneofCase.None; + public BarOneofCase BarCase { + get { return barCase_; } + } + public const int FooIntFieldNumber = 1; - private bool hasFooInt; - private int fooInt_; public bool HasFooInt { - get { return hasFooInt; } + get { return fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return fooInt_; } + get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } } public const int FooStringFieldNumber = 2; - private bool hasFooString; - private string fooString_ = ""; public bool HasFooString { - get { return hasFooString; } + get { return fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return fooString_; } + get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } } public const int FooCordFieldNumber = 3; - private bool hasFooCord; - private string fooCord_ = ""; public bool HasFooCord { - get { return hasFooCord; } + get { return fooCase_ == FooOneofCase.FooCord; } } public string FooCord { - get { return fooCord_; } + get { return fooCase_ == FooOneofCase.FooCord ? (string) foo_ : ""; } } public const int FooStringPieceFieldNumber = 4; - private bool hasFooStringPiece; - private string fooStringPiece_ = ""; public bool HasFooStringPiece { - get { return hasFooStringPiece; } + get { return fooCase_ == FooOneofCase.FooStringPiece; } } public string FooStringPiece { - get { return fooStringPiece_; } + get { return fooCase_ == FooOneofCase.FooStringPiece ? (string) foo_ : ""; } } public const int FooBytesFieldNumber = 5; - private bool hasFooBytes; - private pb::ByteString fooBytes_ = pb::ByteString.Empty; public bool HasFooBytes { - get { return hasFooBytes; } + get { return fooCase_ == FooOneofCase.FooBytes; } } public pb::ByteString FooBytes { - get { return fooBytes_; } + get { return fooCase_ == FooOneofCase.FooBytes ? (pb::ByteString) foo_ : pb::ByteString.Empty; } } public const int FooEnumFieldNumber = 6; - private bool hasFooEnum; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum fooEnum_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; public bool HasFooEnum { - get { return hasFooEnum; } + get { return fooCase_ == FooOneofCase.FooEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum FooEnum { - get { return fooEnum_; } + get { return fooCase_ == FooOneofCase.FooEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; } } public const int FooMessageFieldNumber = 7; - private bool hasFooMessage; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage fooMessage_; public bool HasFooMessage { - get { return hasFooMessage; } + get { return fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooMessage { - get { return fooMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } } public const int FooGroupFieldNumber = 8; - private bool hasFooGroup; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup fooGroup_; public bool HasFooGroup { - get { return hasFooGroup; } + get { return fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup FooGroup { - get { return fooGroup_ ?? global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } } public const int FooLazyMessageFieldNumber = 11; - private bool hasFooLazyMessage; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage fooLazyMessage_; public bool HasFooLazyMessage { - get { return hasFooLazyMessage; } + get { return fooCase_ == FooOneofCase.FooLazyMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooLazyMessage { - get { return fooLazyMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } } public const int BarIntFieldNumber = 12; - private bool hasBarInt; - private int barInt_ = 5; public bool HasBarInt { - get { return hasBarInt; } + get { return barCase_ == BarOneofCase.BarInt; } } public int BarInt { - get { return barInt_; } + get { return barCase_ == BarOneofCase.BarInt ? (int) bar_ : 5; } } public const int BarStringFieldNumber = 13; - private bool hasBarString; - private string barString_ = "STRING"; public bool HasBarString { - get { return hasBarString; } + get { return barCase_ == BarOneofCase.BarString; } } public string BarString { - get { return barString_; } + get { return barCase_ == BarOneofCase.BarString ? (string) bar_ : "STRING"; } } public const int BarCordFieldNumber = 14; - private bool hasBarCord; - private string barCord_ = "CORD"; public bool HasBarCord { - get { return hasBarCord; } + get { return barCase_ == BarOneofCase.BarCord; } } public string BarCord { - get { return barCord_; } + get { return barCase_ == BarOneofCase.BarCord ? (string) bar_ : "CORD"; } } public const int BarStringPieceFieldNumber = 15; - private bool hasBarStringPiece; - private string barStringPiece_ = "SPIECE"; public bool HasBarStringPiece { - get { return hasBarStringPiece; } + get { return barCase_ == BarOneofCase.BarStringPiece; } } public string BarStringPiece { - get { return barStringPiece_; } + get { return barCase_ == BarOneofCase.BarStringPiece ? (string) bar_ : "SPIECE"; } } public const int BarBytesFieldNumber = 16; - private bool hasBarBytes; - private pb::ByteString barBytes_ = (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; public bool HasBarBytes { - get { return hasBarBytes; } + get { return barCase_ == BarOneofCase.BarBytes; } } public pb::ByteString BarBytes { - get { return barBytes_; } + get { return barCase_ == BarOneofCase.BarBytes ? (pb::ByteString) bar_ : (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; } } public const int BarEnumFieldNumber = 17; - private bool hasBarEnum; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum barEnum_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; public bool HasBarEnum { - get { return hasBarEnum; } + get { return barCase_ == BarOneofCase.BarEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum BarEnum { - get { return barEnum_; } + get { return barCase_ == BarOneofCase.BarEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) bar_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; } } public const int BazIntFieldNumber = 18; @@ -23370,49 +23762,49 @@ namespace Google.ProtocolBuffers.TestProtos { public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); string[] field_names = _testOneof2FieldNames; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { output.WriteInt32(1, field_names[11], FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { output.WriteString(2, field_names[14], FooString); } - if (hasFooCord) { + if (fooCase_ == FooOneofCase.FooCord) { output.WriteString(3, field_names[9], FooCord); } - if (hasFooStringPiece) { + if (fooCase_ == FooOneofCase.FooStringPiece) { output.WriteString(4, field_names[15], FooStringPiece); } - if (hasFooBytes) { + if (fooCase_ == FooOneofCase.FooBytes) { output.WriteBytes(5, field_names[8], FooBytes); } - if (hasFooEnum) { + if (fooCase_ == FooOneofCase.FooEnum) { output.WriteEnum(6, field_names[10], (int) FooEnum, FooEnum); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { output.WriteMessage(7, field_names[13], FooMessage); } - if (hasFooGroup) { + if (fooCase_ == FooOneofCase.FooGroup) { output.WriteGroup(8, field_names[16], FooGroup); } - if (hasFooLazyMessage) { + if (fooCase_ == FooOneofCase.FooLazyMessage) { output.WriteMessage(11, field_names[12], FooLazyMessage); } - if (hasBarInt) { + if (barCase_ == BarOneofCase.BarInt) { output.WriteInt32(12, field_names[3], BarInt); } - if (hasBarString) { + if (barCase_ == BarOneofCase.BarString) { output.WriteString(13, field_names[4], BarString); } - if (hasBarCord) { + if (barCase_ == BarOneofCase.BarCord) { output.WriteString(14, field_names[1], BarCord); } - if (hasBarStringPiece) { + if (barCase_ == BarOneofCase.BarStringPiece) { output.WriteString(15, field_names[5], BarStringPiece); } - if (hasBarBytes) { + if (barCase_ == BarOneofCase.BarBytes) { output.WriteBytes(16, field_names[0], BarBytes); } - if (hasBarEnum) { + if (barCase_ == BarOneofCase.BarEnum) { output.WriteEnum(17, field_names[2], (int) BarEnum, BarEnum); } if (hasBazInt) { @@ -23438,49 +23830,49 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { size += pb::CodedOutputStream.ComputeInt32Size(1, FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { size += pb::CodedOutputStream.ComputeStringSize(2, FooString); } - if (hasFooCord) { + if (fooCase_ == FooOneofCase.FooCord) { size += pb::CodedOutputStream.ComputeStringSize(3, FooCord); } - if (hasFooStringPiece) { + if (fooCase_ == FooOneofCase.FooStringPiece) { size += pb::CodedOutputStream.ComputeStringSize(4, FooStringPiece); } - if (hasFooBytes) { + if (fooCase_ == FooOneofCase.FooBytes) { size += pb::CodedOutputStream.ComputeBytesSize(5, FooBytes); } - if (hasFooEnum) { + if (fooCase_ == FooOneofCase.FooEnum) { size += pb::CodedOutputStream.ComputeEnumSize(6, (int) FooEnum); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { size += pb::CodedOutputStream.ComputeMessageSize(7, FooMessage); } - if (hasFooGroup) { + if (fooCase_ == FooOneofCase.FooGroup) { size += pb::CodedOutputStream.ComputeGroupSize(8, FooGroup); } - if (hasFooLazyMessage) { + if (fooCase_ == FooOneofCase.FooLazyMessage) { size += pb::CodedOutputStream.ComputeMessageSize(11, FooLazyMessage); } - if (hasBarInt) { + if (barCase_ == BarOneofCase.BarInt) { size += pb::CodedOutputStream.ComputeInt32Size(12, BarInt); } - if (hasBarString) { + if (barCase_ == BarOneofCase.BarString) { size += pb::CodedOutputStream.ComputeStringSize(13, BarString); } - if (hasBarCord) { + if (barCase_ == BarOneofCase.BarCord) { size += pb::CodedOutputStream.ComputeStringSize(14, BarCord); } - if (hasBarStringPiece) { + if (barCase_ == BarOneofCase.BarStringPiece) { size += pb::CodedOutputStream.ComputeStringSize(15, BarStringPiece); } - if (hasBarBytes) { + if (barCase_ == BarOneofCase.BarBytes) { size += pb::CodedOutputStream.ComputeBytesSize(16, BarBytes); } - if (hasBarEnum) { + if (barCase_ == BarOneofCase.BarEnum) { size += pb::CodedOutputStream.ComputeEnumSize(17, (int) BarEnum); } if (hasBazInt) { @@ -23611,57 +24003,78 @@ namespace Google.ProtocolBuffers.TestProtos { public override Builder MergeFrom(TestOneof2 other) { if (other == global::Google.ProtocolBuffers.TestProtos.TestOneof2.DefaultInstance) return this; PrepareBuilder(); - if (other.HasFooInt) { - FooInt = other.FooInt; - } - if (other.HasFooString) { - FooString = other.FooString; - } - if (other.HasFooCord) { - FooCord = other.FooCord; - } - if (other.HasFooStringPiece) { - FooStringPiece = other.FooStringPiece; - } - if (other.HasFooBytes) { - FooBytes = other.FooBytes; - } - if (other.HasFooEnum) { - FooEnum = other.FooEnum; - } - if (other.HasFooMessage) { - MergeFooMessage(other.FooMessage); - } - if (other.HasFooGroup) { - MergeFooGroup(other.FooGroup); - } - if (other.HasFooLazyMessage) { - MergeFooLazyMessage(other.FooLazyMessage); - } - if (other.HasBarInt) { - BarInt = other.BarInt; - } - if (other.HasBarString) { - BarString = other.BarString; - } - if (other.HasBarCord) { - BarCord = other.BarCord; - } - if (other.HasBarStringPiece) { - BarStringPiece = other.BarStringPiece; - } - if (other.HasBarBytes) { - BarBytes = other.BarBytes; - } - if (other.HasBarEnum) { - BarEnum = other.BarEnum; - } if (other.HasBazInt) { BazInt = other.BazInt; } if (other.HasBazString) { BazString = other.BazString; } + switch (other.FooCase) { + case FooOneofCase.FooInt: { + SetFooInt(other.FooInt); + break; + } + case FooOneofCase.FooString: { + SetFooString(other.FooString); + break; + } + case FooOneofCase.FooCord: { + SetFooCord(other.FooCord); + break; + } + case FooOneofCase.FooStringPiece: { + SetFooStringPiece(other.FooStringPiece); + break; + } + case FooOneofCase.FooBytes: { + SetFooBytes(other.FooBytes); + break; + } + case FooOneofCase.FooEnum: { + SetFooEnum(other.FooEnum); + break; + } + case FooOneofCase.FooMessage: { + MergeFooMessage(other.FooMessage); + break; + } + case FooOneofCase.FooGroup: { + MergeFooGroup(other.FooGroup); + break; + } + case FooOneofCase.FooLazyMessage: { + MergeFooLazyMessage(other.FooLazyMessage); + break; + } + case FooOneofCase.None: { break; } + } + switch (other.BarCase) { + case BarOneofCase.BarInt: { + SetBarInt(other.BarInt); + break; + } + case BarOneofCase.BarString: { + SetBarString(other.BarString); + break; + } + case BarOneofCase.BarCord: { + SetBarCord(other.BarCord); + break; + } + case BarOneofCase.BarStringPiece: { + SetBarStringPiece(other.BarStringPiece); + break; + } + case BarOneofCase.BarBytes: { + SetBarBytes(other.BarBytes); + break; + } + case BarOneofCase.BarEnum: { + SetBarEnum(other.BarEnum); + break; + } + case BarOneofCase.None: { break; } + } this.MergeUnknownFields(other.UnknownFields); return this; } @@ -23706,29 +24119,51 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 8: { - result.hasFooInt = input.ReadInt32(ref result.fooInt_); + int value = 0; + if (input.ReadInt32(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; + } break; } case 18: { - result.hasFooString = input.ReadString(ref result.fooString_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; + } break; } case 26: { - result.hasFooCord = input.ReadString(ref result.fooCord_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooCord; + } break; } case 34: { - result.hasFooStringPiece = input.ReadString(ref result.fooStringPiece_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooStringPiece; + } break; } case 42: { - result.hasFooBytes = input.ReadBytes(ref result.fooBytes_); + pb::ByteString value = pb::ByteString.Empty; + if (input.ReadBytes(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooBytes; + } break; } case 48: { object unknown; - if(input.ReadEnum(ref result.fooEnum_, out unknown)) { - result.hasFooEnum = true; + global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum enumValue = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; + if(input.ReadEnum(ref enumValue, out unknown)) { + result.foo_ = enumValue; + result.fooCase_ = FooOneofCase.FooEnum; } else if(unknown is int) { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -23739,55 +24174,80 @@ namespace Google.ProtocolBuffers.TestProtos { } case 58: { global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(); - if (result.hasFooMessage) { + if (result.fooCase_ == FooOneofCase.FooMessage) { subBuilder.MergeFrom(FooMessage); } input.ReadMessage(subBuilder, extensionRegistry); - FooMessage = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooMessage; break; } case 67: { global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.CreateBuilder(); - if (result.hasFooGroup) { + if (result.fooCase_ == FooOneofCase.FooGroup) { subBuilder.MergeFrom(FooGroup); } input.ReadGroup(8, subBuilder, extensionRegistry); - FooGroup = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooGroup; break; } case 90: { global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(); - if (result.hasFooLazyMessage) { + if (result.fooCase_ == FooOneofCase.FooLazyMessage) { subBuilder.MergeFrom(FooLazyMessage); } input.ReadMessage(subBuilder, extensionRegistry); - FooLazyMessage = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooLazyMessage; break; } case 96: { - result.hasBarInt = input.ReadInt32(ref result.barInt_); + int value = 5; + if (input.ReadInt32(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarInt; + } break; } case 106: { - result.hasBarString = input.ReadString(ref result.barString_); + string value = "STRING"; + if (input.ReadString(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarString; + } break; } case 114: { - result.hasBarCord = input.ReadString(ref result.barCord_); + string value = "CORD"; + if (input.ReadString(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarCord; + } break; } case 122: { - result.hasBarStringPiece = input.ReadString(ref result.barStringPiece_); + string value = "SPIECE"; + if (input.ReadString(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarStringPiece; + } break; } case 130: { - result.hasBarBytes = input.ReadBytes(ref result.barBytes_); + pb::ByteString value = (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; + if (input.ReadBytes(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarBytes; + } break; } case 136: { object unknown; - if(input.ReadEnum(ref result.barEnum_, out unknown)) { - result.hasBarEnum = true; + global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum enumValue = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; + if(input.ReadEnum(ref enumValue, out unknown)) { + result.bar_ = enumValue; + result.barCase_ = BarOneofCase.BarEnum; } else if(unknown is int) { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -23815,370 +24275,388 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasFooInt { - get { return result.hasFooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return result.FooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt ? (int) result.foo_ : 0; } set { SetFooInt(value); } } public Builder SetFooInt(int value) { PrepareBuilder(); - result.hasFooInt = true; - result.fooInt_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; return this; } public Builder ClearFooInt() { PrepareBuilder(); - result.hasFooInt = false; - result.fooInt_ = 0; + if (result.fooCase_ == FooOneofCase.FooInt) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooString { - get { return result.hasFooString; } + get { return result.fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return result.FooString; } + get { return result.fooCase_ == FooOneofCase.FooString ? (string) result.foo_ : ""; } set { SetFooString(value); } } public Builder SetFooString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooString = true; - result.fooString_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; return this; } public Builder ClearFooString() { PrepareBuilder(); - result.hasFooString = false; - result.fooString_ = ""; + if (result.fooCase_ == FooOneofCase.FooString) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooCord { - get { return result.hasFooCord; } + get { return result.fooCase_ == FooOneofCase.FooCord; } } public string FooCord { - get { return result.FooCord; } + get { return result.fooCase_ == FooOneofCase.FooCord ? (string) result.foo_ : ""; } set { SetFooCord(value); } } public Builder SetFooCord(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooCord = true; - result.fooCord_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooCord; return this; } public Builder ClearFooCord() { PrepareBuilder(); - result.hasFooCord = false; - result.fooCord_ = ""; + if (result.fooCase_ == FooOneofCase.FooCord) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooStringPiece { - get { return result.hasFooStringPiece; } + get { return result.fooCase_ == FooOneofCase.FooStringPiece; } } public string FooStringPiece { - get { return result.FooStringPiece; } + get { return result.fooCase_ == FooOneofCase.FooStringPiece ? (string) result.foo_ : ""; } set { SetFooStringPiece(value); } } public Builder SetFooStringPiece(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooStringPiece = true; - result.fooStringPiece_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooStringPiece; return this; } public Builder ClearFooStringPiece() { PrepareBuilder(); - result.hasFooStringPiece = false; - result.fooStringPiece_ = ""; + if (result.fooCase_ == FooOneofCase.FooStringPiece) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooBytes { - get { return result.hasFooBytes; } + get { return result.fooCase_ == FooOneofCase.FooBytes; } } public pb::ByteString FooBytes { - get { return result.FooBytes; } + get { return result.fooCase_ == FooOneofCase.FooBytes ? (pb::ByteString) result.foo_ : pb::ByteString.Empty; } set { SetFooBytes(value); } } public Builder SetFooBytes(pb::ByteString value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooBytes = true; - result.fooBytes_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooBytes; return this; } public Builder ClearFooBytes() { PrepareBuilder(); - result.hasFooBytes = false; - result.fooBytes_ = pb::ByteString.Empty; + if (result.fooCase_ == FooOneofCase.FooBytes) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooEnum { - get { return result.hasFooEnum; } + get { return result.fooCase_ == FooOneofCase.FooEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum FooEnum { - get { return result.FooEnum; } + get { return result.fooCase_ == FooOneofCase.FooEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; } set { SetFooEnum(value); } } public Builder SetFooEnum(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum value) { PrepareBuilder(); - result.hasFooEnum = true; - result.fooEnum_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooEnum; return this; } public Builder ClearFooEnum() { PrepareBuilder(); - result.hasFooEnum = false; - result.fooEnum_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; + if (result.fooCase_ == FooOneofCase.FooEnum) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooMessage { - get { return result.hasFooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooMessage { - get { return result.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } set { SetFooMessage(value); } } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = value; + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = value; return this; } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooMessage && - result.fooMessage_ != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance) { - result.fooMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(result.fooMessage_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooMessage && + result.FooMessage != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(result.FooMessage).MergeFrom(value).BuildPartial(); } else { - result.fooMessage_ = value; + result.foo_ = value; } - result.hasFooMessage = true; + result.fooCase_ = FooOneofCase.FooMessage; return this; } public Builder ClearFooMessage() { - PrepareBuilder(); - result.hasFooMessage = false; - result.fooMessage_ = null; + if (result.fooCase_ == FooOneofCase.FooMessage) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } return this; } public bool HasFooGroup { - get { return result.hasFooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup FooGroup { - get { return result.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } set { SetFooGroup(value); } } public Builder SetFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooGroup = true; - result.fooGroup_ = value; + result.fooCase_ = FooOneofCase.FooGroup; + result.foo_ = value; return this; } public Builder SetFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooGroup = true; - result.fooGroup_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooGroup; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooGroup && - result.fooGroup_ != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance) { - result.fooGroup_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.CreateBuilder(result.fooGroup_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooGroup && + result.FooGroup != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.CreateBuilder(result.FooGroup).MergeFrom(value).BuildPartial(); } else { - result.fooGroup_ = value; + result.foo_ = value; } - result.hasFooGroup = true; + result.fooCase_ = FooOneofCase.FooGroup; return this; } public Builder ClearFooGroup() { - PrepareBuilder(); - result.hasFooGroup = false; - result.fooGroup_ = null; + if (result.fooCase_ == FooOneofCase.FooGroup) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } return this; } public bool HasFooLazyMessage { - get { return result.hasFooLazyMessage; } + get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooLazyMessage { - get { return result.FooLazyMessage; } + get { return result.fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } set { SetFooLazyMessage(value); } } public Builder SetFooLazyMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooLazyMessage = true; - result.fooLazyMessage_ = value; + result.fooCase_ = FooOneofCase.FooLazyMessage; + result.foo_ = value; return this; } public Builder SetFooLazyMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooLazyMessage = true; - result.fooLazyMessage_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooLazyMessage; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooLazyMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooLazyMessage && - result.fooLazyMessage_ != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance) { - result.fooLazyMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(result.fooLazyMessage_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooLazyMessage && + result.FooLazyMessage != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(result.FooLazyMessage).MergeFrom(value).BuildPartial(); } else { - result.fooLazyMessage_ = value; + result.foo_ = value; } - result.hasFooLazyMessage = true; + result.fooCase_ = FooOneofCase.FooLazyMessage; return this; } public Builder ClearFooLazyMessage() { - PrepareBuilder(); - result.hasFooLazyMessage = false; - result.fooLazyMessage_ = null; + if (result.fooCase_ == FooOneofCase.FooLazyMessage) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } return this; } public bool HasBarInt { - get { return result.hasBarInt; } + get { return result.barCase_ == BarOneofCase.BarInt; } } public int BarInt { - get { return result.BarInt; } + get { return result.barCase_ == BarOneofCase.BarInt ? (int) result.bar_ : 5; } set { SetBarInt(value); } } public Builder SetBarInt(int value) { PrepareBuilder(); - result.hasBarInt = true; - result.barInt_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarInt; return this; } public Builder ClearBarInt() { PrepareBuilder(); - result.hasBarInt = false; - result.barInt_ = 5; + if (result.barCase_ == BarOneofCase.BarInt) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarString { - get { return result.hasBarString; } + get { return result.barCase_ == BarOneofCase.BarString; } } public string BarString { - get { return result.BarString; } + get { return result.barCase_ == BarOneofCase.BarString ? (string) result.bar_ : "STRING"; } set { SetBarString(value); } } public Builder SetBarString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasBarString = true; - result.barString_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarString; return this; } public Builder ClearBarString() { PrepareBuilder(); - result.hasBarString = false; - result.barString_ = "STRING"; + if (result.barCase_ == BarOneofCase.BarString) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarCord { - get { return result.hasBarCord; } + get { return result.barCase_ == BarOneofCase.BarCord; } } public string BarCord { - get { return result.BarCord; } + get { return result.barCase_ == BarOneofCase.BarCord ? (string) result.bar_ : "CORD"; } set { SetBarCord(value); } } public Builder SetBarCord(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasBarCord = true; - result.barCord_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarCord; return this; } public Builder ClearBarCord() { PrepareBuilder(); - result.hasBarCord = false; - result.barCord_ = "CORD"; + if (result.barCase_ == BarOneofCase.BarCord) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarStringPiece { - get { return result.hasBarStringPiece; } + get { return result.barCase_ == BarOneofCase.BarStringPiece; } } public string BarStringPiece { - get { return result.BarStringPiece; } + get { return result.barCase_ == BarOneofCase.BarStringPiece ? (string) result.bar_ : "SPIECE"; } set { SetBarStringPiece(value); } } public Builder SetBarStringPiece(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasBarStringPiece = true; - result.barStringPiece_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarStringPiece; return this; } public Builder ClearBarStringPiece() { PrepareBuilder(); - result.hasBarStringPiece = false; - result.barStringPiece_ = "SPIECE"; + if (result.barCase_ == BarOneofCase.BarStringPiece) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarBytes { - get { return result.hasBarBytes; } + get { return result.barCase_ == BarOneofCase.BarBytes; } } public pb::ByteString BarBytes { - get { return result.BarBytes; } + get { return result.barCase_ == BarOneofCase.BarBytes ? (pb::ByteString) result.bar_ : (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; } set { SetBarBytes(value); } } public Builder SetBarBytes(pb::ByteString value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasBarBytes = true; - result.barBytes_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarBytes; return this; } public Builder ClearBarBytes() { PrepareBuilder(); - result.hasBarBytes = false; - result.barBytes_ = (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; + if (result.barCase_ == BarOneofCase.BarBytes) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarEnum { - get { return result.hasBarEnum; } + get { return result.barCase_ == BarOneofCase.BarEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum BarEnum { - get { return result.BarEnum; } + get { return result.barCase_ == BarOneofCase.BarEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) result.bar_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; } set { SetBarEnum(value); } } public Builder SetBarEnum(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum value) { PrepareBuilder(); - result.hasBarEnum = true; - result.barEnum_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarEnum; return this; } public Builder ClearBarEnum() { PrepareBuilder(); - result.hasBarEnum = false; - result.barEnum_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; + if (result.barCase_ == BarOneofCase.BarEnum) { + result.barCase_ = BarOneofCase.None; + } return this; } @@ -24222,6 +24700,26 @@ namespace Google.ProtocolBuffers.TestProtos { result.bazString_ = "BAZ"; return this; } + + public FooOneofCase FooCase { + get { return result.fooCase_; } + } + public Builder ClearFoo() { + PrepareBuilder(); + result.foo_ = null; + result.fooCase_ = FooOneofCase.None; + return this; + } + + public BarOneofCase BarCase { + get { return result.barCase_; } + } + public Builder ClearBar() { + PrepareBuilder(); + result.bar_ = null; + result.barCase_ = BarOneofCase.None; + return this; + } } static TestOneof2() { object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); @@ -24536,34 +25034,40 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object foo_; + public enum FooOneofCase { + FooInt = 1, + FooString = 2, + FooMessage = 3, + None = 0, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + public FooOneofCase FooCase { + get { return fooCase_; } + } + public const int FooIntFieldNumber = 1; - private bool hasFooInt; - private int fooInt_; public bool HasFooInt { - get { return hasFooInt; } + get { return fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return fooInt_; } + get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } } public const int FooStringFieldNumber = 2; - private bool hasFooString; - private string fooString_ = ""; public bool HasFooString { - get { return hasFooString; } + get { return fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return fooString_; } + get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } } public const int FooMessageFieldNumber = 3; - private bool hasFooMessage; - private global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage fooMessage_; public bool HasFooMessage { - get { return hasFooMessage; } + get { return fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage FooMessage { - get { return fooMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage) foo_ : global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } } public override bool IsInitialized { @@ -24578,13 +25082,13 @@ namespace Google.ProtocolBuffers.TestProtos { public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); string[] field_names = _testRequiredOneofFieldNames; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { output.WriteInt32(1, field_names[0], FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { output.WriteString(2, field_names[2], FooString); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { output.WriteMessage(3, field_names[1], FooMessage); } UnknownFields.WriteTo(output); @@ -24604,13 +25108,13 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { size += pb::CodedOutputStream.ComputeInt32Size(1, FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { size += pb::CodedOutputStream.ComputeStringSize(2, FooString); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { size += pb::CodedOutputStream.ComputeMessageSize(3, FooMessage); } size += UnknownFields.SerializedSize; @@ -24735,14 +25239,20 @@ namespace Google.ProtocolBuffers.TestProtos { public override Builder MergeFrom(TestRequiredOneof other) { if (other == global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.DefaultInstance) return this; PrepareBuilder(); - if (other.HasFooInt) { - FooInt = other.FooInt; - } - if (other.HasFooString) { - FooString = other.FooString; - } - if (other.HasFooMessage) { - MergeFooMessage(other.FooMessage); + switch (other.FooCase) { + case FooOneofCase.FooInt: { + SetFooInt(other.FooInt); + break; + } + case FooOneofCase.FooString: { + SetFooString(other.FooString); + break; + } + case FooOneofCase.FooMessage: { + MergeFooMessage(other.FooMessage); + break; + } + case FooOneofCase.None: { break; } } this.MergeUnknownFields(other.UnknownFields); return this; @@ -24788,20 +25298,29 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 8: { - result.hasFooInt = input.ReadInt32(ref result.fooInt_); + int value = 0; + if (input.ReadInt32(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; + } break; } case 18: { - result.hasFooString = input.ReadString(ref result.fooString_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; + } break; } case 26: { global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.CreateBuilder(); - if (result.hasFooMessage) { + if (result.fooCase_ == FooOneofCase.FooMessage) { subBuilder.MergeFrom(FooMessage); } input.ReadMessage(subBuilder, extensionRegistry); - FooMessage = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooMessage; break; } } @@ -24815,83 +25334,97 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasFooInt { - get { return result.hasFooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return result.FooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt ? (int) result.foo_ : 0; } set { SetFooInt(value); } } public Builder SetFooInt(int value) { PrepareBuilder(); - result.hasFooInt = true; - result.fooInt_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; return this; } public Builder ClearFooInt() { PrepareBuilder(); - result.hasFooInt = false; - result.fooInt_ = 0; + if (result.fooCase_ == FooOneofCase.FooInt) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooString { - get { return result.hasFooString; } + get { return result.fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return result.FooString; } + get { return result.fooCase_ == FooOneofCase.FooString ? (string) result.foo_ : ""; } set { SetFooString(value); } } public Builder SetFooString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooString = true; - result.fooString_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; return this; } public Builder ClearFooString() { PrepareBuilder(); - result.hasFooString = false; - result.fooString_ = ""; + if (result.fooCase_ == FooOneofCase.FooString) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooMessage { - get { return result.hasFooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage FooMessage { - get { return result.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } set { SetFooMessage(value); } } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = value; + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = value; return this; } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooMessage(global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooMessage && - result.fooMessage_ != global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance) { - result.fooMessage_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.CreateBuilder(result.fooMessage_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooMessage && + result.FooMessage != global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.CreateBuilder(result.FooMessage).MergeFrom(value).BuildPartial(); } else { - result.fooMessage_ = value; + result.foo_ = value; } - result.hasFooMessage = true; + result.fooCase_ = FooOneofCase.FooMessage; return this; } public Builder ClearFooMessage() { + if (result.fooCase_ == FooOneofCase.FooMessage) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } + return this; + } + + public FooOneofCase FooCase { + get { return result.fooCase_; } + } + public Builder ClearFoo() { PrepareBuilder(); - result.hasFooMessage = false; - result.fooMessage_ = null; + result.foo_ = null; + result.fooCase_ = FooOneofCase.None; return this; } } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestNoFieldPresence.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestNoFieldPresence.cs index 0d212b72..52d7a69b 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestNoFieldPresence.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestNoFieldPresence.cs @@ -97,7 +97,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { internal__static_proto2_nofieldpresence_unittest_TestAllTypes__Descriptor = Descriptor.MessageTypes[0]; internal__static_proto2_nofieldpresence_unittest_TestAllTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_proto2_nofieldpresence_unittest_TestAllTypes__Descriptor, - new string[] { "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalProto2Message", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "OptionalLazyMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedProto2Message", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "RepeatedLazyMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofEnum", }); + new string[] { "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalProto2Message", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalStringPiece", "OptionalCord", "OptionalLazyMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedProto2Message", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedStringPiece", "RepeatedCord", "RepeatedLazyMessage", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofEnum", "OneofField", }); internal__static_proto2_nofieldpresence_unittest_TestAllTypes_NestedMessage__Descriptor = internal__static_proto2_nofieldpresence_unittest_TestAllTypes__Descriptor.NestedTypes[0]; internal__static_proto2_nofieldpresence_unittest_TestAllTypes_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_proto2_nofieldpresence_unittest_TestAllTypes_NestedMessage__Descriptor, @@ -431,6 +431,19 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } #endregion + private object oneofField_; + public enum OneofFieldOneofCase { + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofEnum = 114, + None = 0, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + public const int OptionalInt32FieldNumber = 1; private int optionalInt32_; public int OptionalInt32 { @@ -586,6 +599,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedInt32FieldNumber = 31; + private int repeatedInt32MemoizedSerializedSize; private pbc::PopsicleList repeatedInt32_ = new pbc::PopsicleList(); public scg::IList RepeatedInt32List { get { return pbc::Lists.AsReadOnly(repeatedInt32_); } @@ -598,6 +612,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedInt64FieldNumber = 32; + private int repeatedInt64MemoizedSerializedSize; private pbc::PopsicleList repeatedInt64_ = new pbc::PopsicleList(); public scg::IList RepeatedInt64List { get { return pbc::Lists.AsReadOnly(repeatedInt64_); } @@ -610,6 +625,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedUint32FieldNumber = 33; + private int repeatedUint32MemoizedSerializedSize; private pbc::PopsicleList repeatedUint32_ = new pbc::PopsicleList(); public scg::IList RepeatedUint32List { get { return pbc::Lists.AsReadOnly(repeatedUint32_); } @@ -622,6 +638,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedUint64FieldNumber = 34; + private int repeatedUint64MemoizedSerializedSize; private pbc::PopsicleList repeatedUint64_ = new pbc::PopsicleList(); public scg::IList RepeatedUint64List { get { return pbc::Lists.AsReadOnly(repeatedUint64_); } @@ -634,6 +651,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedSint32FieldNumber = 35; + private int repeatedSint32MemoizedSerializedSize; private pbc::PopsicleList repeatedSint32_ = new pbc::PopsicleList(); public scg::IList RepeatedSint32List { get { return pbc::Lists.AsReadOnly(repeatedSint32_); } @@ -646,6 +664,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedSint64FieldNumber = 36; + private int repeatedSint64MemoizedSerializedSize; private pbc::PopsicleList repeatedSint64_ = new pbc::PopsicleList(); public scg::IList RepeatedSint64List { get { return pbc::Lists.AsReadOnly(repeatedSint64_); } @@ -658,6 +677,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedFixed32FieldNumber = 37; + private int repeatedFixed32MemoizedSerializedSize; private pbc::PopsicleList repeatedFixed32_ = new pbc::PopsicleList(); public scg::IList RepeatedFixed32List { get { return pbc::Lists.AsReadOnly(repeatedFixed32_); } @@ -670,6 +690,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedFixed64FieldNumber = 38; + private int repeatedFixed64MemoizedSerializedSize; private pbc::PopsicleList repeatedFixed64_ = new pbc::PopsicleList(); public scg::IList RepeatedFixed64List { get { return pbc::Lists.AsReadOnly(repeatedFixed64_); } @@ -682,6 +703,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedSfixed32FieldNumber = 39; + private int repeatedSfixed32MemoizedSerializedSize; private pbc::PopsicleList repeatedSfixed32_ = new pbc::PopsicleList(); public scg::IList RepeatedSfixed32List { get { return pbc::Lists.AsReadOnly(repeatedSfixed32_); } @@ -694,6 +716,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedSfixed64FieldNumber = 40; + private int repeatedSfixed64MemoizedSerializedSize; private pbc::PopsicleList repeatedSfixed64_ = new pbc::PopsicleList(); public scg::IList RepeatedSfixed64List { get { return pbc::Lists.AsReadOnly(repeatedSfixed64_); } @@ -706,6 +729,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedFloatFieldNumber = 41; + private int repeatedFloatMemoizedSerializedSize; private pbc::PopsicleList repeatedFloat_ = new pbc::PopsicleList(); public scg::IList RepeatedFloatList { get { return pbc::Lists.AsReadOnly(repeatedFloat_); } @@ -718,6 +742,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedDoubleFieldNumber = 42; + private int repeatedDoubleMemoizedSerializedSize; private pbc::PopsicleList repeatedDouble_ = new pbc::PopsicleList(); public scg::IList RepeatedDoubleList { get { return pbc::Lists.AsReadOnly(repeatedDouble_); } @@ -730,6 +755,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedBoolFieldNumber = 43; + private int repeatedBoolMemoizedSerializedSize; private pbc::PopsicleList repeatedBool_ = new pbc::PopsicleList(); public scg::IList RepeatedBoolList { get { return pbc::Lists.AsReadOnly(repeatedBool_); } @@ -802,6 +828,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedNestedEnumFieldNumber = 51; + private int repeatedNestedEnumMemoizedSerializedSize; private pbc::PopsicleList repeatedNestedEnum_ = new pbc::PopsicleList(); public scg::IList RepeatedNestedEnumList { get { return pbc::Lists.AsReadOnly(repeatedNestedEnum_); } @@ -814,6 +841,7 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int RepeatedForeignEnumFieldNumber = 52; + private int repeatedForeignEnumMemoizedSerializedSize; private pbc::PopsicleList repeatedForeignEnum_ = new pbc::PopsicleList(); public scg::IList RepeatedForeignEnumList { get { return pbc::Lists.AsReadOnly(repeatedForeignEnum_); } @@ -862,31 +890,23 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public const int OneofUint32FieldNumber = 111; - private uint oneofUint32_; public uint OneofUint32 { - get { return oneofUint32_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } } public const int OneofNestedMessageFieldNumber = 112; - private bool hasOneofNestedMessage; - private global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage oneofNestedMessage_; - public bool HasOneofNestedMessage { - get { return hasOneofNestedMessage; } - } public global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage OneofNestedMessage { - get { return oneofNestedMessage_ ?? global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.DefaultInstance; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage) oneofField_ : global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.DefaultInstance; } } public const int OneofStringFieldNumber = 113; - private string oneofString_ = ""; public string OneofString { - get { return oneofString_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } } public const int OneofEnumFieldNumber = 114; - private global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum oneofEnum_ = global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum.FOO; public global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum OneofEnum { - get { return oneofEnum_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofEnum ? (global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum) oneofField_ : global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum.FOO; } } public override void WriteTo(pb::ICodedOutputStream output) { @@ -962,43 +982,43 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { output.WriteMessage(30, field_names[15], OptionalLazyMessage); } if (repeatedInt32_.Count > 0) { - output.WriteInt32Array(31, field_names[36], repeatedInt32_); + output.WritePackedInt32Array(31, field_names[36], repeatedInt32MemoizedSerializedSize, repeatedInt32_); } if (repeatedInt64_.Count > 0) { - output.WriteInt64Array(32, field_names[37], repeatedInt64_); + output.WritePackedInt64Array(32, field_names[37], repeatedInt64MemoizedSerializedSize, repeatedInt64_); } if (repeatedUint32_.Count > 0) { - output.WriteUInt32Array(33, field_names[48], repeatedUint32_); + output.WritePackedUInt32Array(33, field_names[48], repeatedUint32MemoizedSerializedSize, repeatedUint32_); } if (repeatedUint64_.Count > 0) { - output.WriteUInt64Array(34, field_names[49], repeatedUint64_); + output.WritePackedUInt64Array(34, field_names[49], repeatedUint64MemoizedSerializedSize, repeatedUint64_); } if (repeatedSint32_.Count > 0) { - output.WriteSInt32Array(35, field_names[44], repeatedSint32_); + output.WritePackedSInt32Array(35, field_names[44], repeatedSint32MemoizedSerializedSize, repeatedSint32_); } if (repeatedSint64_.Count > 0) { - output.WriteSInt64Array(36, field_names[45], repeatedSint64_); + output.WritePackedSInt64Array(36, field_names[45], repeatedSint64MemoizedSerializedSize, repeatedSint64_); } if (repeatedFixed32_.Count > 0) { - output.WriteFixed32Array(37, field_names[31], repeatedFixed32_); + output.WritePackedFixed32Array(37, field_names[31], repeatedFixed32MemoizedSerializedSize, repeatedFixed32_); } if (repeatedFixed64_.Count > 0) { - output.WriteFixed64Array(38, field_names[32], repeatedFixed64_); + output.WritePackedFixed64Array(38, field_names[32], repeatedFixed64MemoizedSerializedSize, repeatedFixed64_); } if (repeatedSfixed32_.Count > 0) { - output.WriteSFixed32Array(39, field_names[42], repeatedSfixed32_); + output.WritePackedSFixed32Array(39, field_names[42], repeatedSfixed32MemoizedSerializedSize, repeatedSfixed32_); } if (repeatedSfixed64_.Count > 0) { - output.WriteSFixed64Array(40, field_names[43], repeatedSfixed64_); + output.WritePackedSFixed64Array(40, field_names[43], repeatedSfixed64MemoizedSerializedSize, repeatedSfixed64_); } if (repeatedFloat_.Count > 0) { - output.WriteFloatArray(41, field_names[33], repeatedFloat_); + output.WritePackedFloatArray(41, field_names[33], repeatedFloatMemoizedSerializedSize, repeatedFloat_); } if (repeatedDouble_.Count > 0) { - output.WriteDoubleArray(42, field_names[30], repeatedDouble_); + output.WritePackedDoubleArray(42, field_names[30], repeatedDoubleMemoizedSerializedSize, repeatedDouble_); } if (repeatedBool_.Count > 0) { - output.WriteBoolArray(43, field_names[27], repeatedBool_); + output.WritePackedBoolArray(43, field_names[27], repeatedBoolMemoizedSerializedSize, repeatedBool_); } if (repeatedString_.Count > 0) { output.WriteStringArray(44, field_names[46], repeatedString_); @@ -1016,10 +1036,10 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { output.WriteMessageArray(50, field_names[41], repeatedProto2Message_); } if (repeatedNestedEnum_.Count > 0) { - output.WriteEnumArray(51, field_names[39], repeatedNestedEnum_); + output.WritePackedEnumArray(51, field_names[39], repeatedNestedEnumMemoizedSerializedSize, repeatedNestedEnum_); } if (repeatedForeignEnum_.Count > 0) { - output.WriteEnumArray(52, field_names[34], repeatedForeignEnum_); + output.WritePackedEnumArray(52, field_names[34], repeatedForeignEnumMemoizedSerializedSize, repeatedForeignEnum_); } if (repeatedStringPiece_.Count > 0) { output.WriteStringArray(54, field_names[47], repeatedStringPiece_); @@ -1030,16 +1050,16 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { if (repeatedLazyMessage_.Count > 0) { output.WriteMessageArray(57, field_names[38], repeatedLazyMessage_); } - if (OneofUint32 != 0) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { output.WriteUInt32(111, field_names[3], OneofUint32); } - if (hasOneofNestedMessage) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { output.WriteMessage(112, field_names[1], OneofNestedMessage); } - if (OneofString != "") { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { output.WriteString(113, field_names[2], OneofString); } - if (OneofEnum != global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum.FOO) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { output.WriteEnum(114, field_names[0], (int) OneofEnum, OneofEnum); } UnknownFields.WriteTo(output); @@ -1134,7 +1154,10 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { dataSize += pb::CodedOutputStream.ComputeInt32SizeNoTag(element); } size += dataSize; - size += 2 * repeatedInt32_.Count; + if (repeatedInt32_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedInt32MemoizedSerializedSize = dataSize; } { int dataSize = 0; @@ -1142,7 +1165,10 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { dataSize += pb::CodedOutputStream.ComputeInt64SizeNoTag(element); } size += dataSize; - size += 2 * repeatedInt64_.Count; + if (repeatedInt64_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedInt64MemoizedSerializedSize = dataSize; } { int dataSize = 0; @@ -1150,7 +1176,10 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { dataSize += pb::CodedOutputStream.ComputeUInt32SizeNoTag(element); } size += dataSize; - size += 2 * repeatedUint32_.Count; + if (repeatedUint32_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedUint32MemoizedSerializedSize = dataSize; } { int dataSize = 0; @@ -1158,7 +1187,10 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { dataSize += pb::CodedOutputStream.ComputeUInt64SizeNoTag(element); } size += dataSize; - size += 2 * repeatedUint64_.Count; + if (repeatedUint64_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedUint64MemoizedSerializedSize = dataSize; } { int dataSize = 0; @@ -1166,7 +1198,10 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { dataSize += pb::CodedOutputStream.ComputeSInt32SizeNoTag(element); } size += dataSize; - size += 2 * repeatedSint32_.Count; + if (repeatedSint32_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedSint32MemoizedSerializedSize = dataSize; } { int dataSize = 0; @@ -1174,49 +1209,73 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { dataSize += pb::CodedOutputStream.ComputeSInt64SizeNoTag(element); } size += dataSize; - size += 2 * repeatedSint64_.Count; + if (repeatedSint64_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedSint64MemoizedSerializedSize = dataSize; } { int dataSize = 0; dataSize = 4 * repeatedFixed32_.Count; size += dataSize; - size += 2 * repeatedFixed32_.Count; + if (repeatedFixed32_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedFixed32MemoizedSerializedSize = dataSize; } { int dataSize = 0; dataSize = 8 * repeatedFixed64_.Count; size += dataSize; - size += 2 * repeatedFixed64_.Count; + if (repeatedFixed64_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedFixed64MemoizedSerializedSize = dataSize; } { int dataSize = 0; dataSize = 4 * repeatedSfixed32_.Count; size += dataSize; - size += 2 * repeatedSfixed32_.Count; + if (repeatedSfixed32_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedSfixed32MemoizedSerializedSize = dataSize; } { int dataSize = 0; dataSize = 8 * repeatedSfixed64_.Count; size += dataSize; - size += 2 * repeatedSfixed64_.Count; + if (repeatedSfixed64_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedSfixed64MemoizedSerializedSize = dataSize; } { int dataSize = 0; dataSize = 4 * repeatedFloat_.Count; size += dataSize; - size += 2 * repeatedFloat_.Count; + if (repeatedFloat_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedFloatMemoizedSerializedSize = dataSize; } { int dataSize = 0; dataSize = 8 * repeatedDouble_.Count; size += dataSize; - size += 2 * repeatedDouble_.Count; + if (repeatedDouble_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedDoubleMemoizedSerializedSize = dataSize; } { int dataSize = 0; dataSize = 1 * repeatedBool_.Count; size += dataSize; - size += 2 * repeatedBool_.Count; + if (repeatedBool_.Count != 0) { + size += 2 + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize); + } + repeatedBoolMemoizedSerializedSize = dataSize; } { int dataSize = 0; @@ -1250,8 +1309,10 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; - size += 2 * repeatedNestedEnum_.Count; + size += 2; + size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize); } + repeatedNestedEnumMemoizedSerializedSize = dataSize; } { int dataSize = 0; @@ -1260,8 +1321,10 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; - size += 2 * repeatedForeignEnum_.Count; + size += 2; + size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize); } + repeatedForeignEnumMemoizedSerializedSize = dataSize; } { int dataSize = 0; @@ -1282,16 +1345,16 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { foreach (global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage element in RepeatedLazyMessageList) { size += pb::CodedOutputStream.ComputeMessageSize(57, element); } - if (OneofUint32 != 0) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { size += pb::CodedOutputStream.ComputeUInt32Size(111, OneofUint32); } - if (hasOneofNestedMessage) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { size += pb::CodedOutputStream.ComputeMessageSize(112, OneofNestedMessage); } - if (OneofString != "") { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { size += pb::CodedOutputStream.ComputeStringSize(113, OneofString); } - if (OneofEnum != global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum.FOO) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { size += pb::CodedOutputStream.ComputeEnumSize(114, (int) OneofEnum); } size += UnknownFields.SerializedSize; @@ -1577,17 +1640,24 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { if (other.repeatedLazyMessage_.Count != 0) { result.repeatedLazyMessage_.Add(other.repeatedLazyMessage_); } - if (other.OneofUint32 != 0) { - OneofUint32 = other.OneofUint32; - } - if (other.HasOneofNestedMessage) { - MergeOneofNestedMessage(other.OneofNestedMessage); - } - if (other.OneofString != "") { - OneofString = other.OneofString; - } - if (other.OneofEnum != global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum.FOO) { - OneofEnum = other.OneofEnum; + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: { + SetOneofUint32(other.OneofUint32); + break; + } + case OneofFieldOneofCase.OneofNestedMessage: { + MergeOneofNestedMessage(other.OneofNestedMessage); + break; + } + case OneofFieldOneofCase.OneofString: { + SetOneofString(other.OneofString); + break; + } + case OneofFieldOneofCase.OneofEnum: { + SetOneofEnum(other.OneofEnum); + break; + } + case OneofFieldOneofCase.None: { break; } } this.MergeUnknownFields(other.UnknownFields); return this; @@ -1884,25 +1954,37 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { break; } case 888: { - input.ReadUInt32(ref result.oneofUint32_); + uint value = 0; + if (input.ReadUInt32(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } break; } case 898: { global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.CreateBuilder(); - if (result.hasOneofNestedMessage) { + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { subBuilder.MergeFrom(OneofNestedMessage); } input.ReadMessage(subBuilder, extensionRegistry); - OneofNestedMessage = subBuilder.BuildPartial(); + result.oneofField_ = subBuilder.BuildPartial(); + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; break; } case 906: { - input.ReadString(ref result.oneofString_); + string value = ""; + if (input.ReadString(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } break; } case 912: { object unknown; - if(input.ReadEnum(ref result.oneofEnum_, out unknown)) { + global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum enumValue = global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum.FOO; + if(input.ReadEnum(ref enumValue, out unknown)) { + result.oneofField_ = enumValue; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; } else if(unknown is int) { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -3125,88 +3207,106 @@ namespace Google.ProtocolBuffers.TestProtos.Proto3 { } public uint OneofUint32 { - get { return result.OneofUint32; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) result.oneofField_ : 0; } set { SetOneofUint32(value); } } public Builder SetOneofUint32(uint value) { PrepareBuilder(); - result.oneofUint32_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; return this; } public Builder ClearOneofUint32() { PrepareBuilder(); - result.oneofUint32_ = 0; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } return this; } - public bool HasOneofNestedMessage { - get { return result.hasOneofNestedMessage; } - } public global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage OneofNestedMessage { - get { return result.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.DefaultInstance; } set { SetOneofNestedMessage(value); } } public Builder SetOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofNestedMessage = true; - result.oneofNestedMessage_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; + result.oneofField_ = value; return this; } public Builder SetOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasOneofNestedMessage = true; - result.oneofNestedMessage_ = builderForValue.Build(); + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; + result.oneofField_ = builderForValue.Build(); return this; } public Builder MergeOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasOneofNestedMessage && - result.oneofNestedMessage_ != global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.DefaultInstance) { - result.oneofNestedMessage_ = global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.CreateBuilder(result.oneofNestedMessage_).MergeFrom(value).BuildPartial(); + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage && + result.OneofNestedMessage != global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.DefaultInstance) { + result.oneofField_ = global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedMessage.CreateBuilder(result.OneofNestedMessage).MergeFrom(value).BuildPartial(); } else { - result.oneofNestedMessage_ = value; + result.oneofField_ = value; } - result.hasOneofNestedMessage = true; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; return this; } public Builder ClearOneofNestedMessage() { - PrepareBuilder(); - result.hasOneofNestedMessage = false; - result.oneofNestedMessage_ = null; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + PrepareBuilder(); + result.oneofFieldCase_ = OneofFieldOneofCase.None; + result.oneofField_ = null; + } return this; } public string OneofString { - get { return result.OneofString; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) result.oneofField_ : ""; } set { SetOneofString(value); } } public Builder SetOneofString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.oneofString_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofString; return this; } public Builder ClearOneofString() { PrepareBuilder(); - result.oneofString_ = ""; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } return this; } public global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum OneofEnum { - get { return result.OneofEnum; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofEnum ? (global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum.FOO; } set { SetOneofEnum(value); } } public Builder SetOneofEnum(global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum value) { PrepareBuilder(); - result.oneofEnum_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofEnum; return this; } public Builder ClearOneofEnum() { PrepareBuilder(); - result.oneofEnum_ = global::Google.ProtocolBuffers.TestProtos.Proto3.TestAllTypes.Types.NestedEnum.FOO; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofEnum) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } + return this; + } + + public OneofFieldOneofCase OneofFieldCase { + get { return result.oneofFieldCase_; } + } + public Builder ClearOneofField() { + PrepareBuilder(); + result.oneofField_ = null; + result.oneofFieldCase_ = OneofFieldOneofCase.None; return this; } } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestOptimizeFor.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestOptimizeFor.cs index 33e2ef4f..d07df059 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestOptimizeFor.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestOptimizeFor.cs @@ -54,7 +54,7 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor = Descriptor.MessageTypes[0]; internal__static_protobuf_unittest_TestOptimizedForSize__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOptimizedForSize__Descriptor, - new string[] { "I", "Msg", "IntegerField", "StringField", }); + new string[] { "I", "Msg", "IntegerField", "StringField", "Foo", }); global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.TestExtension = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Descriptor.Extensions[0]); global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.TestExtension2 = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestOptimizedForSize.Descriptor.Extensions[1]); internal__static_protobuf_unittest_TestRequiredOptimizedForSize__Descriptor = Descriptor.MessageTypes[1]; @@ -107,6 +107,17 @@ namespace Google.ProtocolBuffers.TestProtos { public static pb::GeneratedExtensionBase TestExtension; public const int TestExtension2FieldNumber = 1235; public static pb::GeneratedExtensionBase TestExtension2; + private object foo_; + public enum FooOneofCase { + IntegerField = 2, + StringField = 3, + None = 0, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + public FooOneofCase FooCase { + get { return fooCase_; } + } + public const int IFieldNumber = 1; private bool hasI; private int i_; @@ -128,23 +139,19 @@ namespace Google.ProtocolBuffers.TestProtos { } public const int IntegerFieldFieldNumber = 2; - private bool hasIntegerField; - private int integerField_; public bool HasIntegerField { - get { return hasIntegerField; } + get { return fooCase_ == FooOneofCase.IntegerField; } } public int IntegerField { - get { return integerField_; } + get { return fooCase_ == FooOneofCase.IntegerField ? (int) foo_ : 0; } } public const int StringFieldFieldNumber = 3; - private bool hasStringField; - private string stringField_ = ""; public bool HasStringField { - get { return hasStringField; } + get { return fooCase_ == FooOneofCase.StringField; } } public string StringField { - get { return stringField_; } + get { return fooCase_ == FooOneofCase.StringField ? (string) foo_ : ""; } } public static TestOptimizedForSize ParseFrom(pb::ByteString data) { @@ -315,43 +322,55 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasIntegerField { - get { return result.hasIntegerField; } + get { return result.fooCase_ == FooOneofCase.IntegerField; } } public int IntegerField { - get { return result.IntegerField; } + get { return result.fooCase_ == FooOneofCase.IntegerField ? (int) result.foo_ : 0; } set { SetIntegerField(value); } } public Builder SetIntegerField(int value) { PrepareBuilder(); - result.hasIntegerField = true; - result.integerField_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.IntegerField; return this; } public Builder ClearIntegerField() { PrepareBuilder(); - result.hasIntegerField = false; - result.integerField_ = 0; + if (result.fooCase_ == FooOneofCase.IntegerField) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasStringField { - get { return result.hasStringField; } + get { return result.fooCase_ == FooOneofCase.StringField; } } public string StringField { - get { return result.StringField; } + get { return result.fooCase_ == FooOneofCase.StringField ? (string) result.foo_ : ""; } set { SetStringField(value); } } public Builder SetStringField(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasStringField = true; - result.stringField_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.StringField; return this; } public Builder ClearStringField() { PrepareBuilder(); - result.hasStringField = false; - result.stringField_ = ""; + if (result.fooCase_ == FooOneofCase.StringField) { + result.fooCase_ = FooOneofCase.None; + } + return this; + } + + public FooOneofCase FooCase { + get { return result.fooCase_; } + } + public Builder ClearFoo() { + PrepareBuilder(); + result.foo_ = null; + result.fooCase_ = FooOneofCase.None; return this; } } diff --git a/csharp/src/ProtocolBuffers.Test/TestResources.cs b/csharp/src/ProtocolBuffers.Test/TestResources.cs index c978ca68..602874f7 100644 --- a/csharp/src/ProtocolBuffers.Test/TestResources.cs +++ b/csharp/src/ProtocolBuffers.Test/TestResources.cs @@ -16,7 +16,7 @@ Q80CAICbQ9ECAAAAAACAakDRAgAAAAAAgHNA2AIB2AIA4gIDMjE14gIDMzE16gIDMjE26gIDMzE2 8wL4AtkB9ALzAvgCvQL0AoIDAwjaAYIDAwi+AooDAwjbAYoDAwi/ApIDAwjcAZIDAwjAApgDApgD A6ADBaADBqgDCKgDCbIDAzIyNLIDAzMyNLoDAzIyNboDAzMyNegDkQPwA5ID+AOTA4AElAOIBKoG kASsBp0ElwEAAKEEmAEAAAAAAACtBJkBAACxBJoBAAAAAAAAvQQAgM1DwQQAAAAAAMB5QMgEANIE -AzQxNdoEAzQxNogFAZAFBJgFB6IFAzQyNKoFAzQyNQ== +AzQxNdoEAzQxNogFAZAFBJgFB6IFAzQyNKoFAzQyNZIHAzYwNA== "); } } @@ -158,6 +158,7 @@ default_foreign_enum: FOREIGN_FOO default_import_enum: IMPORT_FOO default_string_piece: ""424"" default_cord: ""425"" +oneof_bytes: ""604"" "; } @@ -286,6 +287,12 @@ default_cord: ""425"" [protobuf_unittest.default_import_enum_extension]: IMPORT_FOO [protobuf_unittest.default_string_piece_extension]: ""424"" [protobuf_unittest.default_cord_extension]: ""425"" +[protobuf_unittest.oneof_uint32_extension]: 601 +[protobuf_unittest.oneof_nested_message_extension] { + bb: 602 +} +[protobuf_unittest.oneof_string_extension]: ""603"" +[protobuf_unittest.oneof_bytes_extension]: ""604"" "; } } diff --git a/csharp/src/ProtocolBuffers.Test/TestUtil.cs b/csharp/src/ProtocolBuffers.Test/TestUtil.cs index 583e8090..c23c43f6 100644 --- a/csharp/src/ProtocolBuffers.Test/TestUtil.cs +++ b/csharp/src/ProtocolBuffers.Test/TestUtil.cs @@ -182,6 +182,11 @@ namespace Google.ProtocolBuffers registry.Add(Unittest.PackedDoubleExtension); registry.Add(Unittest.PackedBoolExtension); registry.Add(Unittest.PackedEnumExtension); + + registry.Add(Unittest.OneofUint32Extension); + registry.Add(Unittest.OneofNestedMessageExtension); + registry.Add(Unittest.OneofStringExtension); + registry.Add(Unittest.OneofBytesExtension); } /// @@ -316,6 +321,13 @@ namespace Google.ProtocolBuffers message.SetDefaultStringPiece("424"); message.SetDefaultCord("425"); + + message.SetOneofUint32(601); + message.SetOneofNestedMessage( + TestAllTypes.Types.NestedMessage.CreateBuilder().SetBb(602).Build()); + message.SetOneofString("603"); + message.SetOneofBytes(ToBytes("604")); + } /// @@ -517,6 +529,13 @@ namespace Google.ProtocolBuffers Assert.AreEqual("424", message.DefaultStringPiece); Assert.AreEqual("425", message.DefaultCord); + + Assert.IsFalse(message.HasOneofUint32); + Assert.IsFalse(message.HasOneofNestedMessage); + Assert.IsFalse(message.HasOneofString); + Assert.IsTrue(message.HasOneofBytes); + + Assert.AreEqual(ToBytes("604"), message.OneofBytes); } internal static void AssertClear(TestAllTypes message) @@ -661,6 +680,11 @@ namespace Google.ProtocolBuffers Assert.AreEqual("abc", message.DefaultStringPiece); Assert.AreEqual("123", message.DefaultCord); + + Assert.IsFalse(message.HasOneofUint32); + Assert.IsFalse(message.HasOneofNestedMessage); + Assert.IsFalse(message.HasOneofString); + Assert.IsFalse(message.HasOneofBytes); } /// @@ -817,6 +841,12 @@ namespace Google.ProtocolBuffers message.SetExtension(Unittest.DefaultStringPieceExtension, "424"); message.SetExtension(Unittest.DefaultCordExtension, "425"); + + message.SetExtension(Unittest.OneofUint32Extension, 601U); + message.SetExtension(Unittest.OneofNestedMessageExtension, + TestAllTypes.Types.NestedMessage.CreateBuilder().SetBb(602).Build()); + message.SetExtension(Unittest.OneofStringExtension, "603"); + message.SetExtension(Unittest.OneofBytesExtension, ToBytes("604")); } internal static void ModifyRepeatedFields(TestAllTypes.Builder message) @@ -1165,6 +1195,9 @@ namespace Google.ProtocolBuffers Assert.AreEqual("424", message.GetExtension(Unittest.DefaultStringPieceExtension)); Assert.AreEqual("425", message.GetExtension(Unittest.DefaultCordExtension)); + + Assert.IsTrue(message.HasExtension(Unittest.OneofBytesExtension)); + Assert.AreEqual(ToBytes("604"), message.GetExtension(Unittest.OneofBytesExtension)); } /// @@ -1451,6 +1484,11 @@ namespace Google.ProtocolBuffers Assert.AreEqual("abc", message.GetExtension(Unittest.DefaultStringPieceExtension)); Assert.AreEqual("123", message.GetExtension(Unittest.DefaultCordExtension)); + + Assert.IsFalse(message.HasExtension(Unittest.OneofUint32Extension)); + Assert.IsFalse(message.HasExtension(Unittest.OneofNestedMessageExtension)); + Assert.IsFalse(message.HasExtension(Unittest.OneofStringExtension)); + Assert.IsFalse(message.HasExtension(Unittest.OneofBytesExtension)); } /// @@ -1714,6 +1752,75 @@ namespace Google.ProtocolBuffers Assert.AreEqual(ForeignEnum.FOREIGN_BAZ, message.GetExtension(Unittest.UnpackedEnumExtension, 1)); } + public static void AssertAtMostOneFieldSetOneof(TestOneof2 message) + { + int count = 0; + if (message.HasFooInt) { ++count; } + if (message.HasFooString) { ++count; } + if (message.HasFooCord) { ++count; } + if (message.HasFooStringPiece) { ++count; } + if (message.HasFooBytes) { ++count; } + if (message.HasFooEnum) { ++count; } + if (message.HasFooMessage) { ++count; } + if (message.HasFooGroup) { ++count; } + if (message.HasFooLazyMessage) { ++count; } + Assert.True(count <= 1); + + count = 0; + if (message.HasBarInt) { ++count; } + if (message.HasBarString) { ++count; } + if (message.HasBarCord) { ++count; } + if (message.HasBarStringPiece) { ++count; } + if (message.HasBarBytes) { ++count; } + if (message.HasBarEnum) { ++count; } + Assert.True(count <= 1); + + switch (message.FooCase) + { + case TestOneof2.FooOneofCase.FooInt: + { + Assert.True(message.HasFooInt); + break; + } + case TestOneof2.FooOneofCase.FooString: + { + Assert.True(message.HasFooString); + break; + } + case TestOneof2.FooOneofCase.FooCord: + { + Assert.True(message.HasFooCord); + break; + } + case TestOneof2.FooOneofCase.FooBytes: + { + Assert.True(message.HasFooBytes); + break; + } + case TestOneof2.FooOneofCase.FooEnum: + { + Assert.True(message.HasFooEnum); + break; + } + case TestOneof2.FooOneofCase.FooMessage: + { + Assert.True(message.HasFooMessage); + break; + } + case TestOneof2.FooOneofCase.FooGroup: + { + Assert.True(message.HasFooGroup); + break; + } + case TestOneof2.FooOneofCase.FooLazyMessage: + { + Assert.True(message.HasFooLazyMessage); + break; + } + case TestOneof2.FooOneofCase.None: { break; } + } + } + private static readonly string[] TestCultures = {"en-US", "en-GB", "fr-FR", "de-DE"}; public delegate void CultureAction(); diff --git a/csharp/src/ProtocolBuffers.Test/WireFormatTest.cs b/csharp/src/ProtocolBuffers.Test/WireFormatTest.cs index 0c9b8c27..e728a176 100644 --- a/csharp/src/ProtocolBuffers.Test/WireFormatTest.cs +++ b/csharp/src/ProtocolBuffers.Test/WireFormatTest.cs @@ -164,7 +164,7 @@ namespace Google.ProtocolBuffers [Test] public void ExtensionsSerializedSize() { - Assert.AreEqual(TestUtil.GetAllSet().SerializedSize, TestUtil.GetAllExtensionsSet().SerializedSize); + Assert.IsTrue(TestUtil.GetAllSet().SerializedSize < TestUtil.GetAllExtensionsSet().SerializedSize); } private static void AssertFieldsInOrder(ByteString data) diff --git a/csharp/src/ProtocolBuffers/AbstractBuilder.cs b/csharp/src/ProtocolBuffers/AbstractBuilder.cs index e7a41fb3..8e33e931 100644 --- a/csharp/src/ProtocolBuffers/AbstractBuilder.cs +++ b/csharp/src/ProtocolBuffers/AbstractBuilder.cs @@ -58,8 +58,11 @@ namespace Google.ProtocolBuffers public abstract int GetRepeatedFieldCount(FieldDescriptor field); public abstract object this[FieldDescriptor field, int index] { get; set; } public abstract bool HasField(FieldDescriptor field); + public abstract bool HasOneof(OneofDescriptor oneof); + public abstract FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof); public abstract IBuilder CreateBuilderForField(FieldDescriptor field); public abstract TBuilder ClearField(FieldDescriptor field); + public abstract TBuilder ClearOneof(OneofDescriptor oneof); public abstract TBuilder AddRepeatedField(FieldDescriptor field, object value); #endregion @@ -248,6 +251,11 @@ namespace Google.ProtocolBuffers return ClearField(field); } + IBuilder IBuilder.WeakClearOneof(OneofDescriptor oneof) + { + return ClearOneof(oneof); + } + #endregion /// diff --git a/csharp/src/ProtocolBuffers/AbstractMessage.cs b/csharp/src/ProtocolBuffers/AbstractMessage.cs index 16c8c786..ef057e6f 100644 --- a/csharp/src/ProtocolBuffers/AbstractMessage.cs +++ b/csharp/src/ProtocolBuffers/AbstractMessage.cs @@ -62,6 +62,8 @@ namespace Google.ProtocolBuffers public abstract MessageDescriptor DescriptorForType { get; } public abstract IDictionary AllFields { get; } public abstract bool HasField(FieldDescriptor field); + public abstract bool HasOneof(OneofDescriptor oneof); + public abstract FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof); public abstract object this[FieldDescriptor field] { get; } public abstract int GetRepeatedFieldCount(FieldDescriptor field); public abstract object this[FieldDescriptor field, int index] { get; } diff --git a/csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs index 076dc852..e7f5a3c1 100644 --- a/csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs +++ b/csharp/src/ProtocolBuffers/Descriptors/FieldDescriptor.cs @@ -47,6 +47,7 @@ namespace Google.ProtocolBuffers.Descriptors private EnumDescriptor enumType; private MessageDescriptor messageType; private MessageDescriptor containingType; + private OneofDescriptor containingOneof; private object defaultValue; private FieldType fieldType; private MappedType mappedType; @@ -94,6 +95,16 @@ namespace Google.ProtocolBuffers.Descriptors "FieldDescriptorProto.Extendee set for non-extension field."); } containingType = parent; + if (proto.HasOneofIndex) + { + if (proto.OneofIndex < 0 || proto.OneofIndex >= parent.Proto.OneofDeclCount) + { + throw new DescriptorValidationException(this, + "FieldDescriptorProto.oneof_index is out of range for type " + parent.Name); + } + containingOneof = parent.Oneofs[proto.OneofIndex]; + containingOneof.fieldCount ++; + } extensionScope = null; } @@ -253,7 +264,12 @@ namespace Google.ProtocolBuffers.Descriptors { get { return containingType; } } - + + public OneofDescriptor ContainingOneof + { + get { return containingOneof; } + } + /// /// For extensions defined nested within message types, gets /// the outer type. Not valid for non-extension fields. diff --git a/csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs index 5b29849c..c00711b9 100644 --- a/csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs +++ b/csharp/src/ProtocolBuffers/Descriptors/MessageDescriptor.cs @@ -45,6 +45,7 @@ namespace Google.ProtocolBuffers.Descriptors private readonly IList enumTypes; private readonly IList fields; private readonly IList extensions; + private readonly IList oneofs; private bool hasRequiredFields; internal MessageDescriptor(DescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int typeIndex) @@ -52,6 +53,10 @@ namespace Google.ProtocolBuffers.Descriptors { containingType = parent; + oneofs = DescriptorUtil.ConvertAndMakeReadOnly(proto.OneofDeclList, + (oneof, index) => + new OneofDescriptor(oneof, file, this, index)); + nestedTypes = DescriptorUtil.ConvertAndMakeReadOnly(proto.NestedTypeList, (type, index) => new MessageDescriptor(type, file, this, index)); @@ -69,6 +74,19 @@ namespace Google.ProtocolBuffers.Descriptors (field, index) => new FieldDescriptor(field, file, this, index, true)); + for (int i = 0; i < proto.OneofDeclCount; i++) + { + oneofs[i].fields = new FieldDescriptor[oneofs[i].FieldCount]; + oneofs[i].fieldCount = 0; + } + for (int i = 0; i< proto.FieldCount; i++) + { + OneofDescriptor oneofDescriptor = fields[i].ContainingOneof; + if (oneofDescriptor != null) + { + oneofDescriptor.fields[oneofDescriptor.fieldCount++] = fields[i]; + } + } file.DescriptorPool.AddSymbol(this); } @@ -112,6 +130,11 @@ namespace Google.ProtocolBuffers.Descriptors get { return enumTypes; } } + public IList Oneofs + { + get { return oneofs; } + } + /// /// Returns a pre-computed result as to whether this message /// has required fields. This includes optional fields which are @@ -189,6 +212,11 @@ namespace Google.ProtocolBuffers.Descriptors { extension.CrossLink(); } + + foreach (OneofDescriptor oneof in oneofs) + { + // oneof.C + } } internal void CheckRequiredFields() diff --git a/csharp/src/ProtocolBuffers/Descriptors/OneofDescriptor.cs b/csharp/src/ProtocolBuffers/Descriptors/OneofDescriptor.cs new file mode 100644 index 00000000..aa62853b --- /dev/null +++ b/csharp/src/ProtocolBuffers/Descriptors/OneofDescriptor.cs @@ -0,0 +1,78 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// Author: jieluo@google.com (Jie Luo) +// +// 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. +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using Google.ProtocolBuffers.DescriptorProtos; + +namespace Google.ProtocolBuffers.Descriptors +{ + public sealed class OneofDescriptor + { + private int index; + private OneofDescriptorProto proto; + private FileDescriptor file; + private MessageDescriptor containingType; + internal int fieldCount; + internal IList fields; + + internal OneofDescriptor(OneofDescriptorProto proto, FileDescriptor file, + MessageDescriptor parent, int index) + { + this.proto = proto; + this.file = file; + this.index = index; + + containingType = parent; + fieldCount = 0; + } + + public int Index + { + get { return index; } + } + + public MessageDescriptor ContainingType + { + get { return containingType; } + } + + public int FieldCount + { + get { return fieldCount; } + } + + public FieldDescriptor Field(int index) + { + return fields[index]; + } + } +} diff --git a/csharp/src/ProtocolBuffers/DynamicMessage.cs b/csharp/src/ProtocolBuffers/DynamicMessage.cs index e39efb12..0a8772ca 100644 --- a/csharp/src/ProtocolBuffers/DynamicMessage.cs +++ b/csharp/src/ProtocolBuffers/DynamicMessage.cs @@ -48,6 +48,7 @@ namespace Google.ProtocolBuffers { private readonly MessageDescriptor type; private readonly FieldSet fields; + private readonly FieldDescriptor[] oneofCase; private readonly UnknownFieldSet unknownFields; private int memoizedSize = -1; @@ -57,10 +58,12 @@ namespace Google.ProtocolBuffers /// /// /// - private DynamicMessage(MessageDescriptor type, FieldSet fields, UnknownFieldSet unknownFields) + private DynamicMessage(MessageDescriptor type, FieldSet fields, + FieldDescriptor[] oneofCase, UnknownFieldSet unknownFields) { this.type = type; this.fields = fields; + this.oneofCase = oneofCase; this.unknownFields = unknownFields; } @@ -71,7 +74,9 @@ namespace Google.ProtocolBuffers /// public static DynamicMessage GetDefaultInstance(MessageDescriptor type) { - return new DynamicMessage(type, FieldSet.DefaultInstance, UnknownFieldSet.DefaultInstance); + int oneofDescriptorCount = type.Proto.OneofDeclCount; + FieldDescriptor[] oneofCase = new FieldDescriptor[oneofDescriptorCount]; + return new DynamicMessage(type, FieldSet.DefaultInstance, oneofCase, UnknownFieldSet.DefaultInstance); } /// @@ -201,6 +206,23 @@ namespace Google.ProtocolBuffers get { return fields.AllFieldDescriptors; } } + public override bool HasOneof(OneofDescriptor oneof) + { + VerifyContainingOneofType(oneof); + FieldDescriptor field = oneofCase[oneof.Index]; + if (field == null) + { + return false; + } + return true; + } + + public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof) + { + VerifyContainingOneofType(oneof); + return oneofCase[oneof.Index]; + } + public override bool HasField(FieldDescriptor field) { VerifyContainingType(field); @@ -305,6 +327,17 @@ namespace Google.ProtocolBuffers } } + /// + /// Verifies that the oneof is an oneof of this message. + /// + private void VerifyContainingOneofType(OneofDescriptor oneof) + { + if (oneof.ContainingType != type) + { + throw new ArgumentException("OneofDescritpor does not match message type"); + } + } + /// /// Builder for dynamic messages. Instances are created with DynamicMessage.CreateBuilder. /// @@ -312,6 +345,7 @@ namespace Google.ProtocolBuffers { private readonly MessageDescriptor type; private FieldSet fields; + private FieldDescriptor[] oneofCase; private UnknownFieldSet unknownFields; internal Builder(MessageDescriptor type) @@ -319,6 +353,7 @@ namespace Google.ProtocolBuffers this.type = type; this.fields = FieldSet.CreateInstance(); this.unknownFields = UnknownFieldSet.DefaultInstance; + this.oneofCase = new FieldDescriptor[type.Proto.OneofDeclCount]; } protected override Builder ThisBuilder @@ -340,6 +375,23 @@ namespace Google.ProtocolBuffers } fields.MergeFrom(other); MergeUnknownFields(other.UnknownFields); + for (int i = 0; i < oneofCase.Length; i++) + { + if (other.HasOneof(type.Oneofs[i])) + { + if (oneofCase[i] == null) + { + oneofCase[i] = other.OneofFieldDescriptor(type.Oneofs[i]); + } else + { + if (oneofCase[i] != other.OneofFieldDescriptor(type.Oneofs[i])) + { + fields.ClearField(oneofCase[i]); + oneofCase[i] = other.OneofFieldDescriptor(type.Oneofs[i]); + } + } + } + } return this; } @@ -353,7 +405,7 @@ namespace Google.ProtocolBuffers { if (fields != null && !IsInitialized) { - throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)); + throw new UninitializedMessageException(new DynamicMessage(type, fields, oneofCase, unknownFields)); } return BuildPartial(); } @@ -367,7 +419,7 @@ namespace Google.ProtocolBuffers { if (!IsInitialized) { - throw new UninitializedMessageException(new DynamicMessage(type, fields, unknownFields)). + throw new UninitializedMessageException(new DynamicMessage(type, fields, oneofCase, unknownFields)). AsInvalidProtocolBufferException(); } return BuildPartial(); @@ -380,7 +432,7 @@ namespace Google.ProtocolBuffers throw new InvalidOperationException("Build() has already been called on this Builder."); } fields.MakeImmutable(); - DynamicMessage result = new DynamicMessage(type, fields, unknownFields); + DynamicMessage result = new DynamicMessage(type, fields, oneofCase, unknownFields); fields = null; unknownFields = null; return result; @@ -390,6 +442,7 @@ namespace Google.ProtocolBuffers { Builder result = new Builder(type); result.fields.MergeFrom(fields); + result.oneofCase = oneofCase; return result; } @@ -431,6 +484,23 @@ namespace Google.ProtocolBuffers return new Builder(field.MessageType); } + public override bool HasOneof(OneofDescriptor oneof) + { + VerifyContainingOneofType(oneof); + FieldDescriptor field = oneofCase[oneof.Index]; + if (field == null) + { + return false; + } + return true; + } + + public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof) + { + VerifyContainingOneofType(oneof); + return oneofCase[oneof.Index]; + } + public override bool HasField(FieldDescriptor field) { VerifyContainingType(field); @@ -466,6 +536,17 @@ namespace Google.ProtocolBuffers set { VerifyContainingType(field); + OneofDescriptor oneof = field.ContainingOneof; + if (oneof != null) + { + int index = oneof.Index; + FieldDescriptor oldField = oneofCase[index]; + if ((oldField != null) && (oldField != field)) + { + fields.ClearField(oldField); + } + oneofCase[index] = field; + } fields[field] = value; } } @@ -473,10 +554,30 @@ namespace Google.ProtocolBuffers public override Builder ClearField(FieldDescriptor field) { VerifyContainingType(field); + OneofDescriptor oneof = field.ContainingOneof; + if (oneof != null) + { + int index = oneof.Index; + if (oneofCase[index] == field) + { + oneofCase[index] = null; + } + } fields.ClearField(field); return this; } + public override Builder ClearOneof(OneofDescriptor oneof) + { + VerifyContainingOneofType(oneof); + FieldDescriptor field = oneofCase[oneof.Index]; + if (field != null) + { + ClearField(field); + } + return this; + } + public override int GetRepeatedFieldCount(FieldDescriptor field) { VerifyContainingType(field); @@ -507,6 +608,17 @@ namespace Google.ProtocolBuffers throw new ArgumentException("FieldDescriptor does not match message type."); } } + + /// + /// Verifies that the oneof is an oneof of this message. + /// + private void VerifyContainingOneofType(OneofDescriptor oneof) + { + if (oneof.ContainingType != type) + { + throw new ArgumentException("OneofDescriptor does not match message type"); + } + } } } } \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs index 6e20b14e..ad1a4382 100644 --- a/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs +++ b/csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorTable.cs @@ -45,6 +45,7 @@ namespace Google.ProtocolBuffers.FieldAccess where TBuilder : IBuilder { private readonly IFieldAccessor[] accessors; + private readonly OneofAccessor[] oneofs; private readonly MessageDescriptor descriptor; @@ -68,17 +69,28 @@ namespace Google.ProtocolBuffers.FieldAccess { this.descriptor = descriptor; accessors = new IFieldAccessor[descriptor.Fields.Count]; + oneofs = new OneofAccessor[descriptor.Oneofs.Count]; bool supportFieldPresence = descriptor.File.Syntax == FileDescriptor.ProtoSyntax.Proto2; - for (int i = 0; i < accessors.Length; i++) + int fieldSize = accessors.Length; + for (int i = 0; i < fieldSize; i++) { - accessors[i] = CreateAccessor(descriptor.Fields[i], propertyNames[i], supportFieldPresence); + FieldDescriptor field = descriptor.Fields[i]; + string containingOneofName = (field.ContainingOneof != null) ? + propertyNames[fieldSize +field.ContainingOneof.Index] : null; + accessors[i] = CreateAccessor( + field, propertyNames[i], containingOneofName, supportFieldPresence); + } + for (int i = 0; i < oneofs.Length; i++) + { + oneofs[i] = new OneofAccessor(descriptor, propertyNames[i + accessors.Length]); } } /// /// Creates an accessor for a single field /// - private static IFieldAccessor CreateAccessor(FieldDescriptor field, string name, bool supportFieldPresence) + private static IFieldAccessor CreateAccessor( + FieldDescriptor field, string name, string containingOneofName, bool supportFieldPresence) { if (field.IsRepeated) { @@ -97,11 +109,24 @@ namespace Google.ProtocolBuffers.FieldAccess switch (field.MappedType) { case MappedType.Message: - return new SingleMessageAccessor(name); + { + if (field.ContainingOneof != null) + { + return new SingleMessageAccessor( + field, name, containingOneofName, supportFieldPresence); + } + else + { + return new SingleMessageAccessor( + field, name, containingOneofName, true); + } + } case MappedType.Enum: - return new SingleEnumAccessor(field, name, supportFieldPresence); + return new SingleEnumAccessor( + field, name, containingOneofName, supportFieldPresence); default: - return new SinglePrimitiveAccessor(field, name, supportFieldPresence); + return new SinglePrimitiveAccessor( + field, name, containingOneofName, supportFieldPresence); } } } @@ -123,5 +148,14 @@ namespace Google.ProtocolBuffers.FieldAccess return accessors[field.Index]; } } + + internal OneofAccessor Oneof(OneofDescriptor oneof) + { + if (oneof.ContainingType != descriptor) + { + throw new ArgumentException("OneofDescriptor does not match message type"); + } + return oneofs[oneof.Index]; + } } } \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs new file mode 100644 index 00000000..1a4bda76 --- /dev/null +++ b/csharp/src/ProtocolBuffers/FieldAccess/OneofAccessor.cs @@ -0,0 +1,91 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2015 Google Inc. All rights reserved. +// Author: jieluo@google.com (Jie Luo) +// +// 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. +using System; +using System.Reflection; +using Google.ProtocolBuffers.Descriptors; + +namespace Google.ProtocolBuffers.FieldAccess +{ + /// + /// Access for an oneof + /// + internal class OneofAccessor + where TMessage : IMessage + where TBuilder : IBuilder + { + private readonly Func caseDelegate; + private readonly Func clearDelegate; + private MessageDescriptor descriptor; + + internal OneofAccessor(MessageDescriptor descriptor, string name) + { + this.descriptor = descriptor; + MethodInfo clearMethod = typeof(TBuilder).GetMethod("Clear" + name); + PropertyInfo caseProperty = typeof(TMessage).GetProperty(name + "Case"); + if (clearMethod == null || caseProperty == null) + { + throw new ArgumentException("Not all required properties/methods available for oneof"); + } + + + clearDelegate = ReflectionUtil.CreateDelegateFunc(clearMethod); + caseDelegate = ReflectionUtil.CreateUpcastDelegate(caseProperty.GetGetMethod()); + } + + /// + /// Indicates whether the specified message has set any field in the oneof. + /// + public bool Has(TMessage message) + { + return ((int) caseDelegate(message) != 0); + } + + /// + /// Clears the oneof in the specified builder. + /// + public void Clear(TBuilder builder) + { + clearDelegate(builder); + } + + /// + /// Indicates which field in the oneof is set for specified message + /// + public virtual FieldDescriptor GetOneofFieldDescriptor(TMessage message) + { + int fieldNumber = (int) caseDelegate(message); + if (fieldNumber > 0) + { + return descriptor.FindFieldByNumber(fieldNumber); + } + return null; + } + } +} diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs index e63f717c..89e10179 100644 --- a/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs +++ b/csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs @@ -42,7 +42,8 @@ namespace Google.ProtocolBuffers.FieldAccess { private readonly EnumDescriptor enumDescriptor; - internal SingleEnumAccessor(FieldDescriptor field, string name, bool supportFieldPresence) : base(field, name, supportFieldPresence) + internal SingleEnumAccessor(FieldDescriptor field, string name, string containingOneofName, bool supportFieldPresence) + : base(field, name, containingOneofName, supportFieldPresence) { enumDescriptor = field.EnumType; } diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs index 0ec2b0b7..9068d40a 100644 --- a/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs +++ b/csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs @@ -31,6 +31,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using System.Reflection; +using Google.ProtocolBuffers.Descriptors; namespace Google.ProtocolBuffers.FieldAccess { @@ -48,7 +49,8 @@ namespace Google.ProtocolBuffers.FieldAccess /// private readonly Func createBuilderDelegate; - internal SingleMessageAccessor(string name) : base(null, name, true) + internal SingleMessageAccessor(FieldDescriptor field, string name, string containingOneofName, bool supportFieldPresence) + : base(field, name, containingOneofName, supportFieldPresence) { MethodInfo createBuilderMethod = ClrType.GetMethod("CreateBuilder", ReflectionUtil.EmptyTypes); if (createBuilderMethod == null) diff --git a/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs b/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs index b9ab7293..035fcf3c 100644 --- a/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs +++ b/csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs @@ -47,6 +47,7 @@ namespace Google.ProtocolBuffers.FieldAccess private readonly Action setValueDelegate; private readonly Func hasDelegate; private readonly Func clearDelegate; + private readonly Func caseDelegate; /// /// The CLR type of the field (int, the enum type, ByteString, the message etc). @@ -57,7 +58,8 @@ namespace Google.ProtocolBuffers.FieldAccess get { return clrType; } } - internal SinglePrimitiveAccessor(FieldDescriptor fieldDescriptor, string name, bool supportFieldPresence) + internal SinglePrimitiveAccessor( + FieldDescriptor fieldDescriptor, string name, string containingOneofName, bool supportFieldPresence) { PropertyInfo messageProperty = typeof(TMessage).GetProperty(name, null, ReflectionUtil.EmptyTypes); PropertyInfo builderProperty = typeof(TBuilder).GetProperty(name, null, ReflectionUtil.EmptyTypes); @@ -77,7 +79,16 @@ namespace Google.ProtocolBuffers.FieldAccess hasDelegate = ReflectionUtil.CreateDelegateFunc(hasProperty.GetGetMethod()); } else { - hasDelegate = message => !GetValue(message).Equals(fieldDescriptor.DefaultValue); + if (fieldDescriptor.ContainingOneof != null) + { + PropertyInfo caseProperty = typeof(TMessage).GetProperty(containingOneofName + "Case"); + caseDelegate = ReflectionUtil.CreateUpcastDelegate(caseProperty.GetGetMethod()); + hasDelegate = message => OneofFieldNumber(message).Equals(fieldDescriptor.FieldNumber); + } + else + { + hasDelegate = message => !GetValue(message).Equals(fieldDescriptor.DefaultValue); + } } clrType = messageProperty.PropertyType; @@ -86,6 +97,11 @@ namespace Google.ProtocolBuffers.FieldAccess setValueDelegate = ReflectionUtil.CreateDowncastDelegate(builderProperty.GetSetMethod()); } + private int OneofFieldNumber(TMessage message) + { + return (int) caseDelegate(message); + } + public bool Has(TMessage message) { return hasDelegate(message); @@ -143,4 +159,4 @@ namespace Google.ProtocolBuffers.FieldAccess #endregion } -} \ No newline at end of file +} diff --git a/csharp/src/ProtocolBuffers/GeneratedBuilder.cs b/csharp/src/ProtocolBuffers/GeneratedBuilder.cs index e60a4201..0f121ae8 100644 --- a/csharp/src/ProtocolBuffers/GeneratedBuilder.cs +++ b/csharp/src/ProtocolBuffers/GeneratedBuilder.cs @@ -105,6 +105,16 @@ namespace Google.ProtocolBuffers set { InternalFieldAccessors[field].SetRepeated(ThisBuilder, index, value); } } + public override bool HasOneof(OneofDescriptor oneof) + { + return MessageBeingBuilt.HasOneof(oneof); + } + + public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof) + { + return MessageBeingBuilt.OneofFieldDescriptor(oneof); + } + public override bool HasField(FieldDescriptor field) { return MessageBeingBuilt.HasField(field); @@ -121,6 +131,12 @@ namespace Google.ProtocolBuffers return ThisBuilder; } + public override TBuilder ClearOneof(OneofDescriptor oneof) + { + InternalFieldAccessors.Oneof(oneof).Clear(ThisBuilder); + return ThisBuilder; + } + public override TBuilder MergeFrom(TMessage other) { if (other.DescriptorForType != InternalFieldAccessors.Descriptor) diff --git a/csharp/src/ProtocolBuffers/GeneratedMessage.cs b/csharp/src/ProtocolBuffers/GeneratedMessage.cs index c17c15cf..ff3a0c2a 100644 --- a/csharp/src/ProtocolBuffers/GeneratedMessage.cs +++ b/csharp/src/ProtocolBuffers/GeneratedMessage.cs @@ -142,6 +142,16 @@ namespace Google.ProtocolBuffers get { return Dictionaries.AsReadOnly(GetMutableFieldMap()); } } + public override bool HasOneof(OneofDescriptor oneof) + { + return InternalFieldAccessors.Oneof(oneof).Has(ThisMessage); + } + + public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof) + { + return InternalFieldAccessors.Oneof(oneof).GetOneofFieldDescriptor(ThisMessage); + } + public override bool HasField(FieldDescriptor field) { return InternalFieldAccessors[field].Has(ThisMessage); diff --git a/csharp/src/ProtocolBuffers/IBuilder.cs b/csharp/src/ProtocolBuffers/IBuilder.cs index f9c0df61..e765464a 100644 --- a/csharp/src/ProtocolBuffers/IBuilder.cs +++ b/csharp/src/ProtocolBuffers/IBuilder.cs @@ -103,6 +103,11 @@ namespace Google.ProtocolBuffers /// object this[FieldDescriptor field, int index] { get; set; } + + bool HasOneof(OneofDescriptor oneof); + + FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof); + /// /// /// @@ -125,6 +130,7 @@ namespace Google.ProtocolBuffers IBuilder WeakAddRepeatedField(FieldDescriptor field, object value); new IBuilder WeakClear(); IBuilder WeakClearField(FieldDescriptor field); + IBuilder WeakClearOneof(OneofDescriptor oneof); IBuilder WeakMergeFrom(IMessage message); new IBuilder WeakMergeFrom(ByteString data); new IBuilder WeakMergeFrom(ByteString data, ExtensionRegistry registry); @@ -227,6 +233,14 @@ namespace Google.ProtocolBuffers /// TBuilder ClearField(FieldDescriptor field); + /// + /// Clears the oneof. This is exactly equivalent to calling the generated + /// Clear method corresponding to the oneof. + /// + /// + /// + TBuilder ClearOneof(OneofDescriptor oneof); + /// /// Appends the given value as a new element for the specified repeated field. /// diff --git a/csharp/src/ProtocolBuffers/IMessage.cs b/csharp/src/ProtocolBuffers/IMessage.cs index c23bc3f7..dd309d4e 100644 --- a/csharp/src/ProtocolBuffers/IMessage.cs +++ b/csharp/src/ProtocolBuffers/IMessage.cs @@ -67,6 +67,10 @@ namespace Google.ProtocolBuffers /// IDictionary AllFields { get; } + bool HasOneof(OneofDescriptor oneof); + + FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof); + /// /// Returns true if the given field is set. This is exactly equivalent /// to calling the generated "Has" property corresponding to the field. diff --git a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj index 32a343ad..7dc8f665 100644 --- a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj +++ b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj @@ -81,6 +81,7 @@ + @@ -106,6 +107,7 @@ + @@ -146,4 +148,4 @@ --> - \ No newline at end of file + diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs index 083523c0..67898644 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs @@ -355,6 +355,8 @@ namespace Google.ProtocolBuffers.TestProtos { internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_protobuf_unittest_ForeignMessage__Descriptor; internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable; + internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestReservedFields__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_protobuf_unittest_TestAllExtensions__Descriptor; internal static pb::FieldAccess.FieldAccessorTable internal__static_protobuf_unittest_TestAllExtensions__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor; @@ -565,426 +567,429 @@ namespace Google.ProtocolBuffers.TestProtos { "ZXMYciABKAxIABobCg1OZXN0ZWRNZXNzYWdlEgoKAmJiGAEgASgFGhoKDU9w", "dGlvbmFsR3JvdXASCQoBYRgRIAEoBRoaCg1SZXBlYXRlZEdyb3VwEgkKAWEY", "LyABKAUiOQoKTmVzdGVkRW51bRIHCgNGT08QARIHCgNCQVIQAhIHCgNCQVoQ", - "AxIQCgNORUcQ////////////AUINCgtvbmVvZl9maWVsZCJ8ChJOZXN0ZWRU", - "ZXN0QWxsVHlwZXMSNAoFY2hpbGQYASABKAsyJS5wcm90b2J1Zl91bml0dGVz", - "dC5OZXN0ZWRUZXN0QWxsVHlwZXMSMAoHcGF5bG9hZBgCIAEoCzIfLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcyI0ChRUZXN0RGVwcmVjYXRlZEZp", - "ZWxkcxIcChBkZXByZWNhdGVkX2ludDMyGAEgASgFQgIYASIbCg5Gb3JlaWdu", - "TWVzc2FnZRIJCgFjGAEgASgFIh0KEVRlc3RBbGxFeHRlbnNpb25zKggIARCA", - "gICAAiIkChdPcHRpb25hbEdyb3VwX2V4dGVuc2lvbhIJCgFhGBEgASgFIiQK", - "F1JlcGVhdGVkR3JvdXBfZXh0ZW5zaW9uEgkKAWEYLyABKAUimAEKE1Rlc3RO", - "ZXN0ZWRFeHRlbnNpb24yOQoEdGVzdBIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGOoHIAEoCToEdGVzdDJGChduZXN0ZWRfc3RyaW5n", - "X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNp", - "b25zGOsHIAEoCSLVBQoMVGVzdFJlcXVpcmVkEgkKAWEYASACKAUSDgoGZHVt", - "bXkyGAIgASgFEgkKAWIYAyACKAUSDgoGZHVtbXk0GAQgASgFEg4KBmR1bW15", - "NRgFIAEoBRIOCgZkdW1teTYYBiABKAUSDgoGZHVtbXk3GAcgASgFEg4KBmR1", - "bW15OBgIIAEoBRIOCgZkdW1teTkYCSABKAUSDwoHZHVtbXkxMBgKIAEoBRIP", - "CgdkdW1teTExGAsgASgFEg8KB2R1bW15MTIYDCABKAUSDwoHZHVtbXkxMxgN", - "IAEoBRIPCgdkdW1teTE0GA4gASgFEg8KB2R1bW15MTUYDyABKAUSDwoHZHVt", - "bXkxNhgQIAEoBRIPCgdkdW1teTE3GBEgASgFEg8KB2R1bW15MTgYEiABKAUS", - "DwoHZHVtbXkxORgTIAEoBRIPCgdkdW1teTIwGBQgASgFEg8KB2R1bW15MjEY", - "FSABKAUSDwoHZHVtbXkyMhgWIAEoBRIPCgdkdW1teTIzGBcgASgFEg8KB2R1", - "bW15MjQYGCABKAUSDwoHZHVtbXkyNRgZIAEoBRIPCgdkdW1teTI2GBogASgF", - "Eg8KB2R1bW15MjcYGyABKAUSDwoHZHVtbXkyOBgcIAEoBRIPCgdkdW1teTI5", - "GB0gASgFEg8KB2R1bW15MzAYHiABKAUSDwoHZHVtbXkzMRgfIAEoBRIPCgdk", - "dW1teTMyGCAgASgFEgkKAWMYISACKAUyVgoGc2luZ2xlEiQucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMY6AcgASgLMh8ucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdFJlcXVpcmVkMlUKBW11bHRpEiQucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMY6QcgAygLMh8ucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdFJlcXVpcmVkIpoBChNUZXN0UmVxdWlyZWRGb3JlaWduEjkK", - "EG9wdGlvbmFsX21lc3NhZ2UYASABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5U", - "ZXN0UmVxdWlyZWQSOQoQcmVwZWF0ZWRfbWVzc2FnZRgCIAMoCzIfLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RSZXF1aXJlZBINCgVkdW1teRgDIAEoBSJaChFU", - "ZXN0Rm9yZWlnbk5lc3RlZBJFCg5mb3JlaWduX25lc3RlZBgBIAEoCzItLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlIhIK", - "EFRlc3RFbXB0eU1lc3NhZ2UiKgoeVGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRl", - "bnNpb25zKggIARCAgICAAiI3ChtUZXN0TXVsdGlwbGVFeHRlbnNpb25SYW5n", - "ZXMqBAgqECsqBgivIBCUISoKCICABBCAgICAAiI0ChhUZXN0UmVhbGx5TGFy", - "Z2VUYWdOdW1iZXISCQoBYRgBIAEoBRINCgJiYhj///9/IAEoBSJVChRUZXN0", - "UmVjdXJzaXZlTWVzc2FnZRIyCgFhGAEgASgLMicucHJvdG9idWZfdW5pdHRl", - "c3QuVGVzdFJlY3Vyc2l2ZU1lc3NhZ2USCQoBaRgCIAEoBSJLChRUZXN0TXV0", - "dWFsUmVjdXJzaW9uQRIzCgJiYhgBIAEoCzInLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RNdXR1YWxSZWN1cnNpb25CImIKFFRlc3RNdXR1YWxSZWN1cnNpb25C", - "EjIKAWEYASABKAsyJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0TXV0dWFsUmVj", - "dXJzaW9uQRIWCg5vcHRpb25hbF9pbnQzMhgCIAEoBSKzAQoSVGVzdER1cEZp", - "ZWxkTnVtYmVyEgkKAWEYASABKAUSNgoDZm9vGAIgASgKMikucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdER1cEZpZWxkTnVtYmVyLkZvbxI2CgNiYXIYAyABKAoy", - "KS5wcm90b2J1Zl91bml0dGVzdC5UZXN0RHVwRmllbGROdW1iZXIuQmFyGhAK", - "A0ZvbxIJCgFhGAEgASgFGhAKA0JhchIJCgFhGAEgASgFIkwKEFRlc3RFYWdl", - "ck1lc3NhZ2USOAoLc3ViX21lc3NhZ2UYASABKAsyHy5wcm90b2J1Zl91bml0", - "dGVzdC5UZXN0QWxsVHlwZXNCAigAIksKD1Rlc3RMYXp5TWVzc2FnZRI4Cgtz", - "dWJfbWVzc2FnZRgBIAEoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxU", - "eXBlc0ICKAEigAIKGFRlc3ROZXN0ZWRNZXNzYWdlSGFzQml0cxJaChdvcHRp", - "b25hbF9uZXN0ZWRfbWVzc2FnZRgBIAEoCzI5LnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3ROZXN0ZWRNZXNzYWdlSGFzQml0cy5OZXN0ZWRNZXNzYWdlGocBCg1O", - "ZXN0ZWRNZXNzYWdlEiQKHG5lc3RlZG1lc3NhZ2VfcmVwZWF0ZWRfaW50MzIY", - "ASADKAUSUAolbmVzdGVkbWVzc2FnZV9yZXBlYXRlZF9mb3JlaWdubWVzc2Fn", - "ZRgCIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlIuUD", - "ChdUZXN0Q2FtZWxDYXNlRmllbGROYW1lcxIWCg5QcmltaXRpdmVGaWVsZBgB", - "IAEoBRITCgtTdHJpbmdGaWVsZBgCIAEoCRIxCglFbnVtRmllbGQYAyABKA4y", - "Hi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bRI3CgxNZXNzYWdlRmll", - "bGQYBCABKAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZRIc", - "ChBTdHJpbmdQaWVjZUZpZWxkGAUgASgJQgIIAhIVCglDb3JkRmllbGQYBiAB", - "KAlCAggBEh4KFlJlcGVhdGVkUHJpbWl0aXZlRmllbGQYByADKAUSGwoTUmVw", - "ZWF0ZWRTdHJpbmdGaWVsZBgIIAMoCRI5ChFSZXBlYXRlZEVudW1GaWVsZBgJ", - "IAMoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtEj8KFFJlcGVh", - "dGVkTWVzc2FnZUZpZWxkGAogAygLMiEucHJvdG9idWZfdW5pdHRlc3QuRm9y", - "ZWlnbk1lc3NhZ2USJAoYUmVwZWF0ZWRTdHJpbmdQaWVjZUZpZWxkGAsgAygJ", - "QgIIAhIdChFSZXBlYXRlZENvcmRGaWVsZBgMIAMoCUICCAEi1QEKElRlc3RG", - "aWVsZE9yZGVyaW5ncxIRCglteV9zdHJpbmcYCyABKAkSDgoGbXlfaW50GAEg", - "ASgDEhAKCG15X2Zsb2F0GGUgASgCElUKF29wdGlvbmFsX25lc3RlZF9tZXNz", - "YWdlGMgBIAEoCzIzLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RGaWVsZE9yZGVy", - "aW5ncy5OZXN0ZWRNZXNzYWdlGicKDU5lc3RlZE1lc3NhZ2USCgoCb28YAiAB", - "KAMSCgoCYmIYASABKAUqBAgCEAsqBAgMEGUitgcKGFRlc3RFeHRyZW1lRGVm", - "YXVsdFZhbHVlcxI/Cg1lc2NhcGVkX2J5dGVzGAEgASgMOihcMDAwXDAwMVww", - "MDdcMDEwXDAxNFxuXHJcdFwwMTNcXFwnXCJcMzc2EiAKDGxhcmdlX3VpbnQz", - "MhgCIAEoDToKNDI5NDk2NzI5NRIqCgxsYXJnZV91aW50NjQYAyABKAQ6FDE4", - "NDQ2NzQ0MDczNzA5NTUxNjE1EiAKC3NtYWxsX2ludDMyGAQgASgFOgstMjE0", - "NzQ4MzY0NxIpCgtzbWFsbF9pbnQ2NBgFIAEoAzoULTkyMjMzNzIwMzY4NTQ3", - "NzU4MDcSJwoScmVhbGx5X3NtYWxsX2ludDMyGBUgASgFOgstMjE0NzQ4MzY0", - "OBIwChJyZWFsbHlfc21hbGxfaW50NjQYFiABKAM6FC05MjIzMzcyMDM2ODU0", - "Nzc1ODA4EhgKC3V0Zjhfc3RyaW5nGAYgASgJOgPhiLQSFQoKemVyb19mbG9h", - "dBgHIAEoAjoBMBIUCglvbmVfZmxvYXQYCCABKAI6ATESGAoLc21hbGxfZmxv", - "YXQYCSABKAI6AzEuNRIeChJuZWdhdGl2ZV9vbmVfZmxvYXQYCiABKAI6Ai0x", - "EhwKDm5lZ2F0aXZlX2Zsb2F0GAsgASgCOgQtMS41EhoKC2xhcmdlX2Zsb2F0", - "GAwgASgCOgUyZSswOBIkChRzbWFsbF9uZWdhdGl2ZV9mbG9hdBgNIAEoAjoG", - "LThlLTI4EhcKCmluZl9kb3VibGUYDiABKAE6A2luZhIcCg5uZWdfaW5mX2Rv", - "dWJsZRgPIAEoAToELWluZhIXCgpuYW5fZG91YmxlGBAgASgBOgNuYW4SFgoJ", - "aW5mX2Zsb2F0GBEgASgCOgNpbmYSGwoNbmVnX2luZl9mbG9hdBgSIAEoAjoE", - "LWluZhIWCgluYW5fZmxvYXQYEyABKAI6A25hbhIrCgxjcHBfdHJpZ3JhcGgY", - "FCABKAk6FT8gPyA/PyA/PyA/Pz8gPz8vID8/LRIgChBzdHJpbmdfd2l0aF96", - "ZXJvGBcgASgJOgZoZWwAbG8SIgoPYnl0ZXNfd2l0aF96ZXJvGBggASgMOgl3", - "b3JcMDAwbGQSKAoWc3RyaW5nX3BpZWNlX3dpdGhfemVybxgZIAEoCToEYWIA", - "Y0ICCAISIAoOY29yZF93aXRoX3plcm8YGiABKAk6BDEyADNCAggBEiYKEnJl", - "cGxhY2VtZW50X3N0cmluZxgbIAEoCToKJHt1bmtub3dufSJLChFTcGFyc2VF", - "bnVtTWVzc2FnZRI2CgtzcGFyc2VfZW51bRgBIAEoDjIhLnByb3RvYnVmX3Vu", - "aXR0ZXN0LlRlc3RTcGFyc2VFbnVtIhkKCU9uZVN0cmluZxIMCgRkYXRhGAEg", - "ASgJIhoKCk1vcmVTdHJpbmcSDAoEZGF0YRgBIAMoCSIYCghPbmVCeXRlcxIM", - "CgRkYXRhGAEgASgMIhkKCU1vcmVCeXRlcxIMCgRkYXRhGAEgAygMIhwKDElu", - "dDMyTWVzc2FnZRIMCgRkYXRhGAEgASgFIh0KDVVpbnQzMk1lc3NhZ2USDAoE", - "ZGF0YRgBIAEoDSIcCgxJbnQ2NE1lc3NhZ2USDAoEZGF0YRgBIAEoAyIdCg1V", - "aW50NjRNZXNzYWdlEgwKBGRhdGEYASABKAQiGwoLQm9vbE1lc3NhZ2USDAoE", - "ZGF0YRgBIAEoCCLQAQoJVGVzdE9uZW9mEhEKB2Zvb19pbnQYASABKAVIABIU", - "Cgpmb29fc3RyaW5nGAIgASgJSAASNgoLZm9vX21lc3NhZ2UYAyABKAsyHy5w", - "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNIABI5Cghmb29ncm91cBgE", - "IAEoCjIlLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVvZi5Gb29Hcm91cEgA", - "GiAKCEZvb0dyb3VwEgkKAWEYBSABKAUSCQoBYhgGIAEoCUIFCgNmb28i5wEK", - "HFRlc3RPbmVvZkJhY2t3YXJkc0NvbXBhdGlibGUSDwoHZm9vX2ludBgBIAEo", - "BRISCgpmb29fc3RyaW5nGAIgASgJEjQKC2Zvb19tZXNzYWdlGAMgASgLMh8u", - "cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzEkoKCGZvb2dyb3VwGAQg", - "ASgKMjgucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mQmFja3dhcmRzQ29t", - "cGF0aWJsZS5Gb29Hcm91cBogCghGb29Hcm91cBIJCgFhGAUgASgFEgkKAWIY", - "BiABKAkingYKClRlc3RPbmVvZjISEQoHZm9vX2ludBgBIAEoBUgAEhQKCmZv", - "b19zdHJpbmcYAiABKAlIABIWCghmb29fY29yZBgDIAEoCUICCAFIABIeChBm", - "b29fc3RyaW5nX3BpZWNlGAQgASgJQgIIAkgAEhMKCWZvb19ieXRlcxgFIAEo", - "DEgAEjwKCGZvb19lbnVtGAYgASgOMigucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dE9uZW9mMi5OZXN0ZWRFbnVtSAASQgoLZm9vX21lc3NhZ2UYByABKAsyKy5w", - "cm90b2J1Zl91bml0dGVzdC5UZXN0T25lb2YyLk5lc3RlZE1lc3NhZ2VIABI6", - "Cghmb29ncm91cBgIIAEoCjImLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVv", - "ZjIuRm9vR3JvdXBIABJLChBmb29fbGF6eV9tZXNzYWdlGAsgASgLMisucHJv", - "dG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mMi5OZXN0ZWRNZXNzYWdlQgIoAUgA", - "EhQKB2Jhcl9pbnQYDCABKAU6ATVIARIcCgpiYXJfc3RyaW5nGA0gASgJOgZT", - "VFJJTkdIARIcCghiYXJfY29yZBgOIAEoCToEQ09SREICCAFIARImChBiYXJf", - "c3RyaW5nX3BpZWNlGA8gASgJOgZTUElFQ0VCAggCSAESGgoJYmFyX2J5dGVz", - "GBAgASgMOgVCWVRFU0gBEkEKCGJhcl9lbnVtGBEgASgOMigucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdE9uZW9mMi5OZXN0ZWRFbnVtOgNCQVJIARIPCgdiYXpf", - "aW50GBIgASgFEhcKCmJhel9zdHJpbmcYEyABKAk6A0JBWhogCghGb29Hcm91", - "cBIJCgFhGAkgASgFEgkKAWIYCiABKAkaMwoNTmVzdGVkTWVzc2FnZRIPCgdx", - "dXhfaW50GAEgASgDEhEKCWNvcmdlX2ludBgCIAMoBSInCgpOZXN0ZWRFbnVt", - "EgcKA0ZPTxABEgcKA0JBUhACEgcKA0JBWhADQgUKA2Zvb0IFCgNiYXIiuAEK", - "EVRlc3RSZXF1aXJlZE9uZW9mEhEKB2Zvb19pbnQYASABKAVIABIUCgpmb29f", - "c3RyaW5nGAIgASgJSAASSQoLZm9vX21lc3NhZ2UYAyABKAsyMi5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0UmVxdWlyZWRPbmVvZi5OZXN0ZWRNZXNzYWdlSAAa", - "KAoNTmVzdGVkTWVzc2FnZRIXCg9yZXF1aXJlZF9kb3VibGUYASACKAFCBQoD", - "Zm9vIqoDCg9UZXN0UGFja2VkVHlwZXMSGAoMcGFja2VkX2ludDMyGFogAygF", - "QgIQARIYCgxwYWNrZWRfaW50NjQYWyADKANCAhABEhkKDXBhY2tlZF91aW50", - "MzIYXCADKA1CAhABEhkKDXBhY2tlZF91aW50NjQYXSADKARCAhABEhkKDXBh", - "Y2tlZF9zaW50MzIYXiADKBFCAhABEhkKDXBhY2tlZF9zaW50NjQYXyADKBJC", - "AhABEhoKDnBhY2tlZF9maXhlZDMyGGAgAygHQgIQARIaCg5wYWNrZWRfZml4", - "ZWQ2NBhhIAMoBkICEAESGwoPcGFja2VkX3NmaXhlZDMyGGIgAygPQgIQARIb", - "Cg9wYWNrZWRfc2ZpeGVkNjQYYyADKBBCAhABEhgKDHBhY2tlZF9mbG9hdBhk", - "IAMoAkICEAESGQoNcGFja2VkX2RvdWJsZRhlIAMoAUICEAESFwoLcGFja2Vk", - "X2Jvb2wYZiADKAhCAhABEjcKC3BhY2tlZF9lbnVtGGcgAygOMh4ucHJvdG9i", - "dWZfdW5pdHRlc3QuRm9yZWlnbkVudW1CAhABIsgDChFUZXN0VW5wYWNrZWRU", - "eXBlcxIaCg51bnBhY2tlZF9pbnQzMhhaIAMoBUICEAASGgoOdW5wYWNrZWRf", - "aW50NjQYWyADKANCAhAAEhsKD3VucGFja2VkX3VpbnQzMhhcIAMoDUICEAAS", - "GwoPdW5wYWNrZWRfdWludDY0GF0gAygEQgIQABIbCg91bnBhY2tlZF9zaW50", - "MzIYXiADKBFCAhAAEhsKD3VucGFja2VkX3NpbnQ2NBhfIAMoEkICEAASHAoQ", - "dW5wYWNrZWRfZml4ZWQzMhhgIAMoB0ICEAASHAoQdW5wYWNrZWRfZml4ZWQ2", - "NBhhIAMoBkICEAASHQoRdW5wYWNrZWRfc2ZpeGVkMzIYYiADKA9CAhAAEh0K", - "EXVucGFja2VkX3NmaXhlZDY0GGMgAygQQgIQABIaCg51bnBhY2tlZF9mbG9h", - "dBhkIAMoAkICEAASGwoPdW5wYWNrZWRfZG91YmxlGGUgAygBQgIQABIZCg11", - "bnBhY2tlZF9ib29sGGYgAygIQgIQABI5Cg11bnBhY2tlZF9lbnVtGGcgAygO", - "Mh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1CAhAAIiAKFFRlc3RQ", - "YWNrZWRFeHRlbnNpb25zKggIARCAgICAAiIiChZUZXN0VW5wYWNrZWRFeHRl", - "bnNpb25zKggIARCAgICAAiKZBAoVVGVzdER5bmFtaWNFeHRlbnNpb25zEhkK", - "EHNjYWxhcl9leHRlbnNpb24Y0A8gASgHEjcKDmVudW1fZXh0ZW5zaW9uGNEP", - "IAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtElkKFmR5bmFt", - "aWNfZW51bV9leHRlbnNpb24Y0g8gASgOMjgucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdER5bmFtaWNFeHRlbnNpb25zLkR5bmFtaWNFbnVtVHlwZRI9ChFtZXNz", - "YWdlX2V4dGVuc2lvbhjTDyABKAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3Jl", - "aWduTWVzc2FnZRJfChlkeW5hbWljX21lc3NhZ2VfZXh0ZW5zaW9uGNQPIAEo", - "CzI7LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3REeW5hbWljRXh0ZW5zaW9ucy5E", - "eW5hbWljTWVzc2FnZVR5cGUSGwoScmVwZWF0ZWRfZXh0ZW5zaW9uGNUPIAMo", - "CRIdChBwYWNrZWRfZXh0ZW5zaW9uGNYPIAMoEUICEAEaLAoSRHluYW1pY01l", - "c3NhZ2VUeXBlEhYKDWR5bmFtaWNfZmllbGQYtBAgASgFIkcKD0R5bmFtaWNF", - "bnVtVHlwZRIQCgtEWU5BTUlDX0ZPTxCYERIQCgtEWU5BTUlDX0JBUhCZERIQ", - "CgtEWU5BTUlDX0JBWhCaESLAAQojVGVzdFJlcGVhdGVkU2NhbGFyRGlmZmVy", - "ZW50VGFnU2l6ZXMSGAoQcmVwZWF0ZWRfZml4ZWQzMhgMIAMoBxIWCg5yZXBl", - "YXRlZF9pbnQzMhgNIAMoBRIZChByZXBlYXRlZF9maXhlZDY0GP4PIAMoBhIX", - "Cg5yZXBlYXRlZF9pbnQ2NBj/DyADKAMSGAoOcmVwZWF0ZWRfZmxvYXQY/v8P", - "IAMoAhIZCg9yZXBlYXRlZF91aW50NjQY//8PIAMoBCL3CQoQVGVzdFBhcnNp", - "bmdNZXJnZRI7ChJyZXF1aXJlZF9hbGxfdHlwZXMYASACKAsyHy5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMSOwoSb3B0aW9uYWxfYWxsX3R5cGVz", - "GAIgASgLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzEjsKEnJl", - "cGVhdGVkX2FsbF90eXBlcxgDIAMoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxUeXBlcxJICg1vcHRpb25hbGdyb3VwGAogASgKMjEucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdFBhcnNpbmdNZXJnZS5PcHRpb25hbEdyb3VwEkgKDXJl", - "cGVhdGVkZ3JvdXAYFCADKAoyMS5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFy", - "c2luZ01lcmdlLlJlcGVhdGVkR3JvdXAaqgQKF1JlcGVhdGVkRmllbGRzR2Vu", - "ZXJhdG9yEi8KBmZpZWxkMRgBIAMoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxUeXBlcxIvCgZmaWVsZDIYAiADKAsyHy5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsVHlwZXMSLwoGZmllbGQzGAMgAygLMh8ucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdEFsbFR5cGVzElIKBmdyb3VwMRgKIAMoCjJCLnByb3RvYnVm", - "X3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2UuUmVwZWF0ZWRGaWVsZHNHZW5l", - "cmF0b3IuR3JvdXAxElIKBmdyb3VwMhgUIAMoCjJCLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RQYXJzaW5nTWVyZ2UuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3Iu", - "R3JvdXAyEi4KBGV4dDEY6AcgAygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dEFsbFR5cGVzEi4KBGV4dDIY6QcgAygLMh8ucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdEFsbFR5cGVzGjkKBkdyb3VwMRIvCgZmaWVsZDEYCyABKAsyHy5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMaOQoGR3JvdXAyEi8KBmZpZWxk", - "MRgVIAEoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcxpSCg1P", - "cHRpb25hbEdyb3VwEkEKGG9wdGlvbmFsX2dyb3VwX2FsbF90eXBlcxgLIAEo", - "CzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcxpSCg1SZXBlYXRl", - "ZEdyb3VwEkEKGHJlcGVhdGVkX2dyb3VwX2FsbF90eXBlcxgVIAEoCzIfLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcyoJCOgHEICAgIACMlsKDG9w", - "dGlvbmFsX2V4dBIjLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVy", - "Z2UY6AcgASgLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzMlsK", - "DHJlcGVhdGVkX2V4dBIjLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5n", - "TWVyZ2UY6QcgAygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVz", - "IkQKG1Rlc3RDb21tZW50SW5qZWN0aW9uTWVzc2FnZRIlCgFhGAEgASgJOhoq", - "LyA8LSBOZWl0aGVyIHNob3VsZCB0aGlzLiIMCgpGb29SZXF1ZXN0Ig0KC0Zv", - "b1Jlc3BvbnNlIhIKEEZvb0NsaWVudE1lc3NhZ2UiEgoQRm9vU2VydmVyTWVz", - "c2FnZSIMCgpCYXJSZXF1ZXN0Ig0KC0JhclJlc3BvbnNlKkAKC0ZvcmVpZ25F", - "bnVtEg8KC0ZPUkVJR05fRk9PEAQSDwoLRk9SRUlHTl9CQVIQBRIPCgtGT1JF", - "SUdOX0JBWhAGKksKFFRlc3RFbnVtV2l0aER1cFZhbHVlEggKBEZPTzEQARII", - "CgRCQVIxEAISBwoDQkFaEAMSCAoERk9PMhABEggKBEJBUjIQAhoCEAEqiQEK", - "DlRlc3RTcGFyc2VFbnVtEgwKCFNQQVJTRV9BEHsSDgoIU1BBUlNFX0IQpucD", - "Eg8KCFNQQVJTRV9DELKxgAYSFQoIU1BBUlNFX0QQ8f//////////ARIVCghT", - "UEFSU0VfRRC03vz///////8BEgwKCFNQQVJTRV9GEAASDAoIU1BBUlNFX0cQ", - "AjKZAQoLVGVzdFNlcnZpY2USRAoDRm9vEh0ucHJvdG9idWZfdW5pdHRlc3Qu", - "Rm9vUmVxdWVzdBoeLnByb3RvYnVmX3VuaXR0ZXN0LkZvb1Jlc3BvbnNlEkQK", - "A0JhchIdLnByb3RvYnVmX3VuaXR0ZXN0LkJhclJlcXVlc3QaHi5wcm90b2J1", - "Zl91bml0dGVzdC5CYXJSZXNwb25zZTpGChhvcHRpb25hbF9pbnQzMl9leHRl", - "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgB", - "IAEoBTpGChhvcHRpb25hbF9pbnQ2NF9leHRlbnNpb24SJC5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgCIAEoAzpHChlvcHRpb25hbF91", - "aW50MzJfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4", - "dGVuc2lvbnMYAyABKA06RwoZb3B0aW9uYWxfdWludDY0X2V4dGVuc2lvbhIk", - "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAQgASgEOkcK", - "GW9wdGlvbmFsX3NpbnQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsRXh0ZW5zaW9ucxgFIAEoETpHChlvcHRpb25hbF9zaW50NjRf", - "ZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lv", - "bnMYBiABKBI6SAoab3B0aW9uYWxfZml4ZWQzMl9leHRlbnNpb24SJC5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgHIAEoBzpIChpvcHRp", - "b25hbF9maXhlZDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGAggASgGOkkKG29wdGlvbmFsX3NmaXhlZDMyX2V4", + "AxIQCgNORUcQ////////////AUINCgtvbmVvZl9maWVsZCK7AQoSTmVzdGVk", + "VGVzdEFsbFR5cGVzEjQKBWNoaWxkGAEgASgLMiUucHJvdG9idWZfdW5pdHRl", + "c3QuTmVzdGVkVGVzdEFsbFR5cGVzEjAKB3BheWxvYWQYAiABKAsyHy5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMSPQoOcmVwZWF0ZWRfY2hpbGQY", + "AyADKAsyJS5wcm90b2J1Zl91bml0dGVzdC5OZXN0ZWRUZXN0QWxsVHlwZXMi", + "NAoUVGVzdERlcHJlY2F0ZWRGaWVsZHMSHAoQZGVwcmVjYXRlZF9pbnQzMhgB", + "IAEoBUICGAEiGwoORm9yZWlnbk1lc3NhZ2USCQoBYxgBIAEoBSIwChJUZXN0", + "UmVzZXJ2ZWRGaWVsZHNKBAgCEANKBAgPEBBKBAgJEAxSA2JhclIDYmF6Ih0K", + "EVRlc3RBbGxFeHRlbnNpb25zKggIARCAgICAAiIkChdPcHRpb25hbEdyb3Vw", + "X2V4dGVuc2lvbhIJCgFhGBEgASgFIiQKF1JlcGVhdGVkR3JvdXBfZXh0ZW5z", + "aW9uEgkKAWEYLyABKAUimAEKE1Rlc3ROZXN0ZWRFeHRlbnNpb24yOQoEdGVz", + "dBIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGOoHIAEo", + "CToEdGVzdDJGChduZXN0ZWRfc3RyaW5nX2V4dGVuc2lvbhIkLnByb3RvYnVm", + "X3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGOsHIAEoCSLVBQoMVGVzdFJl", + "cXVpcmVkEgkKAWEYASACKAUSDgoGZHVtbXkyGAIgASgFEgkKAWIYAyACKAUS", + "DgoGZHVtbXk0GAQgASgFEg4KBmR1bW15NRgFIAEoBRIOCgZkdW1teTYYBiAB", + "KAUSDgoGZHVtbXk3GAcgASgFEg4KBmR1bW15OBgIIAEoBRIOCgZkdW1teTkY", + "CSABKAUSDwoHZHVtbXkxMBgKIAEoBRIPCgdkdW1teTExGAsgASgFEg8KB2R1", + "bW15MTIYDCABKAUSDwoHZHVtbXkxMxgNIAEoBRIPCgdkdW1teTE0GA4gASgF", + "Eg8KB2R1bW15MTUYDyABKAUSDwoHZHVtbXkxNhgQIAEoBRIPCgdkdW1teTE3", + "GBEgASgFEg8KB2R1bW15MTgYEiABKAUSDwoHZHVtbXkxORgTIAEoBRIPCgdk", + "dW1teTIwGBQgASgFEg8KB2R1bW15MjEYFSABKAUSDwoHZHVtbXkyMhgWIAEo", + "BRIPCgdkdW1teTIzGBcgASgFEg8KB2R1bW15MjQYGCABKAUSDwoHZHVtbXky", + "NRgZIAEoBRIPCgdkdW1teTI2GBogASgFEg8KB2R1bW15MjcYGyABKAUSDwoH", + "ZHVtbXkyOBgcIAEoBRIPCgdkdW1teTI5GB0gASgFEg8KB2R1bW15MzAYHiAB", + "KAUSDwoHZHVtbXkzMRgfIAEoBRIPCgdkdW1teTMyGCAgASgFEgkKAWMYISAC", + "KAUyVgoGc2luZ2xlEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", + "c2lvbnMY6AcgASgLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVk", + "MlUKBW11bHRpEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lv", + "bnMY6QcgAygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlcXVpcmVkIpoB", + "ChNUZXN0UmVxdWlyZWRGb3JlaWduEjkKEG9wdGlvbmFsX21lc3NhZ2UYASAB", + "KAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWlyZWQSOQoQcmVwZWF0", + "ZWRfbWVzc2FnZRgCIAMoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RSZXF1", + "aXJlZBINCgVkdW1teRgDIAEoBSJaChFUZXN0Rm9yZWlnbk5lc3RlZBJFCg5m", + "b3JlaWduX25lc3RlZBgBIAEoCzItLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxUeXBlcy5OZXN0ZWRNZXNzYWdlIhIKEFRlc3RFbXB0eU1lc3NhZ2UiKgoe", + "VGVzdEVtcHR5TWVzc2FnZVdpdGhFeHRlbnNpb25zKggIARCAgICAAiI3ChtU", + "ZXN0TXVsdGlwbGVFeHRlbnNpb25SYW5nZXMqBAgqECsqBgivIBCUISoKCICA", + "BBCAgICAAiI0ChhUZXN0UmVhbGx5TGFyZ2VUYWdOdW1iZXISCQoBYRgBIAEo", + "BRINCgJiYhj///9/IAEoBSJVChRUZXN0UmVjdXJzaXZlTWVzc2FnZRIyCgFh", + "GAEgASgLMicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFJlY3Vyc2l2ZU1lc3Nh", + "Z2USCQoBaRgCIAEoBSJLChRUZXN0TXV0dWFsUmVjdXJzaW9uQRIzCgJiYhgB", + "IAEoCzInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RNdXR1YWxSZWN1cnNpb25C", + "ImIKFFRlc3RNdXR1YWxSZWN1cnNpb25CEjIKAWEYASABKAsyJy5wcm90b2J1", + "Zl91bml0dGVzdC5UZXN0TXV0dWFsUmVjdXJzaW9uQRIWCg5vcHRpb25hbF9p", + "bnQzMhgCIAEoBSKzAQoSVGVzdER1cEZpZWxkTnVtYmVyEgkKAWEYASABKAUS", + "NgoDZm9vGAIgASgKMikucHJvdG9idWZfdW5pdHRlc3QuVGVzdER1cEZpZWxk", + "TnVtYmVyLkZvbxI2CgNiYXIYAyABKAoyKS5wcm90b2J1Zl91bml0dGVzdC5U", + "ZXN0RHVwRmllbGROdW1iZXIuQmFyGhAKA0ZvbxIJCgFhGAEgASgFGhAKA0Jh", + "chIJCgFhGAEgASgFIkwKEFRlc3RFYWdlck1lc3NhZ2USOAoLc3ViX21lc3Nh", + "Z2UYASABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXNCAigA", + "IksKD1Rlc3RMYXp5TWVzc2FnZRI4CgtzdWJfbWVzc2FnZRgBIAEoCzIfLnBy", + "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlc0ICKAEigAIKGFRlc3ROZXN0", + "ZWRNZXNzYWdlSGFzQml0cxJaChdvcHRpb25hbF9uZXN0ZWRfbWVzc2FnZRgB", + "IAEoCzI5LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3ROZXN0ZWRNZXNzYWdlSGFz", + "Qml0cy5OZXN0ZWRNZXNzYWdlGocBCg1OZXN0ZWRNZXNzYWdlEiQKHG5lc3Rl", + "ZG1lc3NhZ2VfcmVwZWF0ZWRfaW50MzIYASADKAUSUAolbmVzdGVkbWVzc2Fn", + "ZV9yZXBlYXRlZF9mb3JlaWdubWVzc2FnZRgCIAMoCzIhLnByb3RvYnVmX3Vu", + "aXR0ZXN0LkZvcmVpZ25NZXNzYWdlIuUDChdUZXN0Q2FtZWxDYXNlRmllbGRO", + "YW1lcxIWCg5QcmltaXRpdmVGaWVsZBgBIAEoBRITCgtTdHJpbmdGaWVsZBgC", + "IAEoCRIxCglFbnVtRmllbGQYAyABKA4yHi5wcm90b2J1Zl91bml0dGVzdC5G", + "b3JlaWduRW51bRI3CgxNZXNzYWdlRmllbGQYBCABKAsyIS5wcm90b2J1Zl91", + "bml0dGVzdC5Gb3JlaWduTWVzc2FnZRIcChBTdHJpbmdQaWVjZUZpZWxkGAUg", + "ASgJQgIIAhIVCglDb3JkRmllbGQYBiABKAlCAggBEh4KFlJlcGVhdGVkUHJp", + "bWl0aXZlRmllbGQYByADKAUSGwoTUmVwZWF0ZWRTdHJpbmdGaWVsZBgIIAMo", + "CRI5ChFSZXBlYXRlZEVudW1GaWVsZBgJIAMoDjIeLnByb3RvYnVmX3VuaXR0", + "ZXN0LkZvcmVpZ25FbnVtEj8KFFJlcGVhdGVkTWVzc2FnZUZpZWxkGAogAygL", + "MiEucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbk1lc3NhZ2USJAoYUmVwZWF0", + "ZWRTdHJpbmdQaWVjZUZpZWxkGAsgAygJQgIIAhIdChFSZXBlYXRlZENvcmRG", + "aWVsZBgMIAMoCUICCAEi1QEKElRlc3RGaWVsZE9yZGVyaW5ncxIRCglteV9z", + "dHJpbmcYCyABKAkSDgoGbXlfaW50GAEgASgDEhAKCG15X2Zsb2F0GGUgASgC", + "ElUKF29wdGlvbmFsX25lc3RlZF9tZXNzYWdlGMgBIAEoCzIzLnByb3RvYnVm", + "X3VuaXR0ZXN0LlRlc3RGaWVsZE9yZGVyaW5ncy5OZXN0ZWRNZXNzYWdlGicK", + "DU5lc3RlZE1lc3NhZ2USCgoCb28YAiABKAMSCgoCYmIYASABKAUqBAgCEAsq", + "BAgMEGUitgcKGFRlc3RFeHRyZW1lRGVmYXVsdFZhbHVlcxI/Cg1lc2NhcGVk", + "X2J5dGVzGAEgASgMOihcMDAwXDAwMVwwMDdcMDEwXDAxNFxuXHJcdFwwMTNc", + "XFwnXCJcMzc2EiAKDGxhcmdlX3VpbnQzMhgCIAEoDToKNDI5NDk2NzI5NRIq", + "CgxsYXJnZV91aW50NjQYAyABKAQ6FDE4NDQ2NzQ0MDczNzA5NTUxNjE1EiAK", + "C3NtYWxsX2ludDMyGAQgASgFOgstMjE0NzQ4MzY0NxIpCgtzbWFsbF9pbnQ2", + "NBgFIAEoAzoULTkyMjMzNzIwMzY4NTQ3NzU4MDcSJwoScmVhbGx5X3NtYWxs", + "X2ludDMyGBUgASgFOgstMjE0NzQ4MzY0OBIwChJyZWFsbHlfc21hbGxfaW50", + "NjQYFiABKAM6FC05MjIzMzcyMDM2ODU0Nzc1ODA4EhgKC3V0Zjhfc3RyaW5n", + "GAYgASgJOgPhiLQSFQoKemVyb19mbG9hdBgHIAEoAjoBMBIUCglvbmVfZmxv", + "YXQYCCABKAI6ATESGAoLc21hbGxfZmxvYXQYCSABKAI6AzEuNRIeChJuZWdh", + "dGl2ZV9vbmVfZmxvYXQYCiABKAI6Ai0xEhwKDm5lZ2F0aXZlX2Zsb2F0GAsg", + "ASgCOgQtMS41EhoKC2xhcmdlX2Zsb2F0GAwgASgCOgUyZSswOBIkChRzbWFs", + "bF9uZWdhdGl2ZV9mbG9hdBgNIAEoAjoGLThlLTI4EhcKCmluZl9kb3VibGUY", + "DiABKAE6A2luZhIcCg5uZWdfaW5mX2RvdWJsZRgPIAEoAToELWluZhIXCgpu", + "YW5fZG91YmxlGBAgASgBOgNuYW4SFgoJaW5mX2Zsb2F0GBEgASgCOgNpbmYS", + "GwoNbmVnX2luZl9mbG9hdBgSIAEoAjoELWluZhIWCgluYW5fZmxvYXQYEyAB", + "KAI6A25hbhIrCgxjcHBfdHJpZ3JhcGgYFCABKAk6FT8gPyA/PyA/PyA/Pz8g", + "Pz8vID8/LRIgChBzdHJpbmdfd2l0aF96ZXJvGBcgASgJOgZoZWwAbG8SIgoP", + "Ynl0ZXNfd2l0aF96ZXJvGBggASgMOgl3b3JcMDAwbGQSKAoWc3RyaW5nX3Bp", + "ZWNlX3dpdGhfemVybxgZIAEoCToEYWIAY0ICCAISIAoOY29yZF93aXRoX3pl", + "cm8YGiABKAk6BDEyADNCAggBEiYKEnJlcGxhY2VtZW50X3N0cmluZxgbIAEo", + "CToKJHt1bmtub3dufSJLChFTcGFyc2VFbnVtTWVzc2FnZRI2CgtzcGFyc2Vf", + "ZW51bRgBIAEoDjIhLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RTcGFyc2VFbnVt", + "IhkKCU9uZVN0cmluZxIMCgRkYXRhGAEgASgJIhoKCk1vcmVTdHJpbmcSDAoE", + "ZGF0YRgBIAMoCSIYCghPbmVCeXRlcxIMCgRkYXRhGAEgASgMIhkKCU1vcmVC", + "eXRlcxIMCgRkYXRhGAEgAygMIhwKDEludDMyTWVzc2FnZRIMCgRkYXRhGAEg", + "ASgFIh0KDVVpbnQzMk1lc3NhZ2USDAoEZGF0YRgBIAEoDSIcCgxJbnQ2NE1l", + "c3NhZ2USDAoEZGF0YRgBIAEoAyIdCg1VaW50NjRNZXNzYWdlEgwKBGRhdGEY", + "ASABKAQiGwoLQm9vbE1lc3NhZ2USDAoEZGF0YRgBIAEoCCLQAQoJVGVzdE9u", + "ZW9mEhEKB2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIgASgJSAAS", + "NgoLZm9vX21lc3NhZ2UYAyABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0", + "QWxsVHlwZXNIABI5Cghmb29ncm91cBgEIAEoCjIlLnByb3RvYnVmX3VuaXR0", + "ZXN0LlRlc3RPbmVvZi5Gb29Hcm91cEgAGiAKCEZvb0dyb3VwEgkKAWEYBSAB", + "KAUSCQoBYhgGIAEoCUIFCgNmb28i5wEKHFRlc3RPbmVvZkJhY2t3YXJkc0Nv", + "bXBhdGlibGUSDwoHZm9vX2ludBgBIAEoBRISCgpmb29fc3RyaW5nGAIgASgJ", + "EjQKC2Zvb19tZXNzYWdlGAMgASgLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVz", + "dEFsbFR5cGVzEkoKCGZvb2dyb3VwGAQgASgKMjgucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdE9uZW9mQmFja3dhcmRzQ29tcGF0aWJsZS5Gb29Hcm91cBogCghG", + "b29Hcm91cBIJCgFhGAUgASgFEgkKAWIYBiABKAkingYKClRlc3RPbmVvZjIS", + "EQoHZm9vX2ludBgBIAEoBUgAEhQKCmZvb19zdHJpbmcYAiABKAlIABIWCghm", + "b29fY29yZBgDIAEoCUICCAFIABIeChBmb29fc3RyaW5nX3BpZWNlGAQgASgJ", + "QgIIAkgAEhMKCWZvb19ieXRlcxgFIAEoDEgAEjwKCGZvb19lbnVtGAYgASgO", + "MigucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mMi5OZXN0ZWRFbnVtSAAS", + "QgoLZm9vX21lc3NhZ2UYByABKAsyKy5wcm90b2J1Zl91bml0dGVzdC5UZXN0", + "T25lb2YyLk5lc3RlZE1lc3NhZ2VIABI6Cghmb29ncm91cBgIIAEoCjImLnBy", + "b3RvYnVmX3VuaXR0ZXN0LlRlc3RPbmVvZjIuRm9vR3JvdXBIABJLChBmb29f", + "bGF6eV9tZXNzYWdlGAsgASgLMisucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9u", + "ZW9mMi5OZXN0ZWRNZXNzYWdlQgIoAUgAEhQKB2Jhcl9pbnQYDCABKAU6ATVI", + "ARIcCgpiYXJfc3RyaW5nGA0gASgJOgZTVFJJTkdIARIcCghiYXJfY29yZBgO", + "IAEoCToEQ09SREICCAFIARImChBiYXJfc3RyaW5nX3BpZWNlGA8gASgJOgZT", + "UElFQ0VCAggCSAESGgoJYmFyX2J5dGVzGBAgASgMOgVCWVRFU0gBEkEKCGJh", + "cl9lbnVtGBEgASgOMigucHJvdG9idWZfdW5pdHRlc3QuVGVzdE9uZW9mMi5O", + "ZXN0ZWRFbnVtOgNCQVJIARIPCgdiYXpfaW50GBIgASgFEhcKCmJhel9zdHJp", + "bmcYEyABKAk6A0JBWhogCghGb29Hcm91cBIJCgFhGAkgASgFEgkKAWIYCiAB", + "KAkaMwoNTmVzdGVkTWVzc2FnZRIPCgdxdXhfaW50GAEgASgDEhEKCWNvcmdl", + "X2ludBgCIAMoBSInCgpOZXN0ZWRFbnVtEgcKA0ZPTxABEgcKA0JBUhACEgcK", + "A0JBWhADQgUKA2Zvb0IFCgNiYXIiuAEKEVRlc3RSZXF1aXJlZE9uZW9mEhEK", + "B2Zvb19pbnQYASABKAVIABIUCgpmb29fc3RyaW5nGAIgASgJSAASSQoLZm9v", + "X21lc3NhZ2UYAyABKAsyMi5wcm90b2J1Zl91bml0dGVzdC5UZXN0UmVxdWly", + "ZWRPbmVvZi5OZXN0ZWRNZXNzYWdlSAAaKAoNTmVzdGVkTWVzc2FnZRIXCg9y", + "ZXF1aXJlZF9kb3VibGUYASACKAFCBQoDZm9vIqoDCg9UZXN0UGFja2VkVHlw", + "ZXMSGAoMcGFja2VkX2ludDMyGFogAygFQgIQARIYCgxwYWNrZWRfaW50NjQY", + "WyADKANCAhABEhkKDXBhY2tlZF91aW50MzIYXCADKA1CAhABEhkKDXBhY2tl", + "ZF91aW50NjQYXSADKARCAhABEhkKDXBhY2tlZF9zaW50MzIYXiADKBFCAhAB", + "EhkKDXBhY2tlZF9zaW50NjQYXyADKBJCAhABEhoKDnBhY2tlZF9maXhlZDMy", + "GGAgAygHQgIQARIaCg5wYWNrZWRfZml4ZWQ2NBhhIAMoBkICEAESGwoPcGFj", + "a2VkX3NmaXhlZDMyGGIgAygPQgIQARIbCg9wYWNrZWRfc2ZpeGVkNjQYYyAD", + "KBBCAhABEhgKDHBhY2tlZF9mbG9hdBhkIAMoAkICEAESGQoNcGFja2VkX2Rv", + "dWJsZRhlIAMoAUICEAESFwoLcGFja2VkX2Jvb2wYZiADKAhCAhABEjcKC3Bh", + "Y2tlZF9lbnVtGGcgAygOMh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVu", + "dW1CAhABIsgDChFUZXN0VW5wYWNrZWRUeXBlcxIaCg51bnBhY2tlZF9pbnQz", + "MhhaIAMoBUICEAASGgoOdW5wYWNrZWRfaW50NjQYWyADKANCAhAAEhsKD3Vu", + "cGFja2VkX3VpbnQzMhhcIAMoDUICEAASGwoPdW5wYWNrZWRfdWludDY0GF0g", + "AygEQgIQABIbCg91bnBhY2tlZF9zaW50MzIYXiADKBFCAhAAEhsKD3VucGFj", + "a2VkX3NpbnQ2NBhfIAMoEkICEAASHAoQdW5wYWNrZWRfZml4ZWQzMhhgIAMo", + "B0ICEAASHAoQdW5wYWNrZWRfZml4ZWQ2NBhhIAMoBkICEAASHQoRdW5wYWNr", + "ZWRfc2ZpeGVkMzIYYiADKA9CAhAAEh0KEXVucGFja2VkX3NmaXhlZDY0GGMg", + "AygQQgIQABIaCg51bnBhY2tlZF9mbG9hdBhkIAMoAkICEAASGwoPdW5wYWNr", + "ZWRfZG91YmxlGGUgAygBQgIQABIZCg11bnBhY2tlZF9ib29sGGYgAygIQgIQ", + "ABI5Cg11bnBhY2tlZF9lbnVtGGcgAygOMh4ucHJvdG9idWZfdW5pdHRlc3Qu", + "Rm9yZWlnbkVudW1CAhAAIiAKFFRlc3RQYWNrZWRFeHRlbnNpb25zKggIARCA", + "gICAAiIiChZUZXN0VW5wYWNrZWRFeHRlbnNpb25zKggIARCAgICAAiKZBAoV", + "VGVzdER5bmFtaWNFeHRlbnNpb25zEhkKEHNjYWxhcl9leHRlbnNpb24Y0A8g", + "ASgHEjcKDmVudW1fZXh0ZW5zaW9uGNEPIAEoDjIeLnByb3RvYnVmX3VuaXR0", + "ZXN0LkZvcmVpZ25FbnVtElkKFmR5bmFtaWNfZW51bV9leHRlbnNpb24Y0g8g", + "ASgOMjgucHJvdG9idWZfdW5pdHRlc3QuVGVzdER5bmFtaWNFeHRlbnNpb25z", + "LkR5bmFtaWNFbnVtVHlwZRI9ChFtZXNzYWdlX2V4dGVuc2lvbhjTDyABKAsy", + "IS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZRJfChlkeW5hbWlj", + "X21lc3NhZ2VfZXh0ZW5zaW9uGNQPIAEoCzI7LnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3REeW5hbWljRXh0ZW5zaW9ucy5EeW5hbWljTWVzc2FnZVR5cGUSGwoS", + "cmVwZWF0ZWRfZXh0ZW5zaW9uGNUPIAMoCRIdChBwYWNrZWRfZXh0ZW5zaW9u", + "GNYPIAMoEUICEAEaLAoSRHluYW1pY01lc3NhZ2VUeXBlEhYKDWR5bmFtaWNf", + "ZmllbGQYtBAgASgFIkcKD0R5bmFtaWNFbnVtVHlwZRIQCgtEWU5BTUlDX0ZP", + "TxCYERIQCgtEWU5BTUlDX0JBUhCZERIQCgtEWU5BTUlDX0JBWhCaESLAAQoj", + "VGVzdFJlcGVhdGVkU2NhbGFyRGlmZmVyZW50VGFnU2l6ZXMSGAoQcmVwZWF0", + "ZWRfZml4ZWQzMhgMIAMoBxIWCg5yZXBlYXRlZF9pbnQzMhgNIAMoBRIZChBy", + "ZXBlYXRlZF9maXhlZDY0GP4PIAMoBhIXCg5yZXBlYXRlZF9pbnQ2NBj/DyAD", + "KAMSGAoOcmVwZWF0ZWRfZmxvYXQY/v8PIAMoAhIZCg9yZXBlYXRlZF91aW50", + "NjQY//8PIAMoBCL3CQoQVGVzdFBhcnNpbmdNZXJnZRI7ChJyZXF1aXJlZF9h", + "bGxfdHlwZXMYASACKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlw", + "ZXMSOwoSb3B0aW9uYWxfYWxsX3R5cGVzGAIgASgLMh8ucHJvdG9idWZfdW5p", + "dHRlc3QuVGVzdEFsbFR5cGVzEjsKEnJlcGVhdGVkX2FsbF90eXBlcxgDIAMo", + "CzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcxJICg1vcHRpb25h", + "bGdyb3VwGAogASgKMjEucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhcnNpbmdN", + "ZXJnZS5PcHRpb25hbEdyb3VwEkgKDXJlcGVhdGVkZ3JvdXAYFCADKAoyMS5w", + "cm90b2J1Zl91bml0dGVzdC5UZXN0UGFyc2luZ01lcmdlLlJlcGVhdGVkR3Jv", + "dXAaqgQKF1JlcGVhdGVkRmllbGRzR2VuZXJhdG9yEi8KBmZpZWxkMRgBIAMo", + "CzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcxIvCgZmaWVsZDIY", + "AiADKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMSLwoGZmll", + "bGQzGAMgAygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzElIK", + "Bmdyb3VwMRgKIAMoCjJCLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5n", + "TWVyZ2UuUmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAxElIKBmdyb3Vw", + "MhgUIAMoCjJCLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2Uu", + "UmVwZWF0ZWRGaWVsZHNHZW5lcmF0b3IuR3JvdXAyEi4KBGV4dDEY6AcgAygL", + "Mh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzEi4KBGV4dDIY6Qcg", + "AygLMh8ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzGjkKBkdyb3Vw", + "MRIvCgZmaWVsZDEYCyABKAsyHy5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxs", + "VHlwZXMaOQoGR3JvdXAyEi8KBmZpZWxkMRgVIAEoCzIfLnByb3RvYnVmX3Vu", + "aXR0ZXN0LlRlc3RBbGxUeXBlcxpSCg1PcHRpb25hbEdyb3VwEkEKGG9wdGlv", + "bmFsX2dyb3VwX2FsbF90eXBlcxgLIAEoCzIfLnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3RBbGxUeXBlcxpSCg1SZXBlYXRlZEdyb3VwEkEKGHJlcGVhdGVkX2dy", + "b3VwX2FsbF90eXBlcxgVIAEoCzIfLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxUeXBlcyoJCOgHEICAgIACMlsKDG9wdGlvbmFsX2V4dBIjLnByb3RvYnVm", + "X3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2UY6AcgASgLMh8ucHJvdG9idWZf", + "dW5pdHRlc3QuVGVzdEFsbFR5cGVzMlsKDHJlcGVhdGVkX2V4dBIjLnByb3Rv", + "YnVmX3VuaXR0ZXN0LlRlc3RQYXJzaW5nTWVyZ2UY6QcgAygLMh8ucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzIkQKG1Rlc3RDb21tZW50SW5qZWN0", + "aW9uTWVzc2FnZRIlCgFhGAEgASgJOhoqLyA8LSBOZWl0aGVyIHNob3VsZCB0", + "aGlzLiIMCgpGb29SZXF1ZXN0Ig0KC0Zvb1Jlc3BvbnNlIhIKEEZvb0NsaWVu", + "dE1lc3NhZ2UiEgoQRm9vU2VydmVyTWVzc2FnZSIMCgpCYXJSZXF1ZXN0Ig0K", + "C0JhclJlc3BvbnNlKkAKC0ZvcmVpZ25FbnVtEg8KC0ZPUkVJR05fRk9PEAQS", + "DwoLRk9SRUlHTl9CQVIQBRIPCgtGT1JFSUdOX0JBWhAGKksKFFRlc3RFbnVt", + "V2l0aER1cFZhbHVlEggKBEZPTzEQARIICgRCQVIxEAISBwoDQkFaEAMSCAoE", + "Rk9PMhABEggKBEJBUjIQAhoCEAEqiQEKDlRlc3RTcGFyc2VFbnVtEgwKCFNQ", + "QVJTRV9BEHsSDgoIU1BBUlNFX0IQpucDEg8KCFNQQVJTRV9DELKxgAYSFQoI", + "U1BBUlNFX0QQ8f//////////ARIVCghTUEFSU0VfRRC03vz///////8BEgwK", + "CFNQQVJTRV9GEAASDAoIU1BBUlNFX0cQAjKZAQoLVGVzdFNlcnZpY2USRAoD", + "Rm9vEh0ucHJvdG9idWZfdW5pdHRlc3QuRm9vUmVxdWVzdBoeLnByb3RvYnVm", + "X3VuaXR0ZXN0LkZvb1Jlc3BvbnNlEkQKA0JhchIdLnByb3RvYnVmX3VuaXR0", + "ZXN0LkJhclJlcXVlc3QaHi5wcm90b2J1Zl91bml0dGVzdC5CYXJSZXNwb25z", + "ZTpGChhvcHRpb25hbF9pbnQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0", + "dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgBIAEoBTpGChhvcHRpb25hbF9pbnQ2", + "NF9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", + "aW9ucxgCIAEoAzpHChlvcHRpb25hbF91aW50MzJfZXh0ZW5zaW9uEiQucHJv", + "dG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYAyABKA06RwoZb3B0", + "aW9uYWxfdWludDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", + "c3RBbGxFeHRlbnNpb25zGAQgASgEOkcKGW9wdGlvbmFsX3NpbnQzMl9leHRl", + "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgF", + "IAEoETpHChlvcHRpb25hbF9zaW50NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZf", + "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYBiABKBI6SAoab3B0aW9uYWxf", + "Zml4ZWQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxs", + "RXh0ZW5zaW9ucxgHIAEoBzpIChpvcHRpb25hbF9maXhlZDY0X2V4dGVuc2lv", + "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAggASgG", + "OkkKG29wdGlvbmFsX3NmaXhlZDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3Vu", + "aXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAkgASgPOkkKG29wdGlvbmFsX3Nm", + "aXhlZDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxF", + "eHRlbnNpb25zGAogASgQOkYKGG9wdGlvbmFsX2Zsb2F0X2V4dGVuc2lvbhIk", + "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAsgASgCOkcK", + "GW9wdGlvbmFsX2RvdWJsZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", + "dC5UZXN0QWxsRXh0ZW5zaW9ucxgMIAEoATpFChdvcHRpb25hbF9ib29sX2V4", + "dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25z", + "GA0gASgIOkcKGW9wdGlvbmFsX3N0cmluZ19leHRlbnNpb24SJC5wcm90b2J1", + "Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgOIAEoCTpGChhvcHRpb25h", + "bF9ieXRlc19leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxs", + "RXh0ZW5zaW9ucxgPIAEoDDpxChdvcHRpb25hbGdyb3VwX2V4dGVuc2lvbhIk", + "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGBAgASgKMiou", + "cHJvdG9idWZfdW5pdHRlc3QuT3B0aW9uYWxHcm91cF9leHRlbnNpb246fgoh", + "b3B0aW9uYWxfbmVzdGVkX21lc3NhZ2VfZXh0ZW5zaW9uEiQucHJvdG9idWZf", + "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYEiABKAsyLS5wcm90b2J1Zl91", + "bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkTWVzc2FnZTpzCiJvcHRpb25h", + "bF9mb3JlaWduX21lc3NhZ2VfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdEFsbEV4dGVuc2lvbnMYEyABKAsyIS5wcm90b2J1Zl91bml0dGVz", + "dC5Gb3JlaWduTWVzc2FnZTp4CiFvcHRpb25hbF9pbXBvcnRfbWVzc2FnZV9l", + "eHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9u", + "cxgUIAEoCzInLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRNZXNz", + "YWdlOngKHm9wdGlvbmFsX25lc3RlZF9lbnVtX2V4dGVuc2lvbhIkLnByb3Rv", + "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGBUgASgOMioucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW06bQofb3B0aW9u", + "YWxfZm9yZWlnbl9lbnVtX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3RBbGxFeHRlbnNpb25zGBYgASgOMh4ucHJvdG9idWZfdW5pdHRlc3Qu", + "Rm9yZWlnbkVudW06cgoeb3B0aW9uYWxfaW1wb3J0X2VudW1fZXh0ZW5zaW9u", + "EiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYFyABKA4y", + "JC5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuSW1wb3J0RW51bTpRCh9vcHRp", + "b25hbF9zdHJpbmdfcGllY2VfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdEFsbEV4dGVuc2lvbnMYGCABKAlCAggCOkkKF29wdGlvbmFsX2Nv", + "cmRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", + "c2lvbnMYGSABKAlCAggBOoUBCihvcHRpb25hbF9wdWJsaWNfaW1wb3J0X21l", + "c3NhZ2VfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4", + "dGVuc2lvbnMYGiABKAsyLS5wcm90b2J1Zl91bml0dGVzdF9pbXBvcnQuUHVi", + "bGljSW1wb3J0TWVzc2FnZTqAAQofb3B0aW9uYWxfbGF6eV9tZXNzYWdlX2V4", "dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25z", - "GAkgASgPOkkKG29wdGlvbmFsX3NmaXhlZDY0X2V4dGVuc2lvbhIkLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGAogASgQOkYKGG9wdGlv", - "bmFsX2Zsb2F0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", - "bGxFeHRlbnNpb25zGAsgASgCOkcKGW9wdGlvbmFsX2RvdWJsZV9leHRlbnNp", - "b24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgMIAEo", - "ATpFChdvcHRpb25hbF9ib29sX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RBbGxFeHRlbnNpb25zGA0gASgIOkcKGW9wdGlvbmFsX3N0cmlu", - "Z19leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", - "aW9ucxgOIAEoCTpGChhvcHRpb25hbF9ieXRlc19leHRlbnNpb24SJC5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgPIAEoDDpxChdvcHRp", - "b25hbGdyb3VwX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", - "bGxFeHRlbnNpb25zGBAgASgKMioucHJvdG9idWZfdW5pdHRlc3QuT3B0aW9u", - "YWxHcm91cF9leHRlbnNpb246fgohb3B0aW9uYWxfbmVzdGVkX21lc3NhZ2Vf", + "GBsgASgLMi0ucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3Rl", + "ZE1lc3NhZ2VCAigBOkYKGHJlcGVhdGVkX2ludDMyX2V4dGVuc2lvbhIkLnBy", + "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGB8gAygFOkYKGHJl", + "cGVhdGVkX2ludDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", + "c3RBbGxFeHRlbnNpb25zGCAgAygDOkcKGXJlcGVhdGVkX3VpbnQzMl9leHRl", + "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgh", + "IAMoDTpHChlyZXBlYXRlZF91aW50NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZf", + "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYIiADKAQ6RwoZcmVwZWF0ZWRf", + "c2ludDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxF", + "eHRlbnNpb25zGCMgAygROkcKGXJlcGVhdGVkX3NpbnQ2NF9leHRlbnNpb24S", + "JC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgkIAMoEjpI", + "ChpyZXBlYXRlZF9maXhlZDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0", + "ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCUgAygHOkgKGnJlcGVhdGVkX2ZpeGVk", + "NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", + "c2lvbnMYJiADKAY6SQobcmVwZWF0ZWRfc2ZpeGVkMzJfZXh0ZW5zaW9uEiQu", + "cHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYJyADKA86SQob", + "cmVwZWF0ZWRfc2ZpeGVkNjRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdEFsbEV4dGVuc2lvbnMYKCADKBA6RgoYcmVwZWF0ZWRfZmxvYXRf", "ZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lv", - "bnMYEiABKAsyLS5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVz", - "dGVkTWVzc2FnZTpzCiJvcHRpb25hbF9mb3JlaWduX21lc3NhZ2VfZXh0ZW5z", - "aW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYEyAB", - "KAsyIS5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduTWVzc2FnZTp4CiFvcHRp", - "b25hbF9pbXBvcnRfbWVzc2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0", - "dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgUIAEoCzInLnByb3RvYnVmX3VuaXR0", - "ZXN0X2ltcG9ydC5JbXBvcnRNZXNzYWdlOngKHm9wdGlvbmFsX25lc3RlZF9l", - "bnVtX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRl", - "bnNpb25zGBUgASgOMioucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVz", - "Lk5lc3RlZEVudW06bQofb3B0aW9uYWxfZm9yZWlnbl9lbnVtX2V4dGVuc2lv", - "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGBYgASgO", - "Mh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW06cgoeb3B0aW9uYWxf", - "aW1wb3J0X2VudW1fZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dEFsbEV4dGVuc2lvbnMYFyABKA4yJC5wcm90b2J1Zl91bml0dGVzdF9pbXBv", - "cnQuSW1wb3J0RW51bTpRCh9vcHRpb25hbF9zdHJpbmdfcGllY2VfZXh0ZW5z", - "aW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYGCAB", - "KAlCAggCOkkKF29wdGlvbmFsX2NvcmRfZXh0ZW5zaW9uEiQucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYGSABKAlCAggBOoUBCihvcHRp", - "b25hbF9wdWJsaWNfaW1wb3J0X21lc3NhZ2VfZXh0ZW5zaW9uEiQucHJvdG9i", - "dWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYGiABKAsyLS5wcm90b2J1", - "Zl91bml0dGVzdF9pbXBvcnQuUHVibGljSW1wb3J0TWVzc2FnZTqAAQofb3B0", - "aW9uYWxfbGF6eV9tZXNzYWdlX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RBbGxFeHRlbnNpb25zGBsgASgLMi0ucHJvdG9idWZfdW5pdHRl", - "c3QuVGVzdEFsbFR5cGVzLk5lc3RlZE1lc3NhZ2VCAigBOkYKGHJlcGVhdGVk", - "X2ludDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxF", - "eHRlbnNpb25zGB8gAygFOkYKGHJlcGVhdGVkX2ludDY0X2V4dGVuc2lvbhIk", - "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCAgAygDOkcK", - "GXJlcGVhdGVkX3VpbnQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsRXh0ZW5zaW9ucxghIAMoDTpHChlyZXBlYXRlZF91aW50NjRf", + "bnMYKSADKAI6RwoZcmVwZWF0ZWRfZG91YmxlX2V4dGVuc2lvbhIkLnByb3Rv", + "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCogAygBOkUKF3JlcGVh", + "dGVkX2Jvb2xfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFs", + "bEV4dGVuc2lvbnMYKyADKAg6RwoZcmVwZWF0ZWRfc3RyaW5nX2V4dGVuc2lv", + "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCwgAygJ", + "OkYKGHJlcGVhdGVkX2J5dGVzX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0", + "ZXN0LlRlc3RBbGxFeHRlbnNpb25zGC0gAygMOnEKF3JlcGVhdGVkZ3JvdXBf", "ZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lv", - "bnMYIiADKAQ6RwoZcmVwZWF0ZWRfc2ludDMyX2V4dGVuc2lvbhIkLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCMgAygROkcKGXJlcGVh", - "dGVkX3NpbnQ2NF9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0", - "QWxsRXh0ZW5zaW9ucxgkIAMoEjpIChpyZXBlYXRlZF9maXhlZDMyX2V4dGVu", - "c2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGCUg", - "AygHOkgKGnJlcGVhdGVkX2ZpeGVkNjRfZXh0ZW5zaW9uEiQucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYJiADKAY6SQobcmVwZWF0ZWRf", - "c2ZpeGVkMzJfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFs", - "bEV4dGVuc2lvbnMYJyADKA86SQobcmVwZWF0ZWRfc2ZpeGVkNjRfZXh0ZW5z", - "aW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYKCAD", - "KBA6RgoYcmVwZWF0ZWRfZmxvYXRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYKSADKAI6RwoZcmVwZWF0ZWRfZG91", - "YmxlX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRl", - "bnNpb25zGCogAygBOkUKF3JlcGVhdGVkX2Jvb2xfZXh0ZW5zaW9uEiQucHJv", - "dG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYKyADKAg6RwoZcmVw", - "ZWF0ZWRfc3RyaW5nX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGCwgAygJOkYKGHJlcGVhdGVkX2J5dGVzX2V4dGVu", - "c2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGC0g", - "AygMOnEKF3JlcGVhdGVkZ3JvdXBfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5p", - "dHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYLiADKAoyKi5wcm90b2J1Zl91bml0", - "dGVzdC5SZXBlYXRlZEdyb3VwX2V4dGVuc2lvbjp+CiFyZXBlYXRlZF9uZXN0", - "ZWRfbWVzc2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0", - "QWxsRXh0ZW5zaW9ucxgwIAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", - "bGxUeXBlcy5OZXN0ZWRNZXNzYWdlOnMKInJlcGVhdGVkX2ZvcmVpZ25fbWVz", - "c2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0", - "ZW5zaW9ucxgxIAMoCzIhLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNz", - "YWdlOngKIXJlcGVhdGVkX2ltcG9ydF9tZXNzYWdlX2V4dGVuc2lvbhIkLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGDIgAygLMicucHJv", - "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydE1lc3NhZ2U6eAoecmVwZWF0", - "ZWRfbmVzdGVkX2VudW1fZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdEFsbEV4dGVuc2lvbnMYMyADKA4yKi5wcm90b2J1Zl91bml0dGVzdC5U", - "ZXN0QWxsVHlwZXMuTmVzdGVkRW51bTptCh9yZXBlYXRlZF9mb3JlaWduX2Vu", - "dW1fZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", - "c2lvbnMYNCADKA4yHi5wcm90b2J1Zl91bml0dGVzdC5Gb3JlaWduRW51bTpy", - "Ch5yZXBlYXRlZF9pbXBvcnRfZW51bV9leHRlbnNpb24SJC5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg1IAMoDjIkLnByb3RvYnVmX3Vu", - "aXR0ZXN0X2ltcG9ydC5JbXBvcnRFbnVtOlEKH3JlcGVhdGVkX3N0cmluZ19w", - "aWVjZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0", - "ZW5zaW9ucxg2IAMoCUICCAI6SQoXcmVwZWF0ZWRfY29yZF9leHRlbnNpb24S", - "JC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg3IAMoCUIC", - "CAE6gAEKH3JlcGVhdGVkX2xhenlfbWVzc2FnZV9leHRlbnNpb24SJC5wcm90", - "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg5IAMoCzItLnByb3Rv", - "YnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlQgIoATpJ", - "ChdkZWZhdWx0X2ludDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RBbGxFeHRlbnNpb25zGD0gASgFOgI0MTpJChdkZWZhdWx0X2ludDY0", - "X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNp", - "b25zGD4gASgDOgI0MjpKChhkZWZhdWx0X3VpbnQzMl9leHRlbnNpb24SJC5w", - "cm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg/IAEoDToCNDM6", - "SgoYZGVmYXVsdF91aW50NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRl", - "c3QuVGVzdEFsbEV4dGVuc2lvbnMYQCABKAQ6AjQ0OksKGGRlZmF1bHRfc2lu", - "dDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRl", - "bnNpb25zGEEgASgROgMtNDU6SgoYZGVmYXVsdF9zaW50NjRfZXh0ZW5zaW9u", - "EiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYQiABKBI6", - "AjQ2OksKGWRlZmF1bHRfZml4ZWQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhDIAEoBzoCNDc6SwoZZGVmYXVs", - "dF9maXhlZDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", - "bGxFeHRlbnNpb25zGEQgASgGOgI0ODpMChpkZWZhdWx0X3NmaXhlZDMyX2V4", - "dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25z", - "GEUgASgPOgI0OTpNChpkZWZhdWx0X3NmaXhlZDY0X2V4dGVuc2lvbhIkLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEYgASgQOgMtNTA6", - "SwoXZGVmYXVsdF9mbG9hdF9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsRXh0ZW5zaW9ucxhHIAEoAjoENTEuNTpNChhkZWZhdWx0X2Rv", - "dWJsZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0", - "ZW5zaW9ucxhIIAEoAToFNTIwMDA6SgoWZGVmYXVsdF9ib29sX2V4dGVuc2lv", - "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEkgASgI", - "OgR0cnVlOk0KGGRlZmF1bHRfc3RyaW5nX2V4dGVuc2lvbhIkLnByb3RvYnVm", - "X3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEogASgJOgVoZWxsbzpMChdk", - "ZWZhdWx0X2J5dGVzX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGEsgASgMOgV3b3JsZDp8Ch1kZWZhdWx0X25lc3Rl", - "ZF9lbnVtX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxF", - "eHRlbnNpb25zGFEgASgOMioucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5", - "cGVzLk5lc3RlZEVudW06A0JBUjp5Ch5kZWZhdWx0X2ZvcmVpZ25fZW51bV9l", - "eHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9u", - "cxhSIAEoDjIeLnByb3RvYnVmX3VuaXR0ZXN0LkZvcmVpZ25FbnVtOgtGT1JF", - "SUdOX0JBUjp9Ch1kZWZhdWx0X2ltcG9ydF9lbnVtX2V4dGVuc2lvbhIkLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGFMgASgOMiQucHJv", - "dG9idWZfdW5pdHRlc3RfaW1wb3J0LkltcG9ydEVudW06CklNUE9SVF9CQVI6", - "VQoeZGVmYXVsdF9zdHJpbmdfcGllY2VfZXh0ZW5zaW9uEiQucHJvdG9idWZf", - "dW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYVCABKAk6A2FiY0ICCAI6TQoW", - "ZGVmYXVsdF9jb3JkX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRl", - "c3RBbGxFeHRlbnNpb25zGFUgASgJOgMxMjNCAggBOkQKFm9uZW9mX3VpbnQz", - "Ml9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", - "aW9ucxhvIAEoDTp7Ch5vbmVvZl9uZXN0ZWRfbWVzc2FnZV9leHRlbnNpb24S", - "JC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhwIAEoCzIt", + "bnMYLiADKAoyKi5wcm90b2J1Zl91bml0dGVzdC5SZXBlYXRlZEdyb3VwX2V4", + "dGVuc2lvbjp+CiFyZXBlYXRlZF9uZXN0ZWRfbWVzc2FnZV9leHRlbnNpb24S", + "JC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgwIAMoCzIt", "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdl", - "OkQKFm9uZW9mX3N0cmluZ19leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVz", - "dC5UZXN0QWxsRXh0ZW5zaW9ucxhxIAEoCTpDChVvbmVvZl9ieXRlc19leHRl", - "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhy", - "IAEoDDpCChNteV9leHRlbnNpb25fc3RyaW5nEiUucHJvdG9idWZfdW5pdHRl", - "c3QuVGVzdEZpZWxkT3JkZXJpbmdzGDIgASgJOj8KEG15X2V4dGVuc2lvbl9p", - "bnQSJS5wcm90b2J1Zl91bml0dGVzdC5UZXN0RmllbGRPcmRlcmluZ3MYBSAB", - "KAU6SwoWcGFja2VkX2ludDMyX2V4dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zGFogAygFQgIQATpLChZwYWNrZWRf", + "OnMKInJlcGVhdGVkX2ZvcmVpZ25fbWVzc2FnZV9leHRlbnNpb24SJC5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxgxIAMoCzIhLnByb3Rv", + "YnVmX3VuaXR0ZXN0LkZvcmVpZ25NZXNzYWdlOngKIXJlcGVhdGVkX2ltcG9y", + "dF9tZXNzYWdlX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxFeHRlbnNpb25zGDIgAygLMicucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0", + "LkltcG9ydE1lc3NhZ2U6eAoecmVwZWF0ZWRfbmVzdGVkX2VudW1fZXh0ZW5z", + "aW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYMyAD", + "KA4yKi5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsVHlwZXMuTmVzdGVkRW51", + "bTptCh9yZXBlYXRlZF9mb3JlaWduX2VudW1fZXh0ZW5zaW9uEiQucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMYNCADKA4yHi5wcm90b2J1", + "Zl91bml0dGVzdC5Gb3JlaWduRW51bTpyCh5yZXBlYXRlZF9pbXBvcnRfZW51", + "bV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", + "aW9ucxg1IAMoDjIkLnByb3RvYnVmX3VuaXR0ZXN0X2ltcG9ydC5JbXBvcnRF", + "bnVtOlEKH3JlcGVhdGVkX3N0cmluZ19waWVjZV9leHRlbnNpb24SJC5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxg2IAMoCUICCAI6SQoX", + "cmVwZWF0ZWRfY29yZF9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5U", + "ZXN0QWxsRXh0ZW5zaW9ucxg3IAMoCUICCAE6gAEKH3JlcGVhdGVkX2xhenlf", + "bWVzc2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxs", + "RXh0ZW5zaW9ucxg5IAMoCzItLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxU", + "eXBlcy5OZXN0ZWRNZXNzYWdlQgIoATpJChdkZWZhdWx0X2ludDMyX2V4dGVu", + "c2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGD0g", + "ASgFOgI0MTpJChdkZWZhdWx0X2ludDY0X2V4dGVuc2lvbhIkLnByb3RvYnVm", + "X3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGD4gASgDOgI0MjpKChhkZWZh", + "dWx0X3VpbnQzMl9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0", + "QWxsRXh0ZW5zaW9ucxg/IAEoDToCNDM6SgoYZGVmYXVsdF91aW50NjRfZXh0", + "ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVuc2lvbnMY", + "QCABKAQ6AjQ0OksKGGRlZmF1bHRfc2ludDMyX2V4dGVuc2lvbhIkLnByb3Rv", + "YnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEEgASgROgMtNDU6SgoY", + "ZGVmYXVsdF9zaW50NjRfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3Qu", + "VGVzdEFsbEV4dGVuc2lvbnMYQiABKBI6AjQ2OksKGWRlZmF1bHRfZml4ZWQz", + "Ml9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5z", + "aW9ucxhDIAEoBzoCNDc6SwoZZGVmYXVsdF9maXhlZDY0X2V4dGVuc2lvbhIk", + "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEQgASgGOgI0", + "ODpMChpkZWZhdWx0X3NmaXhlZDMyX2V4dGVuc2lvbhIkLnByb3RvYnVmX3Vu", + "aXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEUgASgPOgI0OTpNChpkZWZhdWx0", + "X3NmaXhlZDY0X2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxFeHRlbnNpb25zGEYgASgQOgMtNTA6SwoXZGVmYXVsdF9mbG9hdF9leHRl", + "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhH", + "IAEoAjoENTEuNTpNChhkZWZhdWx0X2RvdWJsZV9leHRlbnNpb24SJC5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhIIAEoAToFNTIwMDA6", + "SgoWZGVmYXVsdF9ib29sX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3RBbGxFeHRlbnNpb25zGEkgASgIOgR0cnVlOk0KGGRlZmF1bHRfc3Ry", + "aW5nX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRl", + "bnNpb25zGEogASgJOgVoZWxsbzpMChdkZWZhdWx0X2J5dGVzX2V4dGVuc2lv", + "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGEsgASgM", + "OgV3b3JsZDp8Ch1kZWZhdWx0X25lc3RlZF9lbnVtX2V4dGVuc2lvbhIkLnBy", + "b3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGFEgASgOMioucHJv", + "dG9idWZfdW5pdHRlc3QuVGVzdEFsbFR5cGVzLk5lc3RlZEVudW06A0JBUjp5", + "Ch5kZWZhdWx0X2ZvcmVpZ25fZW51bV9leHRlbnNpb24SJC5wcm90b2J1Zl91", + "bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhSIAEoDjIeLnByb3RvYnVmX3Vu", + "aXR0ZXN0LkZvcmVpZ25FbnVtOgtGT1JFSUdOX0JBUjp9Ch1kZWZhdWx0X2lt", + "cG9ydF9lbnVtX2V4dGVuc2lvbhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RB", + "bGxFeHRlbnNpb25zGFMgASgOMiQucHJvdG9idWZfdW5pdHRlc3RfaW1wb3J0", + "LkltcG9ydEVudW06CklNUE9SVF9CQVI6VQoeZGVmYXVsdF9zdHJpbmdfcGll", + "Y2VfZXh0ZW5zaW9uEiQucHJvdG9idWZfdW5pdHRlc3QuVGVzdEFsbEV4dGVu", + "c2lvbnMYVCABKAk6A2FiY0ICCAI6TQoWZGVmYXVsdF9jb3JkX2V4dGVuc2lv", + "bhIkLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RBbGxFeHRlbnNpb25zGFUgASgJ", + "OgMxMjNCAggBOkQKFm9uZW9mX3VpbnQzMl9leHRlbnNpb24SJC5wcm90b2J1", + "Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhvIAEoDTp7Ch5vbmVvZl9u", + "ZXN0ZWRfbWVzc2FnZV9leHRlbnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5U", + "ZXN0QWxsRXh0ZW5zaW9ucxhwIAEoCzItLnByb3RvYnVmX3VuaXR0ZXN0LlRl", + "c3RBbGxUeXBlcy5OZXN0ZWRNZXNzYWdlOkQKFm9uZW9mX3N0cmluZ19leHRl", + "bnNpb24SJC5wcm90b2J1Zl91bml0dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhx", + "IAEoCTpDChVvbmVvZl9ieXRlc19leHRlbnNpb24SJC5wcm90b2J1Zl91bml0", + "dGVzdC5UZXN0QWxsRXh0ZW5zaW9ucxhyIAEoDDpCChNteV9leHRlbnNpb25f", + "c3RyaW5nEiUucHJvdG9idWZfdW5pdHRlc3QuVGVzdEZpZWxkT3JkZXJpbmdz", + "GDIgASgJOj8KEG15X2V4dGVuc2lvbl9pbnQSJS5wcm90b2J1Zl91bml0dGVz", + "dC5UZXN0RmllbGRPcmRlcmluZ3MYBSABKAU6SwoWcGFja2VkX2ludDMyX2V4", + "dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNp", + "b25zGFogAygFQgIQATpLChZwYWNrZWRfaW50NjRfZXh0ZW5zaW9uEicucHJv", + "dG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYWyADKANCAhAB", + "OkwKF3BhY2tlZF91aW50MzJfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYXCADKA1CAhABOkwKF3BhY2tlZF91", "aW50NjRfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tl", - "ZEV4dGVuc2lvbnMYWyADKANCAhABOkwKF3BhY2tlZF91aW50MzJfZXh0ZW5z", + "ZEV4dGVuc2lvbnMYXSADKARCAhABOkwKF3BhY2tlZF9zaW50MzJfZXh0ZW5z", "aW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMY", - "XCADKA1CAhABOkwKF3BhY2tlZF91aW50NjRfZXh0ZW5zaW9uEicucHJvdG9i", - "dWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYXSADKARCAhABOkwK", - "F3BhY2tlZF9zaW50MzJfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdFBhY2tlZEV4dGVuc2lvbnMYXiADKBFCAhABOkwKF3BhY2tlZF9zaW50", - "NjRfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4", - "dGVuc2lvbnMYXyADKBJCAhABOk0KGHBhY2tlZF9maXhlZDMyX2V4dGVuc2lv", - "bhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zGGAg", - "AygHQgIQATpNChhwYWNrZWRfZml4ZWQ2NF9leHRlbnNpb24SJy5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9ucxhhIAMoBkICEAE6TgoZ", - "cGFja2VkX3NmaXhlZDMyX2V4dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RQYWNrZWRFeHRlbnNpb25zGGIgAygPQgIQATpOChlwYWNrZWRfc2Zp", - "eGVkNjRfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tl", - "ZEV4dGVuc2lvbnMYYyADKBBCAhABOksKFnBhY2tlZF9mbG9hdF9leHRlbnNp", - "b24SJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9ucxhk", - "IAMoAkICEAE6TAoXcGFja2VkX2RvdWJsZV9leHRlbnNpb24SJy5wcm90b2J1", - "Zl91bml0dGVzdC5UZXN0UGFja2VkRXh0ZW5zaW9ucxhlIAMoAUICEAE6SgoV", - "cGFja2VkX2Jvb2xfZXh0ZW5zaW9uEicucHJvdG9idWZfdW5pdHRlc3QuVGVz", - "dFBhY2tlZEV4dGVuc2lvbnMYZiADKAhCAhABOmoKFXBhY2tlZF9lbnVtX2V4", - "dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNp", - "b25zGGcgAygOMh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1CAhAB", - "Ok8KGHVucGFja2VkX2ludDMyX2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0", - "ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYWiADKAVCAhAAOk8KGHVucGFj", - "a2VkX2ludDY0X2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RV", - "bnBhY2tlZEV4dGVuc2lvbnMYWyADKANCAhAAOlAKGXVucGFja2VkX3VpbnQz", - "Ml9leHRlbnNpb24SKS5wcm90b2J1Zl91bml0dGVzdC5UZXN0VW5wYWNrZWRF", - "eHRlbnNpb25zGFwgAygNQgIQADpQChl1bnBhY2tlZF91aW50NjRfZXh0ZW5z", + "XiADKBFCAhABOkwKF3BhY2tlZF9zaW50NjRfZXh0ZW5zaW9uEicucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYXyADKBJCAhABOk0K", + "GHBhY2tlZF9maXhlZDMyX2V4dGVuc2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0", + "LlRlc3RQYWNrZWRFeHRlbnNpb25zGGAgAygHQgIQATpNChhwYWNrZWRfZml4", + "ZWQ2NF9leHRlbnNpb24SJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2Vk", + "RXh0ZW5zaW9ucxhhIAMoBkICEAE6TgoZcGFja2VkX3NmaXhlZDMyX2V4dGVu", + "c2lvbhInLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25z", + "GGIgAygPQgIQATpOChlwYWNrZWRfc2ZpeGVkNjRfZXh0ZW5zaW9uEicucHJv", + "dG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYYyADKBBCAhAB", + "OksKFnBhY2tlZF9mbG9hdF9leHRlbnNpb24SJy5wcm90b2J1Zl91bml0dGVz", + "dC5UZXN0UGFja2VkRXh0ZW5zaW9ucxhkIAMoAkICEAE6TAoXcGFja2VkX2Rv", + "dWJsZV9leHRlbnNpb24SJy5wcm90b2J1Zl91bml0dGVzdC5UZXN0UGFja2Vk", + "RXh0ZW5zaW9ucxhlIAMoAUICEAE6SgoVcGFja2VkX2Jvb2xfZXh0ZW5zaW9u", + "EicucHJvdG9idWZfdW5pdHRlc3QuVGVzdFBhY2tlZEV4dGVuc2lvbnMYZiAD", + "KAhCAhABOmoKFXBhY2tlZF9lbnVtX2V4dGVuc2lvbhInLnByb3RvYnVmX3Vu", + "aXR0ZXN0LlRlc3RQYWNrZWRFeHRlbnNpb25zGGcgAygOMh4ucHJvdG9idWZf", + "dW5pdHRlc3QuRm9yZWlnbkVudW1CAhABOk8KGHVucGFja2VkX2ludDMyX2V4", + "dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVu", + "c2lvbnMYWiADKAVCAhAAOk8KGHVucGFja2VkX2ludDY0X2V4dGVuc2lvbhIp", + "LnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYWyAD", + "KANCAhAAOlAKGXVucGFja2VkX3VpbnQzMl9leHRlbnNpb24SKS5wcm90b2J1", + "Zl91bml0dGVzdC5UZXN0VW5wYWNrZWRFeHRlbnNpb25zGFwgAygNQgIQADpQ", + "Chl1bnBhY2tlZF91aW50NjRfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRl", + "c3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhdIAMoBEICEAA6UAoZdW5wYWNr", + "ZWRfc2ludDMyX2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RV", + "bnBhY2tlZEV4dGVuc2lvbnMYXiADKBFCAhAAOlAKGXVucGFja2VkX3NpbnQ2", + "NF9leHRlbnNpb24SKS5wcm90b2J1Zl91bml0dGVzdC5UZXN0VW5wYWNrZWRF", + "eHRlbnNpb25zGF8gAygSQgIQADpRChp1bnBhY2tlZF9maXhlZDMyX2V4dGVu", + "c2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lv", + "bnMYYCADKAdCAhAAOlEKGnVucGFja2VkX2ZpeGVkNjRfZXh0ZW5zaW9uEiku", + "cHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhhIAMo", + "BkICEAA6UgobdW5wYWNrZWRfc2ZpeGVkMzJfZXh0ZW5zaW9uEikucHJvdG9i", + "dWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhiIAMoD0ICEAA6", + "UgobdW5wYWNrZWRfc2ZpeGVkNjRfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5p", + "dHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhjIAMoEEICEAA6TwoYdW5w", + "YWNrZWRfZmxvYXRfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVz", + "dFVucGFja2VkRXh0ZW5zaW9ucxhkIAMoAkICEAA6UAoZdW5wYWNrZWRfZG91", + "YmxlX2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tl", + "ZEV4dGVuc2lvbnMYZSADKAFCAhAAOk4KF3VucGFja2VkX2Jvb2xfZXh0ZW5z", "aW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9u", - "cxhdIAMoBEICEAA6UAoZdW5wYWNrZWRfc2ludDMyX2V4dGVuc2lvbhIpLnBy", - "b3RvYnVmX3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYXiADKBFC", - "AhAAOlAKGXVucGFja2VkX3NpbnQ2NF9leHRlbnNpb24SKS5wcm90b2J1Zl91", - "bml0dGVzdC5UZXN0VW5wYWNrZWRFeHRlbnNpb25zGF8gAygSQgIQADpRChp1", - "bnBhY2tlZF9maXhlZDMyX2V4dGVuc2lvbhIpLnByb3RvYnVmX3VuaXR0ZXN0", - "LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYYCADKAdCAhAAOlEKGnVucGFja2Vk", - "X2ZpeGVkNjRfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVzdFVu", - "cGFja2VkRXh0ZW5zaW9ucxhhIAMoBkICEAA6UgobdW5wYWNrZWRfc2ZpeGVk", - "MzJfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2Vk", - "RXh0ZW5zaW9ucxhiIAMoD0ICEAA6UgobdW5wYWNrZWRfc2ZpeGVkNjRfZXh0", - "ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5z", - "aW9ucxhjIAMoEEICEAA6TwoYdW5wYWNrZWRfZmxvYXRfZXh0ZW5zaW9uEiku", - "cHJvdG9idWZfdW5pdHRlc3QuVGVzdFVucGFja2VkRXh0ZW5zaW9ucxhkIAMo", - "AkICEAA6UAoZdW5wYWNrZWRfZG91YmxlX2V4dGVuc2lvbhIpLnByb3RvYnVm", - "X3VuaXR0ZXN0LlRlc3RVbnBhY2tlZEV4dGVuc2lvbnMYZSADKAFCAhAAOk4K", - "F3VucGFja2VkX2Jvb2xfZXh0ZW5zaW9uEikucHJvdG9idWZfdW5pdHRlc3Qu", - "VGVzdFVucGFja2VkRXh0ZW5zaW9ucxhmIAMoCEICEAA6bgoXdW5wYWNrZWRf", - "ZW51bV9leHRlbnNpb24SKS5wcm90b2J1Zl91bml0dGVzdC5UZXN0VW5wYWNr", - "ZWRFeHRlbnNpb25zGGcgAygOMh4ucHJvdG9idWZfdW5pdHRlc3QuRm9yZWln", - "bkVudW1CAhAAQkFCDVVuaXR0ZXN0UHJvdG9IAYABAYgBAZABAfgBAaoCIUdv", - "b2dsZS5Qcm90b2NvbEJ1ZmZlcnMuVGVzdFByb3Rvcw==")); + "cxhmIAMoCEICEAA6bgoXdW5wYWNrZWRfZW51bV9leHRlbnNpb24SKS5wcm90", + "b2J1Zl91bml0dGVzdC5UZXN0VW5wYWNrZWRFeHRlbnNpb25zGGcgAygOMh4u", + "cHJvdG9idWZfdW5pdHRlc3QuRm9yZWlnbkVudW1CAhAAQkFCDVVuaXR0ZXN0", + "UHJvdG9IAYABAYgBAZABAfgBAaoCIUdvb2dsZS5Qcm90b2NvbEJ1ZmZlcnMu", + "VGVzdFByb3Rvcw==")); pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { descriptor = root; internal__static_protobuf_unittest_TestAllTypes__Descriptor = Descriptor.MessageTypes[0]; internal__static_protobuf_unittest_TestAllTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestAllTypes__Descriptor, - new string[] { "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalGroup", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalImportMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalImportEnum", "OptionalStringPiece", "OptionalCord", "OptionalPublicImportMessage", "OptionalLazyMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedGroup", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedStringPiece", "RepeatedCord", "RepeatedLazyMessage", "DefaultInt32", "DefaultInt64", "DefaultUint32", "DefaultUint64", "DefaultSint32", "DefaultSint64", "DefaultFixed32", "DefaultFixed64", "DefaultSfixed32", "DefaultSfixed64", "DefaultFloat", "DefaultDouble", "DefaultBool", "DefaultString", "DefaultBytes", "DefaultNestedEnum", "DefaultForeignEnum", "DefaultImportEnum", "DefaultStringPiece", "DefaultCord", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", }); + new string[] { "OptionalInt32", "OptionalInt64", "OptionalUint32", "OptionalUint64", "OptionalSint32", "OptionalSint64", "OptionalFixed32", "OptionalFixed64", "OptionalSfixed32", "OptionalSfixed64", "OptionalFloat", "OptionalDouble", "OptionalBool", "OptionalString", "OptionalBytes", "OptionalGroup", "OptionalNestedMessage", "OptionalForeignMessage", "OptionalImportMessage", "OptionalNestedEnum", "OptionalForeignEnum", "OptionalImportEnum", "OptionalStringPiece", "OptionalCord", "OptionalPublicImportMessage", "OptionalLazyMessage", "RepeatedInt32", "RepeatedInt64", "RepeatedUint32", "RepeatedUint64", "RepeatedSint32", "RepeatedSint64", "RepeatedFixed32", "RepeatedFixed64", "RepeatedSfixed32", "RepeatedSfixed64", "RepeatedFloat", "RepeatedDouble", "RepeatedBool", "RepeatedString", "RepeatedBytes", "RepeatedGroup", "RepeatedNestedMessage", "RepeatedForeignMessage", "RepeatedImportMessage", "RepeatedNestedEnum", "RepeatedForeignEnum", "RepeatedImportEnum", "RepeatedStringPiece", "RepeatedCord", "RepeatedLazyMessage", "DefaultInt32", "DefaultInt64", "DefaultUint32", "DefaultUint64", "DefaultSint32", "DefaultSint64", "DefaultFixed32", "DefaultFixed64", "DefaultSfixed32", "DefaultSfixed64", "DefaultFloat", "DefaultDouble", "DefaultBool", "DefaultString", "DefaultBytes", "DefaultNestedEnum", "DefaultForeignEnum", "DefaultImportEnum", "DefaultStringPiece", "DefaultCord", "OneofUint32", "OneofNestedMessage", "OneofString", "OneofBytes", "OneofField", }); internal__static_protobuf_unittest_TestAllTypes_NestedMessage__Descriptor = internal__static_protobuf_unittest_TestAllTypes__Descriptor.NestedTypes[0]; internal__static_protobuf_unittest_TestAllTypes_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestAllTypes_NestedMessage__Descriptor, @@ -1000,7 +1005,7 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_NestedTestAllTypes__Descriptor = Descriptor.MessageTypes[1]; internal__static_protobuf_unittest_NestedTestAllTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_NestedTestAllTypes__Descriptor, - new string[] { "Child", "Payload", }); + new string[] { "Child", "Payload", "RepeatedChild", }); internal__static_protobuf_unittest_TestDeprecatedFields__Descriptor = Descriptor.MessageTypes[2]; internal__static_protobuf_unittest_TestDeprecatedFields__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDeprecatedFields__Descriptor, @@ -1009,67 +1014,71 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_ForeignMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_ForeignMessage__Descriptor, new string[] { "C", }); - internal__static_protobuf_unittest_TestAllExtensions__Descriptor = Descriptor.MessageTypes[4]; + internal__static_protobuf_unittest_TestReservedFields__Descriptor = Descriptor.MessageTypes[4]; + internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestReservedFields__Descriptor, + new string[] { }); + internal__static_protobuf_unittest_TestAllExtensions__Descriptor = Descriptor.MessageTypes[5]; internal__static_protobuf_unittest_TestAllExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestAllExtensions__Descriptor, new string[] { }); - internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor = Descriptor.MessageTypes[5]; + internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor = Descriptor.MessageTypes[6]; internal__static_protobuf_unittest_OptionalGroup_extension__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor, new string[] { "A", }); - internal__static_protobuf_unittest_RepeatedGroup_extension__Descriptor = Descriptor.MessageTypes[6]; + internal__static_protobuf_unittest_RepeatedGroup_extension__Descriptor = Descriptor.MessageTypes[7]; internal__static_protobuf_unittest_RepeatedGroup_extension__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_RepeatedGroup_extension__Descriptor, new string[] { "A", }); - internal__static_protobuf_unittest_TestNestedExtension__Descriptor = Descriptor.MessageTypes[7]; + internal__static_protobuf_unittest_TestNestedExtension__Descriptor = Descriptor.MessageTypes[8]; internal__static_protobuf_unittest_TestNestedExtension__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestNestedExtension__Descriptor, new string[] { }); global::Google.ProtocolBuffers.TestProtos.TestNestedExtension.Test = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestNestedExtension.Descriptor.Extensions[0]); global::Google.ProtocolBuffers.TestProtos.TestNestedExtension.NestedStringExtension = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestNestedExtension.Descriptor.Extensions[1]); - internal__static_protobuf_unittest_TestRequired__Descriptor = Descriptor.MessageTypes[8]; + internal__static_protobuf_unittest_TestRequired__Descriptor = Descriptor.MessageTypes[9]; internal__static_protobuf_unittest_TestRequired__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRequired__Descriptor, new string[] { "A", "Dummy2", "B", "Dummy4", "Dummy5", "Dummy6", "Dummy7", "Dummy8", "Dummy9", "Dummy10", "Dummy11", "Dummy12", "Dummy13", "Dummy14", "Dummy15", "Dummy16", "Dummy17", "Dummy18", "Dummy19", "Dummy20", "Dummy21", "Dummy22", "Dummy23", "Dummy24", "Dummy25", "Dummy26", "Dummy27", "Dummy28", "Dummy29", "Dummy30", "Dummy31", "Dummy32", "C", }); global::Google.ProtocolBuffers.TestProtos.TestRequired.Single = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestRequired.Descriptor.Extensions[0]); global::Google.ProtocolBuffers.TestProtos.TestRequired.Multi = pb::GeneratedRepeatExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestRequired.Descriptor.Extensions[1]); - internal__static_protobuf_unittest_TestRequiredForeign__Descriptor = Descriptor.MessageTypes[9]; + internal__static_protobuf_unittest_TestRequiredForeign__Descriptor = Descriptor.MessageTypes[10]; internal__static_protobuf_unittest_TestRequiredForeign__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRequiredForeign__Descriptor, new string[] { "OptionalMessage", "RepeatedMessage", "Dummy", }); - internal__static_protobuf_unittest_TestForeignNested__Descriptor = Descriptor.MessageTypes[10]; + internal__static_protobuf_unittest_TestForeignNested__Descriptor = Descriptor.MessageTypes[11]; internal__static_protobuf_unittest_TestForeignNested__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestForeignNested__Descriptor, new string[] { "ForeignNested", }); - internal__static_protobuf_unittest_TestEmptyMessage__Descriptor = Descriptor.MessageTypes[11]; + internal__static_protobuf_unittest_TestEmptyMessage__Descriptor = Descriptor.MessageTypes[12]; internal__static_protobuf_unittest_TestEmptyMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestEmptyMessage__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestEmptyMessageWithExtensions__Descriptor = Descriptor.MessageTypes[12]; + internal__static_protobuf_unittest_TestEmptyMessageWithExtensions__Descriptor = Descriptor.MessageTypes[13]; internal__static_protobuf_unittest_TestEmptyMessageWithExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestEmptyMessageWithExtensions__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestMultipleExtensionRanges__Descriptor = Descriptor.MessageTypes[13]; + internal__static_protobuf_unittest_TestMultipleExtensionRanges__Descriptor = Descriptor.MessageTypes[14]; internal__static_protobuf_unittest_TestMultipleExtensionRanges__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestMultipleExtensionRanges__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor = Descriptor.MessageTypes[14]; + internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor = Descriptor.MessageTypes[15]; internal__static_protobuf_unittest_TestReallyLargeTagNumber__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestReallyLargeTagNumber__Descriptor, new string[] { "A", "Bb", }); - internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor = Descriptor.MessageTypes[15]; + internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor = Descriptor.MessageTypes[16]; internal__static_protobuf_unittest_TestRecursiveMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRecursiveMessage__Descriptor, new string[] { "A", "I", }); - internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor = Descriptor.MessageTypes[16]; + internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor = Descriptor.MessageTypes[17]; internal__static_protobuf_unittest_TestMutualRecursionA__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestMutualRecursionA__Descriptor, new string[] { "Bb", }); - internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor = Descriptor.MessageTypes[17]; + internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor = Descriptor.MessageTypes[18]; internal__static_protobuf_unittest_TestMutualRecursionB__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestMutualRecursionB__Descriptor, new string[] { "A", "OptionalInt32", }); - internal__static_protobuf_unittest_TestDupFieldNumber__Descriptor = Descriptor.MessageTypes[18]; + internal__static_protobuf_unittest_TestDupFieldNumber__Descriptor = Descriptor.MessageTypes[19]; internal__static_protobuf_unittest_TestDupFieldNumber__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDupFieldNumber__Descriptor, new string[] { "A", "Foo", "Bar", }); @@ -1081,15 +1090,15 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestDupFieldNumber_Bar__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDupFieldNumber_Bar__Descriptor, new string[] { "A", }); - internal__static_protobuf_unittest_TestEagerMessage__Descriptor = Descriptor.MessageTypes[19]; + internal__static_protobuf_unittest_TestEagerMessage__Descriptor = Descriptor.MessageTypes[20]; internal__static_protobuf_unittest_TestEagerMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestEagerMessage__Descriptor, new string[] { "SubMessage", }); - internal__static_protobuf_unittest_TestLazyMessage__Descriptor = Descriptor.MessageTypes[20]; + internal__static_protobuf_unittest_TestLazyMessage__Descriptor = Descriptor.MessageTypes[21]; internal__static_protobuf_unittest_TestLazyMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestLazyMessage__Descriptor, new string[] { "SubMessage", }); - internal__static_protobuf_unittest_TestNestedMessageHasBits__Descriptor = Descriptor.MessageTypes[21]; + internal__static_protobuf_unittest_TestNestedMessageHasBits__Descriptor = Descriptor.MessageTypes[22]; internal__static_protobuf_unittest_TestNestedMessageHasBits__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestNestedMessageHasBits__Descriptor, new string[] { "OptionalNestedMessage", }); @@ -1097,11 +1106,11 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestNestedMessageHasBits_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestNestedMessageHasBits_NestedMessage__Descriptor, new string[] { "NestedmessageRepeatedInt32", "NestedmessageRepeatedForeignmessage", }); - internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor = Descriptor.MessageTypes[22]; + internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor = Descriptor.MessageTypes[23]; internal__static_protobuf_unittest_TestCamelCaseFieldNames__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestCamelCaseFieldNames__Descriptor, new string[] { "PrimitiveField", "StringField", "EnumField", "MessageField", "StringPieceField", "CordField", "RepeatedPrimitiveField", "RepeatedStringField", "RepeatedEnumField", "RepeatedMessageField", "RepeatedStringPieceField", "RepeatedCordField", }); - internal__static_protobuf_unittest_TestFieldOrderings__Descriptor = Descriptor.MessageTypes[23]; + internal__static_protobuf_unittest_TestFieldOrderings__Descriptor = Descriptor.MessageTypes[24]; internal__static_protobuf_unittest_TestFieldOrderings__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestFieldOrderings__Descriptor, new string[] { "MyString", "MyInt", "MyFloat", "OptionalNestedMessage", }); @@ -1109,59 +1118,59 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestFieldOrderings_NestedMessage__Descriptor, new string[] { "Oo", "Bb", }); - internal__static_protobuf_unittest_TestExtremeDefaultValues__Descriptor = Descriptor.MessageTypes[24]; + internal__static_protobuf_unittest_TestExtremeDefaultValues__Descriptor = Descriptor.MessageTypes[25]; internal__static_protobuf_unittest_TestExtremeDefaultValues__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestExtremeDefaultValues__Descriptor, new string[] { "EscapedBytes", "LargeUint32", "LargeUint64", "SmallInt32", "SmallInt64", "ReallySmallInt32", "ReallySmallInt64", "Utf8String", "ZeroFloat", "OneFloat", "SmallFloat", "NegativeOneFloat", "NegativeFloat", "LargeFloat", "SmallNegativeFloat", "InfDouble", "NegInfDouble", "NanDouble", "InfFloat", "NegInfFloat", "NanFloat", "CppTrigraph", "StringWithZero", "BytesWithZero", "StringPieceWithZero", "CordWithZero", "ReplacementString", }); - internal__static_protobuf_unittest_SparseEnumMessage__Descriptor = Descriptor.MessageTypes[25]; + internal__static_protobuf_unittest_SparseEnumMessage__Descriptor = Descriptor.MessageTypes[26]; internal__static_protobuf_unittest_SparseEnumMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_SparseEnumMessage__Descriptor, new string[] { "SparseEnum", }); - internal__static_protobuf_unittest_OneString__Descriptor = Descriptor.MessageTypes[26]; + internal__static_protobuf_unittest_OneString__Descriptor = Descriptor.MessageTypes[27]; internal__static_protobuf_unittest_OneString__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_OneString__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_MoreString__Descriptor = Descriptor.MessageTypes[27]; + internal__static_protobuf_unittest_MoreString__Descriptor = Descriptor.MessageTypes[28]; internal__static_protobuf_unittest_MoreString__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_MoreString__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_OneBytes__Descriptor = Descriptor.MessageTypes[28]; + internal__static_protobuf_unittest_OneBytes__Descriptor = Descriptor.MessageTypes[29]; internal__static_protobuf_unittest_OneBytes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_OneBytes__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_MoreBytes__Descriptor = Descriptor.MessageTypes[29]; + internal__static_protobuf_unittest_MoreBytes__Descriptor = Descriptor.MessageTypes[30]; internal__static_protobuf_unittest_MoreBytes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_MoreBytes__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_Int32Message__Descriptor = Descriptor.MessageTypes[30]; + internal__static_protobuf_unittest_Int32Message__Descriptor = Descriptor.MessageTypes[31]; internal__static_protobuf_unittest_Int32Message__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_Int32Message__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_Uint32Message__Descriptor = Descriptor.MessageTypes[31]; + internal__static_protobuf_unittest_Uint32Message__Descriptor = Descriptor.MessageTypes[32]; internal__static_protobuf_unittest_Uint32Message__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_Uint32Message__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_Int64Message__Descriptor = Descriptor.MessageTypes[32]; + internal__static_protobuf_unittest_Int64Message__Descriptor = Descriptor.MessageTypes[33]; internal__static_protobuf_unittest_Int64Message__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_Int64Message__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_Uint64Message__Descriptor = Descriptor.MessageTypes[33]; + internal__static_protobuf_unittest_Uint64Message__Descriptor = Descriptor.MessageTypes[34]; internal__static_protobuf_unittest_Uint64Message__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_Uint64Message__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_BoolMessage__Descriptor = Descriptor.MessageTypes[34]; + internal__static_protobuf_unittest_BoolMessage__Descriptor = Descriptor.MessageTypes[35]; internal__static_protobuf_unittest_BoolMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_BoolMessage__Descriptor, new string[] { "Data", }); - internal__static_protobuf_unittest_TestOneof__Descriptor = Descriptor.MessageTypes[35]; + internal__static_protobuf_unittest_TestOneof__Descriptor = Descriptor.MessageTypes[36]; internal__static_protobuf_unittest_TestOneof__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof__Descriptor, - new string[] { "FooInt", "FooString", "FooMessage", "FooGroup", }); + new string[] { "FooInt", "FooString", "FooMessage", "FooGroup", "Foo", }); internal__static_protobuf_unittest_TestOneof_FooGroup__Descriptor = internal__static_protobuf_unittest_TestOneof__Descriptor.NestedTypes[0]; internal__static_protobuf_unittest_TestOneof_FooGroup__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof_FooGroup__Descriptor, new string[] { "A", "B", }); - internal__static_protobuf_unittest_TestOneofBackwardsCompatible__Descriptor = Descriptor.MessageTypes[36]; + internal__static_protobuf_unittest_TestOneofBackwardsCompatible__Descriptor = Descriptor.MessageTypes[37]; internal__static_protobuf_unittest_TestOneofBackwardsCompatible__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneofBackwardsCompatible__Descriptor, new string[] { "FooInt", "FooString", "FooMessage", "FooGroup", }); @@ -1169,10 +1178,10 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestOneofBackwardsCompatible_FooGroup__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneofBackwardsCompatible_FooGroup__Descriptor, new string[] { "A", "B", }); - internal__static_protobuf_unittest_TestOneof2__Descriptor = Descriptor.MessageTypes[37]; + internal__static_protobuf_unittest_TestOneof2__Descriptor = Descriptor.MessageTypes[38]; internal__static_protobuf_unittest_TestOneof2__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof2__Descriptor, - new string[] { "FooInt", "FooString", "FooCord", "FooStringPiece", "FooBytes", "FooEnum", "FooMessage", "FooGroup", "FooLazyMessage", "BarInt", "BarString", "BarCord", "BarStringPiece", "BarBytes", "BarEnum", "BazInt", "BazString", }); + new string[] { "FooInt", "FooString", "FooCord", "FooStringPiece", "FooBytes", "FooEnum", "FooMessage", "FooGroup", "FooLazyMessage", "BarInt", "BarString", "BarCord", "BarStringPiece", "BarBytes", "BarEnum", "BazInt", "BazString", "Foo", "Bar", }); internal__static_protobuf_unittest_TestOneof2_FooGroup__Descriptor = internal__static_protobuf_unittest_TestOneof2__Descriptor.NestedTypes[0]; internal__static_protobuf_unittest_TestOneof2_FooGroup__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof2_FooGroup__Descriptor, @@ -1181,31 +1190,31 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestOneof2_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestOneof2_NestedMessage__Descriptor, new string[] { "QuxInt", "CorgeInt", }); - internal__static_protobuf_unittest_TestRequiredOneof__Descriptor = Descriptor.MessageTypes[38]; + internal__static_protobuf_unittest_TestRequiredOneof__Descriptor = Descriptor.MessageTypes[39]; internal__static_protobuf_unittest_TestRequiredOneof__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRequiredOneof__Descriptor, - new string[] { "FooInt", "FooString", "FooMessage", }); + new string[] { "FooInt", "FooString", "FooMessage", "Foo", }); internal__static_protobuf_unittest_TestRequiredOneof_NestedMessage__Descriptor = internal__static_protobuf_unittest_TestRequiredOneof__Descriptor.NestedTypes[0]; internal__static_protobuf_unittest_TestRequiredOneof_NestedMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRequiredOneof_NestedMessage__Descriptor, new string[] { "RequiredDouble", }); - internal__static_protobuf_unittest_TestPackedTypes__Descriptor = Descriptor.MessageTypes[39]; + internal__static_protobuf_unittest_TestPackedTypes__Descriptor = Descriptor.MessageTypes[40]; internal__static_protobuf_unittest_TestPackedTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestPackedTypes__Descriptor, new string[] { "PackedInt32", "PackedInt64", "PackedUint32", "PackedUint64", "PackedSint32", "PackedSint64", "PackedFixed32", "PackedFixed64", "PackedSfixed32", "PackedSfixed64", "PackedFloat", "PackedDouble", "PackedBool", "PackedEnum", }); - internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor = Descriptor.MessageTypes[40]; + internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor = Descriptor.MessageTypes[41]; internal__static_protobuf_unittest_TestUnpackedTypes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestUnpackedTypes__Descriptor, new string[] { "UnpackedInt32", "UnpackedInt64", "UnpackedUint32", "UnpackedUint64", "UnpackedSint32", "UnpackedSint64", "UnpackedFixed32", "UnpackedFixed64", "UnpackedSfixed32", "UnpackedSfixed64", "UnpackedFloat", "UnpackedDouble", "UnpackedBool", "UnpackedEnum", }); - internal__static_protobuf_unittest_TestPackedExtensions__Descriptor = Descriptor.MessageTypes[41]; + internal__static_protobuf_unittest_TestPackedExtensions__Descriptor = Descriptor.MessageTypes[42]; internal__static_protobuf_unittest_TestPackedExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestPackedExtensions__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestUnpackedExtensions__Descriptor = Descriptor.MessageTypes[42]; + internal__static_protobuf_unittest_TestUnpackedExtensions__Descriptor = Descriptor.MessageTypes[43]; internal__static_protobuf_unittest_TestUnpackedExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestUnpackedExtensions__Descriptor, new string[] { }); - internal__static_protobuf_unittest_TestDynamicExtensions__Descriptor = Descriptor.MessageTypes[43]; + internal__static_protobuf_unittest_TestDynamicExtensions__Descriptor = Descriptor.MessageTypes[44]; internal__static_protobuf_unittest_TestDynamicExtensions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDynamicExtensions__Descriptor, new string[] { "ScalarExtension", "EnumExtension", "DynamicEnumExtension", "MessageExtension", "DynamicMessageExtension", "RepeatedExtension", "PackedExtension", }); @@ -1213,11 +1222,11 @@ namespace Google.ProtocolBuffers.TestProtos { internal__static_protobuf_unittest_TestDynamicExtensions_DynamicMessageType__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestDynamicExtensions_DynamicMessageType__Descriptor, new string[] { "DynamicField", }); - internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor = Descriptor.MessageTypes[44]; + internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor = Descriptor.MessageTypes[45]; internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestRepeatedScalarDifferentTagSizes__Descriptor, new string[] { "RepeatedFixed32", "RepeatedInt32", "RepeatedFixed64", "RepeatedInt64", "RepeatedFloat", "RepeatedUint64", }); - internal__static_protobuf_unittest_TestParsingMerge__Descriptor = Descriptor.MessageTypes[45]; + internal__static_protobuf_unittest_TestParsingMerge__Descriptor = Descriptor.MessageTypes[46]; internal__static_protobuf_unittest_TestParsingMerge__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestParsingMerge__Descriptor, new string[] { "RequiredAllTypes", "OptionalAllTypes", "RepeatedAllTypes", "OptionalGroup", "RepeatedGroup", }); @@ -1243,31 +1252,31 @@ namespace Google.ProtocolBuffers.TestProtos { new string[] { "RepeatedGroupAllTypes", }); global::Google.ProtocolBuffers.TestProtos.TestParsingMerge.OptionalExt = pb::GeneratedSingleExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestParsingMerge.Descriptor.Extensions[0]); global::Google.ProtocolBuffers.TestProtos.TestParsingMerge.RepeatedExt = pb::GeneratedRepeatExtension.CreateInstance(global::Google.ProtocolBuffers.TestProtos.TestParsingMerge.Descriptor.Extensions[1]); - internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor = Descriptor.MessageTypes[46]; + internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor = Descriptor.MessageTypes[47]; internal__static_protobuf_unittest_TestCommentInjectionMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_TestCommentInjectionMessage__Descriptor, new string[] { "A", }); - internal__static_protobuf_unittest_FooRequest__Descriptor = Descriptor.MessageTypes[47]; + internal__static_protobuf_unittest_FooRequest__Descriptor = Descriptor.MessageTypes[48]; internal__static_protobuf_unittest_FooRequest__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_FooRequest__Descriptor, new string[] { }); - internal__static_protobuf_unittest_FooResponse__Descriptor = Descriptor.MessageTypes[48]; + internal__static_protobuf_unittest_FooResponse__Descriptor = Descriptor.MessageTypes[49]; internal__static_protobuf_unittest_FooResponse__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_FooResponse__Descriptor, new string[] { }); - internal__static_protobuf_unittest_FooClientMessage__Descriptor = Descriptor.MessageTypes[49]; + internal__static_protobuf_unittest_FooClientMessage__Descriptor = Descriptor.MessageTypes[50]; internal__static_protobuf_unittest_FooClientMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_FooClientMessage__Descriptor, new string[] { }); - internal__static_protobuf_unittest_FooServerMessage__Descriptor = Descriptor.MessageTypes[50]; + internal__static_protobuf_unittest_FooServerMessage__Descriptor = Descriptor.MessageTypes[51]; internal__static_protobuf_unittest_FooServerMessage__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_FooServerMessage__Descriptor, new string[] { }); - internal__static_protobuf_unittest_BarRequest__Descriptor = Descriptor.MessageTypes[51]; + internal__static_protobuf_unittest_BarRequest__Descriptor = Descriptor.MessageTypes[52]; internal__static_protobuf_unittest_BarRequest__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_BarRequest__Descriptor, new string[] { }); - internal__static_protobuf_unittest_BarResponse__Descriptor = Descriptor.MessageTypes[52]; + internal__static_protobuf_unittest_BarResponse__Descriptor = Descriptor.MessageTypes[53]; internal__static_protobuf_unittest_BarResponse__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_protobuf_unittest_BarResponse__Descriptor, new string[] { }); @@ -2281,6 +2290,19 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object oneofField_; + public enum OneofFieldOneofCase { + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofBytes = 114, + None = 0, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + public const int OptionalInt32FieldNumber = 1; private bool hasOptionalInt32; private int optionalInt32_; @@ -3042,43 +3064,35 @@ namespace Google.ProtocolBuffers.TestProtos { } public const int OneofUint32FieldNumber = 111; - private bool hasOneofUint32; - private uint oneofUint32_; public bool HasOneofUint32 { - get { return hasOneofUint32; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } } public uint OneofUint32 { - get { return oneofUint32_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } } public const int OneofNestedMessageFieldNumber = 112; - private bool hasOneofNestedMessage; - private global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage oneofNestedMessage_; public bool HasOneofNestedMessage { - get { return hasOneofNestedMessage; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { - get { return oneofNestedMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage) oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } } public const int OneofStringFieldNumber = 113; - private bool hasOneofString; - private string oneofString_ = ""; public bool HasOneofString { - get { return hasOneofString; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; } } public string OneofString { - get { return oneofString_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } } public const int OneofBytesFieldNumber = 114; - private bool hasOneofBytes; - private pb::ByteString oneofBytes_ = pb::ByteString.Empty; public bool HasOneofBytes { - get { return hasOneofBytes; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } } public pb::ByteString OneofBytes { - get { return oneofBytes_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } } public override bool IsInitialized { @@ -3303,16 +3317,16 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasDefaultCord) { output.WriteString(85, field_names[2], DefaultCord); } - if (hasOneofUint32) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { output.WriteUInt32(111, field_names[23], OneofUint32); } - if (hasOneofNestedMessage) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { output.WriteMessage(112, field_names[21], OneofNestedMessage); } - if (hasOneofString) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { output.WriteString(113, field_names[22], OneofString); } - if (hasOneofBytes) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { output.WriteBytes(114, field_names[20], OneofBytes); } UnknownFields.WriteTo(output); @@ -3637,16 +3651,16 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasDefaultCord) { size += pb::CodedOutputStream.ComputeStringSize(85, DefaultCord); } - if (hasOneofUint32) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { size += pb::CodedOutputStream.ComputeUInt32Size(111, OneofUint32); } - if (hasOneofNestedMessage) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { size += pb::CodedOutputStream.ComputeMessageSize(112, OneofNestedMessage); } - if (hasOneofString) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { size += pb::CodedOutputStream.ComputeStringSize(113, OneofString); } - if (hasOneofBytes) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { size += pb::CodedOutputStream.ComputeBytesSize(114, OneofBytes); } size += UnknownFields.SerializedSize; @@ -4009,17 +4023,24 @@ namespace Google.ProtocolBuffers.TestProtos { if (other.HasDefaultCord) { DefaultCord = other.DefaultCord; } - if (other.HasOneofUint32) { - OneofUint32 = other.OneofUint32; - } - if (other.HasOneofNestedMessage) { - MergeOneofNestedMessage(other.OneofNestedMessage); - } - if (other.HasOneofString) { - OneofString = other.OneofString; - } - if (other.HasOneofBytes) { - OneofBytes = other.OneofBytes; + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: { + SetOneofUint32(other.OneofUint32); + break; + } + case OneofFieldOneofCase.OneofNestedMessage: { + MergeOneofNestedMessage(other.OneofNestedMessage); + break; + } + case OneofFieldOneofCase.OneofString: { + SetOneofString(other.OneofString); + break; + } + case OneofFieldOneofCase.OneofBytes: { + SetOneofBytes(other.OneofBytes); + break; + } + case OneofFieldOneofCase.None: { break; } } this.MergeUnknownFields(other.UnknownFields); return this; @@ -4470,24 +4491,37 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 888: { - result.hasOneofUint32 = input.ReadUInt32(ref result.oneofUint32_); + uint value = 0; + if (input.ReadUInt32(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } break; } case 898: { global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.CreateBuilder(); - if (result.hasOneofNestedMessage) { + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { subBuilder.MergeFrom(OneofNestedMessage); } input.ReadMessage(subBuilder, extensionRegistry); - OneofNestedMessage = subBuilder.BuildPartial(); + result.oneofField_ = subBuilder.BuildPartial(); + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; break; } case 906: { - result.hasOneofString = input.ReadString(ref result.oneofString_); + string value = ""; + if (input.ReadString(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } break; } case 914: { - result.hasOneofBytes = input.ReadBytes(ref result.oneofBytes_); + pb::ByteString value = pb::ByteString.Empty; + if (input.ReadBytes(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } break; } } @@ -6377,104 +6411,119 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofUint32 { - get { return result.hasOneofUint32; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } } public uint OneofUint32 { - get { return result.OneofUint32; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) result.oneofField_ : 0; } set { SetOneofUint32(value); } } public Builder SetOneofUint32(uint value) { PrepareBuilder(); - result.hasOneofUint32 = true; - result.oneofUint32_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; return this; } public Builder ClearOneofUint32() { PrepareBuilder(); - result.hasOneofUint32 = false; - result.oneofUint32_ = 0; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } return this; } public bool HasOneofNestedMessage { - get { return result.hasOneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { - get { return result.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } set { SetOneofNestedMessage(value); } } public Builder SetOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofNestedMessage = true; - result.oneofNestedMessage_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; + result.oneofField_ = value; return this; } public Builder SetOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasOneofNestedMessage = true; - result.oneofNestedMessage_ = builderForValue.Build(); + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; + result.oneofField_ = builderForValue.Build(); return this; } public Builder MergeOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasOneofNestedMessage && - result.oneofNestedMessage_ != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance) { - result.oneofNestedMessage_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.CreateBuilder(result.oneofNestedMessage_).MergeFrom(value).BuildPartial(); + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage && + result.OneofNestedMessage != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance) { + result.oneofField_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.CreateBuilder(result.OneofNestedMessage).MergeFrom(value).BuildPartial(); } else { - result.oneofNestedMessage_ = value; + result.oneofField_ = value; } - result.hasOneofNestedMessage = true; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; return this; } public Builder ClearOneofNestedMessage() { - PrepareBuilder(); - result.hasOneofNestedMessage = false; - result.oneofNestedMessage_ = null; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + PrepareBuilder(); + result.oneofFieldCase_ = OneofFieldOneofCase.None; + result.oneofField_ = null; + } return this; } public bool HasOneofString { - get { return result.hasOneofString; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofString; } } public string OneofString { - get { return result.OneofString; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) result.oneofField_ : ""; } set { SetOneofString(value); } } public Builder SetOneofString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofString = true; - result.oneofString_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofString; return this; } public Builder ClearOneofString() { PrepareBuilder(); - result.hasOneofString = false; - result.oneofString_ = ""; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } return this; } public bool HasOneofBytes { - get { return result.hasOneofBytes; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } } public pb::ByteString OneofBytes { - get { return result.OneofBytes; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) result.oneofField_ : pb::ByteString.Empty; } set { SetOneofBytes(value); } } public Builder SetOneofBytes(pb::ByteString value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofBytes = true; - result.oneofBytes_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; return this; } public Builder ClearOneofBytes() { PrepareBuilder(); - result.hasOneofBytes = false; - result.oneofBytes_ = pb::ByteString.Empty; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } + return this; + } + + public OneofFieldOneofCase OneofFieldCase { + get { return result.oneofFieldCase_; } + } + public Builder ClearOneofField() { + PrepareBuilder(); + result.oneofField_ = null; + result.oneofFieldCase_ = OneofFieldOneofCase.None; return this; } } @@ -6487,8 +6536,8 @@ namespace Google.ProtocolBuffers.TestProtos { public sealed partial class NestedTestAllTypes : pb::GeneratedMessage { private NestedTestAllTypes() { } private static readonly NestedTestAllTypes defaultInstance = new NestedTestAllTypes().MakeReadOnly(); - private static readonly string[] _nestedTestAllTypesFieldNames = new string[] { "child", "payload" }; - private static readonly uint[] _nestedTestAllTypesFieldTags = new uint[] { 10, 18 }; + private static readonly string[] _nestedTestAllTypesFieldNames = new string[] { "child", "payload", "repeated_child" }; + private static readonly uint[] _nestedTestAllTypesFieldTags = new uint[] { 10, 18, 26 }; public static NestedTestAllTypes DefaultInstance { get { return defaultInstance; } } @@ -6529,6 +6578,18 @@ namespace Google.ProtocolBuffers.TestProtos { get { return payload_ ?? global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } } + public const int RepeatedChildFieldNumber = 3; + private pbc::PopsicleList repeatedChild_ = new pbc::PopsicleList(); + public scg::IList RepeatedChildList { + get { return repeatedChild_; } + } + public int RepeatedChildCount { + get { return repeatedChild_.Count; } + } + public global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes GetRepeatedChild(int index) { + return repeatedChild_[index]; + } + public override bool IsInitialized { get { return true; @@ -6544,6 +6605,9 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasPayload) { output.WriteMessage(2, field_names[1], Payload); } + if (repeatedChild_.Count > 0) { + output.WriteMessageArray(3, field_names[2], repeatedChild_); + } UnknownFields.WriteTo(output); } @@ -6567,6 +6631,9 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasPayload) { size += pb::CodedOutputStream.ComputeMessageSize(2, Payload); } + foreach (global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes element in RepeatedChildList) { + size += pb::CodedOutputStream.ComputeMessageSize(3, element); + } size += UnknownFields.SerializedSize; memoizedSerializedSize = size; return size; @@ -6602,6 +6669,7 @@ namespace Google.ProtocolBuffers.TestProtos { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } private NestedTestAllTypes MakeReadOnly() { + repeatedChild_.MakeReadOnly(); return this; } @@ -6695,6 +6763,9 @@ namespace Google.ProtocolBuffers.TestProtos { if (other.HasPayload) { MergePayload(other.Payload); } + if (other.repeatedChild_.Count != 0) { + result.repeatedChild_.Add(other.repeatedChild_); + } this.MergeUnknownFields(other.UnknownFields); return this; } @@ -6756,6 +6827,10 @@ namespace Google.ProtocolBuffers.TestProtos { Payload = subBuilder.BuildPartial(); break; } + case 26: { + input.ReadMessageArray(tag, field_name, result.repeatedChild_, global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes.DefaultInstance, extensionRegistry); + break; + } } } @@ -6845,6 +6920,50 @@ namespace Google.ProtocolBuffers.TestProtos { result.payload_ = null; return this; } + + public pbc::IPopsicleList RepeatedChildList { + get { return PrepareBuilder().repeatedChild_; } + } + public int RepeatedChildCount { + get { return result.RepeatedChildCount; } + } + public global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes GetRepeatedChild(int index) { + return result.GetRepeatedChild(index); + } + public Builder SetRepeatedChild(int index, global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.repeatedChild_[index] = value; + return this; + } + public Builder SetRepeatedChild(int index, global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.repeatedChild_[index] = builderForValue.Build(); + return this; + } + public Builder AddRepeatedChild(global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.repeatedChild_.Add(value); + return this; + } + public Builder AddRepeatedChild(global::Google.ProtocolBuffers.TestProtos.NestedTestAllTypes.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.repeatedChild_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeRepeatedChild(scg::IEnumerable values) { + PrepareBuilder(); + result.repeatedChild_.Add(values); + return this; + } + public Builder ClearRepeatedChild() { + PrepareBuilder(); + result.repeatedChild_.Clear(); + return this; + } } static NestedTestAllTypes() { object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); @@ -7408,43 +7527,40 @@ namespace Google.ProtocolBuffers.TestProtos { } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class TestAllExtensions : pb::ExtendableMessage { - private TestAllExtensions() { } - private static readonly TestAllExtensions defaultInstance = new TestAllExtensions().MakeReadOnly(); - private static readonly string[] _testAllExtensionsFieldNames = new string[] { }; - private static readonly uint[] _testAllExtensionsFieldTags = new uint[] { }; - public static TestAllExtensions DefaultInstance { + public sealed partial class TestReservedFields : pb::GeneratedMessage { + private TestReservedFields() { } + private static readonly TestReservedFields defaultInstance = new TestReservedFields().MakeReadOnly(); + private static readonly string[] _testReservedFieldsFieldNames = new string[] { }; + private static readonly uint[] _testReservedFieldsFieldTags = new uint[] { }; + public static TestReservedFields DefaultInstance { get { return defaultInstance; } } - public override TestAllExtensions DefaultInstanceForType { + public override TestReservedFields DefaultInstanceForType { get { return DefaultInstance; } } - protected override TestAllExtensions ThisMessage { + protected override TestReservedFields ThisMessage { get { return this; } } public static pbd::MessageDescriptor Descriptor { - get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestAllExtensions__Descriptor; } + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestReservedFields__Descriptor; } } - protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { - get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestAllExtensions__FieldAccessorTable; } + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestReservedFields__FieldAccessorTable; } } public override bool IsInitialized { get { - if (!ExtensionsAreInitialized) return false; return true; } } public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); - string[] field_names = _testAllExtensionsFieldNames; - pb::ExtendableMessage.ExtensionWriter extensionWriter = CreateExtensionWriter(this); - extensionWriter.WriteUntil(536870912, output); + string[] field_names = _testReservedFieldsFieldNames; UnknownFields.WriteTo(output); } @@ -7462,54 +7578,53 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - size += ExtensionsSerializedSize; size += UnknownFields.SerializedSize; memoizedSerializedSize = size; return size; } - public static TestAllExtensions ParseFrom(pb::ByteString data) { + public static TestReservedFields ParseFrom(pb::ByteString data) { return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); } - public static TestAllExtensions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); } - public static TestAllExtensions ParseFrom(byte[] data) { + public static TestReservedFields ParseFrom(byte[] data) { return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); } - public static TestAllExtensions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); } - public static TestAllExtensions ParseFrom(global::System.IO.Stream input) { + public static TestReservedFields ParseFrom(global::System.IO.Stream input) { return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); } - public static TestAllExtensions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } - public static TestAllExtensions ParseDelimitedFrom(global::System.IO.Stream input) { + public static TestReservedFields ParseDelimitedFrom(global::System.IO.Stream input) { return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); } - public static TestAllExtensions ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); } - public static TestAllExtensions ParseFrom(pb::ICodedInputStream input) { + public static TestReservedFields ParseFrom(pb::ICodedInputStream input) { return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); } - public static TestAllExtensions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + public static TestReservedFields ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } - private TestAllExtensions MakeReadOnly() { + private TestReservedFields MakeReadOnly() { return this; } public static Builder CreateBuilder() { return new Builder(); } public override Builder ToBuilder() { return CreateBuilder(this); } public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(TestAllExtensions prototype) { + public static Builder CreateBuilder(TestReservedFields prototype) { return new Builder(prototype); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::ExtendableBuilder { + public sealed partial class Builder : pb::GeneratedBuilder { protected override Builder ThisBuilder { get { return this; } } @@ -7517,18 +7632,18 @@ namespace Google.ProtocolBuffers.TestProtos { result = DefaultInstance; resultIsReadOnly = true; } - internal Builder(TestAllExtensions cloneFrom) { + internal Builder(TestReservedFields cloneFrom) { result = cloneFrom; resultIsReadOnly = true; } private bool resultIsReadOnly; - private TestAllExtensions result; + private TestReservedFields result; - private TestAllExtensions PrepareBuilder() { + private TestReservedFields PrepareBuilder() { if (resultIsReadOnly) { - TestAllExtensions original = result; - result = new TestAllExtensions(); + TestReservedFields original = result; + result = new TestReservedFields(); resultIsReadOnly = false; MergeFrom(original); } @@ -7539,7 +7654,7 @@ namespace Google.ProtocolBuffers.TestProtos { get { return result.IsInitialized; } } - protected override TestAllExtensions MessageBeingBuilt { + protected override TestReservedFields MessageBeingBuilt { get { return PrepareBuilder(); } } @@ -7558,14 +7673,14 @@ namespace Google.ProtocolBuffers.TestProtos { } public override pbd::MessageDescriptor DescriptorForType { - get { return global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.Descriptor; } + get { return global::Google.ProtocolBuffers.TestProtos.TestReservedFields.Descriptor; } } - public override TestAllExtensions DefaultInstanceForType { - get { return global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.DefaultInstance; } + public override TestReservedFields DefaultInstanceForType { + get { return global::Google.ProtocolBuffers.TestProtos.TestReservedFields.DefaultInstance; } } - public override TestAllExtensions BuildPartial() { + public override TestReservedFields BuildPartial() { if (resultIsReadOnly) { return result; } @@ -7574,18 +7689,17 @@ namespace Google.ProtocolBuffers.TestProtos { } public override Builder MergeFrom(pb::IMessage other) { - if (other is TestAllExtensions) { - return MergeFrom((TestAllExtensions) other); + if (other is TestReservedFields) { + return MergeFrom((TestReservedFields) other); } else { base.MergeFrom(other); return this; } } - public override Builder MergeFrom(TestAllExtensions other) { - if (other == global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.DefaultInstance) return this; + public override Builder MergeFrom(TestReservedFields other) { + if (other == global::Google.ProtocolBuffers.TestProtos.TestReservedFields.DefaultInstance) return this; PrepareBuilder(); - this.MergeExtensionFields(other); this.MergeUnknownFields(other.UnknownFields); return this; } @@ -7601,9 +7715,9 @@ namespace Google.ProtocolBuffers.TestProtos { string field_name; while (input.ReadTag(out tag, out field_name)) { if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_testAllExtensionsFieldNames, field_name, global::System.StringComparer.Ordinal); + int field_ordinal = global::System.Array.BinarySearch(_testReservedFieldsFieldNames, field_name, global::System.StringComparer.Ordinal); if(field_ordinal >= 0) - tag = _testAllExtensionsFieldTags[field_ordinal]; + tag = _testReservedFieldsFieldTags[field_ordinal]; else { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -7639,59 +7753,49 @@ namespace Google.ProtocolBuffers.TestProtos { } } - static TestAllExtensions() { + static TestReservedFields() { object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class OptionalGroup_extension : pb::GeneratedMessage { - private OptionalGroup_extension() { } - private static readonly OptionalGroup_extension defaultInstance = new OptionalGroup_extension().MakeReadOnly(); - private static readonly string[] _optionalGroupExtensionFieldNames = new string[] { "a" }; - private static readonly uint[] _optionalGroupExtensionFieldTags = new uint[] { 136 }; - public static OptionalGroup_extension DefaultInstance { + public sealed partial class TestAllExtensions : pb::ExtendableMessage { + private TestAllExtensions() { } + private static readonly TestAllExtensions defaultInstance = new TestAllExtensions().MakeReadOnly(); + private static readonly string[] _testAllExtensionsFieldNames = new string[] { }; + private static readonly uint[] _testAllExtensionsFieldTags = new uint[] { }; + public static TestAllExtensions DefaultInstance { get { return defaultInstance; } } - public override OptionalGroup_extension DefaultInstanceForType { + public override TestAllExtensions DefaultInstanceForType { get { return DefaultInstance; } } - protected override OptionalGroup_extension ThisMessage { + protected override TestAllExtensions ThisMessage { get { return this; } } public static pbd::MessageDescriptor Descriptor { - get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor; } - } - - protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { - get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_OptionalGroup_extension__FieldAccessorTable; } + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestAllExtensions__Descriptor; } } - public const int AFieldNumber = 17; - private bool hasA; - private int a_; - public bool HasA { - get { return hasA; } - } - public int A { - get { return a_; } + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_TestAllExtensions__FieldAccessorTable; } } public override bool IsInitialized { get { + if (!ExtensionsAreInitialized) return false; return true; } } public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); - string[] field_names = _optionalGroupExtensionFieldNames; - if (hasA) { - output.WriteInt32(17, field_names[0], A); - } + string[] field_names = _testAllExtensionsFieldNames; + pb::ExtendableMessage.ExtensionWriter extensionWriter = CreateExtensionWriter(this); + extensionWriter.WriteUntil(536870912, output); UnknownFields.WriteTo(output); } @@ -7709,56 +7813,54 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - if (hasA) { - size += pb::CodedOutputStream.ComputeInt32Size(17, A); - } + size += ExtensionsSerializedSize; size += UnknownFields.SerializedSize; memoizedSerializedSize = size; return size; } - public static OptionalGroup_extension ParseFrom(pb::ByteString data) { + public static TestAllExtensions ParseFrom(pb::ByteString data) { return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(byte[] data) { + public static TestAllExtensions ParseFrom(byte[] data) { return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(global::System.IO.Stream input) { + public static TestAllExtensions ParseFrom(global::System.IO.Stream input) { return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } - public static OptionalGroup_extension ParseDelimitedFrom(global::System.IO.Stream input) { + public static TestAllExtensions ParseDelimitedFrom(global::System.IO.Stream input) { return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); } - public static OptionalGroup_extension ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(pb::ICodedInputStream input) { + public static TestAllExtensions ParseFrom(pb::ICodedInputStream input) { return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); } - public static OptionalGroup_extension ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + public static TestAllExtensions ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); } - private OptionalGroup_extension MakeReadOnly() { + private TestAllExtensions MakeReadOnly() { return this; } public static Builder CreateBuilder() { return new Builder(); } public override Builder ToBuilder() { return CreateBuilder(this); } public override Builder CreateBuilderForType() { return new Builder(); } - public static Builder CreateBuilder(OptionalGroup_extension prototype) { + public static Builder CreateBuilder(TestAllExtensions prototype) { return new Builder(prototype); } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class Builder : pb::GeneratedBuilder { + public sealed partial class Builder : pb::ExtendableBuilder { protected override Builder ThisBuilder { get { return this; } } @@ -7766,18 +7868,18 @@ namespace Google.ProtocolBuffers.TestProtos { result = DefaultInstance; resultIsReadOnly = true; } - internal Builder(OptionalGroup_extension cloneFrom) { + internal Builder(TestAllExtensions cloneFrom) { result = cloneFrom; resultIsReadOnly = true; } private bool resultIsReadOnly; - private OptionalGroup_extension result; + private TestAllExtensions result; - private OptionalGroup_extension PrepareBuilder() { + private TestAllExtensions PrepareBuilder() { if (resultIsReadOnly) { - OptionalGroup_extension original = result; - result = new OptionalGroup_extension(); + TestAllExtensions original = result; + result = new TestAllExtensions(); resultIsReadOnly = false; MergeFrom(original); } @@ -7788,7 +7890,7 @@ namespace Google.ProtocolBuffers.TestProtos { get { return result.IsInitialized; } } - protected override OptionalGroup_extension MessageBeingBuilt { + protected override TestAllExtensions MessageBeingBuilt { get { return PrepareBuilder(); } } @@ -7807,14 +7909,14 @@ namespace Google.ProtocolBuffers.TestProtos { } public override pbd::MessageDescriptor DescriptorForType { - get { return global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.Descriptor; } + get { return global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.Descriptor; } } - public override OptionalGroup_extension DefaultInstanceForType { - get { return global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.DefaultInstance; } + public override TestAllExtensions DefaultInstanceForType { + get { return global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.DefaultInstance; } } - public override OptionalGroup_extension BuildPartial() { + public override TestAllExtensions BuildPartial() { if (resultIsReadOnly) { return result; } @@ -7823,20 +7925,18 @@ namespace Google.ProtocolBuffers.TestProtos { } public override Builder MergeFrom(pb::IMessage other) { - if (other is OptionalGroup_extension) { - return MergeFrom((OptionalGroup_extension) other); + if (other is TestAllExtensions) { + return MergeFrom((TestAllExtensions) other); } else { base.MergeFrom(other); return this; } } - public override Builder MergeFrom(OptionalGroup_extension other) { - if (other == global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.DefaultInstance) return this; + public override Builder MergeFrom(TestAllExtensions other) { + if (other == global::Google.ProtocolBuffers.TestProtos.TestAllExtensions.DefaultInstance) return this; PrepareBuilder(); - if (other.HasA) { - A = other.A; - } + this.MergeExtensionFields(other); this.MergeUnknownFields(other.UnknownFields); return this; } @@ -7852,9 +7952,9 @@ namespace Google.ProtocolBuffers.TestProtos { string field_name; while (input.ReadTag(out tag, out field_name)) { if(tag == 0 && field_name != null) { - int field_ordinal = global::System.Array.BinarySearch(_optionalGroupExtensionFieldNames, field_name, global::System.StringComparer.Ordinal); + int field_ordinal = global::System.Array.BinarySearch(_testAllExtensionsFieldNames, field_name, global::System.StringComparer.Ordinal); if(field_ordinal >= 0) - tag = _optionalGroupExtensionFieldTags[field_ordinal]; + tag = _testAllExtensionsFieldTags[field_ordinal]; else { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -7880,10 +7980,6 @@ namespace Google.ProtocolBuffers.TestProtos { ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); break; } - case 136: { - result.hasA = input.ReadInt32(ref result.a_); - break; - } } } @@ -7893,39 +7989,294 @@ namespace Google.ProtocolBuffers.TestProtos { return this; } - - public bool HasA { - get { return result.hasA; } - } - public int A { - get { return result.A; } - set { SetA(value); } - } - public Builder SetA(int value) { - PrepareBuilder(); - result.hasA = true; - result.a_ = value; - return this; - } - public Builder ClearA() { - PrepareBuilder(); - result.hasA = false; - result.a_ = 0; - return this; - } } - static OptionalGroup_extension() { + static TestAllExtensions() { object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); } } [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - public sealed partial class RepeatedGroup_extension : pb::GeneratedMessage { - private RepeatedGroup_extension() { } - private static readonly RepeatedGroup_extension defaultInstance = new RepeatedGroup_extension().MakeReadOnly(); - private static readonly string[] _repeatedGroupExtensionFieldNames = new string[] { "a" }; - private static readonly uint[] _repeatedGroupExtensionFieldTags = new uint[] { 376 }; - public static RepeatedGroup_extension DefaultInstance { + public sealed partial class OptionalGroup_extension : pb::GeneratedMessage { + private OptionalGroup_extension() { } + private static readonly OptionalGroup_extension defaultInstance = new OptionalGroup_extension().MakeReadOnly(); + private static readonly string[] _optionalGroupExtensionFieldNames = new string[] { "a" }; + private static readonly uint[] _optionalGroupExtensionFieldTags = new uint[] { 136 }; + public static OptionalGroup_extension DefaultInstance { + get { return defaultInstance; } + } + + public override OptionalGroup_extension DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override OptionalGroup_extension ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_OptionalGroup_extension__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.TestProtos.Unittest.internal__static_protobuf_unittest_OptionalGroup_extension__FieldAccessorTable; } + } + + public const int AFieldNumber = 17; + private bool hasA; + private int a_; + public bool HasA { + get { return hasA; } + } + public int A { + get { return a_; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _optionalGroupExtensionFieldNames; + if (hasA) { + output.WriteInt32(17, field_names[0], A); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasA) { + size += pb::CodedOutputStream.ComputeInt32Size(17, A); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static OptionalGroup_extension ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static OptionalGroup_extension ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static OptionalGroup_extension ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static OptionalGroup_extension ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private OptionalGroup_extension MakeReadOnly() { + return this; + } + + public static Builder CreateBuilder() { return new Builder(); } + public override Builder ToBuilder() { return CreateBuilder(this); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(OptionalGroup_extension prototype) { + return new Builder(prototype); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class Builder : pb::GeneratedBuilder { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() { + result = DefaultInstance; + resultIsReadOnly = true; + } + internal Builder(OptionalGroup_extension cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private OptionalGroup_extension result; + + private OptionalGroup_extension PrepareBuilder() { + if (resultIsReadOnly) { + OptionalGroup_extension original = result; + result = new OptionalGroup_extension(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override OptionalGroup_extension MessageBeingBuilt { + get { return PrepareBuilder(); } + } + + public override Builder Clear() { + result = DefaultInstance; + resultIsReadOnly = true; + return this; + } + + public override Builder Clone() { + if (resultIsReadOnly) { + return new Builder(result); + } else { + return new Builder().MergeFrom(result); + } + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.Descriptor; } + } + + public override OptionalGroup_extension DefaultInstanceForType { + get { return global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.DefaultInstance; } + } + + public override OptionalGroup_extension BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is OptionalGroup_extension) { + return MergeFrom((OptionalGroup_extension) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(OptionalGroup_extension other) { + if (other == global::Google.ProtocolBuffers.TestProtos.OptionalGroup_extension.DefaultInstance) return this; + PrepareBuilder(); + if (other.HasA) { + A = other.A; + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::ICodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + PrepareBuilder(); + pb::UnknownFieldSet.Builder unknownFields = null; + uint tag; + string field_name; + while (input.ReadTag(out tag, out field_name)) { + if(tag == 0 && field_name != null) { + int field_ordinal = global::System.Array.BinarySearch(_optionalGroupExtensionFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _optionalGroupExtensionFieldTags[field_ordinal]; + else { + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + continue; + } + } + switch (tag) { + case 0: { + throw pb::InvalidProtocolBufferException.InvalidTag(); + } + default: { + if (pb::WireFormat.IsEndGroupTag(tag)) { + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + break; + } + case 136: { + result.hasA = input.ReadInt32(ref result.a_); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public bool HasA { + get { return result.hasA; } + } + public int A { + get { return result.A; } + set { SetA(value); } + } + public Builder SetA(int value) { + PrepareBuilder(); + result.hasA = true; + result.a_ = value; + return this; + } + public Builder ClearA() { + PrepareBuilder(); + result.hasA = false; + result.a_ = 0; + return this; + } + } + static OptionalGroup_extension() { + object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class RepeatedGroup_extension : pb::GeneratedMessage { + private RepeatedGroup_extension() { } + private static readonly RepeatedGroup_extension defaultInstance = new RepeatedGroup_extension().MakeReadOnly(); + private static readonly string[] _repeatedGroupExtensionFieldNames = new string[] { "a" }; + private static readonly uint[] _repeatedGroupExtensionFieldTags = new uint[] { 376 }; + public static RepeatedGroup_extension DefaultInstance { get { return defaultInstance; } } @@ -21288,44 +21639,49 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object foo_; + public enum FooOneofCase { + FooInt = 1, + FooString = 2, + FooMessage = 3, + FooGroup = 4, + None = 0, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + public FooOneofCase FooCase { + get { return fooCase_; } + } + public const int FooIntFieldNumber = 1; - private bool hasFooInt; - private int fooInt_; public bool HasFooInt { - get { return hasFooInt; } + get { return fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return fooInt_; } + get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } } public const int FooStringFieldNumber = 2; - private bool hasFooString; - private string fooString_ = ""; public bool HasFooString { - get { return hasFooString; } + get { return fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return fooString_; } + get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } } public const int FooMessageFieldNumber = 3; - private bool hasFooMessage; - private global::Google.ProtocolBuffers.TestProtos.TestAllTypes fooMessage_; public bool HasFooMessage { - get { return hasFooMessage; } + get { return fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes FooMessage { - get { return fooMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes) foo_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } } public const int FooGroupFieldNumber = 4; - private bool hasFooGroup; - private global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup fooGroup_; public bool HasFooGroup { - get { return hasFooGroup; } + get { return fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup FooGroup { - get { return fooGroup_ ?? global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } } public override bool IsInitialized { @@ -21337,16 +21693,16 @@ namespace Google.ProtocolBuffers.TestProtos { public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); string[] field_names = _testOneofFieldNames; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { output.WriteInt32(1, field_names[0], FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { output.WriteString(2, field_names[2], FooString); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { output.WriteMessage(3, field_names[1], FooMessage); } - if (hasFooGroup) { + if (fooCase_ == FooOneofCase.FooGroup) { output.WriteGroup(4, field_names[3], FooGroup); } UnknownFields.WriteTo(output); @@ -21366,16 +21722,16 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { size += pb::CodedOutputStream.ComputeInt32Size(1, FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { size += pb::CodedOutputStream.ComputeStringSize(2, FooString); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { size += pb::CodedOutputStream.ComputeMessageSize(3, FooMessage); } - if (hasFooGroup) { + if (fooCase_ == FooOneofCase.FooGroup) { size += pb::CodedOutputStream.ComputeGroupSize(4, FooGroup); } size += UnknownFields.SerializedSize; @@ -21500,17 +21856,24 @@ namespace Google.ProtocolBuffers.TestProtos { public override Builder MergeFrom(TestOneof other) { if (other == global::Google.ProtocolBuffers.TestProtos.TestOneof.DefaultInstance) return this; PrepareBuilder(); - if (other.HasFooInt) { - FooInt = other.FooInt; - } - if (other.HasFooString) { - FooString = other.FooString; - } - if (other.HasFooMessage) { - MergeFooMessage(other.FooMessage); - } - if (other.HasFooGroup) { - MergeFooGroup(other.FooGroup); + switch (other.FooCase) { + case FooOneofCase.FooInt: { + SetFooInt(other.FooInt); + break; + } + case FooOneofCase.FooString: { + SetFooString(other.FooString); + break; + } + case FooOneofCase.FooMessage: { + MergeFooMessage(other.FooMessage); + break; + } + case FooOneofCase.FooGroup: { + MergeFooGroup(other.FooGroup); + break; + } + case FooOneofCase.None: { break; } } this.MergeUnknownFields(other.UnknownFields); return this; @@ -21556,29 +21919,39 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 8: { - result.hasFooInt = input.ReadInt32(ref result.fooInt_); + int value = 0; + if (input.ReadInt32(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; + } break; } case 18: { - result.hasFooString = input.ReadString(ref result.fooString_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; + } break; } case 26: { global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.CreateBuilder(); - if (result.hasFooMessage) { + if (result.fooCase_ == FooOneofCase.FooMessage) { subBuilder.MergeFrom(FooMessage); } input.ReadMessage(subBuilder, extensionRegistry); - FooMessage = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooMessage; break; } case 35: { global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.CreateBuilder(); - if (result.hasFooGroup) { + if (result.fooCase_ == FooOneofCase.FooGroup) { subBuilder.MergeFrom(FooGroup); } input.ReadGroup(4, subBuilder, extensionRegistry); - FooGroup = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooGroup; break; } } @@ -21592,123 +21965,139 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasFooInt { - get { return result.hasFooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return result.FooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt ? (int) result.foo_ : 0; } set { SetFooInt(value); } } public Builder SetFooInt(int value) { PrepareBuilder(); - result.hasFooInt = true; - result.fooInt_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; return this; } public Builder ClearFooInt() { PrepareBuilder(); - result.hasFooInt = false; - result.fooInt_ = 0; + if (result.fooCase_ == FooOneofCase.FooInt) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooString { - get { return result.hasFooString; } + get { return result.fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return result.FooString; } + get { return result.fooCase_ == FooOneofCase.FooString ? (string) result.foo_ : ""; } set { SetFooString(value); } } public Builder SetFooString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooString = true; - result.fooString_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; return this; } public Builder ClearFooString() { PrepareBuilder(); - result.hasFooString = false; - result.fooString_ = ""; + if (result.fooCase_ == FooOneofCase.FooString) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooMessage { - get { return result.hasFooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes FooMessage { - get { return result.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } set { SetFooMessage(value); } } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = value; + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = value; return this; } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypes value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooMessage && - result.fooMessage_ != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance) { - result.fooMessage_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.CreateBuilder(result.fooMessage_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooMessage && + result.FooMessage != global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypes.CreateBuilder(result.FooMessage).MergeFrom(value).BuildPartial(); } else { - result.fooMessage_ = value; + result.foo_ = value; } - result.hasFooMessage = true; + result.fooCase_ = FooOneofCase.FooMessage; return this; } public Builder ClearFooMessage() { - PrepareBuilder(); - result.hasFooMessage = false; - result.fooMessage_ = null; + if (result.fooCase_ == FooOneofCase.FooMessage) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } return this; } public bool HasFooGroup { - get { return result.hasFooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup FooGroup { - get { return result.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } set { SetFooGroup(value); } } public Builder SetFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup value) { pb::ThrowHelper.ThrowIfNull(value, "value"); - PrepareBuilder(); - result.hasFooGroup = true; - result.fooGroup_ = value; + PrepareBuilder(); + result.fooCase_ = FooOneofCase.FooGroup; + result.foo_ = value; return this; } public Builder SetFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooGroup = true; - result.fooGroup_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooGroup; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooGroup && - result.fooGroup_ != global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance) { - result.fooGroup_ = global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.CreateBuilder(result.fooGroup_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooGroup && + result.FooGroup != global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.CreateBuilder(result.FooGroup).MergeFrom(value).BuildPartial(); } else { - result.fooGroup_ = value; + result.foo_ = value; } - result.hasFooGroup = true; + result.fooCase_ = FooOneofCase.FooGroup; return this; } public Builder ClearFooGroup() { + if (result.fooCase_ == FooOneofCase.FooGroup) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } + return this; + } + + public FooOneofCase FooCase { + get { return result.fooCase_; } + } + public Builder ClearFoo() { PrepareBuilder(); - result.hasFooGroup = false; - result.fooGroup_ = null; + result.foo_ = null; + result.fooCase_ = FooOneofCase.None; return this; } } @@ -23191,154 +23580,157 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object foo_; + public enum FooOneofCase { + FooInt = 1, + FooString = 2, + FooCord = 3, + FooStringPiece = 4, + FooBytes = 5, + FooEnum = 6, + FooMessage = 7, + FooGroup = 8, + FooLazyMessage = 11, + None = 0, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + public FooOneofCase FooCase { + get { return fooCase_; } + } + + private object bar_; + public enum BarOneofCase { + BarInt = 12, + BarString = 13, + BarCord = 14, + BarStringPiece = 15, + BarBytes = 16, + BarEnum = 17, + None = 0, + } + private BarOneofCase barCase_ = BarOneofCase.None; + public BarOneofCase BarCase { + get { return barCase_; } + } + public const int FooIntFieldNumber = 1; - private bool hasFooInt; - private int fooInt_; public bool HasFooInt { - get { return hasFooInt; } + get { return fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return fooInt_; } + get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } } public const int FooStringFieldNumber = 2; - private bool hasFooString; - private string fooString_ = ""; public bool HasFooString { - get { return hasFooString; } + get { return fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return fooString_; } + get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } } public const int FooCordFieldNumber = 3; - private bool hasFooCord; - private string fooCord_ = ""; public bool HasFooCord { - get { return hasFooCord; } + get { return fooCase_ == FooOneofCase.FooCord; } } public string FooCord { - get { return fooCord_; } + get { return fooCase_ == FooOneofCase.FooCord ? (string) foo_ : ""; } } public const int FooStringPieceFieldNumber = 4; - private bool hasFooStringPiece; - private string fooStringPiece_ = ""; public bool HasFooStringPiece { - get { return hasFooStringPiece; } + get { return fooCase_ == FooOneofCase.FooStringPiece; } } public string FooStringPiece { - get { return fooStringPiece_; } + get { return fooCase_ == FooOneofCase.FooStringPiece ? (string) foo_ : ""; } } public const int FooBytesFieldNumber = 5; - private bool hasFooBytes; - private pb::ByteString fooBytes_ = pb::ByteString.Empty; public bool HasFooBytes { - get { return hasFooBytes; } + get { return fooCase_ == FooOneofCase.FooBytes; } } public pb::ByteString FooBytes { - get { return fooBytes_; } + get { return fooCase_ == FooOneofCase.FooBytes ? (pb::ByteString) foo_ : pb::ByteString.Empty; } } public const int FooEnumFieldNumber = 6; - private bool hasFooEnum; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum fooEnum_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; public bool HasFooEnum { - get { return hasFooEnum; } + get { return fooCase_ == FooOneofCase.FooEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum FooEnum { - get { return fooEnum_; } + get { return fooCase_ == FooOneofCase.FooEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; } } public const int FooMessageFieldNumber = 7; - private bool hasFooMessage; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage fooMessage_; public bool HasFooMessage { - get { return hasFooMessage; } + get { return fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooMessage { - get { return fooMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } } public const int FooGroupFieldNumber = 8; - private bool hasFooGroup; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup fooGroup_; public bool HasFooGroup { - get { return hasFooGroup; } + get { return fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup FooGroup { - get { return fooGroup_ ?? global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } } public const int FooLazyMessageFieldNumber = 11; - private bool hasFooLazyMessage; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage fooLazyMessage_; public bool HasFooLazyMessage { - get { return hasFooLazyMessage; } + get { return fooCase_ == FooOneofCase.FooLazyMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooLazyMessage { - get { return fooLazyMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } } public const int BarIntFieldNumber = 12; - private bool hasBarInt; - private int barInt_ = 5; public bool HasBarInt { - get { return hasBarInt; } + get { return barCase_ == BarOneofCase.BarInt; } } public int BarInt { - get { return barInt_; } + get { return barCase_ == BarOneofCase.BarInt ? (int) bar_ : 5; } } public const int BarStringFieldNumber = 13; - private bool hasBarString; - private string barString_ = "STRING"; public bool HasBarString { - get { return hasBarString; } + get { return barCase_ == BarOneofCase.BarString; } } public string BarString { - get { return barString_; } + get { return barCase_ == BarOneofCase.BarString ? (string) bar_ : "STRING"; } } public const int BarCordFieldNumber = 14; - private bool hasBarCord; - private string barCord_ = "CORD"; public bool HasBarCord { - get { return hasBarCord; } + get { return barCase_ == BarOneofCase.BarCord; } } public string BarCord { - get { return barCord_; } + get { return barCase_ == BarOneofCase.BarCord ? (string) bar_ : "CORD"; } } public const int BarStringPieceFieldNumber = 15; - private bool hasBarStringPiece; - private string barStringPiece_ = "SPIECE"; public bool HasBarStringPiece { - get { return hasBarStringPiece; } + get { return barCase_ == BarOneofCase.BarStringPiece; } } public string BarStringPiece { - get { return barStringPiece_; } + get { return barCase_ == BarOneofCase.BarStringPiece ? (string) bar_ : "SPIECE"; } } public const int BarBytesFieldNumber = 16; - private bool hasBarBytes; - private pb::ByteString barBytes_ = (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; public bool HasBarBytes { - get { return hasBarBytes; } + get { return barCase_ == BarOneofCase.BarBytes; } } public pb::ByteString BarBytes { - get { return barBytes_; } + get { return barCase_ == BarOneofCase.BarBytes ? (pb::ByteString) bar_ : (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; } } public const int BarEnumFieldNumber = 17; - private bool hasBarEnum; - private global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum barEnum_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; public bool HasBarEnum { - get { return hasBarEnum; } + get { return barCase_ == BarOneofCase.BarEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum BarEnum { - get { return barEnum_; } + get { return barCase_ == BarOneofCase.BarEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) bar_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; } } public const int BazIntFieldNumber = 18; @@ -23370,49 +23762,49 @@ namespace Google.ProtocolBuffers.TestProtos { public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); string[] field_names = _testOneof2FieldNames; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { output.WriteInt32(1, field_names[11], FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { output.WriteString(2, field_names[14], FooString); } - if (hasFooCord) { + if (fooCase_ == FooOneofCase.FooCord) { output.WriteString(3, field_names[9], FooCord); } - if (hasFooStringPiece) { + if (fooCase_ == FooOneofCase.FooStringPiece) { output.WriteString(4, field_names[15], FooStringPiece); } - if (hasFooBytes) { + if (fooCase_ == FooOneofCase.FooBytes) { output.WriteBytes(5, field_names[8], FooBytes); } - if (hasFooEnum) { + if (fooCase_ == FooOneofCase.FooEnum) { output.WriteEnum(6, field_names[10], (int) FooEnum, FooEnum); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { output.WriteMessage(7, field_names[13], FooMessage); } - if (hasFooGroup) { + if (fooCase_ == FooOneofCase.FooGroup) { output.WriteGroup(8, field_names[16], FooGroup); } - if (hasFooLazyMessage) { + if (fooCase_ == FooOneofCase.FooLazyMessage) { output.WriteMessage(11, field_names[12], FooLazyMessage); } - if (hasBarInt) { + if (barCase_ == BarOneofCase.BarInt) { output.WriteInt32(12, field_names[3], BarInt); } - if (hasBarString) { + if (barCase_ == BarOneofCase.BarString) { output.WriteString(13, field_names[4], BarString); } - if (hasBarCord) { + if (barCase_ == BarOneofCase.BarCord) { output.WriteString(14, field_names[1], BarCord); } - if (hasBarStringPiece) { + if (barCase_ == BarOneofCase.BarStringPiece) { output.WriteString(15, field_names[5], BarStringPiece); } - if (hasBarBytes) { + if (barCase_ == BarOneofCase.BarBytes) { output.WriteBytes(16, field_names[0], BarBytes); } - if (hasBarEnum) { + if (barCase_ == BarOneofCase.BarEnum) { output.WriteEnum(17, field_names[2], (int) BarEnum, BarEnum); } if (hasBazInt) { @@ -23438,49 +23830,49 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { size += pb::CodedOutputStream.ComputeInt32Size(1, FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { size += pb::CodedOutputStream.ComputeStringSize(2, FooString); } - if (hasFooCord) { + if (fooCase_ == FooOneofCase.FooCord) { size += pb::CodedOutputStream.ComputeStringSize(3, FooCord); } - if (hasFooStringPiece) { + if (fooCase_ == FooOneofCase.FooStringPiece) { size += pb::CodedOutputStream.ComputeStringSize(4, FooStringPiece); } - if (hasFooBytes) { + if (fooCase_ == FooOneofCase.FooBytes) { size += pb::CodedOutputStream.ComputeBytesSize(5, FooBytes); } - if (hasFooEnum) { + if (fooCase_ == FooOneofCase.FooEnum) { size += pb::CodedOutputStream.ComputeEnumSize(6, (int) FooEnum); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { size += pb::CodedOutputStream.ComputeMessageSize(7, FooMessage); } - if (hasFooGroup) { + if (fooCase_ == FooOneofCase.FooGroup) { size += pb::CodedOutputStream.ComputeGroupSize(8, FooGroup); } - if (hasFooLazyMessage) { + if (fooCase_ == FooOneofCase.FooLazyMessage) { size += pb::CodedOutputStream.ComputeMessageSize(11, FooLazyMessage); } - if (hasBarInt) { + if (barCase_ == BarOneofCase.BarInt) { size += pb::CodedOutputStream.ComputeInt32Size(12, BarInt); } - if (hasBarString) { + if (barCase_ == BarOneofCase.BarString) { size += pb::CodedOutputStream.ComputeStringSize(13, BarString); } - if (hasBarCord) { + if (barCase_ == BarOneofCase.BarCord) { size += pb::CodedOutputStream.ComputeStringSize(14, BarCord); } - if (hasBarStringPiece) { + if (barCase_ == BarOneofCase.BarStringPiece) { size += pb::CodedOutputStream.ComputeStringSize(15, BarStringPiece); } - if (hasBarBytes) { + if (barCase_ == BarOneofCase.BarBytes) { size += pb::CodedOutputStream.ComputeBytesSize(16, BarBytes); } - if (hasBarEnum) { + if (barCase_ == BarOneofCase.BarEnum) { size += pb::CodedOutputStream.ComputeEnumSize(17, (int) BarEnum); } if (hasBazInt) { @@ -23611,57 +24003,78 @@ namespace Google.ProtocolBuffers.TestProtos { public override Builder MergeFrom(TestOneof2 other) { if (other == global::Google.ProtocolBuffers.TestProtos.TestOneof2.DefaultInstance) return this; PrepareBuilder(); - if (other.HasFooInt) { - FooInt = other.FooInt; - } - if (other.HasFooString) { - FooString = other.FooString; - } - if (other.HasFooCord) { - FooCord = other.FooCord; - } - if (other.HasFooStringPiece) { - FooStringPiece = other.FooStringPiece; - } - if (other.HasFooBytes) { - FooBytes = other.FooBytes; - } - if (other.HasFooEnum) { - FooEnum = other.FooEnum; - } - if (other.HasFooMessage) { - MergeFooMessage(other.FooMessage); - } - if (other.HasFooGroup) { - MergeFooGroup(other.FooGroup); - } - if (other.HasFooLazyMessage) { - MergeFooLazyMessage(other.FooLazyMessage); - } - if (other.HasBarInt) { - BarInt = other.BarInt; - } - if (other.HasBarString) { - BarString = other.BarString; - } - if (other.HasBarCord) { - BarCord = other.BarCord; - } - if (other.HasBarStringPiece) { - BarStringPiece = other.BarStringPiece; - } - if (other.HasBarBytes) { - BarBytes = other.BarBytes; - } - if (other.HasBarEnum) { - BarEnum = other.BarEnum; - } if (other.HasBazInt) { BazInt = other.BazInt; } if (other.HasBazString) { BazString = other.BazString; } + switch (other.FooCase) { + case FooOneofCase.FooInt: { + SetFooInt(other.FooInt); + break; + } + case FooOneofCase.FooString: { + SetFooString(other.FooString); + break; + } + case FooOneofCase.FooCord: { + SetFooCord(other.FooCord); + break; + } + case FooOneofCase.FooStringPiece: { + SetFooStringPiece(other.FooStringPiece); + break; + } + case FooOneofCase.FooBytes: { + SetFooBytes(other.FooBytes); + break; + } + case FooOneofCase.FooEnum: { + SetFooEnum(other.FooEnum); + break; + } + case FooOneofCase.FooMessage: { + MergeFooMessage(other.FooMessage); + break; + } + case FooOneofCase.FooGroup: { + MergeFooGroup(other.FooGroup); + break; + } + case FooOneofCase.FooLazyMessage: { + MergeFooLazyMessage(other.FooLazyMessage); + break; + } + case FooOneofCase.None: { break; } + } + switch (other.BarCase) { + case BarOneofCase.BarInt: { + SetBarInt(other.BarInt); + break; + } + case BarOneofCase.BarString: { + SetBarString(other.BarString); + break; + } + case BarOneofCase.BarCord: { + SetBarCord(other.BarCord); + break; + } + case BarOneofCase.BarStringPiece: { + SetBarStringPiece(other.BarStringPiece); + break; + } + case BarOneofCase.BarBytes: { + SetBarBytes(other.BarBytes); + break; + } + case BarOneofCase.BarEnum: { + SetBarEnum(other.BarEnum); + break; + } + case BarOneofCase.None: { break; } + } this.MergeUnknownFields(other.UnknownFields); return this; } @@ -23706,29 +24119,51 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 8: { - result.hasFooInt = input.ReadInt32(ref result.fooInt_); + int value = 0; + if (input.ReadInt32(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; + } break; } case 18: { - result.hasFooString = input.ReadString(ref result.fooString_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; + } break; } case 26: { - result.hasFooCord = input.ReadString(ref result.fooCord_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooCord; + } break; } case 34: { - result.hasFooStringPiece = input.ReadString(ref result.fooStringPiece_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooStringPiece; + } break; } case 42: { - result.hasFooBytes = input.ReadBytes(ref result.fooBytes_); + pb::ByteString value = pb::ByteString.Empty; + if (input.ReadBytes(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooBytes; + } break; } case 48: { object unknown; - if(input.ReadEnum(ref result.fooEnum_, out unknown)) { - result.hasFooEnum = true; + global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum enumValue = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; + if(input.ReadEnum(ref enumValue, out unknown)) { + result.foo_ = enumValue; + result.fooCase_ = FooOneofCase.FooEnum; } else if(unknown is int) { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -23739,55 +24174,80 @@ namespace Google.ProtocolBuffers.TestProtos { } case 58: { global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(); - if (result.hasFooMessage) { + if (result.fooCase_ == FooOneofCase.FooMessage) { subBuilder.MergeFrom(FooMessage); } input.ReadMessage(subBuilder, extensionRegistry); - FooMessage = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooMessage; break; } case 67: { global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.CreateBuilder(); - if (result.hasFooGroup) { + if (result.fooCase_ == FooOneofCase.FooGroup) { subBuilder.MergeFrom(FooGroup); } input.ReadGroup(8, subBuilder, extensionRegistry); - FooGroup = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooGroup; break; } case 90: { global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(); - if (result.hasFooLazyMessage) { + if (result.fooCase_ == FooOneofCase.FooLazyMessage) { subBuilder.MergeFrom(FooLazyMessage); } input.ReadMessage(subBuilder, extensionRegistry); - FooLazyMessage = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooLazyMessage; break; } case 96: { - result.hasBarInt = input.ReadInt32(ref result.barInt_); + int value = 5; + if (input.ReadInt32(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarInt; + } break; } case 106: { - result.hasBarString = input.ReadString(ref result.barString_); + string value = "STRING"; + if (input.ReadString(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarString; + } break; } case 114: { - result.hasBarCord = input.ReadString(ref result.barCord_); + string value = "CORD"; + if (input.ReadString(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarCord; + } break; } case 122: { - result.hasBarStringPiece = input.ReadString(ref result.barStringPiece_); + string value = "SPIECE"; + if (input.ReadString(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarStringPiece; + } break; } case 130: { - result.hasBarBytes = input.ReadBytes(ref result.barBytes_); + pb::ByteString value = (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; + if (input.ReadBytes(ref value)) { + result.bar_ = value; + result.barCase_ = BarOneofCase.BarBytes; + } break; } case 136: { object unknown; - if(input.ReadEnum(ref result.barEnum_, out unknown)) { - result.hasBarEnum = true; + global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum enumValue = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; + if(input.ReadEnum(ref enumValue, out unknown)) { + result.bar_ = enumValue; + result.barCase_ = BarOneofCase.BarEnum; } else if(unknown is int) { if (unknownFields == null) { unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); @@ -23815,370 +24275,388 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasFooInt { - get { return result.hasFooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return result.FooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt ? (int) result.foo_ : 0; } set { SetFooInt(value); } } public Builder SetFooInt(int value) { PrepareBuilder(); - result.hasFooInt = true; - result.fooInt_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; return this; } public Builder ClearFooInt() { PrepareBuilder(); - result.hasFooInt = false; - result.fooInt_ = 0; + if (result.fooCase_ == FooOneofCase.FooInt) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooString { - get { return result.hasFooString; } + get { return result.fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return result.FooString; } + get { return result.fooCase_ == FooOneofCase.FooString ? (string) result.foo_ : ""; } set { SetFooString(value); } } public Builder SetFooString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooString = true; - result.fooString_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; return this; } public Builder ClearFooString() { PrepareBuilder(); - result.hasFooString = false; - result.fooString_ = ""; + if (result.fooCase_ == FooOneofCase.FooString) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooCord { - get { return result.hasFooCord; } + get { return result.fooCase_ == FooOneofCase.FooCord; } } public string FooCord { - get { return result.FooCord; } + get { return result.fooCase_ == FooOneofCase.FooCord ? (string) result.foo_ : ""; } set { SetFooCord(value); } } public Builder SetFooCord(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooCord = true; - result.fooCord_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooCord; return this; } public Builder ClearFooCord() { PrepareBuilder(); - result.hasFooCord = false; - result.fooCord_ = ""; + if (result.fooCase_ == FooOneofCase.FooCord) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooStringPiece { - get { return result.hasFooStringPiece; } + get { return result.fooCase_ == FooOneofCase.FooStringPiece; } } public string FooStringPiece { - get { return result.FooStringPiece; } + get { return result.fooCase_ == FooOneofCase.FooStringPiece ? (string) result.foo_ : ""; } set { SetFooStringPiece(value); } } public Builder SetFooStringPiece(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooStringPiece = true; - result.fooStringPiece_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooStringPiece; return this; } public Builder ClearFooStringPiece() { PrepareBuilder(); - result.hasFooStringPiece = false; - result.fooStringPiece_ = ""; + if (result.fooCase_ == FooOneofCase.FooStringPiece) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooBytes { - get { return result.hasFooBytes; } + get { return result.fooCase_ == FooOneofCase.FooBytes; } } public pb::ByteString FooBytes { - get { return result.FooBytes; } + get { return result.fooCase_ == FooOneofCase.FooBytes ? (pb::ByteString) result.foo_ : pb::ByteString.Empty; } set { SetFooBytes(value); } } public Builder SetFooBytes(pb::ByteString value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooBytes = true; - result.fooBytes_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooBytes; return this; } public Builder ClearFooBytes() { PrepareBuilder(); - result.hasFooBytes = false; - result.fooBytes_ = pb::ByteString.Empty; + if (result.fooCase_ == FooOneofCase.FooBytes) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooEnum { - get { return result.hasFooEnum; } + get { return result.fooCase_ == FooOneofCase.FooEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum FooEnum { - get { return result.FooEnum; } + get { return result.fooCase_ == FooOneofCase.FooEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; } set { SetFooEnum(value); } } public Builder SetFooEnum(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum value) { PrepareBuilder(); - result.hasFooEnum = true; - result.fooEnum_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooEnum; return this; } public Builder ClearFooEnum() { PrepareBuilder(); - result.hasFooEnum = false; - result.fooEnum_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; + if (result.fooCase_ == FooOneofCase.FooEnum) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooMessage { - get { return result.hasFooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooMessage { - get { return result.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } set { SetFooMessage(value); } } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = value; + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = value; return this; } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooMessage && - result.fooMessage_ != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance) { - result.fooMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(result.fooMessage_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooMessage && + result.FooMessage != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(result.FooMessage).MergeFrom(value).BuildPartial(); } else { - result.fooMessage_ = value; + result.foo_ = value; } - result.hasFooMessage = true; + result.fooCase_ = FooOneofCase.FooMessage; return this; } public Builder ClearFooMessage() { - PrepareBuilder(); - result.hasFooMessage = false; - result.fooMessage_ = null; + if (result.fooCase_ == FooOneofCase.FooMessage) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } return this; } public bool HasFooGroup { - get { return result.hasFooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup FooGroup { - get { return result.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } set { SetFooGroup(value); } } public Builder SetFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooGroup = true; - result.fooGroup_ = value; + result.fooCase_ = FooOneofCase.FooGroup; + result.foo_ = value; return this; } public Builder SetFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooGroup = true; - result.fooGroup_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooGroup; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooGroup(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooGroup && - result.fooGroup_ != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance) { - result.fooGroup_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.CreateBuilder(result.fooGroup_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooGroup && + result.FooGroup != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.CreateBuilder(result.FooGroup).MergeFrom(value).BuildPartial(); } else { - result.fooGroup_ = value; + result.foo_ = value; } - result.hasFooGroup = true; + result.fooCase_ = FooOneofCase.FooGroup; return this; } public Builder ClearFooGroup() { - PrepareBuilder(); - result.hasFooGroup = false; - result.fooGroup_ = null; + if (result.fooCase_ == FooOneofCase.FooGroup) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } return this; } public bool HasFooLazyMessage { - get { return result.hasFooLazyMessage; } + get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooLazyMessage { - get { return result.FooLazyMessage; } + get { return result.fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } set { SetFooLazyMessage(value); } } public Builder SetFooLazyMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooLazyMessage = true; - result.fooLazyMessage_ = value; + result.fooCase_ = FooOneofCase.FooLazyMessage; + result.foo_ = value; return this; } public Builder SetFooLazyMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooLazyMessage = true; - result.fooLazyMessage_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooLazyMessage; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooLazyMessage(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooLazyMessage && - result.fooLazyMessage_ != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance) { - result.fooLazyMessage_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(result.fooLazyMessage_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooLazyMessage && + result.FooLazyMessage != global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.CreateBuilder(result.FooLazyMessage).MergeFrom(value).BuildPartial(); } else { - result.fooLazyMessage_ = value; + result.foo_ = value; } - result.hasFooLazyMessage = true; + result.fooCase_ = FooOneofCase.FooLazyMessage; return this; } public Builder ClearFooLazyMessage() { - PrepareBuilder(); - result.hasFooLazyMessage = false; - result.fooLazyMessage_ = null; + if (result.fooCase_ == FooOneofCase.FooLazyMessage) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } return this; } public bool HasBarInt { - get { return result.hasBarInt; } + get { return result.barCase_ == BarOneofCase.BarInt; } } public int BarInt { - get { return result.BarInt; } + get { return result.barCase_ == BarOneofCase.BarInt ? (int) result.bar_ : 5; } set { SetBarInt(value); } } public Builder SetBarInt(int value) { PrepareBuilder(); - result.hasBarInt = true; - result.barInt_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarInt; return this; } public Builder ClearBarInt() { PrepareBuilder(); - result.hasBarInt = false; - result.barInt_ = 5; + if (result.barCase_ == BarOneofCase.BarInt) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarString { - get { return result.hasBarString; } + get { return result.barCase_ == BarOneofCase.BarString; } } public string BarString { - get { return result.BarString; } + get { return result.barCase_ == BarOneofCase.BarString ? (string) result.bar_ : "STRING"; } set { SetBarString(value); } } public Builder SetBarString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasBarString = true; - result.barString_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarString; return this; } public Builder ClearBarString() { PrepareBuilder(); - result.hasBarString = false; - result.barString_ = "STRING"; + if (result.barCase_ == BarOneofCase.BarString) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarCord { - get { return result.hasBarCord; } + get { return result.barCase_ == BarOneofCase.BarCord; } } public string BarCord { - get { return result.BarCord; } + get { return result.barCase_ == BarOneofCase.BarCord ? (string) result.bar_ : "CORD"; } set { SetBarCord(value); } } public Builder SetBarCord(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasBarCord = true; - result.barCord_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarCord; return this; } public Builder ClearBarCord() { PrepareBuilder(); - result.hasBarCord = false; - result.barCord_ = "CORD"; + if (result.barCase_ == BarOneofCase.BarCord) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarStringPiece { - get { return result.hasBarStringPiece; } + get { return result.barCase_ == BarOneofCase.BarStringPiece; } } public string BarStringPiece { - get { return result.BarStringPiece; } + get { return result.barCase_ == BarOneofCase.BarStringPiece ? (string) result.bar_ : "SPIECE"; } set { SetBarStringPiece(value); } } public Builder SetBarStringPiece(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasBarStringPiece = true; - result.barStringPiece_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarStringPiece; return this; } public Builder ClearBarStringPiece() { PrepareBuilder(); - result.hasBarStringPiece = false; - result.barStringPiece_ = "SPIECE"; + if (result.barCase_ == BarOneofCase.BarStringPiece) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarBytes { - get { return result.hasBarBytes; } + get { return result.barCase_ == BarOneofCase.BarBytes; } } public pb::ByteString BarBytes { - get { return result.BarBytes; } + get { return result.barCase_ == BarOneofCase.BarBytes ? (pb::ByteString) result.bar_ : (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; } set { SetBarBytes(value); } } public Builder SetBarBytes(pb::ByteString value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasBarBytes = true; - result.barBytes_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarBytes; return this; } public Builder ClearBarBytes() { PrepareBuilder(); - result.hasBarBytes = false; - result.barBytes_ = (pb::ByteString) global::Google.ProtocolBuffers.TestProtos.TestOneof2.Descriptor.Fields[13].DefaultValue; + if (result.barCase_ == BarOneofCase.BarBytes) { + result.barCase_ = BarOneofCase.None; + } return this; } public bool HasBarEnum { - get { return result.hasBarEnum; } + get { return result.barCase_ == BarOneofCase.BarEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum BarEnum { - get { return result.BarEnum; } + get { return result.barCase_ == BarOneofCase.BarEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) result.bar_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; } set { SetBarEnum(value); } } public Builder SetBarEnum(global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum value) { PrepareBuilder(); - result.hasBarEnum = true; - result.barEnum_ = value; + result.bar_ = value; + result.barCase_ = BarOneofCase.BarEnum; return this; } public Builder ClearBarEnum() { PrepareBuilder(); - result.hasBarEnum = false; - result.barEnum_ = global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; + if (result.barCase_ == BarOneofCase.BarEnum) { + result.barCase_ = BarOneofCase.None; + } return this; } @@ -24222,6 +24700,26 @@ namespace Google.ProtocolBuffers.TestProtos { result.bazString_ = "BAZ"; return this; } + + public FooOneofCase FooCase { + get { return result.fooCase_; } + } + public Builder ClearFoo() { + PrepareBuilder(); + result.foo_ = null; + result.fooCase_ = FooOneofCase.None; + return this; + } + + public BarOneofCase BarCase { + get { return result.barCase_; } + } + public Builder ClearBar() { + PrepareBuilder(); + result.bar_ = null; + result.barCase_ = BarOneofCase.None; + return this; + } } static TestOneof2() { object.ReferenceEquals(global::Google.ProtocolBuffers.TestProtos.Unittest.Descriptor, null); @@ -24536,34 +25034,40 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object foo_; + public enum FooOneofCase { + FooInt = 1, + FooString = 2, + FooMessage = 3, + None = 0, + } + private FooOneofCase fooCase_ = FooOneofCase.None; + public FooOneofCase FooCase { + get { return fooCase_; } + } + public const int FooIntFieldNumber = 1; - private bool hasFooInt; - private int fooInt_; public bool HasFooInt { - get { return hasFooInt; } + get { return fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return fooInt_; } + get { return fooCase_ == FooOneofCase.FooInt ? (int) foo_ : 0; } } public const int FooStringFieldNumber = 2; - private bool hasFooString; - private string fooString_ = ""; public bool HasFooString { - get { return hasFooString; } + get { return fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return fooString_; } + get { return fooCase_ == FooOneofCase.FooString ? (string) foo_ : ""; } } public const int FooMessageFieldNumber = 3; - private bool hasFooMessage; - private global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage fooMessage_; public bool HasFooMessage { - get { return hasFooMessage; } + get { return fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage FooMessage { - get { return fooMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } + get { return fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage) foo_ : global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } } public override bool IsInitialized { @@ -24578,13 +25082,13 @@ namespace Google.ProtocolBuffers.TestProtos { public override void WriteTo(pb::ICodedOutputStream output) { CalcSerializedSize(); string[] field_names = _testRequiredOneofFieldNames; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { output.WriteInt32(1, field_names[0], FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { output.WriteString(2, field_names[2], FooString); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { output.WriteMessage(3, field_names[1], FooMessage); } UnknownFields.WriteTo(output); @@ -24604,13 +25108,13 @@ namespace Google.ProtocolBuffers.TestProtos { if (size != -1) return size; size = 0; - if (hasFooInt) { + if (fooCase_ == FooOneofCase.FooInt) { size += pb::CodedOutputStream.ComputeInt32Size(1, FooInt); } - if (hasFooString) { + if (fooCase_ == FooOneofCase.FooString) { size += pb::CodedOutputStream.ComputeStringSize(2, FooString); } - if (hasFooMessage) { + if (fooCase_ == FooOneofCase.FooMessage) { size += pb::CodedOutputStream.ComputeMessageSize(3, FooMessage); } size += UnknownFields.SerializedSize; @@ -24735,14 +25239,20 @@ namespace Google.ProtocolBuffers.TestProtos { public override Builder MergeFrom(TestRequiredOneof other) { if (other == global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.DefaultInstance) return this; PrepareBuilder(); - if (other.HasFooInt) { - FooInt = other.FooInt; - } - if (other.HasFooString) { - FooString = other.FooString; - } - if (other.HasFooMessage) { - MergeFooMessage(other.FooMessage); + switch (other.FooCase) { + case FooOneofCase.FooInt: { + SetFooInt(other.FooInt); + break; + } + case FooOneofCase.FooString: { + SetFooString(other.FooString); + break; + } + case FooOneofCase.FooMessage: { + MergeFooMessage(other.FooMessage); + break; + } + case FooOneofCase.None: { break; } } this.MergeUnknownFields(other.UnknownFields); return this; @@ -24788,20 +25298,29 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 8: { - result.hasFooInt = input.ReadInt32(ref result.fooInt_); + int value = 0; + if (input.ReadInt32(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; + } break; } case 18: { - result.hasFooString = input.ReadString(ref result.fooString_); + string value = ""; + if (input.ReadString(ref value)) { + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; + } break; } case 26: { global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.CreateBuilder(); - if (result.hasFooMessage) { + if (result.fooCase_ == FooOneofCase.FooMessage) { subBuilder.MergeFrom(FooMessage); } input.ReadMessage(subBuilder, extensionRegistry); - FooMessage = subBuilder.BuildPartial(); + result.foo_ = subBuilder.BuildPartial(); + result.fooCase_ = FooOneofCase.FooMessage; break; } } @@ -24815,83 +25334,97 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasFooInt { - get { return result.hasFooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt; } } public int FooInt { - get { return result.FooInt; } + get { return result.fooCase_ == FooOneofCase.FooInt ? (int) result.foo_ : 0; } set { SetFooInt(value); } } public Builder SetFooInt(int value) { PrepareBuilder(); - result.hasFooInt = true; - result.fooInt_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooInt; return this; } public Builder ClearFooInt() { PrepareBuilder(); - result.hasFooInt = false; - result.fooInt_ = 0; + if (result.fooCase_ == FooOneofCase.FooInt) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooString { - get { return result.hasFooString; } + get { return result.fooCase_ == FooOneofCase.FooString; } } public string FooString { - get { return result.FooString; } + get { return result.fooCase_ == FooOneofCase.FooString ? (string) result.foo_ : ""; } set { SetFooString(value); } } public Builder SetFooString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooString = true; - result.fooString_ = value; + result.foo_ = value; + result.fooCase_ = FooOneofCase.FooString; return this; } public Builder ClearFooString() { PrepareBuilder(); - result.hasFooString = false; - result.fooString_ = ""; + if (result.fooCase_ == FooOneofCase.FooString) { + result.fooCase_ = FooOneofCase.None; + } return this; } public bool HasFooMessage { - get { return result.hasFooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage FooMessage { - get { return result.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } set { SetFooMessage(value); } } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = value; + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = value; return this; } public Builder SetFooMessage(global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasFooMessage = true; - result.fooMessage_ = builderForValue.Build(); + result.fooCase_ = FooOneofCase.FooMessage; + result.foo_ = builderForValue.Build(); return this; } public Builder MergeFooMessage(global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasFooMessage && - result.fooMessage_ != global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance) { - result.fooMessage_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.CreateBuilder(result.fooMessage_).MergeFrom(value).BuildPartial(); + if (result.fooCase_ == FooOneofCase.FooMessage && + result.FooMessage != global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance) { + result.foo_ = global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.CreateBuilder(result.FooMessage).MergeFrom(value).BuildPartial(); } else { - result.fooMessage_ = value; + result.foo_ = value; } - result.hasFooMessage = true; + result.fooCase_ = FooOneofCase.FooMessage; return this; } public Builder ClearFooMessage() { + if (result.fooCase_ == FooOneofCase.FooMessage) { + PrepareBuilder(); + result.fooCase_ = FooOneofCase.None; + result.foo_ = null; + } + return this; + } + + public FooOneofCase FooCase { + get { return result.fooCase_; } + } + public Builder ClearFoo() { PrepareBuilder(); - result.hasFooMessage = false; - result.fooMessage_ = null; + result.foo_ = null; + result.fooCase_ = FooOneofCase.None; return this; } } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs index e6cc2adb..84860b69 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs @@ -1971,6 +1971,19 @@ namespace Google.ProtocolBuffers.TestProtos { } #endregion + private object oneofField_; + public enum OneofFieldOneofCase { + OneofUint32 = 111, + OneofNestedMessage = 112, + OneofString = 113, + OneofBytes = 114, + None = 0, + } + private OneofFieldOneofCase oneofFieldCase_ = OneofFieldOneofCase.None; + public OneofFieldOneofCase OneofFieldCase { + get { return oneofFieldCase_; } + } + public const int OptionalInt32FieldNumber = 1; private bool hasOptionalInt32; private int optionalInt32_; @@ -2732,43 +2745,35 @@ namespace Google.ProtocolBuffers.TestProtos { } public const int OneofUint32FieldNumber = 111; - private bool hasOneofUint32; - private uint oneofUint32_; public bool HasOneofUint32 { - get { return hasOneofUint32; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } } public uint OneofUint32 { - get { return oneofUint32_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) oneofField_ : 0; } } public const int OneofNestedMessageFieldNumber = 112; - private bool hasOneofNestedMessage; - private global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage oneofNestedMessage_; public bool HasOneofNestedMessage { - get { return hasOneofNestedMessage; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage OneofNestedMessage { - get { return oneofNestedMessage_ ?? global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.DefaultInstance; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage) oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.DefaultInstance; } } public const int OneofStringFieldNumber = 113; - private bool hasOneofString; - private string oneofString_ = ""; public bool HasOneofString { - get { return hasOneofString; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString; } } public string OneofString { - get { return oneofString_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) oneofField_ : ""; } } public const int OneofBytesFieldNumber = 114; - private bool hasOneofBytes; - private pb::ByteString oneofBytes_ = pb::ByteString.Empty; public bool HasOneofBytes { - get { return hasOneofBytes; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } } public pb::ByteString OneofBytes { - get { return oneofBytes_; } + get { return oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) oneofField_ : pb::ByteString.Empty; } } public override bool IsInitialized { @@ -2993,16 +2998,16 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasDefaultCord) { output.WriteString(85, field_names[2], DefaultCord); } - if (hasOneofUint32) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { output.WriteUInt32(111, field_names[23], OneofUint32); } - if (hasOneofNestedMessage) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { output.WriteMessage(112, field_names[21], OneofNestedMessage); } - if (hasOneofString) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { output.WriteString(113, field_names[22], OneofString); } - if (hasOneofBytes) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { output.WriteBytes(114, field_names[20], OneofBytes); } } @@ -3326,16 +3331,16 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasDefaultCord) { size += pb::CodedOutputStream.ComputeStringSize(85, DefaultCord); } - if (hasOneofUint32) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { size += pb::CodedOutputStream.ComputeUInt32Size(111, OneofUint32); } - if (hasOneofNestedMessage) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { size += pb::CodedOutputStream.ComputeMessageSize(112, OneofNestedMessage); } - if (hasOneofString) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { size += pb::CodedOutputStream.ComputeStringSize(113, OneofString); } - if (hasOneofBytes) { + if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { size += pb::CodedOutputStream.ComputeBytesSize(114, OneofBytes); } memoizedSerializedSize = size; @@ -3520,15 +3525,8 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasDefaultCord) { hash ^= defaultCord_.GetHashCode(); } - if (hasOneofUint32) { - hash ^= oneofUint32_.GetHashCode(); - } - if (hasOneofNestedMessage) hash ^= oneofNestedMessage_.GetHashCode(); - if (hasOneofString) { - hash ^= oneofString_.GetHashCode(); - } - if (hasOneofBytes) { - hash ^= oneofBytes_.GetHashCode(); + if (oneofFieldCase_ != OneofFieldOneofCase.None) { + hash ^= oneofField_.GetHashCode(); } return hash; } @@ -3657,10 +3655,10 @@ namespace Google.ProtocolBuffers.TestProtos { if (hasDefaultImportEnum != other.hasDefaultImportEnum || (hasDefaultImportEnum && !defaultImportEnum_.Equals(other.defaultImportEnum_))) return false; if (hasDefaultStringPiece != other.hasDefaultStringPiece || (hasDefaultStringPiece && !defaultStringPiece_.Equals(other.defaultStringPiece_))) return false; if (hasDefaultCord != other.hasDefaultCord || (hasDefaultCord && !defaultCord_.Equals(other.defaultCord_))) return false; - if (hasOneofUint32 != other.hasOneofUint32 || (hasOneofUint32 && !oneofUint32_.Equals(other.oneofUint32_))) return false; - if (hasOneofNestedMessage != other.hasOneofNestedMessage || (hasOneofNestedMessage && !oneofNestedMessage_.Equals(other.oneofNestedMessage_))) return false; - if (hasOneofString != other.hasOneofString || (hasOneofString && !oneofString_.Equals(other.oneofString_))) return false; - if (hasOneofBytes != other.hasOneofBytes || (hasOneofBytes && !oneofBytes_.Equals(other.oneofBytes_))) return false; + if (!OneofUint32.Equals(other.OneofUint32)) return false; + if (!OneofNestedMessage.Equals(other.OneofNestedMessage)) return false; + if (!OneofString.Equals(other.OneofString)) return false; + if (!OneofBytes.Equals(other.OneofBytes)) return false; return true; } @@ -3736,10 +3734,10 @@ namespace Google.ProtocolBuffers.TestProtos { PrintField("default_import_enum", hasDefaultImportEnum, defaultImportEnum_, writer); PrintField("default_string_piece", hasDefaultStringPiece, defaultStringPiece_, writer); PrintField("default_cord", hasDefaultCord, defaultCord_, writer); - PrintField("oneof_uint32", hasOneofUint32, oneofUint32_, writer); - PrintField("oneof_nested_message", hasOneofNestedMessage, oneofNestedMessage_, writer); - PrintField("oneof_string", hasOneofString, oneofString_, writer); - PrintField("oneof_bytes", hasOneofBytes, oneofBytes_, writer); + PrintField("oneof_uint32", oneofFieldCase_ == OneofFieldOneofCase.OneofUint32, oneofField_, writer); + PrintField("oneof_nested_message", oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage, oneofField_, writer); + PrintField("oneof_string", oneofFieldCase_ == OneofFieldOneofCase.OneofString, oneofField_, writer); + PrintField("oneof_bytes", oneofFieldCase_ == OneofFieldOneofCase.OneofBytes, oneofField_, writer); } #endregion @@ -4095,17 +4093,24 @@ namespace Google.ProtocolBuffers.TestProtos { if (other.HasDefaultCord) { DefaultCord = other.DefaultCord; } - if (other.HasOneofUint32) { - OneofUint32 = other.OneofUint32; - } - if (other.HasOneofNestedMessage) { - MergeOneofNestedMessage(other.OneofNestedMessage); - } - if (other.HasOneofString) { - OneofString = other.OneofString; - } - if (other.HasOneofBytes) { - OneofBytes = other.OneofBytes; + switch (other.OneofFieldCase) { + case OneofFieldOneofCase.OneofUint32: { + SetOneofUint32(other.OneofUint32); + break; + } + case OneofFieldOneofCase.OneofNestedMessage: { + MergeOneofNestedMessage(other.OneofNestedMessage); + break; + } + case OneofFieldOneofCase.OneofString: { + SetOneofString(other.OneofString); + break; + } + case OneofFieldOneofCase.OneofBytes: { + SetOneofBytes(other.OneofBytes); + break; + } + case OneofFieldOneofCase.None: { break; } } return this; } @@ -4497,24 +4502,37 @@ namespace Google.ProtocolBuffers.TestProtos { break; } case 888: { - result.hasOneofUint32 = input.ReadUInt32(ref result.oneofUint32_); + uint value = 0; + if (input.ReadUInt32(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; + } break; } case 898: { global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.Builder subBuilder = global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.CreateBuilder(); - if (result.hasOneofNestedMessage) { + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { subBuilder.MergeFrom(OneofNestedMessage); } input.ReadMessage(subBuilder, extensionRegistry); - OneofNestedMessage = subBuilder.BuildPartial(); + result.oneofField_ = subBuilder.BuildPartial(); + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; break; } case 906: { - result.hasOneofString = input.ReadString(ref result.oneofString_); + string value = ""; + if (input.ReadString(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofString; + } break; } case 914: { - result.hasOneofBytes = input.ReadBytes(ref result.oneofBytes_); + pb::ByteString value = pb::ByteString.Empty; + if (input.ReadBytes(ref value)) { + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; + } break; } } @@ -6401,104 +6419,119 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofUint32 { - get { return result.hasOneofUint32; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32; } } public uint OneofUint32 { - get { return result.OneofUint32; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32 ? (uint) result.oneofField_ : 0; } set { SetOneofUint32(value); } } public Builder SetOneofUint32(uint value) { PrepareBuilder(); - result.hasOneofUint32 = true; - result.oneofUint32_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; return this; } public Builder ClearOneofUint32() { PrepareBuilder(); - result.hasOneofUint32 = false; - result.oneofUint32_ = 0; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } return this; } public bool HasOneofNestedMessage { - get { return result.hasOneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage OneofNestedMessage { - get { return result.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.DefaultInstance; } set { SetOneofNestedMessage(value); } } public Builder SetOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofNestedMessage = true; - result.oneofNestedMessage_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; + result.oneofField_ = value; return this; } public Builder SetOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.Builder builderForValue) { pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); PrepareBuilder(); - result.hasOneofNestedMessage = true; - result.oneofNestedMessage_ = builderForValue.Build(); + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; + result.oneofField_ = builderForValue.Build(); return this; } public Builder MergeOneofNestedMessage(global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - if (result.hasOneofNestedMessage && - result.oneofNestedMessage_ != global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.DefaultInstance) { - result.oneofNestedMessage_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.CreateBuilder(result.oneofNestedMessage_).MergeFrom(value).BuildPartial(); + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage && + result.OneofNestedMessage != global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.DefaultInstance) { + result.oneofField_ = global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.CreateBuilder(result.OneofNestedMessage).MergeFrom(value).BuildPartial(); } else { - result.oneofNestedMessage_ = value; + result.oneofField_ = value; } - result.hasOneofNestedMessage = true; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofNestedMessage; return this; } public Builder ClearOneofNestedMessage() { - PrepareBuilder(); - result.hasOneofNestedMessage = false; - result.oneofNestedMessage_ = null; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { + PrepareBuilder(); + result.oneofFieldCase_ = OneofFieldOneofCase.None; + result.oneofField_ = null; + } return this; } public bool HasOneofString { - get { return result.hasOneofString; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofString; } } public string OneofString { - get { return result.OneofString; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofString ? (string) result.oneofField_ : ""; } set { SetOneofString(value); } } public Builder SetOneofString(string value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofString = true; - result.oneofString_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofString; return this; } public Builder ClearOneofString() { PrepareBuilder(); - result.hasOneofString = false; - result.oneofString_ = ""; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofString) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } return this; } public bool HasOneofBytes { - get { return result.hasOneofBytes; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes; } } public pb::ByteString OneofBytes { - get { return result.OneofBytes; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes ? (pb::ByteString) result.oneofField_ : pb::ByteString.Empty; } set { SetOneofBytes(value); } } public Builder SetOneofBytes(pb::ByteString value) { pb::ThrowHelper.ThrowIfNull(value, "value"); PrepareBuilder(); - result.hasOneofBytes = true; - result.oneofBytes_ = value; + result.oneofField_ = value; + result.oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; return this; } public Builder ClearOneofBytes() { PrepareBuilder(); - result.hasOneofBytes = false; - result.oneofBytes_ = pb::ByteString.Empty; + if (result.oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { + result.oneofFieldCase_ = OneofFieldOneofCase.None; + } + return this; + } + + public OneofFieldOneofCase OneofFieldCase { + get { return result.oneofFieldCase_; } + } + public Builder ClearOneofField() { + PrepareBuilder(); + result.oneofField_ = null; + result.oneofFieldCase_ = OneofFieldOneofCase.None; return this; } } diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 34d1c5c6..a2d8a98b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -49,6 +49,11 @@ namespace csharp { EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + if (SupportFieldPresence(descriptor_->file())) { + has_property_check = "has" + property_name(); + } else { + has_property_check = property_name() + " != " + default_value(); + } } EnumFieldGenerator::~EnumFieldGenerator() { @@ -122,8 +127,7 @@ void EnumFieldGenerator::GenerateBuildingCode(Writer* writer) { void EnumFieldGenerator::GenerateParsingCode(Writer* writer) { writer->WriteLine("object unknown;"); - writer->WriteLine("if(input.ReadEnum(ref result.$0$_, out unknown)) {", - name()); + writer->WriteLine("if(input.ReadEnum(ref result.$0$_, out unknown)) {", name()); if (SupportFieldPresence(descriptor_->file())) { writer->WriteLine(" result.has$0$ = true;", property_name()); } @@ -141,11 +145,7 @@ void EnumFieldGenerator::GenerateParsingCode(Writer* writer) { } void EnumFieldGenerator::GenerateSerializationCode(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (has$0$) {", property_name()); - } else { - writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); - } + writer->WriteLine("if ($0$) {", has_property_check); writer->WriteLine( " output.WriteEnum($0$, field_names[$2$], (int) $1$, $1$);", number(), property_name(), field_ordinal()); @@ -153,11 +153,7 @@ void EnumFieldGenerator::GenerateSerializationCode(Writer* writer) { } void EnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (has$0$) {", property_name()); - } else { - writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); - } + writer->WriteLine("if ($0$) {", has_property_check); writer->WriteLine( " size += pb::CodedOutputStream.ComputeEnumSize($0$, (int) $1$);", number(), property_name()); @@ -165,11 +161,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { } void EnumFieldGenerator::WriteHash(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (has$0$) {", property_name()); - } else { - writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); - } + writer->WriteLine("if ($0$) {", has_property_check); writer->WriteLine(" hash ^= $0$_.GetHashCode();", name()); writer->WriteLine("}"); } @@ -184,13 +176,94 @@ void EnumFieldGenerator::WriteEquals(Writer* writer) { } } void EnumFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", + descriptor_->name(), has_property_check, name()); +} + +EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : EnumFieldGenerator(descriptor, fieldOrdinal) { + has_property_check = oneof_name() + "Case_ == " + oneof_property_name() + + "OneofCase." + property_name(); +} + +EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { +} + +void EnumOneofFieldGenerator::GenerateMembers(Writer* writer) { + AddDeprecatedFlag(writer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("PrintField(\"$0$\", has$1$, $2$_, writer);", - descriptor_->name(), property_name(), name()); - } else { - writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", - descriptor_->name(), name()); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return $0$; }", has_property_check); + writer->WriteLine("}"); + } + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return $0$ ? ($1$) $2$_ : $3$; }", + has_property_check, type_name(), oneof_name(), default_value()); + writer->WriteLine("}"); +} + +void EnumOneofFieldGenerator::GenerateBuilderMembers(Writer* writer) { + AddDeprecatedFlag(writer); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return result.$0$; }", has_property_check); + writer->WriteLine("}"); } + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return result.$0$ ? ($1$) result.$2$_ : $3$; }", + has_property_check, type_name(), oneof_name(), default_value()); + writer->WriteLine(" set { Set$0$(value); }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), + type_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_ = value;", oneof_name()); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", + oneof_name(), oneof_property_name(), property_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" if (result.$0$) {", has_property_check); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", + oneof_name(), oneof_property_name()); + writer->WriteLine(" }"); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void EnumOneofFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine("if (!$0$.Equals(other.$0$)) return false;", property_name()); +} +void EnumOneofFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", + descriptor_->name(), has_property_check, oneof_name()); +} + +void EnumOneofFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine("object unknown;"); + writer->WriteLine("$0$ enumValue = $1$;", type_name(), default_value()); + writer->WriteLine("if(input.ReadEnum(ref enumValue, out unknown)) {", + name()); + writer->WriteLine(" result.$0$_ = enumValue;", oneof_name()); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", + oneof_name(), oneof_property_name(), property_name()); + writer->WriteLine("} else if(unknown is int) {"); + if (!use_lite_runtime()) { + writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now + writer->WriteLine( + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); + writer->WriteLine(" }"); + writer->WriteLine( + " unknownFields.MergeVarintField($0$, (ulong)(int)unknown);", + number()); + } + writer->WriteLine("}"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h index b21fa9dc..565287b2 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -60,10 +60,28 @@ class EnumFieldGenerator : public FieldGeneratorBase { virtual void WriteEquals(Writer* writer); virtual void WriteToString(Writer* writer); + protected: + string has_property_check; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; +class EnumOneofFieldGenerator : public EnumFieldGenerator { + public: + EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~EnumOneofFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); +}; + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 145b6743..dfc803e6 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -81,6 +81,14 @@ void FieldGeneratorBase::AddPublicMemberAttributes(Writer* writer) { AddDeprecatedFlag(writer); } +std::string FieldGeneratorBase::oneof_property_name() { + return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), true); +} + +std::string FieldGeneratorBase::oneof_name() { + return UnderscoresToCamelCase(descriptor_->containing_oneof()->name(), false); +} + std::string FieldGeneratorBase::property_name() { return GetPropertyName(descriptor_); } diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index 311f7a6e..312da12b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -71,6 +71,8 @@ class FieldGeneratorBase : public SourceGeneratorBase { void AddPublicMemberAttributes(Writer* writer); + std::string oneof_property_name(); + std::string oneof_name(); std::string property_name(); std::string name(); std::string type_name(); diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc index 4580b7be..76e2c850 100644 --- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc +++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc @@ -346,19 +346,31 @@ FieldGeneratorBase* CreateFieldGenerator(const FieldDescriptor* descriptor, if (descriptor->is_repeated()) { return new RepeatedMessageFieldGenerator(descriptor, fieldOrdinal); } else { - return new MessageFieldGenerator(descriptor, fieldOrdinal); + if (descriptor->containing_oneof()) { + return new MessageOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new MessageFieldGenerator(descriptor, fieldOrdinal); + } } case FieldDescriptor::TYPE_ENUM: if (descriptor->is_repeated()) { return new RepeatedEnumFieldGenerator(descriptor, fieldOrdinal); } else { - return new EnumFieldGenerator(descriptor, fieldOrdinal); + if (descriptor->containing_oneof()) { + return new EnumOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new EnumFieldGenerator(descriptor, fieldOrdinal); + } } default: if (descriptor->is_repeated()) { return new RepeatedPrimitiveFieldGenerator(descriptor, fieldOrdinal); } else { - return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); + if (descriptor->containing_oneof()) { + return new PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal); + } else { + return new PrimitiveFieldGenerator(descriptor, fieldOrdinal); + } } } } diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 96f7c17c..22681235 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -156,6 +156,10 @@ void MessageGenerator::GenerateStaticVariableInitializers(Writer* writer) { for (int i = 0; i < descriptor_->field_count(); i++) { writer->Write("\"$0$\", ", GetPropertyName(descriptor_->field(i))); } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + writer->Write("\"$0$\", ", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + } writer->WriteLine("});"); } @@ -260,6 +264,31 @@ void MessageGenerator::Generate(Writer* writer) { writer->WriteLine(); } + // oneof + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + writer->WriteLine("private object $0$_;", name); + writer->WriteLine("public enum $0$OneofCase {", property_name); + writer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + writer->WriteLine("$0$ = $1$,", + GetPropertyName(field), + SimpleItoa(field->number())); + } + writer->WriteLine("None = 0,"); + writer->Outdent(); + writer->WriteLine("}"); + writer->WriteLine("private $0$OneofCase $1$Case_ = $0$OneofCase.None;", + property_name, name); + writer->WriteLine("public $0$OneofCase $0$Case {", property_name); + writer->WriteLine(" get { return $0$Case_; }", name); + writer->WriteLine("}"); + writer->WriteLine(); + } + + // Fields for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); @@ -310,9 +339,19 @@ void MessageGenerator::GenerateLiteRuntimeMethods(Writer* writer) { writer->Indent(); writer->WriteLine("int hash = GetType().GetHashCode();"); for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->WriteHash(writer); + const FieldDescriptor* field = descriptor_->field(i); + if (field->containing_oneof() == NULL) { + scoped_ptr generator( + CreateFieldGeneratorInternal(field)); + generator->WriteHash(writer); + } + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + writer->WriteLine("if ($0$Case_ != $1$OneofCase.None) {", name, property_name); + writer->WriteLine(" hash ^= $0$_.GetHashCode();", name); + writer->WriteLine("}"); } if (callbase) { writer->WriteLine("hash ^= base.GetHashCode();"); @@ -577,6 +616,23 @@ void MessageGenerator::GenerateBuilder(Writer* writer) { // No field comment :( generator->GenerateBuilderMembers(writer); } + + // oneof + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + writer->WriteLine(); + string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + writer->WriteLine("public $0$OneofCase $0$Case {", property_name); + writer->WriteLine(" get { return result.$0$Case_; }", name); + writer->WriteLine("}"); + writer->WriteLine("public Builder Clear$0$() {", property_name); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_ = null;", name); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", name, property_name); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + } + writer->Outdent(); writer->WriteLine("}"); } @@ -675,10 +731,37 @@ void MessageGenerator::GenerateCommonBuilderMethods(Writer* writer) { full_class_name()); writer->WriteLine("PrepareBuilder();"); for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateMergingCode(writer); + if (!descriptor_->field(i)->containing_oneof()) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateMergingCode(writer); + } + } + + // Merge oneof fields + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + writer->WriteLine("switch (other.$0$Case) {", property_name); + writer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + writer->WriteLine("case $0$OneofCase.$1$: {", + property_name, GetPropertyName(field)); + if (field->type() == FieldDescriptor::TYPE_GROUP || + field->type() == FieldDescriptor::TYPE_MESSAGE) { + writer->WriteLine(" Merge$0$(other.$0$);", GetPropertyName(field)); + } else { + writer->WriteLine(" Set$0$(other.$0$);", GetPropertyName(field)); + } + writer->WriteLine(" break;"); + writer->WriteLine("}"); + } + writer->WriteLine("case $0$OneofCase.None: { break; }", property_name); + writer->Outdent(); + writer->WriteLine("}"); } + // if message type has extensions if (descriptor_->extension_range_count() > 0) { writer->WriteLine(" this.MergeExtensionFields(other);"); diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 10464c4b..b533d735 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -50,6 +50,7 @@ namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + has_property_check = "has" + property_name(); } MessageFieldGenerator::~MessageFieldGenerator() { @@ -149,7 +150,7 @@ void MessageFieldGenerator::GenerateParsingCode(Writer* writer) { } void MessageFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if (has$0$) {", property_name()); + writer->WriteLine("if ($0$) {", has_property_check); writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", message_or_group(), number(), property_name(), field_ordinal()); @@ -157,7 +158,7 @@ void MessageFieldGenerator::GenerateSerializationCode(Writer* writer) { } void MessageFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if (has$0$) {", property_name()); + writer->WriteLine("if ($0$) {", has_property_check); writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", message_or_group(), number(), property_name()); writer->WriteLine("}"); @@ -177,6 +178,119 @@ void MessageFieldGenerator::WriteToString(Writer* writer) { property_name(), name(), GetFieldName(descriptor_)); } +MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + int fieldOrdinal) + : MessageFieldGenerator(descriptor, fieldOrdinal) { + has_property_check = oneof_name() + "Case_ == " + oneof_property_name() + + "OneofCase." + property_name(); +} + +MessageOneofFieldGenerator::~MessageOneofFieldGenerator() { + +} + +void MessageOneofFieldGenerator::GenerateMembers(Writer* writer) { + if (SupportFieldPresence(descriptor_->file())) { + AddDeprecatedFlag(writer); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return $0$; }", has_property_check); + writer->WriteLine("}"); + } + AddDeprecatedFlag(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return $0$ ? ($1$) $2$_ : $3$; }", + has_property_check, type_name(), oneof_name(), default_value()); + writer->WriteLine("}"); +} + +void MessageOneofFieldGenerator::GenerateBuilderMembers(Writer* writer) { + if (SupportFieldPresence(descriptor_->file())) { + AddDeprecatedFlag(writer); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return result.$0$; }", has_property_check); + writer->WriteLine("}"); + } + AddDeprecatedFlag(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return result.$0$ ? ($1$) result.$2$_ : $3$; }", + has_property_check, type_name(), oneof_name(), default_value()); + writer->WriteLine(" set { Set$0$(value); }", property_name()); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), + type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", + oneof_name(), oneof_property_name(), property_name()); + writer->WriteLine(" result.$0$_ = value;", oneof_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Set$0$($1$.Builder builderForValue) {", + property_name(), type_name()); + AddNullCheck(writer, "builderForValue"); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", + oneof_name(), oneof_property_name(), property_name()); + writer->WriteLine(" result.$0$_ = builderForValue.Build();", oneof_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Merge$0$($1$ value) {", property_name(), + type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" if (result.$0$ &&", has_property_check); + writer->WriteLine(" result.$0$ != $1$) {", property_name(), default_value()); + writer->WriteLine( + " result.$0$_ = $1$.CreateBuilder(result.$2$).MergeFrom(value).BuildPartial();", + oneof_name(), type_name(), property_name()); + writer->WriteLine(" } else {"); + writer->WriteLine(" result.$0$_ = value;", oneof_name()); + writer->WriteLine(" }"); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", + oneof_name(), oneof_property_name(), property_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" if (result.$0$) {", has_property_check); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", + oneof_name(), oneof_property_name()); + writer->WriteLine(" result.$0$_ = null;", oneof_name()); + writer->WriteLine(" }"); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void MessageOneofFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine("$0$.Builder subBuilder = $0$.CreateBuilder();", + type_name()); + writer->WriteLine("if (result.$0$) {", has_property_check); + writer->WriteLine(" subBuilder.MergeFrom($0$);", property_name()); + writer->WriteLine("}"); + + if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { + writer->WriteLine("input.ReadGroup($0$, subBuilder, extensionRegistry);", + number()); + } else { + writer->WriteLine("input.ReadMessage(subBuilder, extensionRegistry);"); + } + writer->WriteLine("result.$0$_ = subBuilder.BuildPartial();", oneof_name()); + writer->WriteLine("result.$0$Case_ = $1$OneofCase.$2$;", + oneof_name(), oneof_property_name(), property_name()); +} + +void MessageOneofFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine("if (!$0$.Equals(other.$0$)) return false;", property_name()); +} +void MessageOneofFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", + descriptor_->name(), has_property_check, oneof_name()); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index 48bf8be5..d455ade5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -60,10 +60,28 @@ class MessageFieldGenerator : public FieldGeneratorBase { virtual void WriteEquals(Writer* writer); virtual void WriteToString(Writer* writer); + protected: + string has_property_check; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; +class MessageOneofFieldGenerator : public MessageFieldGenerator { + public: + MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~MessageOneofFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); +}; + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index a193afda..a54edfe3 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -50,6 +50,11 @@ namespace csharp { PrimitiveFieldGenerator::PrimitiveFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + if (SupportFieldPresence(descriptor_->file())) { + has_property_check = "has" + property_name(); + } else { + has_property_check = property_name() + " != " + default_value(); + } } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { @@ -133,11 +138,7 @@ void PrimitiveFieldGenerator::GenerateParsingCode(Writer* writer) { } void PrimitiveFieldGenerator::GenerateSerializationCode(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (has$0$) {", property_name()); - } else { - writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); - } + writer->WriteLine("if ($0$) {", has_property_check); writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", capitalized_type_name(), number(), property_name(), field_ordinal()); @@ -145,22 +146,14 @@ void PrimitiveFieldGenerator::GenerateSerializationCode(Writer* writer) { } void PrimitiveFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (has$0$) {", property_name()); - } else { - writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); - } + writer->WriteLine("if ($0$) {", has_property_check); writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", capitalized_type_name(), number(), property_name()); writer->WriteLine("}"); } void PrimitiveFieldGenerator::WriteHash(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (has$0$) {", property_name()); - } else { - writer->WriteLine("if ($0$ != $1$) {", property_name(), default_value()); - } + writer->WriteLine("if ($0$) {", has_property_check); writer->WriteLine(" hash ^= $0$_.GetHashCode();", name()); writer->WriteLine("}"); } @@ -175,13 +168,84 @@ void PrimitiveFieldGenerator::WriteEquals(Writer* writer) { } } void PrimitiveFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", + descriptor_->name(), has_property_check, name()); +} + +PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, int fieldOrdinal) + : PrimitiveFieldGenerator(descriptor, fieldOrdinal) { + has_property_check = oneof_name() + "Case_ == " + oneof_property_name() + + "OneofCase." + property_name(); +} + +PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() { +} + +void PrimitiveOneofFieldGenerator::GenerateMembers(Writer* writer) { + AddDeprecatedFlag(writer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("PrintField(\"$0$\", has$1$, $2$_, writer);", - descriptor_->name(), property_name(), name()); - } else { - writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", - descriptor_->name(), name()); + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return $0$; }", has_property_check); + writer->WriteLine("}"); } + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return $0$ ? ($1$) $2$_ : $3$; }", + has_property_check, type_name(), oneof_name(), default_value()); + writer->WriteLine("}"); +} + +void PrimitiveOneofFieldGenerator::GenerateBuilderMembers(Writer* writer) { + AddDeprecatedFlag(writer); + if (SupportFieldPresence(descriptor_->file())) { + writer->WriteLine("public bool Has$0$ {", property_name()); + writer->WriteLine(" get { return result.$0$; }", has_property_check); + writer->WriteLine("}"); + } + AddPublicMemberAttributes(writer); + writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); + writer->WriteLine(" get { return result.$0$ ? ($1$) result.$2$_ : $3$; }", + has_property_check, type_name(), oneof_name(), default_value()); + writer->WriteLine(" set { Set$0$(value); }", property_name()); + writer->WriteLine("}"); + AddPublicMemberAttributes(writer); + writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), + type_name()); + AddNullCheck(writer); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" result.$0$_ = value;", oneof_name()); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", + oneof_name(), oneof_property_name(), property_name()); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); + AddDeprecatedFlag(writer); + writer->WriteLine("public Builder Clear$0$() {", property_name()); + writer->WriteLine(" PrepareBuilder();"); + writer->WriteLine(" if (result.$0$) {", has_property_check); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", + oneof_name(), oneof_property_name()); + writer->WriteLine(" }"); + writer->WriteLine(" return this;"); + writer->WriteLine("}"); +} + +void PrimitiveOneofFieldGenerator::WriteEquals(Writer* writer) { + writer->WriteLine("if (!$0$.Equals(other.$0$)) return false;", property_name()); +} +void PrimitiveOneofFieldGenerator::WriteToString(Writer* writer) { + writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", + descriptor_->name(), has_property_check, oneof_name()); +} + +void PrimitiveOneofFieldGenerator::GenerateParsingCode(Writer* writer) { + writer->WriteLine("$0$ value = $1$;", type_name(), default_value()); + writer->WriteLine("if (input.Read$0$(ref value)) {", + capitalized_type_name()); + writer->WriteLine(" result.$0$_ = value;", oneof_name()); + writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", + oneof_name(), oneof_property_name(), property_name()); + writer->WriteLine("}"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index fb27ab43..ecc6ed91 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -60,10 +60,28 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { virtual void WriteEquals(Writer* writer); virtual void WriteToString(Writer* writer); + protected: + string has_property_check; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; +class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { + public: + PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); + ~PrimitiveOneofFieldGenerator(); + + virtual void GenerateMembers(Writer* writer); + virtual void GenerateBuilderMembers(Writer* writer); + virtual void WriteEquals(Writer* writer); + virtual void WriteToString(Writer* writer); + virtual void GenerateParsingCode(Writer* writer); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); +}; + } // namespace csharp } // namespace compiler } // namespace protobuf -- cgit v1.2.3 From a21a2cf7d39648fa8fe7e98789d0590e336a471f Mon Sep 17 00:00:00 2001 From: Jie Luo Date: Fri, 29 May 2015 17:57:05 -0700 Subject: Change the C# enum generator inherit from primitive generator --- csharp/src/AddressBook/Addressbook.cs | 2 +- .../ProtocolBuffers.Test/TestProtos/Unittest.cs | 24 +- .../TestProtos/UnittestIssues.cs | 4 +- .../TestProtos/UnknownEnumTest.cs | 4 +- .../DescriptorProtos/DescriptorProtoFile.cs | 712 ++++++++++++++++++--- .../TestProtos/Unittest.cs | 24 +- .../TestProtos/UnittestExtrasFull.cs | 2 +- .../TestProtos/UnittestExtrasLite.cs | 4 +- .../TestProtos/UnittestLite.cs | 12 +- .../protobuf/compiler/csharp/csharp_enum_field.cc | 168 +---- .../protobuf/compiler/csharp/csharp_enum_field.h | 23 +- 11 files changed, 677 insertions(+), 302 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.cs index bc6199b1..58ad28ad 100644 --- a/csharp/src/AddressBook/Addressbook.cs +++ b/csharp/src/AddressBook/Addressbook.cs @@ -407,7 +407,7 @@ namespace Google.ProtocolBuffers.Examples.AddressBook { } public bool HasType { - get { return result.hasType; } + get { return result.hasType; } } public global::Google.ProtocolBuffers.Examples.AddressBook.Person.Types.PhoneType Type { get { return result.Type; } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs index 67898644..4dda7bcd 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs @@ -4997,7 +4997,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalNestedEnum { - get { return result.hasOptionalNestedEnum; } + get { return result.hasOptionalNestedEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedEnum OptionalNestedEnum { get { return result.OptionalNestedEnum; } @@ -5017,7 +5017,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalForeignEnum { - get { return result.hasOptionalForeignEnum; } + get { return result.hasOptionalForeignEnum; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnum OptionalForeignEnum { get { return result.OptionalForeignEnum; } @@ -5037,7 +5037,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalImportEnum { - get { return result.hasOptionalImportEnum; } + get { return result.hasOptionalImportEnum; } } public global::Google.ProtocolBuffers.TestProtos.ImportEnum OptionalImportEnum { get { return result.OptionalImportEnum; } @@ -6309,7 +6309,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultNestedEnum { - get { return result.hasDefaultNestedEnum; } + get { return result.hasDefaultNestedEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedEnum DefaultNestedEnum { get { return result.DefaultNestedEnum; } @@ -6329,7 +6329,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultForeignEnum { - get { return result.hasDefaultForeignEnum; } + get { return result.hasDefaultForeignEnum; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnum DefaultForeignEnum { get { return result.DefaultForeignEnum; } @@ -6349,7 +6349,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultImportEnum { - get { return result.hasDefaultImportEnum; } + get { return result.hasDefaultImportEnum; } } public global::Google.ProtocolBuffers.TestProtos.ImportEnum DefaultImportEnum { get { return result.DefaultImportEnum; } @@ -16021,7 +16021,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasEnumField { - get { return result.hasEnumField; } + get { return result.hasEnumField; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnum EnumField { get { return result.EnumField; } @@ -18747,7 +18747,7 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasSparseEnum { - get { return result.hasSparseEnum; } + get { return result.hasSparseEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestSparseEnum SparseEnum { get { return result.SparseEnum; } @@ -24384,7 +24384,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooEnum { - get { return result.fooCase_ == FooOneofCase.FooEnum; } + get { return result.fooCase_ == FooOneofCase.FooEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum FooEnum { get { return result.fooCase_ == FooOneofCase.FooEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; } @@ -24640,7 +24640,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasBarEnum { - get { return result.barCase_ == BarOneofCase.BarEnum; } + get { return result.barCase_ == BarOneofCase.BarEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum BarEnum { get { return result.barCase_ == BarOneofCase.BarEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) result.bar_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; } @@ -28899,7 +28899,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasEnumExtension { - get { return result.hasEnumExtension; } + get { return result.hasEnumExtension; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnum EnumExtension { get { return result.EnumExtension; } @@ -28919,7 +28919,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDynamicEnumExtension { - get { return result.hasDynamicEnumExtension; } + get { return result.hasDynamicEnumExtension; } } public global::Google.ProtocolBuffers.TestProtos.TestDynamicExtensions.Types.DynamicEnumType DynamicEnumExtension { get { return result.DynamicEnumExtension; } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs index 602f21b2..4ce086c6 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs @@ -1062,7 +1062,7 @@ namespace UnitTest.Issues.TestProtos { public bool HasValue { - get { return result.hasValue; } + get { return result.hasValue; } } public global::UnitTest.Issues.TestProtos.NegativeEnum Value { get { return result.Value; } @@ -1965,7 +1965,7 @@ namespace UnitTest.Issues.TestProtos { [global::System.ObsoleteAttribute()] public bool HasEnumValue { - get { return result.hasEnumValue; } + get { return result.hasEnumValue; } } [global::System.ObsoleteAttribute()] public global::UnitTest.Issues.TestProtos.DeprecatedEnum EnumValue { diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnknownEnumTest.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnknownEnumTest.cs index f703479d..0b7ead79 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnknownEnumTest.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnknownEnumTest.cs @@ -378,7 +378,7 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasValue { - get { return result.hasValue; } + get { return result.hasValue; } } public global::Google.ProtocolBuffers.TestProtos.DownRevision.Types.Enum Value { get { return result.Value; } @@ -748,7 +748,7 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasValue { - get { return result.hasValue; } + get { return result.hasValue; } } public global::Google.ProtocolBuffers.TestProtos.UpRevision.Types.Enum Value { get { return result.Value; } diff --git a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs index ef3bcdc3..9361711b 100644 --- a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs +++ b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs @@ -25,6 +25,8 @@ namespace Google.ProtocolBuffers.DescriptorProtos { internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_DescriptorProto__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor; internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable; + internal static pbd::MessageDescriptor internal__static_google_protobuf_DescriptorProto_ReservedRange__Descriptor; + internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_google_protobuf_FieldDescriptorProto__Descriptor; internal static pb::FieldAccess.FieldAccessorTable internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable; internal static pbd::MessageDescriptor internal__static_google_protobuf_OneofDescriptorProto__Descriptor; @@ -82,7 +84,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { "KAsyJS5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8SLQoH", "b3B0aW9ucxgIIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0aW9ucxI5", "ChBzb3VyY2VfY29kZV9pbmZvGAkgASgLMh8uZ29vZ2xlLnByb3RvYnVmLlNv", - "dXJjZUNvZGVJbmZvEg4KBnN5bnRheBgMIAEoCSLkAwoPRGVzY3JpcHRvclBy", + "dXJjZUNvZGVJbmZvEg4KBnN5bnRheBgMIAEoCSLwBAoPRGVzY3JpcHRvclBy", "b3RvEgwKBG5hbWUYASABKAkSNAoFZmllbGQYAiADKAsyJS5nb29nbGUucHJv", "dG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8SOAoJZXh0ZW5zaW9uGAYgAygL", "MiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEjUKC25l", @@ -92,88 +94,94 @@ namespace Google.ProtocolBuffers.DescriptorProtos { "b29nbGUucHJvdG9idWYuRGVzY3JpcHRvclByb3RvLkV4dGVuc2lvblJhbmdl", "EjkKCm9uZW9mX2RlY2wYCCADKAsyJS5nb29nbGUucHJvdG9idWYuT25lb2ZE", "ZXNjcmlwdG9yUHJvdG8SMAoHb3B0aW9ucxgHIAEoCzIfLmdvb2dsZS5wcm90", - "b2J1Zi5NZXNzYWdlT3B0aW9ucxosCg5FeHRlbnNpb25SYW5nZRINCgVzdGFy", - "dBgBIAEoBRILCgNlbmQYAiABKAUiqQUKFEZpZWxkRGVzY3JpcHRvclByb3Rv", - "EgwKBG5hbWUYASABKAkSDgoGbnVtYmVyGAMgASgFEjoKBWxhYmVsGAQgASgO", - "MisuZ29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvLkxhYmVs", - "EjgKBHR5cGUYBSABKA4yKi5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlw", - "dG9yUHJvdG8uVHlwZRIRCgl0eXBlX25hbWUYBiABKAkSEAoIZXh0ZW5kZWUY", - "AiABKAkSFQoNZGVmYXVsdF92YWx1ZRgHIAEoCRITCgtvbmVvZl9pbmRleBgJ", - "IAEoBRIuCgdvcHRpb25zGAggASgLMh0uZ29vZ2xlLnByb3RvYnVmLkZpZWxk", - "T3B0aW9ucyK2AgoEVHlwZRIPCgtUWVBFX0RPVUJMRRABEg4KClRZUEVfRkxP", - "QVQQAhIOCgpUWVBFX0lOVDY0EAMSDwoLVFlQRV9VSU5UNjQQBBIOCgpUWVBF", - "X0lOVDMyEAUSEAoMVFlQRV9GSVhFRDY0EAYSEAoMVFlQRV9GSVhFRDMyEAcS", - "DQoJVFlQRV9CT09MEAgSDwoLVFlQRV9TVFJJTkcQCRIOCgpUWVBFX0dST1VQ", - "EAoSEAoMVFlQRV9NRVNTQUdFEAsSDgoKVFlQRV9CWVRFUxAMEg8KC1RZUEVf", - "VUlOVDMyEA0SDQoJVFlQRV9FTlVNEA4SEQoNVFlQRV9TRklYRUQzMhAPEhEK", - "DVRZUEVfU0ZJWEVENjQQEBIPCgtUWVBFX1NJTlQzMhAREg8KC1RZUEVfU0lO", - "VDY0EBIiQwoFTGFiZWwSEgoOTEFCRUxfT1BUSU9OQUwQARISCg5MQUJFTF9S", - "RVFVSVJFRBACEhIKDkxBQkVMX1JFUEVBVEVEEAMiJAoUT25lb2ZEZXNjcmlw", - "dG9yUHJvdG8SDAoEbmFtZRgBIAEoCSKMAQoTRW51bURlc2NyaXB0b3JQcm90", - "bxIMCgRuYW1lGAEgASgJEjgKBXZhbHVlGAIgAygLMikuZ29vZ2xlLnByb3Rv", - "YnVmLkVudW1WYWx1ZURlc2NyaXB0b3JQcm90bxItCgdvcHRpb25zGAMgASgL", - "MhwuZ29vZ2xlLnByb3RvYnVmLkVudW1PcHRpb25zImwKGEVudW1WYWx1ZURl", - "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg4KBm51bWJlchgCIAEoBRIy", - "CgdvcHRpb25zGAMgASgLMiEuZ29vZ2xlLnByb3RvYnVmLkVudW1WYWx1ZU9w", - "dGlvbnMikAEKFlNlcnZpY2VEZXNjcmlwdG9yUHJvdG8SDAoEbmFtZRgBIAEo", - "CRI2CgZtZXRob2QYAiADKAsyJi5nb29nbGUucHJvdG9idWYuTWV0aG9kRGVz", - "Y3JpcHRvclByb3RvEjAKB29wdGlvbnMYAyABKAsyHy5nb29nbGUucHJvdG9i", - "dWYuU2VydmljZU9wdGlvbnMiwQEKFU1ldGhvZERlc2NyaXB0b3JQcm90bxIM", - "CgRuYW1lGAEgASgJEhIKCmlucHV0X3R5cGUYAiABKAkSEwoLb3V0cHV0X3R5", - "cGUYAyABKAkSLwoHb3B0aW9ucxgEIAEoCzIeLmdvb2dsZS5wcm90b2J1Zi5N", - "ZXRob2RPcHRpb25zEh8KEGNsaWVudF9zdHJlYW1pbmcYBSABKAg6BWZhbHNl", - "Eh8KEHNlcnZlcl9zdHJlYW1pbmcYBiABKAg6BWZhbHNlIoEFCgtGaWxlT3B0", - "aW9ucxIUCgxqYXZhX3BhY2thZ2UYASABKAkSHAoUamF2YV9vdXRlcl9jbGFz", - "c25hbWUYCCABKAkSIgoTamF2YV9tdWx0aXBsZV9maWxlcxgKIAEoCDoFZmFs", - "c2USLAodamF2YV9nZW5lcmF0ZV9lcXVhbHNfYW5kX2hhc2gYFCABKAg6BWZh", - "bHNlEiUKFmphdmFfc3RyaW5nX2NoZWNrX3V0ZjgYGyABKAg6BWZhbHNlEkYK", - "DG9wdGltaXplX2ZvchgJIAEoDjIpLmdvb2dsZS5wcm90b2J1Zi5GaWxlT3B0", - "aW9ucy5PcHRpbWl6ZU1vZGU6BVNQRUVEEhIKCmdvX3BhY2thZ2UYCyABKAkS", - "IgoTY2NfZ2VuZXJpY19zZXJ2aWNlcxgQIAEoCDoFZmFsc2USJAoVamF2YV9n", - "ZW5lcmljX3NlcnZpY2VzGBEgASgIOgVmYWxzZRIiChNweV9nZW5lcmljX3Nl", - "cnZpY2VzGBIgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGBcgASgIOgVmYWxz", - "ZRIfChBjY19lbmFibGVfYXJlbmFzGB8gASgIOgVmYWxzZRIZChFvYmpjX2Ns", - "YXNzX3ByZWZpeBgkIAEoCRIYChBjc2hhcnBfbmFtZXNwYWNlGCUgASgJEkMK", - "FHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1", - "Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9wdGltaXplTW9kZRIJCgVTUEVF", - "RBABEg0KCUNPREVfU0laRRACEhAKDExJVEVfUlVOVElNRRADKgkI6AcQgICA", - "gAIi5gEKDk1lc3NhZ2VPcHRpb25zEiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9y", - "bWF0GAEgASgIOgVmYWxzZRIuCh9ub19zdGFuZGFyZF9kZXNjcmlwdG9yX2Fj", - "Y2Vzc29yGAIgASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMgASgIOgVmYWxz", - "ZRIRCgltYXBfZW50cnkYByABKAgSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y", - "5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24q", - "CQjoBxCAgICAAiKgAgoMRmllbGRPcHRpb25zEjoKBWN0eXBlGAEgASgOMiMu", - "Z29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToGU1RSSU5HEg4K", - "BnBhY2tlZBgCIAEoCBITCgRsYXp5GAUgASgIOgVmYWxzZRIZCgpkZXByZWNh", - "dGVkGAMgASgIOgVmYWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJDChR1bmlu", - "dGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5p", - "bnRlcnByZXRlZE9wdGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABIICgRDT1JE", - "EAESEAoMU1RSSU5HX1BJRUNFEAIqCQjoBxCAgICAAiKNAQoLRW51bU9wdGlv", - "bnMSEwoLYWxsb3dfYWxpYXMYAiABKAgSGQoKZGVwcmVjYXRlZBgDIAEoCDoF", - "ZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xl", - "LnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiJ9ChBF", - "bnVtVmFsdWVPcHRpb25zEhkKCmRlcHJlY2F0ZWQYASABKAg6BWZhbHNlEkMK", - "FHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1", - "Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIiewoOU2VydmljZU9w", - "dGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USQwoUdW5pbnRlcnBy", + "b2J1Zi5NZXNzYWdlT3B0aW9ucxJGCg5yZXNlcnZlZF9yYW5nZRgJIAMoCzIu", + "Lmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9yUHJvdG8uUmVzZXJ2ZWRSYW5n", + "ZRIVCg1yZXNlcnZlZF9uYW1lGAogAygJGiwKDkV4dGVuc2lvblJhbmdlEg0K", + "BXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBRorCg1SZXNlcnZlZFJhbmdlEg0K", + "BXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBSKpBQoURmllbGREZXNjcmlwdG9y", + "UHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZudW1iZXIYAyABKAUSOgoFbGFiZWwY", + "BCABKA4yKy5nb29nbGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8u", + "TGFiZWwSOAoEdHlwZRgFIAEoDjIqLmdvb2dsZS5wcm90b2J1Zi5GaWVsZERl", + "c2NyaXB0b3JQcm90by5UeXBlEhEKCXR5cGVfbmFtZRgGIAEoCRIQCghleHRl", + "bmRlZRgCIAEoCRIVCg1kZWZhdWx0X3ZhbHVlGAcgASgJEhMKC29uZW9mX2lu", + "ZGV4GAkgASgFEi4KB29wdGlvbnMYCCABKAsyHS5nb29nbGUucHJvdG9idWYu", + "RmllbGRPcHRpb25zIrYCCgRUeXBlEg8KC1RZUEVfRE9VQkxFEAESDgoKVFlQ", + "RV9GTE9BVBACEg4KClRZUEVfSU5UNjQQAxIPCgtUWVBFX1VJTlQ2NBAEEg4K", + "ClRZUEVfSU5UMzIQBRIQCgxUWVBFX0ZJWEVENjQQBhIQCgxUWVBFX0ZJWEVE", + "MzIQBxINCglUWVBFX0JPT0wQCBIPCgtUWVBFX1NUUklORxAJEg4KClRZUEVf", + "R1JPVVAQChIQCgxUWVBFX01FU1NBR0UQCxIOCgpUWVBFX0JZVEVTEAwSDwoL", + "VFlQRV9VSU5UMzIQDRINCglUWVBFX0VOVU0QDhIRCg1UWVBFX1NGSVhFRDMy", + "EA8SEQoNVFlQRV9TRklYRUQ2NBAQEg8KC1RZUEVfU0lOVDMyEBESDwoLVFlQ", + "RV9TSU5UNjQQEiJDCgVMYWJlbBISCg5MQUJFTF9PUFRJT05BTBABEhIKDkxB", + "QkVMX1JFUVVJUkVEEAISEgoOTEFCRUxfUkVQRUFURUQQAyIkChRPbmVvZkRl", + "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJIowBChNFbnVtRGVzY3JpcHRv", + "clByb3RvEgwKBG5hbWUYASABKAkSOAoFdmFsdWUYAiADKAsyKS5nb29nbGUu", + "cHJvdG9idWYuRW51bVZhbHVlRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMY", + "AyABKAsyHC5nb29nbGUucHJvdG9idWYuRW51bU9wdGlvbnMibAoYRW51bVZh", + "bHVlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoGbnVtYmVyGAIg", + "ASgFEjIKB29wdGlvbnMYAyABKAsyIS5nb29nbGUucHJvdG9idWYuRW51bVZh", + "bHVlT3B0aW9ucyKQAQoWU2VydmljZURlc2NyaXB0b3JQcm90bxIMCgRuYW1l", + "GAEgASgJEjYKBm1ldGhvZBgCIAMoCzImLmdvb2dsZS5wcm90b2J1Zi5NZXRo", + "b2REZXNjcmlwdG9yUHJvdG8SMAoHb3B0aW9ucxgDIAEoCzIfLmdvb2dsZS5w", + "cm90b2J1Zi5TZXJ2aWNlT3B0aW9ucyLBAQoVTWV0aG9kRGVzY3JpcHRvclBy", + "b3RvEgwKBG5hbWUYASABKAkSEgoKaW5wdXRfdHlwZRgCIAEoCRITCgtvdXRw", + "dXRfdHlwZRgDIAEoCRIvCgdvcHRpb25zGAQgASgLMh4uZ29vZ2xlLnByb3Rv", + "YnVmLk1ldGhvZE9wdGlvbnMSHwoQY2xpZW50X3N0cmVhbWluZxgFIAEoCDoF", + "ZmFsc2USHwoQc2VydmVyX3N0cmVhbWluZxgGIAEoCDoFZmFsc2UigQUKC0Zp", + "bGVPcHRpb25zEhQKDGphdmFfcGFja2FnZRgBIAEoCRIcChRqYXZhX291dGVy", + "X2NsYXNzbmFtZRgIIAEoCRIiChNqYXZhX211bHRpcGxlX2ZpbGVzGAogASgI", + "OgVmYWxzZRIsCh1qYXZhX2dlbmVyYXRlX2VxdWFsc19hbmRfaGFzaBgUIAEo", + "CDoFZmFsc2USJQoWamF2YV9zdHJpbmdfY2hlY2tfdXRmOBgbIAEoCDoFZmFs", + "c2USRgoMb3B0aW1pemVfZm9yGAkgASgOMikuZ29vZ2xlLnByb3RvYnVmLkZp", + "bGVPcHRpb25zLk9wdGltaXplTW9kZToFU1BFRUQSEgoKZ29fcGFja2FnZRgL", + "IAEoCRIiChNjY19nZW5lcmljX3NlcnZpY2VzGBAgASgIOgVmYWxzZRIkChVq", + "YXZhX2dlbmVyaWNfc2VydmljZXMYESABKAg6BWZhbHNlEiIKE3B5X2dlbmVy", + "aWNfc2VydmljZXMYEiABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYFyABKAg6", + "BWZhbHNlEh8KEGNjX2VuYWJsZV9hcmVuYXMYHyABKAg6BWZhbHNlEhkKEW9i", + "amNfY2xhc3NfcHJlZml4GCQgASgJEhgKEGNzaGFycF9uYW1lc3BhY2UYJSAB", + "KAkSQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnBy", + "b3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24iOgoMT3B0aW1pemVNb2RlEgkK", + "BVNQRUVEEAESDQoJQ09ERV9TSVpFEAISEAoMTElURV9SVU5USU1FEAMqCQjo", + "BxCAgICAAiLmAQoOTWVzc2FnZU9wdGlvbnMSJgoXbWVzc2FnZV9zZXRfd2ly", + "ZV9mb3JtYXQYASABKAg6BWZhbHNlEi4KH25vX3N0YW5kYXJkX2Rlc2NyaXB0", + "b3JfYWNjZXNzb3IYAiABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6", + "BWZhbHNlEhEKCW1hcF9lbnRyeRgHIAEoCBJDChR1bmludGVycHJldGVkX29w", + "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w", + "dGlvbioJCOgHEICAgIACIpgDCgxGaWVsZE9wdGlvbnMSOgoFY3R5cGUYASAB", + "KA4yIy5nb29nbGUucHJvdG9idWYuRmllbGRPcHRpb25zLkNUeXBlOgZTVFJJ", + "TkcSDgoGcGFja2VkGAIgASgIEj8KBmpzdHlwZRgGIAEoDjIkLmdvb2dsZS5w", + "cm90b2J1Zi5GaWVsZE9wdGlvbnMuSlNUeXBlOglKU19OT1JNQUwSEwoEbGF6", + "eRgFIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USEwoE", + "d2VhaxgKIAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcg", + "AygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24iLwoF", + "Q1R5cGUSCgoGU1RSSU5HEAASCAoEQ09SRBABEhAKDFNUUklOR19QSUVDRRAC", + "IjUKBkpTVHlwZRINCglKU19OT1JNQUwQABINCglKU19TVFJJTkcQARINCglK", + "U19OVU1CRVIQAioJCOgHEICAgIACIo0BCgtFbnVtT3B0aW9ucxITCgthbGxv", + "d19hbGlhcxgCIAEoCBIZCgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRJDChR1", + "bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYu", + "VW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACIn0KEEVudW1WYWx1ZU9w", + "dGlvbnMSGQoKZGVwcmVjYXRlZBgBIAEoCDoFZmFsc2USQwoUdW5pbnRlcnBy", "ZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJw", - "cmV0ZWRPcHRpb24qCQjoBxCAgICAAiJ6Cg1NZXRob2RPcHRpb25zEhkKCmRl", - "cHJlY2F0ZWQYISABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9u", - "GOcHIAMoCzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9u", - "KgkI6AcQgICAgAIingIKE1VuaW50ZXJwcmV0ZWRPcHRpb24SOwoEbmFtZRgC", - "IAMoCzItLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uLk5h", - "bWVQYXJ0EhgKEGlkZW50aWZpZXJfdmFsdWUYAyABKAkSGgoScG9zaXRpdmVf", - "aW50X3ZhbHVlGAQgASgEEhoKEm5lZ2F0aXZlX2ludF92YWx1ZRgFIAEoAxIU", - "Cgxkb3VibGVfdmFsdWUYBiABKAESFAoMc3RyaW5nX3ZhbHVlGAcgASgMEhcK", - "D2FnZ3JlZ2F0ZV92YWx1ZRgIIAEoCRozCghOYW1lUGFydBIRCgluYW1lX3Bh", - "cnQYASACKAkSFAoMaXNfZXh0ZW5zaW9uGAIgAigIItUBCg5Tb3VyY2VDb2Rl", - "SW5mbxI6Cghsb2NhdGlvbhgBIAMoCzIoLmdvb2dsZS5wcm90b2J1Zi5Tb3Vy", - "Y2VDb2RlSW5mby5Mb2NhdGlvbhqGAQoITG9jYXRpb24SEAoEcGF0aBgBIAMo", - "BUICEAESEAoEc3BhbhgCIAMoBUICEAESGAoQbGVhZGluZ19jb21tZW50cxgD", - "IAEoCRIZChF0cmFpbGluZ19jb21tZW50cxgEIAEoCRIhChlsZWFkaW5nX2Rl", - "dGFjaGVkX2NvbW1lbnRzGAYgAygJQlkKE2NvbS5nb29nbGUucHJvdG9idWZC", - "EERlc2NyaXB0b3JQcm90b3NIAaICA0dQQqoCJ0dvb2dsZS5Qcm90b2NvbEJ1", - "ZmZlcnMuRGVzY3JpcHRvclByb3Rvcw==")); + "cmV0ZWRPcHRpb24qCQjoBxCAgICAAiJ7Cg5TZXJ2aWNlT3B0aW9ucxIZCgpk", + "ZXByZWNhdGVkGCEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlv", + "bhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlv", + "bioJCOgHEICAgIACInoKDU1ldGhvZE9wdGlvbnMSGQoKZGVwcmVjYXRlZBgh", + "IAEoCDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQu", + "Z29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICA", + "AiKeAgoTVW5pbnRlcnByZXRlZE9wdGlvbhI7CgRuYW1lGAIgAygLMi0uZ29v", + "Z2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24uTmFtZVBhcnQSGAoQ", + "aWRlbnRpZmllcl92YWx1ZRgDIAEoCRIaChJwb3NpdGl2ZV9pbnRfdmFsdWUY", + "BCABKAQSGgoSbmVnYXRpdmVfaW50X3ZhbHVlGAUgASgDEhQKDGRvdWJsZV92", + "YWx1ZRgGIAEoARIUCgxzdHJpbmdfdmFsdWUYByABKAwSFwoPYWdncmVnYXRl", + "X3ZhbHVlGAggASgJGjMKCE5hbWVQYXJ0EhEKCW5hbWVfcGFydBgBIAIoCRIU", + "Cgxpc19leHRlbnNpb24YAiACKAgi1QEKDlNvdXJjZUNvZGVJbmZvEjoKCGxv", + "Y2F0aW9uGAEgAygLMiguZ29vZ2xlLnByb3RvYnVmLlNvdXJjZUNvZGVJbmZv", + "LkxvY2F0aW9uGoYBCghMb2NhdGlvbhIQCgRwYXRoGAEgAygFQgIQARIQCgRz", + "cGFuGAIgAygFQgIQARIYChBsZWFkaW5nX2NvbW1lbnRzGAMgASgJEhkKEXRy", + "YWlsaW5nX2NvbW1lbnRzGAQgASgJEiEKGWxlYWRpbmdfZGV0YWNoZWRfY29t", + "bWVudHMYBiADKAlCWQoTY29tLmdvb2dsZS5wcm90b2J1ZkIQRGVzY3JpcHRv", + "clByb3Rvc0gBogIDR1BCqgInR29vZ2xlLlByb3RvY29sQnVmZmVycy5EZXNj", + "cmlwdG9yUHJvdG9z")); pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) { descriptor = root; internal__static_google_protobuf_FileDescriptorSet__Descriptor = Descriptor.MessageTypes[0]; @@ -187,11 +195,15 @@ namespace Google.ProtocolBuffers.DescriptorProtos { internal__static_google_protobuf_DescriptorProto__Descriptor = Descriptor.MessageTypes[2]; internal__static_google_protobuf_DescriptorProto__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_google_protobuf_DescriptorProto__Descriptor, - new string[] { "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", }); + new string[] { "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName", }); internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor = internal__static_google_protobuf_DescriptorProto__Descriptor.NestedTypes[0]; internal__static_google_protobuf_DescriptorProto_ExtensionRange__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_google_protobuf_DescriptorProto_ExtensionRange__Descriptor, new string[] { "Start", "End", }); + internal__static_google_protobuf_DescriptorProto_ReservedRange__Descriptor = internal__static_google_protobuf_DescriptorProto__Descriptor.NestedTypes[1]; + internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable = + new pb::FieldAccess.FieldAccessorTable(internal__static_google_protobuf_DescriptorProto_ReservedRange__Descriptor, + new string[] { "Start", "End", }); internal__static_google_protobuf_FieldDescriptorProto__Descriptor = Descriptor.MessageTypes[3]; internal__static_google_protobuf_FieldDescriptorProto__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_google_protobuf_FieldDescriptorProto__Descriptor, @@ -227,7 +239,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { internal__static_google_protobuf_FieldOptions__Descriptor = Descriptor.MessageTypes[11]; internal__static_google_protobuf_FieldOptions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_google_protobuf_FieldOptions__Descriptor, - new string[] { "Ctype", "Packed", "Lazy", "Deprecated", "Weak", "UninterpretedOption", }); + new string[] { "Ctype", "Packed", "Jstype", "Lazy", "Deprecated", "Weak", "UninterpretedOption", }); internal__static_google_protobuf_EnumOptions__Descriptor = Descriptor.MessageTypes[12]; internal__static_google_protobuf_EnumOptions__FieldAccessorTable = new pb::FieldAccess.FieldAccessorTable(internal__static_google_protobuf_EnumOptions__Descriptor, @@ -1563,8 +1575,8 @@ namespace Google.ProtocolBuffers.DescriptorProtos { public sealed partial class DescriptorProto : pb::GeneratedMessage { private DescriptorProto() { } private static readonly DescriptorProto defaultInstance = new DescriptorProto().MakeReadOnly(); - private static readonly string[] _descriptorProtoFieldNames = new string[] { "enum_type", "extension", "extension_range", "field", "name", "nested_type", "oneof_decl", "options" }; - private static readonly uint[] _descriptorProtoFieldTags = new uint[] { 34, 50, 42, 18, 10, 26, 66, 58 }; + private static readonly string[] _descriptorProtoFieldNames = new string[] { "enum_type", "extension", "extension_range", "field", "name", "nested_type", "oneof_decl", "options", "reserved_name", "reserved_range" }; + private static readonly uint[] _descriptorProtoFieldTags = new uint[] { 34, 50, 42, 18, 10, 26, 66, 58, 82, 74 }; public static DescriptorProto DefaultInstance { get { return defaultInstance; } } @@ -1906,6 +1918,324 @@ namespace Google.ProtocolBuffers.DescriptorProtos { } } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class ReservedRange : pb::GeneratedMessage { + private ReservedRange() { } + private static readonly ReservedRange defaultInstance = new ReservedRange().MakeReadOnly(); + private static readonly string[] _reservedRangeFieldNames = new string[] { "end", "start" }; + private static readonly uint[] _reservedRangeFieldTags = new uint[] { 16, 8 }; + public static ReservedRange DefaultInstance { + get { return defaultInstance; } + } + + public override ReservedRange DefaultInstanceForType { + get { return DefaultInstance; } + } + + protected override ReservedRange ThisMessage { + get { return this; } + } + + public static pbd::MessageDescriptor Descriptor { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ReservedRange__Descriptor; } + } + + protected override pb::FieldAccess.FieldAccessorTable InternalFieldAccessors { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.internal__static_google_protobuf_DescriptorProto_ReservedRange__FieldAccessorTable; } + } + + public const int StartFieldNumber = 1; + private bool hasStart; + private int start_; + public bool HasStart { + get { return hasStart; } + } + public int Start { + get { return start_; } + } + + public const int EndFieldNumber = 2; + private bool hasEnd; + private int end_; + public bool HasEnd { + get { return hasEnd; } + } + public int End { + get { return end_; } + } + + public override bool IsInitialized { + get { + return true; + } + } + + public override void WriteTo(pb::ICodedOutputStream output) { + CalcSerializedSize(); + string[] field_names = _reservedRangeFieldNames; + if (hasStart) { + output.WriteInt32(1, field_names[1], Start); + } + if (hasEnd) { + output.WriteInt32(2, field_names[0], End); + } + UnknownFields.WriteTo(output); + } + + private int memoizedSerializedSize = -1; + public override int SerializedSize { + get { + int size = memoizedSerializedSize; + if (size != -1) return size; + return CalcSerializedSize(); + } + } + + private int CalcSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (hasStart) { + size += pb::CodedOutputStream.ComputeInt32Size(1, Start); + } + if (hasEnd) { + size += pb::CodedOutputStream.ComputeInt32Size(2, End); + } + size += UnknownFields.SerializedSize; + memoizedSerializedSize = size; + return size; + } + public static ReservedRange ParseFrom(pb::ByteString data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static ReservedRange ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static ReservedRange ParseFrom(byte[] data) { + return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed(); + } + public static ReservedRange ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed(); + } + public static ReservedRange ParseFrom(global::System.IO.Stream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static ReservedRange ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + public static ReservedRange ParseDelimitedFrom(global::System.IO.Stream input) { + return CreateBuilder().MergeDelimitedFrom(input).BuildParsed(); + } + public static ReservedRange ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) { + return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed(); + } + public static ReservedRange ParseFrom(pb::ICodedInputStream input) { + return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed(); + } + public static ReservedRange ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed(); + } + private ReservedRange MakeReadOnly() { + return this; + } + + public static Builder CreateBuilder() { return new Builder(); } + public override Builder ToBuilder() { return CreateBuilder(this); } + public override Builder CreateBuilderForType() { return new Builder(); } + public static Builder CreateBuilder(ReservedRange prototype) { + return new Builder(prototype); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + public sealed partial class Builder : pb::GeneratedBuilder { + protected override Builder ThisBuilder { + get { return this; } + } + public Builder() { + result = DefaultInstance; + resultIsReadOnly = true; + } + internal Builder(ReservedRange cloneFrom) { + result = cloneFrom; + resultIsReadOnly = true; + } + + private bool resultIsReadOnly; + private ReservedRange result; + + private ReservedRange PrepareBuilder() { + if (resultIsReadOnly) { + ReservedRange original = result; + result = new ReservedRange(); + resultIsReadOnly = false; + MergeFrom(original); + } + return result; + } + + public override bool IsInitialized { + get { return result.IsInitialized; } + } + + protected override ReservedRange MessageBeingBuilt { + get { return PrepareBuilder(); } + } + + public override Builder Clear() { + result = DefaultInstance; + resultIsReadOnly = true; + return this; + } + + public override Builder Clone() { + if (resultIsReadOnly) { + return new Builder(result); + } else { + return new Builder().MergeFrom(result); + } + } + + public override pbd::MessageDescriptor DescriptorForType { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange.Descriptor; } + } + + public override ReservedRange DefaultInstanceForType { + get { return global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange.DefaultInstance; } + } + + public override ReservedRange BuildPartial() { + if (resultIsReadOnly) { + return result; + } + resultIsReadOnly = true; + return result.MakeReadOnly(); + } + + public override Builder MergeFrom(pb::IMessage other) { + if (other is ReservedRange) { + return MergeFrom((ReservedRange) other); + } else { + base.MergeFrom(other); + return this; + } + } + + public override Builder MergeFrom(ReservedRange other) { + if (other == global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange.DefaultInstance) return this; + PrepareBuilder(); + if (other.HasStart) { + Start = other.Start; + } + if (other.HasEnd) { + End = other.End; + } + this.MergeUnknownFields(other.UnknownFields); + return this; + } + + public override Builder MergeFrom(pb::ICodedInputStream input) { + return MergeFrom(input, pb::ExtensionRegistry.Empty); + } + + public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) { + PrepareBuilder(); + pb::UnknownFieldSet.Builder unknownFields = null; + uint tag; + string field_name; + while (input.ReadTag(out tag, out field_name)) { + if(tag == 0 && field_name != null) { + int field_ordinal = global::System.Array.BinarySearch(_reservedRangeFieldNames, field_name, global::System.StringComparer.Ordinal); + if(field_ordinal >= 0) + tag = _reservedRangeFieldTags[field_ordinal]; + else { + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + continue; + } + } + switch (tag) { + case 0: { + throw pb::InvalidProtocolBufferException.InvalidTag(); + } + default: { + if (pb::WireFormat.IsEndGroupTag(tag)) { + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + ParseUnknownField(input, unknownFields, extensionRegistry, tag, field_name); + break; + } + case 8: { + result.hasStart = input.ReadInt32(ref result.start_); + break; + } + case 16: { + result.hasEnd = input.ReadInt32(ref result.end_); + break; + } + } + } + + if (unknownFields != null) { + this.UnknownFields = unknownFields.Build(); + } + return this; + } + + + public bool HasStart { + get { return result.hasStart; } + } + public int Start { + get { return result.Start; } + set { SetStart(value); } + } + public Builder SetStart(int value) { + PrepareBuilder(); + result.hasStart = true; + result.start_ = value; + return this; + } + public Builder ClearStart() { + PrepareBuilder(); + result.hasStart = false; + result.start_ = 0; + return this; + } + + public bool HasEnd { + get { return result.hasEnd; } + } + public int End { + get { return result.End; } + set { SetEnd(value); } + } + public Builder SetEnd(int value) { + PrepareBuilder(); + result.hasEnd = true; + result.end_ = value; + return this; + } + public Builder ClearEnd() { + PrepareBuilder(); + result.hasEnd = false; + result.end_ = 0; + return this; + } + } + static ReservedRange() { + object.ReferenceEquals(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor, null); + } + } + } #endregion @@ -2001,6 +2331,30 @@ namespace Google.ProtocolBuffers.DescriptorProtos { get { return options_ ?? global::Google.ProtocolBuffers.DescriptorProtos.MessageOptions.DefaultInstance; } } + public const int ReservedRangeFieldNumber = 9; + private pbc::PopsicleList reservedRange_ = new pbc::PopsicleList(); + public scg::IList ReservedRangeList { + get { return reservedRange_; } + } + public int ReservedRangeCount { + get { return reservedRange_.Count; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange GetReservedRange(int index) { + return reservedRange_[index]; + } + + public const int ReservedNameFieldNumber = 10; + private pbc::PopsicleList reservedName_ = new pbc::PopsicleList(); + public scg::IList ReservedNameList { + get { return pbc::Lists.AsReadOnly(reservedName_); } + } + public int ReservedNameCount { + get { return reservedName_.Count; } + } + public string GetReservedName(int index) { + return reservedName_[index]; + } + public override bool IsInitialized { get { foreach (global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto element in FieldList) { @@ -2049,6 +2403,12 @@ namespace Google.ProtocolBuffers.DescriptorProtos { if (oneofDecl_.Count > 0) { output.WriteMessageArray(8, field_names[6], oneofDecl_); } + if (reservedRange_.Count > 0) { + output.WriteMessageArray(9, field_names[9], reservedRange_); + } + if (reservedName_.Count > 0) { + output.WriteStringArray(10, field_names[8], reservedName_); + } UnknownFields.WriteTo(output); } @@ -2090,6 +2450,17 @@ namespace Google.ProtocolBuffers.DescriptorProtos { if (hasOptions) { size += pb::CodedOutputStream.ComputeMessageSize(7, Options); } + foreach (global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange element in ReservedRangeList) { + size += pb::CodedOutputStream.ComputeMessageSize(9, element); + } + { + int dataSize = 0; + foreach (string element in ReservedNameList) { + dataSize += pb::CodedOutputStream.ComputeStringSizeNoTag(element); + } + size += dataSize; + size += 1 * reservedName_.Count; + } size += UnknownFields.SerializedSize; memoizedSerializedSize = size; return size; @@ -2131,6 +2502,8 @@ namespace Google.ProtocolBuffers.DescriptorProtos { enumType_.MakeReadOnly(); extensionRange_.MakeReadOnly(); oneofDecl_.MakeReadOnly(); + reservedRange_.MakeReadOnly(); + reservedName_.MakeReadOnly(); return this; } @@ -2242,6 +2615,12 @@ namespace Google.ProtocolBuffers.DescriptorProtos { if (other.HasOptions) { MergeOptions(other.Options); } + if (other.reservedRange_.Count != 0) { + result.reservedRange_.Add(other.reservedRange_); + } + if (other.reservedName_.Count != 0) { + result.reservedName_.Add(other.reservedName_); + } this.MergeUnknownFields(other.UnknownFields); return this; } @@ -2322,6 +2701,14 @@ namespace Google.ProtocolBuffers.DescriptorProtos { input.ReadMessageArray(tag, field_name, result.oneofDecl_, global::Google.ProtocolBuffers.DescriptorProtos.OneofDescriptorProto.DefaultInstance, extensionRegistry); break; } + case 74: { + input.ReadMessageArray(tag, field_name, result.reservedRange_, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange.DefaultInstance, extensionRegistry); + break; + } + case 82: { + input.ReadStringArray(tag, field_name, result.reservedName_); + break; + } } } @@ -2656,6 +3043,82 @@ namespace Google.ProtocolBuffers.DescriptorProtos { result.options_ = null; return this; } + + public pbc::IPopsicleList ReservedRangeList { + get { return PrepareBuilder().reservedRange_; } + } + public int ReservedRangeCount { + get { return result.ReservedRangeCount; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange GetReservedRange(int index) { + return result.GetReservedRange(index); + } + public Builder SetReservedRange(int index, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.reservedRange_[index] = value; + return this; + } + public Builder SetReservedRange(int index, global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.reservedRange_[index] = builderForValue.Build(); + return this; + } + public Builder AddReservedRange(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.reservedRange_.Add(value); + return this; + } + public Builder AddReservedRange(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProto.Types.ReservedRange.Builder builderForValue) { + pb::ThrowHelper.ThrowIfNull(builderForValue, "builderForValue"); + PrepareBuilder(); + result.reservedRange_.Add(builderForValue.Build()); + return this; + } + public Builder AddRangeReservedRange(scg::IEnumerable values) { + PrepareBuilder(); + result.reservedRange_.Add(values); + return this; + } + public Builder ClearReservedRange() { + PrepareBuilder(); + result.reservedRange_.Clear(); + return this; + } + + public pbc::IPopsicleList ReservedNameList { + get { return PrepareBuilder().reservedName_; } + } + public int ReservedNameCount { + get { return result.ReservedNameCount; } + } + public string GetReservedName(int index) { + return result.GetReservedName(index); + } + public Builder SetReservedName(int index, string value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.reservedName_[index] = value; + return this; + } + public Builder AddReservedName(string value) { + pb::ThrowHelper.ThrowIfNull(value, "value"); + PrepareBuilder(); + result.reservedName_.Add(value); + return this; + } + public Builder AddRangeReservedName(scg::IEnumerable values) { + PrepareBuilder(); + result.reservedName_.Add(values); + return this; + } + public Builder ClearReservedName() { + PrepareBuilder(); + result.reservedName_.Clear(); + return this; + } } static DescriptorProto() { object.ReferenceEquals(global::Google.ProtocolBuffers.DescriptorProtos.DescriptorProtoFile.Descriptor, null); @@ -3195,7 +3658,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { } public bool HasLabel { - get { return result.hasLabel; } + get { return result.hasLabel; } } public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Label Label { get { return result.Label; } @@ -3215,7 +3678,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { } public bool HasType { - get { return result.hasType; } + get { return result.hasType; } } public global::Google.ProtocolBuffers.DescriptorProtos.FieldDescriptorProto.Types.Type Type { get { return result.Type; } @@ -6095,7 +6558,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { } public bool HasOptimizeFor { - get { return result.hasOptimizeFor; } + get { return result.hasOptimizeFor; } } public global::Google.ProtocolBuffers.DescriptorProtos.FileOptions.Types.OptimizeMode OptimizeFor { get { return result.OptimizeFor; } @@ -6812,8 +7275,8 @@ namespace Google.ProtocolBuffers.DescriptorProtos { public sealed partial class FieldOptions : pb::ExtendableMessage { private FieldOptions() { } private static readonly FieldOptions defaultInstance = new FieldOptions().MakeReadOnly(); - private static readonly string[] _fieldOptionsFieldNames = new string[] { "ctype", "deprecated", "lazy", "packed", "uninterpreted_option", "weak" }; - private static readonly uint[] _fieldOptionsFieldTags = new uint[] { 8, 24, 40, 16, 7994, 80 }; + private static readonly string[] _fieldOptionsFieldNames = new string[] { "ctype", "deprecated", "jstype", "lazy", "packed", "uninterpreted_option", "weak" }; + private static readonly uint[] _fieldOptionsFieldTags = new uint[] { 8, 24, 48, 40, 16, 7994, 80 }; public static FieldOptions DefaultInstance { get { return defaultInstance; } } @@ -6843,6 +7306,12 @@ namespace Google.ProtocolBuffers.DescriptorProtos { STRING_PIECE = 2, } + public enum JSType { + JS_NORMAL = 0, + JS_STRING = 1, + JS_NUMBER = 2, + } + } #endregion @@ -6866,6 +7335,16 @@ namespace Google.ProtocolBuffers.DescriptorProtos { get { return packed_; } } + public const int JstypeFieldNumber = 6; + private bool hasJstype; + private global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.JSType jstype_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL; + public bool HasJstype { + get { return hasJstype; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.JSType Jstype { + get { return jstype_; } + } + public const int LazyFieldNumber = 5; private bool hasLazy; private bool lazy_; @@ -6926,19 +7405,22 @@ namespace Google.ProtocolBuffers.DescriptorProtos { output.WriteEnum(1, field_names[0], (int) Ctype, Ctype); } if (hasPacked) { - output.WriteBool(2, field_names[3], Packed); + output.WriteBool(2, field_names[4], Packed); } if (hasDeprecated) { output.WriteBool(3, field_names[1], Deprecated); } if (hasLazy) { - output.WriteBool(5, field_names[2], Lazy); + output.WriteBool(5, field_names[3], Lazy); + } + if (hasJstype) { + output.WriteEnum(6, field_names[2], (int) Jstype, Jstype); } if (hasWeak) { - output.WriteBool(10, field_names[5], Weak); + output.WriteBool(10, field_names[6], Weak); } if (uninterpretedOption_.Count > 0) { - output.WriteMessageArray(999, field_names[4], uninterpretedOption_); + output.WriteMessageArray(999, field_names[5], uninterpretedOption_); } extensionWriter.WriteUntil(536870912, output); UnknownFields.WriteTo(output); @@ -6964,6 +7446,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos { if (hasPacked) { size += pb::CodedOutputStream.ComputeBoolSize(2, Packed); } + if (hasJstype) { + size += pb::CodedOutputStream.ComputeEnumSize(6, (int) Jstype); + } if (hasLazy) { size += pb::CodedOutputStream.ComputeBoolSize(5, Lazy); } @@ -7106,6 +7591,9 @@ namespace Google.ProtocolBuffers.DescriptorProtos { if (other.HasPacked) { Packed = other.Packed; } + if (other.HasJstype) { + Jstype = other.Jstype; + } if (other.HasLazy) { Lazy = other.Lazy; } @@ -7186,6 +7674,18 @@ namespace Google.ProtocolBuffers.DescriptorProtos { result.hasLazy = input.ReadBool(ref result.lazy_); break; } + case 48: { + object unknown; + if(input.ReadEnum(ref result.jstype_, out unknown)) { + result.hasJstype = true; + } else if(unknown is int) { + if (unknownFields == null) { + unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields); + } + unknownFields.MergeVarintField(6, (ulong)(int)unknown); + } + break; + } case 80: { result.hasWeak = input.ReadBool(ref result.weak_); break; @@ -7205,7 +7705,7 @@ namespace Google.ProtocolBuffers.DescriptorProtos { public bool HasCtype { - get { return result.hasCtype; } + get { return result.hasCtype; } } public global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.CType Ctype { get { return result.Ctype; } @@ -7244,6 +7744,26 @@ namespace Google.ProtocolBuffers.DescriptorProtos { return this; } + public bool HasJstype { + get { return result.hasJstype; } + } + public global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.JSType Jstype { + get { return result.Jstype; } + set { SetJstype(value); } + } + public Builder SetJstype(global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.JSType value) { + PrepareBuilder(); + result.hasJstype = true; + result.jstype_ = value; + return this; + } + public Builder ClearJstype() { + PrepareBuilder(); + result.hasJstype = false; + result.jstype_ = global::Google.ProtocolBuffers.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL; + return this; + } + public bool HasLazy { get { return result.hasLazy; } } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs index 67898644..4dda7bcd 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs @@ -4997,7 +4997,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalNestedEnum { - get { return result.hasOptionalNestedEnum; } + get { return result.hasOptionalNestedEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedEnum OptionalNestedEnum { get { return result.OptionalNestedEnum; } @@ -5017,7 +5017,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalForeignEnum { - get { return result.hasOptionalForeignEnum; } + get { return result.hasOptionalForeignEnum; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnum OptionalForeignEnum { get { return result.OptionalForeignEnum; } @@ -5037,7 +5037,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalImportEnum { - get { return result.hasOptionalImportEnum; } + get { return result.hasOptionalImportEnum; } } public global::Google.ProtocolBuffers.TestProtos.ImportEnum OptionalImportEnum { get { return result.OptionalImportEnum; } @@ -6309,7 +6309,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultNestedEnum { - get { return result.hasDefaultNestedEnum; } + get { return result.hasDefaultNestedEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedEnum DefaultNestedEnum { get { return result.DefaultNestedEnum; } @@ -6329,7 +6329,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultForeignEnum { - get { return result.hasDefaultForeignEnum; } + get { return result.hasDefaultForeignEnum; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnum DefaultForeignEnum { get { return result.DefaultForeignEnum; } @@ -6349,7 +6349,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultImportEnum { - get { return result.hasDefaultImportEnum; } + get { return result.hasDefaultImportEnum; } } public global::Google.ProtocolBuffers.TestProtos.ImportEnum DefaultImportEnum { get { return result.DefaultImportEnum; } @@ -16021,7 +16021,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasEnumField { - get { return result.hasEnumField; } + get { return result.hasEnumField; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnum EnumField { get { return result.EnumField; } @@ -18747,7 +18747,7 @@ namespace Google.ProtocolBuffers.TestProtos { public bool HasSparseEnum { - get { return result.hasSparseEnum; } + get { return result.hasSparseEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestSparseEnum SparseEnum { get { return result.SparseEnum; } @@ -24384,7 +24384,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooEnum { - get { return result.fooCase_ == FooOneofCase.FooEnum; } + get { return result.fooCase_ == FooOneofCase.FooEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum FooEnum { get { return result.fooCase_ == FooOneofCase.FooEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.FOO; } @@ -24640,7 +24640,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasBarEnum { - get { return result.barCase_ == BarOneofCase.BarEnum; } + get { return result.barCase_ == BarOneofCase.BarEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum BarEnum { get { return result.barCase_ == BarOneofCase.BarEnum ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum) result.bar_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedEnum.BAR; } @@ -28899,7 +28899,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasEnumExtension { - get { return result.hasEnumExtension; } + get { return result.hasEnumExtension; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnum EnumExtension { get { return result.EnumExtension; } @@ -28919,7 +28919,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDynamicEnumExtension { - get { return result.hasDynamicEnumExtension; } + get { return result.hasDynamicEnumExtension; } } public global::Google.ProtocolBuffers.TestProtos.TestDynamicExtensions.Types.DynamicEnumType DynamicEnumExtension { get { return result.DynamicEnumExtension; } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasFull.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasFull.cs index 827bedef..73c4b182 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasFull.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasFull.cs @@ -326,7 +326,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasType { - get { return result.hasType; } + get { return result.hasType; } } public global::Google.ProtocolBuffers.TestProtos.TestInteropPerson.Types.PhoneType Type { get { return result.Type; } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasLite.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasLite.cs index 441a7c60..ceb9e861 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasLite.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestExtrasLite.cs @@ -524,7 +524,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasEn { - get { return result.hasEn; } + get { return result.hasEn; } } public global::Google.ProtocolBuffers.TestProtos.ExtraEnum En { get { return result.En; } @@ -873,7 +873,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasType { - get { return result.hasType; } + get { return result.hasType; } } public global::Google.ProtocolBuffers.TestProtos.TestInteropPersonLite.Types.PhoneType Type { get { return result.Type; } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs index 84860b69..d84a505f 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs @@ -5005,7 +5005,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalNestedEnum { - get { return result.hasOptionalNestedEnum; } + get { return result.hasOptionalNestedEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum OptionalNestedEnum { get { return result.OptionalNestedEnum; } @@ -5025,7 +5025,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalForeignEnum { - get { return result.hasOptionalForeignEnum; } + get { return result.hasOptionalForeignEnum; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite OptionalForeignEnum { get { return result.OptionalForeignEnum; } @@ -5045,7 +5045,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOptionalImportEnum { - get { return result.hasOptionalImportEnum; } + get { return result.hasOptionalImportEnum; } } public global::Google.ProtocolBuffers.TestProtos.ImportEnumLite OptionalImportEnum { get { return result.OptionalImportEnum; } @@ -6317,7 +6317,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultNestedEnum { - get { return result.hasDefaultNestedEnum; } + get { return result.hasDefaultNestedEnum; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedEnum DefaultNestedEnum { get { return result.DefaultNestedEnum; } @@ -6337,7 +6337,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultForeignEnum { - get { return result.hasDefaultForeignEnum; } + get { return result.hasDefaultForeignEnum; } } public global::Google.ProtocolBuffers.TestProtos.ForeignEnumLite DefaultForeignEnum { get { return result.DefaultForeignEnum; } @@ -6357,7 +6357,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasDefaultImportEnum { - get { return result.hasDefaultImportEnum; } + get { return result.hasDefaultImportEnum; } } public global::Google.ProtocolBuffers.TestProtos.ImportEnumLite DefaultImportEnum { get { return result.DefaultImportEnum; } diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index a2d8a98b..28f5a05c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -48,81 +48,10 @@ namespace csharp { EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) - : FieldGeneratorBase(descriptor, fieldOrdinal) { - if (SupportFieldPresence(descriptor_->file())) { - has_property_check = "has" + property_name(); - } else { - has_property_check = property_name() + " != " + default_value(); - } + : PrimitiveFieldGenerator(descriptor, fieldOrdinal) { } EnumFieldGenerator::~EnumFieldGenerator() { - -} - -void EnumFieldGenerator::GenerateMembers(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("private bool has$0$;", property_name()); - } - writer->WriteLine("private $0$ $1$_ = $2$;", type_name(), name(), - default_value()); - AddDeprecatedFlag(writer); - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return has$0$; }", property_name()); - writer->WriteLine("}"); - } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$_; }", name()); - writer->WriteLine("}"); -} - -void EnumFieldGenerator::GenerateBuilderMembers(Writer* writer) { - AddDeprecatedFlag(writer); - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.has$0$; }", property_name()); - writer->WriteLine("}"); - } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$; }", property_name()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - writer->WriteLine(" PrepareBuilder();"); - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine(" result.has$0$ = true;", property_name()); - } - writer->WriteLine(" result.$0$_ = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine(" result.has$0$ = false;", property_name()); - } - writer->WriteLine(" result.$0$_ = $1$;", name(), default_value()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); -} - -void EnumFieldGenerator::GenerateMergingCode(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (other.Has$0$) {", property_name()); - } else { - writer->WriteLine("if (other.$0$ != $1$) {", property_name(), default_value()); - } - writer->WriteLine(" $0$ = other.$0$;", property_name()); - writer->WriteLine("}"); -} - -void EnumFieldGenerator::GenerateBuildingCode(Writer* writer) { - // Nothing to do here for enum types } void EnumFieldGenerator::GenerateParsingCode(Writer* writer) { @@ -160,91 +89,14 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { writer->WriteLine("}"); } -void EnumFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" hash ^= $0$_.GetHashCode();", name()); - writer->WriteLine("}"); -} -void EnumFieldGenerator::WriteEquals(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine( - "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", - property_name(), name()); - } else { - writer->WriteLine( - "if (!$0$_.Equals(other.$0$_)) return false;", name()); - } -} -void EnumFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", - descriptor_->name(), has_property_check, name()); -} - EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) - : EnumFieldGenerator(descriptor, fieldOrdinal) { - has_property_check = oneof_name() + "Case_ == " + oneof_property_name() + - "OneofCase." + property_name(); + : PrimitiveOneofFieldGenerator(descriptor, fieldOrdinal) { } EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { } -void EnumOneofFieldGenerator::GenerateMembers(Writer* writer) { - AddDeprecatedFlag(writer); - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return $0$; }", has_property_check); - writer->WriteLine("}"); - } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$ ? ($1$) $2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine("}"); -} - -void EnumOneofFieldGenerator::GenerateBuilderMembers(Writer* writer) { - AddDeprecatedFlag(writer); - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.$0$; }", has_property_check); - writer->WriteLine("}"); - } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$ ? ($1$) result.$2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" if (result.$0$) {", has_property_check); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", - oneof_name(), oneof_property_name()); - writer->WriteLine(" }"); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); -} - -void EnumOneofFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if (!$0$.Equals(other.$0$)) return false;", property_name()); -} -void EnumOneofFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", - descriptor_->name(), has_property_check, oneof_name()); -} - void EnumOneofFieldGenerator::GenerateParsingCode(Writer* writer) { writer->WriteLine("object unknown;"); writer->WriteLine("$0$ enumValue = $1$;", type_name(), default_value()); @@ -266,6 +118,22 @@ void EnumOneofFieldGenerator::GenerateParsingCode(Writer* writer) { writer->WriteLine("}"); } +void EnumOneofFieldGenerator::GenerateSerializationCode(Writer* writer) { + writer->WriteLine("if ($0$) {", has_property_check); + writer->WriteLine( + " output.WriteEnum($0$, field_names[$2$], (int) $1$, $1$);", number(), + property_name(), field_ordinal()); + writer->WriteLine("}"); +} + +void EnumOneofFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { + writer->WriteLine("if ($0$) {", has_property_check); + writer->WriteLine( + " size += pb::CodedOutputStream.ComputeEnumSize($0$, (int) $1$);", + number(), property_name()); + writer->WriteLine("}"); +} + } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h index 565287b2..c6b7b848 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -34,7 +34,7 @@ #include #include -#include +#include namespace google { namespace protobuf { @@ -43,40 +43,27 @@ namespace csharp { class Writer; -class EnumFieldGenerator : public FieldGeneratorBase { +class EnumFieldGenerator : public PrimitiveFieldGenerator { public: EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~EnumFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); virtual void GenerateParsingCode(Writer* writer); virtual void GenerateSerializationCode(Writer* writer); virtual void GenerateSerializedSizeCode(Writer* writer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - - protected: - string has_property_check; - private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; -class EnumOneofFieldGenerator : public EnumFieldGenerator { +class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator { public: EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~EnumOneofFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateSerializationCode(Writer* writer); + virtual void GenerateSerializedSizeCode(Writer* writer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); -- cgit v1.2.3 From 0af3ed5189182985573dbea30e173aca0f9a1685 Mon Sep 17 00:00:00 2001 From: Dan Barry Date: Tue, 2 Jun 2015 17:00:40 -0700 Subject: Add protoc path detection for Mac OS --- src/google/protobuf/compiler/command_line_interface.cc | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index 667b2b63..c57cfd3d 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -53,6 +53,10 @@ #include #endif +#ifdef __APPLE__ +#include +#endif + #include #include #include @@ -186,6 +190,16 @@ bool GetProtocAbsolutePath(string* path) { #ifdef _WIN32 char buffer[MAX_PATH]; int len = GetModuleFileName(NULL, buffer, MAX_PATH); +#elif __APPLE__ + char buffer[PATH_MAX]; + int len = 0; + + char dirtybuffer[PATH_MAX]; + uint32_t size = sizeof(dirtybuffer); + if (_NSGetExecutablePath(dirtybuffer, &size) == 0) { + realpath(dirtybuffer, buffer); + len = strlen(buffer); + } #else char buffer[PATH_MAX]; int len = readlink("/proc/self/exe", buffer, PATH_MAX); -- cgit v1.2.3 From 90da3514cdc372b8221a32f9fc97da0d4e047e92 Mon Sep 17 00:00:00 2001 From: Jie Luo Date: Wed, 3 Jun 2015 18:02:17 -0700 Subject: Migrate writer to io::Printer for C# --- .../ProtocolBuffers.Test/TestProtos/Unittest.cs | 14 +- .../TestProtos/Unittest.cs | 14 +- .../TestProtos/UnittestLite.cs | 2 +- src/google/protobuf/compiler/csharp/csharp_enum.cc | 25 +- src/google/protobuf/compiler/csharp/csharp_enum.h | 4 +- .../protobuf/compiler/csharp/csharp_enum_field.cc | 107 +- .../protobuf/compiler/csharp/csharp_enum_field.h | 14 +- .../protobuf/compiler/csharp/csharp_extension.cc | 138 +-- .../protobuf/compiler/csharp/csharp_extension.h | 28 +- .../protobuf/compiler/csharp/csharp_field_base.cc | 54 +- .../protobuf/compiler/csharp/csharp_field_base.h | 33 +- .../protobuf/compiler/csharp/csharp_generator.cc | 8 +- .../protobuf/compiler/csharp/csharp_message.cc | 1119 ++++++++++---------- .../protobuf/compiler/csharp/csharp_message.h | 26 +- .../compiler/csharp/csharp_message_field.cc | 419 ++++---- .../compiler/csharp/csharp_message_field.h | 35 +- .../compiler/csharp/csharp_primitive_field.cc | 313 +++--- .../compiler/csharp/csharp_primitive_field.h | 35 +- .../compiler/csharp/csharp_repeated_enum_field.cc | 278 ++--- .../compiler/csharp/csharp_repeated_enum_field.h | 20 +- .../csharp/csharp_repeated_message_field.cc | 260 +++-- .../csharp/csharp_repeated_message_field.h | 20 +- .../csharp/csharp_repeated_primitive_field.cc | 256 ++--- .../csharp/csharp_repeated_primitive_field.h | 20 +- .../csharp/csharp_source_generator_base.cc | 3 +- .../compiler/csharp/csharp_source_generator_base.h | 4 +- .../compiler/csharp/csharp_umbrella_class.cc | 249 ++--- .../compiler/csharp/csharp_umbrella_class.h | 10 +- 28 files changed, 1861 insertions(+), 1647 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs index 4dda7bcd..d3441937 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs @@ -6432,7 +6432,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofNestedMessage { - get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } @@ -22008,7 +22008,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } @@ -22050,7 +22050,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooGroup { - get { return result.fooCase_ == FooOneofCase.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup FooGroup { get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } @@ -24405,7 +24405,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } @@ -24447,7 +24447,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooGroup { - get { return result.fooCase_ == FooOneofCase.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup FooGroup { get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } @@ -24489,7 +24489,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooLazyMessage { - get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } + get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooLazyMessage { get { return result.fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } @@ -25377,7 +25377,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs index 4dda7bcd..d3441937 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/Unittest.cs @@ -6432,7 +6432,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofNestedMessage { - get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage OneofNestedMessage { get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage.DefaultInstance; } @@ -22008,7 +22008,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypes FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypes) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypes.DefaultInstance; } @@ -22050,7 +22050,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooGroup { - get { return result.fooCase_ == FooOneofCase.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup FooGroup { get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof.Types.FooGroup.DefaultInstance; } @@ -24405,7 +24405,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } @@ -24447,7 +24447,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooGroup { - get { return result.fooCase_ == FooOneofCase.FooGroup; } + get { return result.fooCase_ == FooOneofCase.FooGroup; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup FooGroup { get { return result.fooCase_ == FooOneofCase.FooGroup ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.FooGroup.DefaultInstance; } @@ -24489,7 +24489,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooLazyMessage { - get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } + get { return result.fooCase_ == FooOneofCase.FooLazyMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage FooLazyMessage { get { return result.fooCase_ == FooOneofCase.FooLazyMessage ? (global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestOneof2.Types.NestedMessage.DefaultInstance; } @@ -25377,7 +25377,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasFooMessage { - get { return result.fooCase_ == FooOneofCase.FooMessage; } + get { return result.fooCase_ == FooOneofCase.FooMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage FooMessage { get { return result.fooCase_ == FooOneofCase.FooMessage ? (global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage) result.foo_ : global::Google.ProtocolBuffers.TestProtos.TestRequiredOneof.Types.NestedMessage.DefaultInstance; } diff --git a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs index d84a505f..bf0da956 100644 --- a/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs +++ b/csharp/src/ProtocolBuffersLite.Test/TestProtos/UnittestLite.cs @@ -6440,7 +6440,7 @@ namespace Google.ProtocolBuffers.TestProtos { } public bool HasOneofNestedMessage { - get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } + get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage; } } public global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage OneofNestedMessage { get { return result.oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage ? (global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage) result.oneofField_ : global::Google.ProtocolBuffers.TestProtos.TestAllTypesLite.Types.NestedMessage.DefaultInstance; } diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index 27643e61..0e8f9836 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -40,7 +40,6 @@ #include #include -#include using google::protobuf::internal::scoped_ptr; @@ -57,20 +56,20 @@ EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) : EnumGenerator::~EnumGenerator() { } -void EnumGenerator::Generate(Writer* writer) { - WriteGeneratedCodeAttributes(writer); - writer->WriteLine("$0$ enum $1$ {", - class_access_level(), - descriptor_->name()); - writer->Indent(); +void EnumGenerator::Generate(io::Printer* printer) { + WriteGeneratedCodeAttributes(printer); + printer->Print("$access_level$ enum $name$ {\n", + "access_level", class_access_level(), + "name", descriptor_->name()); + printer->Indent(); for (int i = 0; i < descriptor_->value_count(); i++) { - writer->WriteLine("$0$ = $1$,", - descriptor_->value(i)->name(), - SimpleItoa(descriptor_->value(i)->number())); + printer->Print("$name$ = $number$,\n", + "name", descriptor_->value(i)->name(), + "number", SimpleItoa(descriptor_->value(i)->number())); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h index eaa7a9c5..2cf2fad4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum.h @@ -41,14 +41,12 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class EnumGenerator : public SourceGeneratorBase { public: EnumGenerator(const EnumDescriptor* descriptor); ~EnumGenerator(); - void Generate(Writer* writer); + void Generate(io::Printer* printer); private: const EnumDescriptor* descriptor_; diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 28f5a05c..51a95b9f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -39,7 +39,6 @@ #include #include -#include namespace google { namespace protobuf { @@ -54,39 +53,38 @@ EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor, EnumFieldGenerator::~EnumFieldGenerator() { } -void EnumFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("object unknown;"); - writer->WriteLine("if(input.ReadEnum(ref result.$0$_, out unknown)) {", name()); +void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print(variables_, + "object unknown;\n" + "if(input.ReadEnum(ref result.$name$_, out unknown)) {\n"); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine(" result.has$0$ = true;", property_name()); + printer->Print(variables_, + " result.has$property_name$ = true;\n"); } - writer->WriteLine("} else if(unknown is int) {"); + printer->Print("} else if(unknown is int) {\n"); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); - writer->WriteLine( - " unknownFields.MergeVarintField($0$, (ulong)(int)unknown);", - number()); + printer->Print(variables_, + " if (unknownFields == null) {\n" // First unknown field - create builder now + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n" + " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); } - writer->WriteLine("}"); + printer->Print("}\n"); } -void EnumFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine( - " output.WriteEnum($0$, field_names[$2$], (int) $1$, $1$);", number(), - property_name(), field_ordinal()); - writer->WriteLine("}"); +void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print(variables_, + "if ($has_property_check$) {\n" + " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" + "}\n"); } -void EnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine( - " size += pb::CodedOutputStream.ComputeEnumSize($0$, (int) $1$);", - number(), property_name()); - writer->WriteLine("}"); +void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + "}\n"); } EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor, @@ -97,41 +95,40 @@ EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descript EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { } -void EnumOneofFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("object unknown;"); - writer->WriteLine("$0$ enumValue = $1$;", type_name(), default_value()); - writer->WriteLine("if(input.ReadEnum(ref enumValue, out unknown)) {", - name()); - writer->WriteLine(" result.$0$_ = enumValue;", oneof_name()); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine("} else if(unknown is int) {"); +void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "object unknown;\n" + "$type_name$ enumValue = $default_value$;\n" + "if(input.ReadEnum(ref enumValue, out unknown)) {\n" + " result.$oneof_name$_ = enumValue;\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + "} else if(unknown is int) {\n"); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); - writer->WriteLine( - " unknownFields.MergeVarintField($0$, (ulong)(int)unknown);", - number()); + printer->Print( + variables_, + " if (unknownFields == null) {\n" // First unknown field - create builder now + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n" + " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); } - writer->WriteLine("}"); + printer->Print("}\n"); } -void EnumOneofFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine( - " output.WriteEnum($0$, field_names[$2$], (int) $1$, $1$);", number(), - property_name(), field_ordinal()); - writer->WriteLine("}"); +void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" + "}\n"); } -void EnumOneofFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine( - " size += pb::CodedOutputStream.ComputeEnumSize($0$, (int) $1$);", - number(), property_name()); - writer->WriteLine("}"); +void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + "}\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h index c6b7b848..e627b7cc 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h @@ -41,16 +41,14 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class EnumFieldGenerator : public PrimitiveFieldGenerator { public: EnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~EnumFieldGenerator(); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); @@ -61,9 +59,9 @@ class EnumOneofFieldGenerator : public PrimitiveOneofFieldGenerator { EnumOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~EnumOneofFieldGenerator(); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc index 2bac320d..8b665ae4 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ b/src/google/protobuf/compiler/csharp/csharp_extension.cc @@ -39,7 +39,6 @@ #include #include -#include #include using google::protobuf::internal::scoped_ptr; @@ -52,20 +51,34 @@ namespace csharp { ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) : FieldGeneratorBase(descriptor, 0) { if (descriptor_->extension_scope()) { - scope_ = GetClassName(descriptor_->extension_scope()); + variables_["scope"] = GetClassName(descriptor_->extension_scope()); } else { - scope_ = GetFullUmbrellaClassName(descriptor_->file()); + variables_["scope"] = GetFullUmbrellaClassName(descriptor_->file()); + } + variables_["extends"] = GetClassName(descriptor_->containing_type()); + variables_["capitalized_type_name"] = capitalized_type_name(); + variables_["full_name"] = descriptor_->full_name(); + variables_["access_level"] = class_access_level(); + variables_["index"] = SimpleItoa(descriptor_->index()); + variables_["property_name"] = property_name(); + variables_["type_name"] = type_name(); + if (use_lite_runtime()) { + variables_["generated_extension"] = descriptor_->is_repeated() ? + "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"; + } else { + variables_["generated_extension"] = descriptor_->is_repeated() ? + "GeneratedRepeatExtension" : "GeneratedExtension"; } - extends_ = GetClassName(descriptor_->containing_type()); } ExtensionGenerator::~ExtensionGenerator() { } -void ExtensionGenerator::Generate(Writer* writer) { - writer->WriteLine("public const int $0$ = $1$;", - GetFieldConstantName(descriptor_), - SimpleItoa(descriptor_->number())); +void ExtensionGenerator::Generate(io::Printer* printer) { + printer->Print( + "public const int $constant_name$ = $number$;\n", + "constant_name", GetFieldConstantName(descriptor_), + "number", SimpleItoa(descriptor_->number())); if (use_lite_runtime()) { // TODO(jtattermusch): include the following check @@ -75,36 +88,34 @@ void ExtensionGenerator::Generate(Writer* writer) { // "option message_set_wire_format = true; is not supported in Lite runtime extensions."); //} - writer->Write("$0$ ", class_access_level()); - writer->WriteLine( - "static pb::$3$<$0$, $1$> $2$;", - extends_, - type_name(), - property_name(), - descriptor_->is_repeated() ? - "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"); + printer->Print( + variables_, + "$access_level$ static pb::$generated_extension$<$extends$, $type_name$> $property_name$;\n"); } else if (descriptor_->is_repeated()) { - writer->WriteLine( - "$0$ static pb::GeneratedExtensionBase> $2$;", - class_access_level(), type_name(), property_name()); + printer->Print( + variables_, + "$access_level$ static pb::GeneratedExtensionBase> $property_name$;\n"); } else { - writer->WriteLine("$0$ static pb::GeneratedExtensionBase<$1$> $2$;", - class_access_level(), type_name(), property_name()); + printer->Print( + variables_, + "$access_level$ static pb::GeneratedExtensionBase<$type_name$> $property_name$;\n"); } } -void ExtensionGenerator::GenerateStaticVariableInitializers(Writer* writer) { +void ExtensionGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { if (use_lite_runtime()) { - writer->WriteLine("$0$.$1$ = ", scope_, property_name()); - writer->Indent(); - writer->WriteLine( - "new pb::$0$<$1$, $2$>(", - descriptor_->is_repeated() ? - "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite", - extends_, type_name()); - writer->Indent(); - writer->WriteLine("\"$0$\",", descriptor_->full_name()); - writer->WriteLine("$0$.DefaultInstance,", extends_); + printer->Print( + variables_, + "$scope$.$property_name$ = \n"); + printer->Indent(); + printer->Print( + variables_, + "new pb::$generated_extension$<$extends$, $type_name$>(\n"); + printer->Indent(); + printer->Print( + variables_, + "\"$full_name$\",\n" + "$extends$.DefaultInstance,\n"); if (!descriptor_->is_repeated()) { std::string default_val; if (descriptor_->has_default_value()) { @@ -112,52 +123,59 @@ void ExtensionGenerator::GenerateStaticVariableInitializers(Writer* writer) { } else { default_val = is_nullable_type() ? "null" : ("default(" + type_name() + ")"); } - writer->WriteLine("$0$,", default_val); + printer->Print("$default_val$,\n", "default_val", default_val); } - writer->WriteLine( - "$0$,", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_MESSAGE) ? - type_name() + ".DefaultInstance" : "null"); - writer->WriteLine( - "$0$,", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_ENUM) ? - "new EnumLiteMap<" + type_name() + ">()" : "null"); - writer->WriteLine("$0$.$1$FieldNumber,", scope_, - GetPropertyName(descriptor_)); - writer->Write("pbd::FieldType.$0$", capitalized_type_name()); + printer->Print( + "$message_val$,\n", + "message_val", + (GetCSharpType(descriptor_->type()) == CSHARPTYPE_MESSAGE) ? + type_name() + ".DefaultInstance" : "null"); + printer->Print( + "$enum_val$,\n", + "enum_val", + (GetCSharpType(descriptor_->type()) == CSHARPTYPE_ENUM) ? + "new EnumLiteMap<" + type_name() + ">()" : "null"); + printer->Print( + variables_, + "$scope$.$property_name$FieldNumber,\n" + "pbd::FieldType.$capitalized_type_name$"); if (descriptor_->is_repeated()) { - writer->WriteLine(","); - writer->Write(descriptor_->is_packed() ? "true" : "false"); + printer->Print( + ",\n" + "$is_packed$", + "is_packed", descriptor_->is_packed() ? "true" : "false"); } - writer->Outdent(); - writer->WriteLine(");"); - writer->Outdent(); + printer->Outdent(); + printer->Print(");\n"); + printer->Outdent(); } else if (descriptor_->is_repeated()) { - writer->WriteLine( - "$0$.$1$ = pb::GeneratedRepeatExtension<$2$>.CreateInstance($0$.Descriptor.Extensions[$3$]);", - scope_, property_name(), type_name(), SimpleItoa(descriptor_->index())); + printer->Print( + variables_, + "$scope$.$property_name$ = pb::GeneratedRepeatExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); } else { - writer->WriteLine( - "$0$.$1$ = pb::GeneratedSingleExtension<$2$>.CreateInstance($0$.Descriptor.Extensions[$3$]);", - scope_, property_name(), type_name(), SimpleItoa(descriptor_->index())); + printer->Print( + variables_, + "$scope$.$property_name$ = pb::GeneratedSingleExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); } } -void ExtensionGenerator::GenerateExtensionRegistrationCode(Writer* writer) { - writer->WriteLine("registry.Add($0$.$1$);", scope_, property_name()); +void ExtensionGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { + printer->Print( + variables_, + "registry.Add($scope$.$property_name$);\n"); } -void ExtensionGenerator::WriteHash(Writer* writer) { +void ExtensionGenerator::WriteHash(io::Printer* printer) { } -void ExtensionGenerator::WriteEquals(Writer* writer) { +void ExtensionGenerator::WriteEquals(io::Printer* printer) { } -void ExtensionGenerator::WriteToString(Writer* writer) { +void ExtensionGenerator::WriteToString(io::Printer* printer) { } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.h b/src/google/protobuf/compiler/csharp/csharp_extension.h index 203f6e5e..f251a21c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_extension.h +++ b/src/google/protobuf/compiler/csharp/csharp_extension.h @@ -41,28 +41,26 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class ExtensionGenerator : public FieldGeneratorBase { public: ExtensionGenerator(const FieldDescriptor* descriptor); ~ExtensionGenerator(); - void GenerateStaticVariableInitializers(Writer* writer); - void GenerateExtensionRegistrationCode(Writer* writer); - void Generate(Writer* writer); + void GenerateStaticVariableInitializers(io::Printer* printer); + void GenerateExtensionRegistrationCode(io::Printer* printer); + void Generate(io::Printer* printer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); - virtual void GenerateMembers(Writer* writer) {}; - virtual void GenerateBuilderMembers(Writer* writer) {}; - virtual void GenerateMergingCode(Writer* writer) {}; - virtual void GenerateBuildingCode(Writer* writer) {}; - virtual void GenerateParsingCode(Writer* writer) {}; - virtual void GenerateSerializationCode(Writer* writer) {}; - virtual void GenerateSerializedSizeCode(Writer* writer) {}; + virtual void GenerateMembers(io::Printer* printer) {}; + virtual void GenerateBuilderMembers(io::Printer* printer) {}; + virtual void GenerateMergingCode(io::Printer* printer) {}; + virtual void GenerateBuildingCode(io::Printer* printer) {}; + virtual void GenerateParsingCode(io::Printer* printer) {}; + virtual void GenerateSerializationCode(io::Printer* printer) {}; + virtual void GenerateSerializedSizeCode(io::Printer* printer) {}; private: std::string scope_; diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index dfc803e6..c3ce426b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -41,7 +41,6 @@ #include #include -#include using google::protobuf::internal::scoped_ptr; @@ -50,35 +49,72 @@ namespace protobuf { namespace compiler { namespace csharp { +void FieldGeneratorBase::SetCommonFieldVariables( + map* variables) { + (*variables)["property_name"] = property_name(); + (*variables)["type_name"] = type_name(); + (*variables)["name"] = name(); + (*variables)["descriptor_name"] = descriptor_->name(); + (*variables)["default_value"] = default_value(); + if (has_default_value()) { + (*variables)["name_def_message"] = + (*variables)["name"] + "_ = " + (*variables)["default_value"]; + } else { + (*variables)["name_def_message"] = (*variables)["name"] + "_"; + } + (*variables)["capitalized_type_name"] = capitalized_type_name(); + (*variables)["number"] = number(); + (*variables)["field_ordinal"] = field_ordinal(); + if (SupportFieldPresence(descriptor_->file())) { + (*variables)["has_property_check"] = "has" + (*variables)["property_name"]; + (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; + } else { + (*variables)["has_property_check"] = + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + (*variables)["other_has_property_check"] = "other." + + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + } +} + +void FieldGeneratorBase::SetCommonOneofFieldVariables( + map* variables) { + (*variables)["oneof_name"] = oneof_name(); + (*variables)["has_property_check"] = oneof_name() + "Case_ == " + oneof_property_name() + + "OneofCase." + property_name(); + (*variables)["oneof_property_name"] = oneof_property_name(); +} + FieldGeneratorBase::FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal) : SourceGeneratorBase(descriptor->file()), descriptor_(descriptor), fieldOrdinal_(fieldOrdinal) { + SetCommonFieldVariables(&variables_); } FieldGeneratorBase::~FieldGeneratorBase() { } -void FieldGeneratorBase::AddDeprecatedFlag(Writer* writer) { +void FieldGeneratorBase::AddDeprecatedFlag(io::Printer* printer) { if (descriptor_->options().deprecated()) { - writer->WriteLine("[global::System.ObsoleteAttribute()]"); + printer->Print("[global::System.ObsoleteAttribute()]\n"); } } -void FieldGeneratorBase::AddNullCheck(Writer* writer) { - AddNullCheck(writer, "value"); +void FieldGeneratorBase::AddNullCheck(io::Printer* printer) { + AddNullCheck(printer, "value"); } -void FieldGeneratorBase::AddNullCheck(Writer* writer, const std::string& name) { +void FieldGeneratorBase::AddNullCheck(io::Printer* printer, const std::string& name) { if (is_nullable_type()) { - writer->WriteLine(" pb::ThrowHelper.ThrowIfNull($0$, \"$0$\");", name); + printer->Print(" pb::ThrowHelper.ThrowIfNull($name$, \"$name$\");\n", + "name", name); } } -void FieldGeneratorBase::AddPublicMemberAttributes(Writer* writer) { - AddDeprecatedFlag(writer); +void FieldGeneratorBase::AddPublicMemberAttributes(io::Printer* printer) { + AddDeprecatedFlag(printer); } std::string FieldGeneratorBase::oneof_property_name() { diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index 312da12b..b1570587 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -49,27 +49,29 @@ class FieldGeneratorBase : public SourceGeneratorBase { FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal); ~FieldGeneratorBase(); - virtual void GenerateMembers(Writer* writer) = 0; - virtual void GenerateBuilderMembers(Writer* writer) = 0; - virtual void GenerateMergingCode(Writer* writer) = 0; - virtual void GenerateBuildingCode(Writer* writer) = 0; - virtual void GenerateParsingCode(Writer* writer) = 0; - virtual void GenerateSerializationCode(Writer* writer) = 0; - virtual void GenerateSerializedSizeCode(Writer* writer) = 0; - - virtual void WriteHash(Writer* writer) = 0; - virtual void WriteEquals(Writer* writer) = 0; - virtual void WriteToString(Writer* writer) = 0; + virtual void GenerateMembers(io::Printer* printer) = 0; + virtual void GenerateBuilderMembers(io::Printer* printer) = 0; + virtual void GenerateMergingCode(io::Printer* printer) = 0; + virtual void GenerateBuildingCode(io::Printer* printer) = 0; + virtual void GenerateParsingCode(io::Printer* printer) = 0; + virtual void GenerateSerializationCode(io::Printer* printer) = 0; + virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0; + + virtual void WriteHash(io::Printer* printer) = 0; + virtual void WriteEquals(io::Printer* printer) = 0; + virtual void WriteToString(io::Printer* printer) = 0; protected: const FieldDescriptor* descriptor_; const int fieldOrdinal_; + map variables_; - void AddDeprecatedFlag(Writer* writer); - void AddNullCheck(Writer* writer); - void AddNullCheck(Writer* writer, const std::string& name); + void AddDeprecatedFlag(io::Printer* printer); + void AddNullCheck(io::Printer* printer); + void AddNullCheck(io::Printer* printer, const std::string& name); - void AddPublicMemberAttributes(Writer* writer); + void AddPublicMemberAttributes(io::Printer* printer); + void SetCommonOneofFieldVariables(map* variables); std::string oneof_property_name(); std::string oneof_name(); @@ -85,6 +87,7 @@ class FieldGeneratorBase : public SourceGeneratorBase { std::string field_ordinal(); private: + void SetCommonFieldVariables(map* variables); std::string GetStringDefaultValueInternal(); std::string GetBytesDefaultValueInternal(); diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index 64c4bd7d..2a416fac 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -40,7 +40,6 @@ #include #include #include -#include using google::protobuf::internal::scoped_ptr; @@ -55,9 +54,9 @@ std::string GetOutputFile(const google::protobuf::FileDescriptor* file, const st } void GenerateFile(const google::protobuf::FileDescriptor* file, - Writer* writer) { + io::Printer* printer) { UmbrellaClassGenerator umbrellaGenerator(file); - umbrellaGenerator.Generate(writer); + umbrellaGenerator.Generate(printer); } bool Generator::Generate( @@ -83,9 +82,8 @@ bool Generator::Generate( scoped_ptr output( generator_context->Open(filename)); io::Printer printer(output.get(), '$'); - Writer writer(&printer); - GenerateFile(file, &writer); + GenerateFile(file, &printer); return true; } diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 22681235..66b87110 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -30,6 +30,7 @@ #include #include +#include #include #include @@ -46,7 +47,6 @@ #include #include #include -#include using google::protobuf::internal::scoped_ptr; @@ -105,7 +105,7 @@ std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) { return "static_" + result; } -void MessageGenerator::GenerateStaticVariables(Writer* writer) { +void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { // Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is // used in the construction of descriptors, we have a tricky bootstrapping // problem. To help control static initialization order, we make sure all @@ -117,175 +117,184 @@ void MessageGenerator::GenerateStaticVariables(Writer* writer) { if (!use_lite_runtime()) { // The descriptor for this type. - std::string access = "internal"; - writer->WriteLine( - "$0$ static pbd::MessageDescriptor internal__$1$__Descriptor;", access, - identifier); - writer->WriteLine( - "$0$ static pb::FieldAccess.FieldAccessorTable<$1$, $1$.Builder> internal__$2$__FieldAccessorTable;", - access, full_class_name(), identifier); + printer->Print( + "internal static pbd::MessageDescriptor internal__$identifier$__Descriptor;\n" + "internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder> internal__$identifier$__FieldAccessorTable;\n", + "identifier", GetUniqueFileScopeIdentifier(descriptor_), + "full_class_name", full_class_name()); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariables(writer); + messageGenerator.GenerateStaticVariables(printer); } } -void MessageGenerator::GenerateStaticVariableInitializers(Writer* writer) { - std::string identifier = GetUniqueFileScopeIdentifier(descriptor_); - +void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { + map vars; + vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); + vars["index"] = SimpleItoa(descriptor_->index()); + vars["full_class_name"] = full_class_name(); + if (descriptor_->containing_type() != NULL) { + vars["parent"] = GetUniqueFileScopeIdentifier( + descriptor_->containing_type()); + } if (!use_lite_runtime()) { - writer->Write("internal__$0$__Descriptor = ", identifier); + printer->Print(vars, "internal__$identifier$__Descriptor = "); if (!descriptor_->containing_type()) { - writer->WriteLine("Descriptor.MessageTypes[$0$];", - SimpleItoa(descriptor_->index())); + printer->Print(vars, "Descriptor.MessageTypes[$index$];\n"); } else { - writer->WriteLine( - "internal__$0$__Descriptor.NestedTypes[$1$];", - GetUniqueFileScopeIdentifier(descriptor_->containing_type()), - SimpleItoa(descriptor_->index())); + printer->Print(vars, "internal__$parent$__Descriptor.NestedTypes[$index$];\n"); } - writer->WriteLine("internal__$0$__FieldAccessorTable = ", identifier); - writer->WriteLine( - " new pb::FieldAccess.FieldAccessorTable<$1$, $1$.Builder>(internal__$0$__Descriptor,", - identifier, full_class_name()); - writer->Write(" new string[] { "); + printer->Print( + vars, + "internal__$identifier$__FieldAccessorTable = \n" + " new pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder>(internal__$identifier$__Descriptor,\n"); + printer->Print(" new string[] { "); for (int i = 0; i < descriptor_->field_count(); i++) { - writer->Write("\"$0$\", ", GetPropertyName(descriptor_->field(i))); + printer->Print("\"$property_name$\", ", + "property_name", GetPropertyName(descriptor_->field(i))); } for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - writer->Write("\"$0$\", ", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + printer->Print("\"$oneof_name$\", ", + "oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); } - writer->WriteLine("});"); + printer->Print("});\n"); } // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateStaticVariableInitializers(writer); + messageGenerator.GenerateStaticVariableInitializers(printer); } for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(writer); + extensionGenerator.GenerateStaticVariableInitializers(printer); } } -void MessageGenerator::Generate(Writer* writer) { - writer->WriteLine( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); - WriteGeneratedCodeAttributes(writer); - writer->WriteLine( - "$0$ sealed partial class $1$ : pb::$2$Message$3$<$1$, $1$.Builder> {", - class_access_level(), class_name(), - descriptor_->extension_range_count() > 0 ? "Extendable" : "Generated", - runtime_suffix()); - writer->Indent(); - writer->WriteLine("private $0$() { }", class_name()); // Private ctor. - // Must call MakeReadOnly() to make sure all lists are made read-only - writer->WriteLine( - "private static readonly $0$ defaultInstance = new $0$().MakeReadOnly();", - class_name()); +void MessageGenerator::Generate(io::Printer* printer) { + map vars; + vars["class_name"] = class_name(); + vars["access_level"] = class_access_level(); + vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? + "Extendable" : "Generated"; + vars["suffix"] = runtime_suffix(); + vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file()); + vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); + + printer->Print( + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + vars, + "$access_level$ sealed partial class $class_name$ : pb::$extendable_or_generated$Message$suffix$<$class_name$, $class_name$.Builder> {\n"); + printer->Indent(); + printer->Print( + vars, + "private $class_name$() { }\n" // Private ctor. + // Must call MakeReadOnly() to make sure all lists are made read-only + "private static readonly $class_name$ defaultInstance = new $class_name$().MakeReadOnly();\n"); if (optimize_speed()) { - writer->WriteLine( - "private static readonly string[] _$0$FieldNames = new string[] { $2$$1$$2$ };", - UnderscoresToCamelCase(class_name(), false), - JoinStrings(field_names(), "\", \""), - field_names().size() > 0 ? "\"" : ""); + printer->Print( + "private static readonly string[] _$name$FieldNames = " + "new string[] { $slash$$field_names$$slash$ };\n", + "name", UnderscoresToCamelCase(class_name(), false), + "field_names", JoinStrings(field_names(), "\", \""), + "slash", field_names().size() > 0 ? "\"" : ""); std::vector tags; for (int i = 0; i < field_names().size(); i++) { uint32 tag = internal::WireFormat::MakeTag( descriptor_->FindFieldByName(field_names()[i])); tags.push_back(SimpleItoa(tag)); } - writer->WriteLine( - "private static readonly uint[] _$0$FieldTags = new uint[] { $1$ };", - UnderscoresToCamelCase(class_name(), false), JoinStrings(tags, ", ")); - } - writer->WriteLine("public static $0$ DefaultInstance {", class_name()); - writer->WriteLine(" get { return defaultInstance; }"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("public override $0$ DefaultInstanceForType {", - class_name()); - writer->WriteLine(" get { return DefaultInstance; }"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("protected override $0$ ThisMessage {", class_name()); - writer->WriteLine(" get { return this; }"); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + "private static readonly uint[] _$name$FieldTags = new uint[] { $tags$ };\n", + "name", UnderscoresToCamelCase(class_name(), false), + "tags", JoinStrings(tags, ", ")); + } + printer->Print( + vars, + "public static $class_name$ DefaultInstance {\n" + " get { return defaultInstance; }\n" + "}\n" + "\n" + "public override $class_name$ DefaultInstanceForType {\n" + " get { return DefaultInstance; }\n" + "}\n" + "\n" + "protected override $class_name$ ThisMessage {\n" + " get { return this; }\n" + "}\n\n"); + if (!use_lite_runtime()) { - writer->WriteLine("public static pbd::MessageDescriptor Descriptor {"); - writer->WriteLine(" get { return $0$.internal__$1$__Descriptor; }", - GetFullUmbrellaClassName(descriptor_->file()), - GetUniqueFileScopeIdentifier(descriptor_)); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine( - "protected override pb::FieldAccess.FieldAccessorTable<$0$, $0$.Builder> InternalFieldAccessors {", - class_name()); - writer->WriteLine(" get { return $0$.internal__$1$__FieldAccessorTable; }", - GetFullUmbrellaClassName(descriptor_->file()), - GetUniqueFileScopeIdentifier(descriptor_)); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + vars, + "public static pbd::MessageDescriptor Descriptor {\n" + " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n" + "}\n" + "\n" + "protected override pb::FieldAccess.FieldAccessorTable<$class_name$, $class_name$.Builder> InternalFieldAccessors {\n" + " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" + "}\n" + "\n"); } // Extensions don't need to go in an extra nested type for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.Generate(writer); + extensionGenerator.Generate(printer); } if (descriptor_->enum_type_count() + descriptor_->nested_type_count() > 0) { - writer->WriteLine("#region Nested types"); - writer->WriteLine( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); - WriteGeneratedCodeAttributes(writer); - writer->WriteLine("public static partial class Types {"); - writer->Indent(); + printer->Print("#region Nested types\n" + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("public static partial class Types {\n"); + printer->Indent(); for (int i = 0; i < descriptor_->enum_type_count(); i++) { EnumGenerator enumGenerator(descriptor_->enum_type(i)); - enumGenerator.Generate(writer); + enumGenerator.Generate(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.Generate(writer); + messageGenerator.Generate(printer); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n" + "#endregion\n" + "\n"); } // oneof for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - writer->WriteLine("private object $0$_;", name); - writer->WriteLine("public enum $0$OneofCase {", property_name); - writer->Indent(); + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print( + vars, + "private object $name$_;\n" + "public enum $property_name$OneofCase {\n"); + printer->Indent(); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - writer->WriteLine("$0$ = $1$,", - GetPropertyName(field), - SimpleItoa(field->number())); + printer->Print("$field_property_name$ = $index$,\n", + "field_property_name", GetPropertyName(field), + "index", SimpleItoa(field->number())); } - writer->WriteLine("None = 0,"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("private $0$OneofCase $1$Case_ = $0$OneofCase.None;", - property_name, name); - writer->WriteLine("public $0$OneofCase $0$Case {", property_name); - writer->WriteLine(" get { return $0$Case_; }", name); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print("None = 0,\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print( + vars, + "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n" + "public $property_name$OneofCase $property_name$Case {\n" + " get { return $name$Case_; }\n" + "}\n\n"); } // Fields @@ -293,108 +302,119 @@ void MessageGenerator::Generate(Writer* writer) { const FieldDescriptor* fieldDescriptor = descriptor_->field(i); // Rats: we lose the debug comment here :( - writer->WriteLine("public const int $0$ = $1$;", - GetFieldConstantName(fieldDescriptor), - SimpleItoa(fieldDescriptor->number())); + printer->Print( + "public const int $field_constant_name$ = $index$;\n", + "field_constant_name", GetFieldConstantName(fieldDescriptor), + "index", SimpleItoa(fieldDescriptor->number())); scoped_ptr generator( CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateMembers(writer); - writer->WriteLine(); + generator->GenerateMembers(printer); + printer->Print("\n"); } if (optimize_speed()) { if (SupportFieldPresence(descriptor_->file())) { - GenerateIsInitialized(writer); + GenerateIsInitialized(printer); } - GenerateMessageSerializationMethods(writer); + GenerateMessageSerializationMethods(printer); } if (use_lite_runtime()) { - GenerateLiteRuntimeMethods(writer); + GenerateLiteRuntimeMethods(printer); } - GenerateParseFromMethods(writer); - GenerateBuilder(writer); + GenerateParseFromMethods(printer); + GenerateBuilder(printer); // Force the static initialization code for the file to run, since it may // initialize static variables declared in this class. - writer->WriteLine("static $0$() {", class_name()); + printer->Print(vars, "static $class_name$() {\n"); // We call object.ReferenceEquals() just to make it a valid statement on its own. // Another option would be GetType(), but that causes problems in DescriptorProtoFile, // where the bootstrapping is somewhat recursive - type initializers call // each other, effectively. We temporarily see Descriptor as null. - writer->WriteLine(" object.ReferenceEquals($0$.Descriptor, null);", - GetFullUmbrellaClassName(descriptor_->file())); - writer->WriteLine("}"); + printer->Print( + vars, + " object.ReferenceEquals($umbrella_class_name$.Descriptor, null);\n" + "}\n"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); } -void MessageGenerator::GenerateLiteRuntimeMethods(Writer* writer) { +void MessageGenerator::GenerateLiteRuntimeMethods(io::Printer* printer) { + map vars; + vars["class_name"] = class_name(); + bool callbase = descriptor_->extension_range_count() > 0; - writer->WriteLine("#region Lite runtime methods"); - writer->WriteLine("public override int GetHashCode() {"); - writer->Indent(); - writer->WriteLine("int hash = GetType().GetHashCode();"); + printer->Print("#region Lite runtime methods\n" + "public override int GetHashCode() {\n"); + printer->Indent(); + printer->Print("int hash = GetType().GetHashCode();\n"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); if (field->containing_oneof() == NULL) { scoped_ptr generator( CreateFieldGeneratorInternal(field)); - generator->WriteHash(writer); + generator->WriteHash(printer); } } for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - writer->WriteLine("if ($0$Case_ != $1$OneofCase.None) {", name, property_name); - writer->WriteLine(" hash ^= $0$_.GetHashCode();", name); - writer->WriteLine("}"); + printer->Print( + "if ($name$Case_ != $property_name$OneofCase.None) {\n" + " hash ^= $name$_.GetHashCode();\n" + "}\n", + "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), + "property_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); } if (callbase) { - writer->WriteLine("hash ^= base.GetHashCode();"); - } - writer->WriteLine("return hash;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); - - writer->WriteLine("public override bool Equals(object obj) {"); - writer->Indent(); - writer->WriteLine("$0$ other = obj as $0$;", class_name()); - writer->WriteLine("if (other == null) return false;"); + printer->Print("hash ^= base.GetHashCode();\n"); + } + printer->Print("return hash;\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); + + printer->Print("public override bool Equals(object obj) {\n"); + printer->Indent(); + printer->Print( + vars, + "$class_name$ other = obj as $class_name$;\n" + "if (other == null) return false;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->WriteEquals(writer); + generator->WriteEquals(printer); } if (callbase) { - writer->WriteLine("if (!base.Equals(other)) return false;"); + printer->Print("if (!base.Equals(other)) return false;\n"); } - writer->WriteLine("return true;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print("return true;\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); - writer->WriteLine( - "public override void PrintTo(global::System.IO.TextWriter writer) {"); - writer->Indent(); + printer->Print( + "public override void PrintTo(global::System.IO.TextWriter writer) {\n"); + printer->Indent(); for (int i = 0; i < fields_by_number().size(); i++) { scoped_ptr generator( CreateFieldGeneratorInternal(fields_by_number()[i])); - generator->WriteToString(writer); + generator->WriteToString(printer); } if (callbase) { - writer->WriteLine("base.PrintTo(writer);"); + printer->Print("base.PrintTo(writer);\n"); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("#endregion\n"); + printer->Print("\n"); } bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1, @@ -402,7 +422,7 @@ bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1, return r1->start < r2->start; } -void MessageGenerator::GenerateMessageSerializationMethods(Writer* writer) { +void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { std::vector extension_ranges_sorted; for (int i = 0; i < descriptor_->extension_range_count(); i++) { extension_ranges_sorted.push_back(descriptor_->extension_range(i)); @@ -410,439 +430,442 @@ void MessageGenerator::GenerateMessageSerializationMethods(Writer* writer) { std::sort(extension_ranges_sorted.begin(), extension_ranges_sorted.end(), CompareExtensionRangesStart); - writer->WriteLine( - "public override void WriteTo(pb::ICodedOutputStream output) {"); - writer->Indent(); + printer->Print( + "public override void WriteTo(pb::ICodedOutputStream output) {\n"); + printer->Indent(); // Make sure we've computed the serialized length, so that packed fields are generated correctly. - writer->WriteLine("CalcSerializedSize();"); - writer->WriteLine("string[] field_names = _$0$FieldNames;", - UnderscoresToCamelCase(class_name(), false)); + printer->Print("CalcSerializedSize();\n" + "string[] field_names = _$class_name$FieldNames;\n", + "class_name", UnderscoresToCamelCase(class_name(), false)); if (descriptor_->extension_range_count()) { - writer->WriteLine( - "pb::ExtendableMessage$1$<$0$, $0$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);", - class_name(), runtime_suffix()); + printer->Print( + "pb::ExtendableMessage$runtime_suffix$<$class_name$, $class_name$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);\n", + "class_name", class_name(), + "runtime_suffix", runtime_suffix()); } // Merge the fields and the extension ranges, both sorted by field number. for (int i = 0, j = 0; i < fields_by_number().size() || j < extension_ranges_sorted.size();) { if (i == fields_by_number().size()) { - GenerateSerializeOneExtensionRange(writer, extension_ranges_sorted[j++]); + GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); } else if (j == extension_ranges_sorted.size()) { - GenerateSerializeOneField(writer, fields_by_number()[i++]); + GenerateSerializeOneField(printer, fields_by_number()[i++]); } else if (fields_by_number()[i]->number() < extension_ranges_sorted[j]->start) { - GenerateSerializeOneField(writer, fields_by_number()[i++]); + GenerateSerializeOneField(printer, fields_by_number()[i++]); } else { - GenerateSerializeOneExtensionRange(writer, extension_ranges_sorted[j++]); + GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); } } if (!use_lite_runtime()) { if (descriptor_->options().message_set_wire_format()) { - writer->WriteLine("UnknownFields.WriteAsMessageSetTo(output);"); + printer->Print("UnknownFields.WriteAsMessageSetTo(output);\n"); } else { - writer->WriteLine("UnknownFields.WriteTo(output);"); + printer->Print("UnknownFields.WriteTo(output);\n"); } } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("private int memoizedSerializedSize = -1;"); - writer->WriteLine("public override int SerializedSize {"); - writer->Indent(); - writer->WriteLine("get {"); - writer->Indent(); - writer->WriteLine("int size = memoizedSerializedSize;"); - writer->WriteLine("if (size != -1) return size;"); - writer->WriteLine("return CalcSerializedSize();"); - writer->Outdent(); - writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); - - writer->WriteLine("private int CalcSerializedSize() {"); - writer->Indent(); - writer->WriteLine("int size = memoizedSerializedSize;"); - writer->WriteLine("if (size != -1) return size;"); - writer->WriteLine(); - writer->WriteLine("size = 0;"); + printer->Outdent(); + printer->Print( + "}\n" + "\n" + "private int memoizedSerializedSize = -1;\n" + "public override int SerializedSize {\n"); + printer->Indent(); + printer->Print("get {\n"); + printer->Indent(); + printer->Print( + "int size = memoizedSerializedSize;\n" + "if (size != -1) return size;\n" + "return CalcSerializedSize();\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); + + printer->Print("private int CalcSerializedSize() {\n"); + printer->Indent(); + printer->Print( + "int size = memoizedSerializedSize;\n" + "if (size != -1) return size;\n" + "\n" + "size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateSerializedSizeCode(writer); + generator->GenerateSerializedSizeCode(printer); } if (descriptor_->extension_range_count() > 0) { - writer->WriteLine("size += ExtensionsSerializedSize;"); + printer->Print("size += ExtensionsSerializedSize;\n"); } if (!use_lite_runtime()) { if (descriptor_->options().message_set_wire_format()) { - writer->WriteLine("size += UnknownFields.SerializedSizeAsMessageSet;"); + printer->Print("size += UnknownFields.SerializedSizeAsMessageSet;\n"); } else { - writer->WriteLine("size += UnknownFields.SerializedSize;"); + printer->Print("size += UnknownFields.SerializedSize;\n"); } } - writer->WriteLine("memoizedSerializedSize = size;"); - writer->WriteLine("return size;"); - writer->Outdent(); - writer->WriteLine("}"); + printer->Print( + "memoizedSerializedSize = size;\n" + "return size;\n"); + printer->Outdent(); + printer->Print("}\n"); } void MessageGenerator::GenerateSerializeOneField( - Writer* writer, const FieldDescriptor* fieldDescriptor) { + io::Printer* printer, const FieldDescriptor* fieldDescriptor) { scoped_ptr generator( CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateSerializationCode(writer); + generator->GenerateSerializationCode(printer); } void MessageGenerator::GenerateSerializeOneExtensionRange( - Writer* writer, const Descriptor::ExtensionRange* extensionRange) { - writer->WriteLine("extensionWriter.WriteUntil($0$, output);", - SimpleItoa(extensionRange->end)); + io::Printer* printer, const Descriptor::ExtensionRange* extensionRange) { + printer->Print("extensionWriter.WriteUntil($range_end$, output);\n", + "range_end", SimpleItoa(extensionRange->end)); } -void MessageGenerator::GenerateParseFromMethods(Writer* writer) { +void MessageGenerator::GenerateParseFromMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized // for code size. - - writer->WriteLine("public static $0$ ParseFrom(pb::ByteString data) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine("public static $0$ ParseFrom(byte[] data) {", class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(global::System.IO.Stream input) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseDelimitedFrom(global::System.IO.Stream input) {", - class_name()); - writer->WriteLine( - " return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(pb::ICodedInputStream input) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();"); - writer->WriteLine("}"); - writer->WriteLine( - "public static $0$ ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {", - class_name()); - writer->WriteLine( - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();"); - writer->WriteLine("}"); + map vars; + vars["class_name"] = class_name(); + + printer->Print( + vars, + "public static $class_name$ ParseFrom(pb::ByteString data) {\n" + " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {\n" + " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(byte[] data) {\n" + " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {\n" + " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(global::System.IO.Stream input) {\n" + " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" + " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input) {\n" + " return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" + " return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(pb::ICodedInputStream input) {\n" + " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" + "}\n" + "public static $class_name$ ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n" + " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" + "}\n"); } -void MessageGenerator::GenerateBuilder(Writer* writer) { - writer->WriteLine("private $0$ MakeReadOnly() {", class_name()); - writer->Indent(); +void MessageGenerator::GenerateBuilder(io::Printer* printer) { + map vars; + vars["class_name"] = class_name(); + vars["access_level"] = class_access_level(); + vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? + "Extendable" : "Generated"; + vars["suffix"] = runtime_suffix(); + + printer->Print(vars, "private $class_name$ MakeReadOnly() {\n"); + printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateBuildingCode(writer); - } - writer->WriteLine("return this;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); - - writer->WriteLine( - "public static Builder CreateBuilder() { return new Builder(); }"); - writer->WriteLine( - "public override Builder ToBuilder() { return CreateBuilder(this); }"); - writer->WriteLine( - "public override Builder CreateBuilderForType() { return new Builder(); }"); - writer->WriteLine("public static Builder CreateBuilder($0$ prototype) {", - class_name()); - writer->WriteLine(" return new Builder(prototype);"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); - WriteGeneratedCodeAttributes(writer); - writer->WriteLine( - "$0$ sealed partial class Builder : pb::$2$Builder$3$<$1$, Builder> {", - class_access_level(), class_name(), - descriptor_->extension_range_count() > 0 ? "Extendable" : "Generated", - runtime_suffix()); - writer->Indent(); - writer->WriteLine("protected override Builder ThisBuilder {"); - writer->WriteLine(" get { return this; }"); - writer->WriteLine("}"); - GenerateCommonBuilderMethods(writer); + generator->GenerateBuildingCode(printer); + } + printer->Print("return this;\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + printer->Print( + vars, + "public static Builder CreateBuilder() { return new Builder(); }\n" + "public override Builder ToBuilder() { return CreateBuilder(this); }\n" + "public override Builder CreateBuilderForType() { return new Builder(); }\n" + "public static Builder CreateBuilder($class_name$ prototype) {\n" + " return new Builder(prototype);\n" + "}\n" + "\n" + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + vars, + "$access_level$ sealed partial class Builder : pb::$extendable_or_generated$Builder$suffix$<$class_name$, Builder> {\n"); + printer->Indent(); + printer->Print( + "protected override Builder ThisBuilder {\n" + " get { return this; }\n" + "}\n"); + GenerateCommonBuilderMethods(printer); if (optimize_speed()) { - GenerateBuilderParsingMethods(writer); + GenerateBuilderParsingMethods(printer); } for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - writer->WriteLine(); + printer->Print("\n"); // No field comment :( - generator->GenerateBuilderMembers(writer); + generator->GenerateBuilderMembers(printer); } // oneof for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - writer->WriteLine(); + printer->Print("\n"); string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - writer->WriteLine("public $0$OneofCase $0$Case {", property_name); - writer->WriteLine(" get { return result.$0$Case_; }", name); - writer->WriteLine("}"); - writer->WriteLine("public Builder Clear$0$() {", property_name); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_ = null;", name); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", name, property_name); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - } - - writer->Outdent(); - writer->WriteLine("}"); + printer->Print( + "public $property_name$OneofCase $property_name$Case {\n" + " get { return result.$name$Case_; }\n" + "}\n" + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.$name$_ = null;\n" + " result.$name$Case_ = $property_name$OneofCase.None;\n" + " return this;\n" + "}\n", + "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), + "property_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + } + + printer->Outdent(); + printer->Print("}\n"); } -void MessageGenerator::GenerateCommonBuilderMethods(Writer* writer) { - //default constructor - writer->WriteLine("public Builder() {"); - //Durring static initialization of message, DefaultInstance is expected to return null. - writer->WriteLine(" result = DefaultInstance;"); - writer->WriteLine(" resultIsReadOnly = true;"); - writer->WriteLine("}"); - //clone constructor - writer->WriteLine("internal Builder($0$ cloneFrom) {", class_name()); - writer->WriteLine(" result = cloneFrom;"); - writer->WriteLine(" resultIsReadOnly = true;"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("private bool resultIsReadOnly;"); - writer->WriteLine("private $0$ result;", class_name()); - writer->WriteLine(); - writer->WriteLine("private $0$ PrepareBuilder() {", class_name()); - writer->WriteLine(" if (resultIsReadOnly) {"); - writer->WriteLine(" $0$ original = result;", class_name()); - writer->WriteLine(" result = new $0$();", class_name()); - writer->WriteLine(" resultIsReadOnly = false;"); - writer->WriteLine(" MergeFrom(original);"); - writer->WriteLine(" }"); - writer->WriteLine(" return result;"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("public override bool IsInitialized {"); - writer->WriteLine(" get { return result.IsInitialized; }"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("protected override $0$ MessageBeingBuilt {", class_name()); - writer->WriteLine(" get { return PrepareBuilder(); }"); - writer->WriteLine("}"); - writer->WriteLine(); +void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { + map vars; + vars["class_name"] = class_name(); + vars["full_class_name"] = full_class_name(); + vars["suffix"] = runtime_suffix(); + + printer->Print( + vars, + //default constructor + "public Builder() {\n" + //Durring static initialization of message, DefaultInstance is expected to return null. + " result = DefaultInstance;\n" + " resultIsReadOnly = true;\n" + "}\n" + //clone constructor + "internal Builder($class_name$ cloneFrom) {\n" + " result = cloneFrom;\n" + " resultIsReadOnly = true;\n" + "}\n" + "\n" + "private bool resultIsReadOnly;\n" + "private $class_name$ result;\n" + "\n" + "private $class_name$ PrepareBuilder() {\n" + " if (resultIsReadOnly) {\n" + " $class_name$ original = result;\n" + " result = new $class_name$();\n" + " resultIsReadOnly = false;\n" + " MergeFrom(original);\n" + " }\n" + " return result;\n" + "}\n" + "\n" + "public override bool IsInitialized {\n" + " get { return result.IsInitialized; }\n" + "}\n" + "\n" + "protected override $class_name$ MessageBeingBuilt {\n" + " get { return PrepareBuilder(); }\n" + "}\n" + "\n"); //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break - writer->WriteLine("public override Builder Clear() {"); - writer->WriteLine(" result = DefaultInstance;"); - writer->WriteLine(" resultIsReadOnly = true;"); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("public override Builder Clone() {"); - writer->WriteLine(" if (resultIsReadOnly) {"); - writer->WriteLine(" return new Builder(result);"); - writer->WriteLine(" } else {"); - writer->WriteLine(" return new Builder().MergeFrom(result);"); - writer->WriteLine(" }"); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + "public override Builder Clear() {\n" + " result = DefaultInstance;\n" + " resultIsReadOnly = true;\n" + " return this;\n" + "}\n" + "\n" + "public override Builder Clone() {\n" + " if (resultIsReadOnly) {\n" + " return new Builder(result);\n" + " } else {\n" + " return new Builder().MergeFrom(result);\n" + " }\n" + "}\n" + "\n"); if (!use_lite_runtime()) { - writer->WriteLine( - "public override pbd::MessageDescriptor DescriptorForType {"); - writer->WriteLine(" get { return $0$.Descriptor; }", full_class_name()); - writer->WriteLine("}"); - writer->WriteLine(); - } - writer->WriteLine("public override $0$ DefaultInstanceForType {", - class_name()); - writer->WriteLine(" get { return $0$.DefaultInstance; }", full_class_name()); - writer->WriteLine("}"); - writer->WriteLine(); - - writer->WriteLine("public override $0$ BuildPartial() {", class_name()); - writer->Indent(); - writer->WriteLine("if (resultIsReadOnly) {"); - writer->WriteLine(" return result;"); - writer->WriteLine("}"); - writer->WriteLine("resultIsReadOnly = true;"); - writer->WriteLine("return result.MakeReadOnly();"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + vars, + "public override pbd::MessageDescriptor DescriptorForType {\n" + " get { return $full_class_name$.Descriptor; }\n" + "}\n\n"); + } + printer->Print( + vars, + "public override $class_name$ DefaultInstanceForType {\n" + " get { return $full_class_name$.DefaultInstance; }\n" + "}\n\n"); + + printer->Print( + vars, + "public override $class_name$ BuildPartial() {\n" + " if (resultIsReadOnly) {\n" + " return result;\n" + " }\n" + " resultIsReadOnly = true;\n" + " return result.MakeReadOnly();\n" + "}\n\n"); if (optimize_speed()) { - writer->WriteLine( - "public override Builder MergeFrom(pb::IMessage$0$ other) {", - runtime_suffix()); - writer->WriteLine(" if (other is $0$) {", class_name()); - writer->WriteLine(" return MergeFrom(($0$) other);", class_name()); - writer->WriteLine(" } else {"); - writer->WriteLine(" base.MergeFrom(other);"); - writer->WriteLine(" return this;"); - writer->WriteLine(" }"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine("public override Builder MergeFrom($0$ other) {", - class_name()); + printer->Print( + vars, + "public override Builder MergeFrom(pb::IMessage$suffix$ other) {\n" + " if (other is $class_name$) {\n" + " return MergeFrom(($class_name$) other);\n" + " } else {\n" + " base.MergeFrom(other);\n" + " return this;\n" + " }\n" + "}\n\n"); + + printer->Print(vars,"public override Builder MergeFrom($class_name$ other) {\n"); // Optimization: If other is the default instance, we know none of its // fields are set so we can skip the merge. - writer->Indent(); - writer->WriteLine("if (other == $0$.DefaultInstance) return this;", - full_class_name()); - writer->WriteLine("PrepareBuilder();"); + printer->Indent(); + printer->Print( + vars, + "if (other == $full_class_name$.DefaultInstance) return this;\n" + "PrepareBuilder();\n"); for (int i = 0; i < descriptor_->field_count(); i++) { if (!descriptor_->field(i)->containing_oneof()) { scoped_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateMergingCode(writer); + generator->GenerateMergingCode(printer); } } // Merge oneof fields for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - writer->WriteLine("switch (other.$0$Case) {", property_name); - writer->Indent(); + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print(vars, "switch (other.$property_name$Case) {\n"); + printer->Indent(); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - writer->WriteLine("case $0$OneofCase.$1$: {", - property_name, GetPropertyName(field)); + vars["field_property_name"] = GetPropertyName(field); + printer->Print( + vars, + "case $property_name$OneofCase.$field_property_name$: {\n"); if (field->type() == FieldDescriptor::TYPE_GROUP || field->type() == FieldDescriptor::TYPE_MESSAGE) { - writer->WriteLine(" Merge$0$(other.$0$);", GetPropertyName(field)); + printer->Print( + vars, + " Merge$field_property_name$(other.$field_property_name$);\n"); } else { - writer->WriteLine(" Set$0$(other.$0$);", GetPropertyName(field)); + printer->Print( + vars, + " Set$field_property_name$(other.$field_property_name$);\n"); } - writer->WriteLine(" break;"); - writer->WriteLine("}"); + printer->Print(" break;\n"); + printer->Print("}\n"); } - writer->WriteLine("case $0$OneofCase.None: { break; }", property_name); - writer->Outdent(); - writer->WriteLine("}"); + printer->Print(vars, "case $property_name$OneofCase.None: { break; }\n"); + printer->Outdent(); + printer->Print("}\n"); } // if message type has extensions if (descriptor_->extension_range_count() > 0) { - writer->WriteLine(" this.MergeExtensionFields(other);"); + printer->Print(" this.MergeExtensionFields(other);\n"); } if (!use_lite_runtime()) { - writer->WriteLine("this.MergeUnknownFields(other.UnknownFields);"); + printer->Print("this.MergeUnknownFields(other.UnknownFields);\n"); } - writer->WriteLine("return this;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print("return this;\n"); + printer->Outdent(); + printer->Print("}\n\n"); } } -void MessageGenerator::GenerateBuilderParsingMethods(Writer* writer) { - writer->WriteLine( - "public override Builder MergeFrom(pb::ICodedInputStream input) {"); - writer->WriteLine(" return MergeFrom(input, pb::ExtensionRegistry.Empty);"); - writer->WriteLine("}"); - writer->WriteLine(); - writer->WriteLine( - "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {"); - writer->Indent(); - writer->WriteLine("PrepareBuilder();"); +void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { + printer->Print( + "public override Builder MergeFrom(pb::ICodedInputStream input) {\n" + " return MergeFrom(input, pb::ExtensionRegistry.Empty);\n" + "}\n\n"); + + printer->Print( + "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n"); + printer->Indent(); + printer->Print("PrepareBuilder();\n"); if (!use_lite_runtime()) { - writer->WriteLine("pb::UnknownFieldSet.Builder unknownFields = null;"); - } - writer->WriteLine("uint tag;"); - writer->WriteLine("string field_name;"); - writer->WriteLine("while (input.ReadTag(out tag, out field_name)) {"); - writer->Indent(); - writer->WriteLine("if(tag == 0 && field_name != null) {"); - writer->Indent(); + printer->Print("pb::UnknownFieldSet.Builder unknownFields = null;\n"); + } + printer->Print( + "uint tag;\n" + "string field_name;\n" + "while (input.ReadTag(out tag, out field_name)) {\n"); + printer->Indent(); + printer->Print("if(tag == 0 && field_name != null) {\n"); + printer->Indent(); //if you change from StringComparer.Ordinal, the array sort in FieldNames { get; } must also change - writer->WriteLine( - "int field_ordinal = global::System.Array.BinarySearch(_$0$FieldNames, field_name, global::System.StringComparer.Ordinal);", - UnderscoresToCamelCase(class_name(), false)); - writer->WriteLine("if(field_ordinal >= 0)"); - writer->WriteLine(" tag = _$0$FieldTags[field_ordinal];", - UnderscoresToCamelCase(class_name(), false)); - writer->WriteLine("else {"); + printer->Print( + "int field_ordinal = global::System.Array.BinarySearch(_$camel_class_name$FieldNames, field_name, global::System.StringComparer.Ordinal);\n" + "if(field_ordinal >= 0)\n" + " tag = _$camel_class_name$FieldTags[field_ordinal];\n" + "else {\n", + "camel_class_name", UnderscoresToCamelCase(class_name(), false)); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); - } - writer->WriteLine( - " ParseUnknownField(input, $0$extensionRegistry, tag, field_name);", - use_lite_runtime() ? "" : "unknownFields, "); - writer->WriteLine(" continue;"); - writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - - writer->WriteLine("switch (tag) {"); - writer->Indent(); - writer->WriteLine("case 0: {"); // 0 signals EOF / limit reached - writer->WriteLine(" throw pb::InvalidProtocolBufferException.InvalidTag();"); - writer->WriteLine("}"); - writer->WriteLine("default: {"); - writer->WriteLine(" if (pb::WireFormat.IsEndGroupTag(tag)) {"); + printer->Print( + " if (unknownFields == null) {\n" // First unknown field - create builder now + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n"); + } + printer->Print( + " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", + "prefix", use_lite_runtime() ? "" : "unknownFields, "); + printer->Print(" continue;\n"); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); + + printer->Print("switch (tag) {\n"); + printer->Indent(); + printer->Print( + "case 0: {\n" // 0 signals EOF / limit reached + " throw pb::InvalidProtocolBufferException.InvalidTag();\n" + "}\n" + "default: {\n" + " if (pb::WireFormat.IsEndGroupTag(tag)) {\n"); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields != null) {"); - writer->WriteLine(" this.UnknownFields = unknownFields.Build();"); - writer->WriteLine(" }"); - } - writer->WriteLine(" return this;"); // it's an endgroup tag - writer->WriteLine(" }"); + printer->Print( + " if (unknownFields != null) {\n" + " this.UnknownFields = unknownFields.Build();\n" + " }\n"); + } + printer->Print( + " return this;\n" // it's an endgroup tag + " }\n"); if (!use_lite_runtime()) { - writer->WriteLine(" if (unknownFields == null) {"); // First unknown field - create builder now - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); + printer->Print( + " if (unknownFields == null) {\n" // First unknown field - create builder now + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n"); } - writer->WriteLine( - " ParseUnknownField(input, $0$extensionRegistry, tag, field_name);", - use_lite_runtime() ? "" : "unknownFields, "); - writer->WriteLine(" break;"); - writer->WriteLine("}"); + printer->Print( + " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", + "prefix", use_lite_runtime() ? "" : "unknownFields, "); + printer->Print(" break;\n"); + printer->Print("}\n"); for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; @@ -853,53 +876,54 @@ void MessageGenerator::GenerateBuilderParsingMethods(Writer* writer) { && (wt == internal::WireFormatLite::WIRETYPE_VARINT || wt == internal::WireFormatLite::WIRETYPE_FIXED32 || wt == internal::WireFormatLite::WIRETYPE_FIXED64)) { - writer->WriteLine( - "case $0$:", - SimpleItoa( - internal::WireFormatLite::MakeTag( - field->number(), - internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); + printer->Print( + "case $number$:\n", + "number", + SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED))); } - writer->WriteLine("case $0$: {", SimpleItoa(tag)); - writer->Indent(); + printer->Print("case $tag$: {\n", "tag", SimpleItoa(tag)); + printer->Indent(); scoped_ptr generator( CreateFieldGeneratorInternal(field)); - generator->GenerateParsingCode(writer); - writer->WriteLine("break;"); - writer->Outdent(); - writer->WriteLine("}"); + generator->GenerateParsingCode(printer); + printer->Print("break;\n"); + printer->Outdent(); + printer->Print("}\n"); } - writer->Outdent(); - writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); if (!use_lite_runtime()) { - writer->WriteLine("if (unknownFields != null) {"); - writer->WriteLine(" this.UnknownFields = unknownFields.Build();"); - writer->WriteLine("}"); - } - writer->WriteLine("return this;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print( + "if (unknownFields != null) {\n" + " this.UnknownFields = unknownFields.Build();\n" + "}\n"); + } + printer->Print("return this;\n"); + printer->Outdent(); + printer->Print("}\n\n"); } -void MessageGenerator::GenerateIsInitialized(Writer* writer) { - writer->WriteLine("public override bool IsInitialized {"); - writer->Indent(); - writer->WriteLine("get {"); - writer->Indent(); +void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { + printer->Print("public override bool IsInitialized {\n"); + printer->Indent(); + printer->Print("get {\n"); + printer->Indent(); // Check that all required fields in this message are set. // TODO(kenton): We can optimize this when we switch to putting all the // "has" fields into a single bitfield. for (int i = 0; i < descriptor_->field_count(); i++) { if (descriptor_->field(i)->is_required()) { - writer->WriteLine("if (!has$0$) return false;", - GetPropertyName(descriptor_->field(i))); + printer->Print("if (!has$property_name$) return false;\n", + "property_name", GetPropertyName(descriptor_->field(i))); } } @@ -916,43 +940,48 @@ void MessageGenerator::GenerateIsInitialized(Writer* writer) { string propertyName = UnderscoresToPascalCase(GetFieldName(field)); if (field->is_repeated()) { - writer->WriteLine("foreach ($0$ element in $1$List) {", - GetClassName(field->message_type()), - propertyName); - writer->WriteLine(" if (!element.IsInitialized) return false;"); - writer->WriteLine("}"); + printer->Print( + "foreach ($class_name$ element in $property_name$List) {\n" + " if (!element.IsInitialized) return false;\n" + "}\n", + "class_name", GetClassName(field->message_type()), + "property_name", propertyName); } else if (field->is_optional()) { - writer->WriteLine("if (Has$0$) {", propertyName); - writer->WriteLine(" if (!$0$.IsInitialized) return false;", propertyName); - writer->WriteLine("}"); + printer->Print( + "if (Has$property_name$) {\n" + " if (!$property_name$.IsInitialized) return false;\n" + "}\n", + "property_name", propertyName); } else { - writer->WriteLine("if (!$0$.IsInitialized) return false;", propertyName); + printer->Print( + "if (!$property_name$.IsInitialized) return false;\n", + "property_name", propertyName); } } if (descriptor_->extension_range_count() > 0) { - writer->WriteLine("if (!ExtensionsAreInitialized) return false;"); - } - writer->WriteLine("return true;"); - writer->Outdent(); - writer->WriteLine("}"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine(); + printer->Print("if (!ExtensionsAreInitialized) return false;\n"); + } + printer->Print("return true;\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("\n"); } -void MessageGenerator::GenerateExtensionRegistrationCode(Writer* writer) { +void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { for (int i = 0; i < descriptor_->extension_count(); i++) { ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(writer); + extensionGenerator.GenerateExtensionRegistrationCode(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(writer); + messageGenerator.GenerateExtensionRegistrationCode(printer); } } diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index b8d15df0..ebe58618 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -51,27 +51,27 @@ class MessageGenerator : public SourceGeneratorBase { MessageGenerator(const Descriptor* descriptor); ~MessageGenerator(); - void GenerateStaticVariables(Writer* printer); - void GenerateStaticVariableInitializers(Writer* printer); - void GenerateExtensionRegistrationCode(Writer* printer); - void Generate(Writer* printer); + void GenerateStaticVariables(io::Printer* printer); + void GenerateStaticVariableInitializers(io::Printer* printer); + void GenerateExtensionRegistrationCode(io::Printer* printer); + void Generate(io::Printer* printer); private: const Descriptor* descriptor_; std::vector field_names_; std::vector fields_by_number_; - void GenerateLiteRuntimeMethods(Writer* writer); - void GenerateMessageSerializationMethods(Writer* writer); - void GenerateSerializeOneField(Writer* writer, + void GenerateLiteRuntimeMethods(io::Printer* printer); + void GenerateMessageSerializationMethods(io::Printer* printer); + void GenerateSerializeOneField(io::Printer* printer, const FieldDescriptor* fieldDescriptor); void GenerateSerializeOneExtensionRange( - Writer* writer, const Descriptor::ExtensionRange* extendsionRange); - void GenerateParseFromMethods(Writer* writer); - void GenerateBuilder(Writer* writer); - void GenerateCommonBuilderMethods(Writer* writer); - void GenerateBuilderParsingMethods(Writer* writer); - void GenerateIsInitialized(Writer* writer); + io::Printer* printer, const Descriptor::ExtensionRange* extendsionRange); + void GenerateParseFromMethods(io::Printer* printer); + void GenerateBuilder(io::Printer* printer); + void GenerateCommonBuilderMethods(io::Printer* printer); + void GenerateBuilderParsingMethods(io::Printer* printer); + void GenerateIsInitialized(io::Printer* printer); int GetFieldOrdinal(const FieldDescriptor* descriptor); FieldGeneratorBase* CreateFieldGeneratorInternal( diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index b533d735..50eb9df6 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -40,7 +40,6 @@ #include #include -#include namespace google { namespace protobuf { @@ -50,245 +49,291 @@ namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - has_property_check = "has" + property_name(); + variables_["has_property_check"] = "has" + property_name(); + variables_["message_or_group"] = message_or_group(); } MessageFieldGenerator::~MessageFieldGenerator() { } -void MessageFieldGenerator::GenerateMembers(Writer* writer) { - writer->WriteLine("private bool has$0$;", property_name()); - writer->WriteLine("private $0$ $1$_;", type_name(), name()); - AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return has$0$; }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$_ ?? $1$; }", name(), default_value()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { + printer->Print( + variables_, + "private bool has$property_name$;\n" + "private $type_name$ $name$_;\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return has$property_name$; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return $name$_ ?? $default_value$; }\n" + "}\n"); } -void MessageFieldGenerator::GenerateBuilderMembers(Writer* writer) { - AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.has$0$; }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$; }", property_name()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = true;", property_name()); - writer->WriteLine(" result.$0$_ = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$($1$.Builder builderForValue) {", - property_name(), type_name()); - AddNullCheck(writer, "builderForValue"); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = true;", property_name()); - writer->WriteLine(" result.$0$_ = builderForValue.Build();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Merge$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" if (result.has$0$ &&", property_name()); - writer->WriteLine(" result.$0$_ != $1$) {", name(), default_value()); - writer->WriteLine( - " result.$0$_ = $1$.CreateBuilder(result.$0$_).MergeFrom(value).BuildPartial();", - name(), type_name()); - writer->WriteLine(" } else {"); - writer->WriteLine(" result.$0$_ = value;", name()); - writer->WriteLine(" }"); - writer->WriteLine(" result.has$0$ = true;", property_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.has$0$ = false;", property_name()); - writer->WriteLine(" result.$0$_ = null;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return result.has$property_name$; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return result.$property_name$; }\n" + " set { Set$property_name$(value); }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.has$property_name$ = true;\n" + " result.$name$_ = value;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); + AddNullCheck(printer, "builderForValue"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.has$property_name$ = true;\n" + " result.$name$_ = builderForValue.Build();\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Merge$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " if (result.has$property_name$ &&\n" + " result.$name$_ != $default_value$) {\n" + " result.$name$_ = $type_name$.CreateBuilder(result.$name$_).MergeFrom(value).BuildPartial();\n" + " } else {\n" + " result.$name$_ = value;\n" + " }\n" + " result.has$property_name$ = true;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.has$property_name$ = false;\n" + " result.$name$_ = null;\n" + " return this;\n" + "}\n"); } -void MessageFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.Has$0$) {", property_name()); - writer->WriteLine(" Merge$0$(other.$0$);", property_name()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.Has$property_name$) {\n" + " Merge$property_name$(other.$property_name$);\n" + "}\n"); } -void MessageFieldGenerator::GenerateBuildingCode(Writer* writer) { +void MessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { // Nothing to do for singular fields } -void MessageFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("$0$.Builder subBuilder = $0$.CreateBuilder();", - type_name()); - writer->WriteLine("if (result.has$0$) {", property_name()); - writer->WriteLine(" subBuilder.MergeFrom($0$);", property_name()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" + "if (result.has$property_name$) {\n" + " subBuilder.MergeFrom($property_name$);\n" + "}\n"); if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - writer->WriteLine("input.ReadGroup($0$, subBuilder, extensionRegistry);", - number()); + printer->Print( + variables_, + "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); } else { - writer->WriteLine("input.ReadMessage(subBuilder, extensionRegistry);"); + printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); } - writer->WriteLine("$0$ = subBuilder.BuildPartial();", property_name()); + printer->Print( + variables_, + "$property_name$ = subBuilder.BuildPartial();\n"); } -void MessageFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", - message_or_group(), number(), property_name(), - field_ordinal()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " output.Write$message_or_group$($number$, field_names[$field_ordinal$], $property_name$);\n" + "}\n"); } -void MessageFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", - message_or_group(), number(), property_name()); - writer->WriteLine("}"); +void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, $property_name$);\n" + "}\n"); } -void MessageFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("if (has$0$) hash ^= $1$_.GetHashCode();", property_name(), - name()); +void MessageFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "if (has$property_name$) hash ^= $name$_.GetHashCode();\n"); } -void MessageFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine( - "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", - property_name(), name()); +void MessageFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); } -void MessageFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$2$\", has$0$, $1$_, writer);", - property_name(), name(), GetFieldName(descriptor_)); +void MessageFieldGenerator::WriteToString(io::Printer* printer) { + variables_["field_name"] = GetFieldName(descriptor_); + printer->Print( + variables_, + "PrintField(\"$field_name$\", has$property_name$, $name$_, writer);\n"); } MessageOneofFieldGenerator::MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : MessageFieldGenerator(descriptor, fieldOrdinal) { - has_property_check = oneof_name() + "Case_ == " + oneof_property_name() + - "OneofCase." + property_name(); + SetCommonOneofFieldVariables(&variables_); } MessageOneofFieldGenerator::~MessageOneofFieldGenerator() { } -void MessageOneofFieldGenerator::GenerateMembers(Writer* writer) { +void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return $0$; }", has_property_check); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return $has_property_check$; }\n" + "}\n"); } - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$ ? ($1$) $2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" + "}\n"); } -void MessageOneofFieldGenerator::GenerateBuilderMembers(Writer* writer) { +void MessageOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(writer); - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.$0$; }", has_property_check); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return result.$has_property_check$; }\n" + "}\n"); } - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$ ? ($1$) result.$2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$($1$.Builder builderForValue) {", - property_name(), type_name()); - AddNullCheck(writer, "builderForValue"); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" result.$0$_ = builderForValue.Build();", oneof_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Merge$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" if (result.$0$ &&", has_property_check); - writer->WriteLine(" result.$0$ != $1$) {", property_name(), default_value()); - writer->WriteLine( - " result.$0$_ = $1$.CreateBuilder(result.$2$).MergeFrom(value).BuildPartial();", - oneof_name(), type_name(), property_name()); - writer->WriteLine(" } else {"); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" }"); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" if (result.$0$) {", has_property_check); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", - oneof_name(), oneof_property_name()); - writer->WriteLine(" result.$0$_ = null;", oneof_name()); - writer->WriteLine(" }"); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" + " set { Set$property_name$(value); }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " result.$oneof_name$_ = value;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); + AddNullCheck(printer, "builderForValue"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " result.$oneof_name$_ = builderForValue.Build();\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Merge$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " if (result.$has_property_check$ &&\n" + " result.$property_name$ != $default_value$) {\n" + " result.$oneof_name$_ = $type_name$.CreateBuilder(result.$property_name$).MergeFrom(value).BuildPartial();\n" + " } else {\n" + " result.$oneof_name$_ = value;\n" + " }\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " if (result.$has_property_check$) {\n" + " PrepareBuilder();\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" + " result.$oneof_name$_ = null;\n" + " }\n" + " return this;\n" + "}\n"); } -void MessageOneofFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("$0$.Builder subBuilder = $0$.CreateBuilder();", - type_name()); - writer->WriteLine("if (result.$0$) {", has_property_check); - writer->WriteLine(" subBuilder.MergeFrom($0$);", property_name()); - writer->WriteLine("}"); +void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" + "if (result.$has_property_check$) {\n" + " subBuilder.MergeFrom($property_name$);\n" + "}\n"); if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - writer->WriteLine("input.ReadGroup($0$, subBuilder, extensionRegistry);", - number()); + printer->Print( + variables_, + "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); } else { - writer->WriteLine("input.ReadMessage(subBuilder, extensionRegistry);"); + printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); } - writer->WriteLine("result.$0$_ = subBuilder.BuildPartial();", oneof_name()); - writer->WriteLine("result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); + printer->Print( + variables_, + "result.$oneof_name$_ = subBuilder.BuildPartial();\n" + "result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); } -void MessageOneofFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if (!$0$.Equals(other.$0$)) return false;", property_name()); +void MessageOneofFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); } -void MessageOneofFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", - descriptor_->name(), has_property_check, oneof_name()); +void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print( + variables_, + "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index d455ade5..d820908c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -48,20 +48,17 @@ class MessageFieldGenerator : public FieldGeneratorBase { MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); - - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - - protected: - string has_property_check; + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); @@ -72,11 +69,11 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { MessageOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageOneofFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index a54edfe3..652eb6b9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -40,7 +40,6 @@ #include #include -#include namespace google { namespace protobuf { @@ -50,202 +49,232 @@ namespace csharp { PrimitiveFieldGenerator::PrimitiveFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - if (SupportFieldPresence(descriptor_->file())) { - has_property_check = "has" + property_name(); - } else { - has_property_check = property_name() + " != " + default_value(); - } } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { } -void PrimitiveFieldGenerator::GenerateMembers(Writer* writer) { +void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("private bool has$0$;", property_name()); + printer->Print(variables_, "private bool has$property_name$;\n"); } - writer->WriteLine("private $0$ $1$_$2$;", type_name(), name(), - has_default_value() ? " = " + default_value() : ""); - AddDeprecatedFlag(writer); + printer->Print( + variables_, + "private $type_name$ $name_def_message$;\n"); + AddDeprecatedFlag(printer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return has$0$; }", property_name()); - writer->WriteLine("}"); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return has$property_name$; }\n" + "}\n"); } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$_; }", name()); - writer->WriteLine("}"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return $name$_; }\n" + "}\n"); } -void PrimitiveFieldGenerator::GenerateBuilderMembers(Writer* writer) { - AddDeprecatedFlag(writer); +void PrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { + AddDeprecatedFlag(printer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.has$0$; }", property_name()); - writer->WriteLine("}"); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return result.has$property_name$; }\n" + "}\n"); } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$; }", property_name()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return result.$property_name$; }\n" + " set { Set$property_name$(value); }\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print(" PrepareBuilder();\n"); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine(" result.has$0$ = true;", property_name()); + printer->Print( + variables_, + " result.has$property_name$ = true;\n"); } - writer->WriteLine(" result.$0$_ = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); + printer->Print( + variables_, + " result.$name$_ = value;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n"); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine(" result.has$0$ = false;", property_name()); + printer->Print( + variables_, + " result.has$property_name$ = false;\n"); } - writer->WriteLine(" result.$0$_ = $1$;", name(), default_value()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + printer->Print( + variables_, + " result.$name$_ = $default_value$;\n" + " return this;\n" + "}\n"); } -void PrimitiveFieldGenerator::GenerateMergingCode(Writer* writer) { - if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("if (other.Has$0$) {", property_name()); - } else { - writer->WriteLine("if (other.$0$ != $1$) {", property_name(), default_value()); - } - writer->WriteLine(" $0$ = other.$0$;", property_name()); - writer->WriteLine("}"); +void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($other_has_property_check$) {\n" + " $property_name$ = other.$property_name$;\n" + "}\n"); } -void PrimitiveFieldGenerator::GenerateBuildingCode(Writer* writer) { +void PrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { // Nothing to do here for primitive types } -void PrimitiveFieldGenerator::GenerateParsingCode(Writer* writer) { +void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("result.has$0$ = input.Read$1$(ref result.$2$_);", - property_name(), capitalized_type_name(), name()); + printer->Print( + variables_, + "result.has$property_name$ = input.Read$capitalized_type_name$(ref result.$name$_);\n"); } else { - writer->WriteLine("input.Read$0$(ref result.$1$_);", - capitalized_type_name(), name()); + printer->Print( + variables_, + "input.Read$capitalized_type_name$(ref result.$name$_);\n"); } } -void PrimitiveFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" output.Write$0$($1$, field_names[$3$], $2$);", - capitalized_type_name(), number(), property_name(), - field_ordinal()); - writer->WriteLine("}"); +void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " output.Write$capitalized_type_name$($number$, field_names[$field_ordinal$], $property_name$);\n" + "}\n"); } -void PrimitiveFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" size += pb::CodedOutputStream.Compute$0$Size($1$, $2$);", - capitalized_type_name(), number(), property_name()); - writer->WriteLine("}"); +void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.Compute$capitalized_type_name$Size($number$, $property_name$);\n" + "}\n"); } -void PrimitiveFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("if ($0$) {", has_property_check); - writer->WriteLine(" hash ^= $0$_.GetHashCode();", name()); - writer->WriteLine("}"); +void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "if ($has_property_check$) {\n" + " hash ^= $name$_.GetHashCode();\n" + "}\n"); } -void PrimitiveFieldGenerator::WriteEquals(Writer* writer) { +void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine( - "if (has$0$ != other.has$0$ || (has$0$ && !$1$_.Equals(other.$1$_))) return false;", - property_name(), name()); + printer->Print( + variables_, + "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); } else { - writer->WriteLine( - "if (!$0$_.Equals(other.$0$_)) return false;", name()); + printer->Print( + variables_, + "if (!$name$_.Equals(other.$name$_)) return false;\n"); } } -void PrimitiveFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", - descriptor_->name(), has_property_check, name()); +void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print( + variables_, + "PrintField(\"$descriptor_name$\", $has_property_check$, $name$_, writer);\n"); } PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : PrimitiveFieldGenerator(descriptor, fieldOrdinal) { - has_property_check = oneof_name() + "Case_ == " + oneof_property_name() + - "OneofCase." + property_name(); + SetCommonOneofFieldVariables(&variables_); } PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() { } -void PrimitiveOneofFieldGenerator::GenerateMembers(Writer* writer) { - AddDeprecatedFlag(writer); +void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { + AddDeprecatedFlag(printer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return $0$; }", has_property_check); - writer->WriteLine("}"); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return $has_property_check$; }\n" + "}\n"); } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return $0$ ? ($1$) $2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine("}"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" + "}\n"); } -void PrimitiveOneofFieldGenerator::GenerateBuilderMembers(Writer* writer) { - AddDeprecatedFlag(writer); +void PrimitiveOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { + AddDeprecatedFlag(printer); if (SupportFieldPresence(descriptor_->file())) { - writer->WriteLine("public bool Has$0$ {", property_name()); - writer->WriteLine(" get { return result.$0$; }", has_property_check); - writer->WriteLine("}"); + printer->Print( + variables_, + "public bool Has$property_name$ {\n" + " get { return result.$has_property_check$; }\n" + "}\n"); } - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ $1$ {", type_name(), property_name()); - writer->WriteLine(" get { return result.$0$ ? ($1$) result.$2$_ : $3$; }", - has_property_check, type_name(), oneof_name(), default_value()); - writer->WriteLine(" set { Set$0$(value); }", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Set$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" if (result.$0$) {", has_property_check); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.None;", - oneof_name(), oneof_property_name()); - writer->WriteLine(" }"); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); -} - -void PrimitiveOneofFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if (!$0$.Equals(other.$0$)) return false;", property_name()); -} -void PrimitiveOneofFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$, $2$_, writer);", - descriptor_->name(), has_property_check, oneof_name()); -} - -void PrimitiveOneofFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("$0$ value = $1$;", type_name(), default_value()); - writer->WriteLine("if (input.Read$0$(ref value)) {", - capitalized_type_name()); - writer->WriteLine(" result.$0$_ = value;", oneof_name()); - writer->WriteLine(" result.$0$Case_ = $1$OneofCase.$2$;", - oneof_name(), oneof_property_name(), property_name()); - writer->WriteLine("}"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ $property_name$ {\n" + " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" + " set { Set$property_name$(value); }\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder Set$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$oneof_name$_ = value;\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " if (result.$has_property_check$) {\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" + " }\n" + " return this;\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); +} +void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print(variables_, + "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); +} + +void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "$type_name$ value = $default_value$;\n" + "if (input.Read$capitalized_type_name$(ref value)) {\n" + " result.$oneof_name$_ = value;\n" + " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + "}\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index ecc6ed91..8a2d5020 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -48,20 +48,17 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); - - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - - protected: - string has_property_check; + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); + + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); @@ -72,11 +69,11 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveOneofFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index cc8745ae..f5ebcfb1 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -40,7 +40,6 @@ #include #include -#include namespace google { namespace protobuf { @@ -56,168 +55,193 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { } -void RepeatedEnumFieldGenerator::GenerateMembers(Writer* writer) { +void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) { if (descriptor_->is_packed() && optimize_speed()) { - writer->WriteLine("private int $0$MemoizedSerializedSize;", name()); + printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } - writer->WriteLine( - "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", - type_name(), name()); - AddDeprecatedFlag(writer); - writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return pbc::Lists.AsReadOnly($0$_); }", name()); - writer->WriteLine("}"); + printer->Print(variables_, + "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public scg::IList<$type_name$> $property_name$List {\n" + " get { return pbc::Lists.AsReadOnly($name$_); }\n" + "}\n"); // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return $0$_.Count; }", name()); - writer->WriteLine("}"); - - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return $0$_[index];", name()); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return $name$_.Count; }\n" + "}\n"); + + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return $name$_[index];\n" + "}\n"); } -void RepeatedEnumFieldGenerator::GenerateBuilderMembers(Writer* writer) { +void RepeatedEnumFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { // Note: We can return the original list here, because we make it unmodifiable when we build // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(writer); - writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return result.$0$Count; }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return result.Get$0$(index);", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", - property_name(), type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_[index] = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), - type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine( - "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", - property_name(), type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(values);", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Clear();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" + " get { return PrepareBuilder().$name$_; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return result.$property_name$Count; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return result.Get$property_name$(index);\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$(int index, $type_name$ value) {\n"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_[index] = value;\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print(variables_, + "public Builder Add$property_name$($type_name$ value) {\n"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_.Add(value);\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" + " PrepareBuilder();\n" + " result.$name$_.Add(values);\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.$name$_.Clear();\n" + " return this;\n" + "}\n"); } -void RepeatedEnumFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.$0$_.Count != 0) {", name()); - writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); - writer->WriteLine("}"); +void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$name$_.Count != 0) {\n" + " result.$name$_.Add(other.$name$_);\n" + "}\n"); } -void RepeatedEnumFieldGenerator::GenerateBuildingCode(Writer* writer) { - writer->WriteLine("$0$_.MakeReadOnly();", name()); +void RepeatedEnumFieldGenerator::GenerateBuildingCode(io::Printer* printer) { + printer->Print(variables_, "$name$_.MakeReadOnly();\n"); } -void RepeatedEnumFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("scg::ICollection unknownItems;"); - writer->WriteLine( - "input.ReadEnumArray<$0$>(tag, field_name, result.$1$_, out unknownItems);", - type_name(), name()); +void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "scg::ICollection unknownItems;\n" + "input.ReadEnumArray<$type_name$>(tag, field_name, result.$name$_, out unknownItems);\n"); if (!use_lite_runtime()) { - writer->WriteLine("if (unknownItems != null) {"); - writer->WriteLine(" if (unknownFields == null) {"); - writer->WriteLine( - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);"); - writer->WriteLine(" }"); - writer->WriteLine(" foreach (object rawValue in unknownItems)"); - writer->WriteLine(" if (rawValue is int)"); - writer->WriteLine( - " unknownFields.MergeVarintField($0$, (ulong)(int)rawValue);", - number()); - writer->WriteLine("}"); + printer->Print( + variables_, + "if (unknownItems != null) {\n" + " if (unknownFields == null) {\n" + " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" + " }\n" + " foreach (object rawValue in unknownItems)\n" + " if (rawValue is int)\n" + " unknownFields.MergeVarintField($number$, (ulong)(int)rawValue);\n" + "}\n"); } } -void RepeatedEnumFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$_.Count > 0) {", name()); - writer->Indent(); +void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print(variables_, "if ($name$_.Count > 0) {\n"); + printer->Indent(); if (descriptor_->is_packed()) { - writer->WriteLine( - "output.WritePackedEnumArray($0$, field_names[$2$], $1$MemoizedSerializedSize, $1$_);", - number(), name(), field_ordinal()); + printer->Print( + variables_, + "output.WritePackedEnumArray($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); } else { - writer->WriteLine("output.WriteEnumArray($0$, field_names[$2$], $1$_);", - number(), name(), field_ordinal()); + printer->Print(variables_, + "output.WriteEnumArray($number$, field_names[$field_ordinal$], $name$_);\n"); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } -void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("{"); - writer->Indent(); - writer->WriteLine("int dataSize = 0;"); - writer->WriteLine("if ($0$_.Count > 0) {", name()); - writer->Indent(); - writer->WriteLine("foreach ($0$ element in $1$_) {", type_name(), name()); - writer->WriteLine( - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);"); - writer->WriteLine("}"); - writer->WriteLine("size += dataSize;"); +void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print("{\n"); + printer->Indent(); + printer->Print( + variables_, + "int dataSize = 0;\n" + "if ($name$_.Count > 0) {\n"); + printer->Indent(); + printer->Print( + variables_, + "foreach ($type_name$ element in $name$_) {\n" + " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" + "}\n" + "size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); if (descriptor_->is_packed()) { - writer->WriteLine("size += $0$;", SimpleItoa(tagSize)); - writer->WriteLine( - "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);"); + printer->Print( + "size += $tag_size$;\n" + "size += pb::CodedOutputStream.ComputeRawVarint32Size((uint) dataSize);\n", + "tag_size", SimpleItoa(tagSize)); } else { - writer->WriteLine("size += $0$ * $1$_.Count;", SimpleItoa(tagSize), name()); + printer->Print( + "size += $tag_size$ * $name$_.Count;\n", + "tag_size", SimpleItoa(tagSize), "name", name()); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); // cache the data size for packed fields. if (descriptor_->is_packed()) { - writer->WriteLine("$0$MemoizedSerializedSize = dataSize;", name()); + printer->Print(variables_, + "$name$MemoizedSerializedSize = dataSize;\n"); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } -void RepeatedEnumFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); - writer->WriteLine(" hash ^= i.GetHashCode();"); +void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "foreach($type_name$ i in $name$_)\n" + " hash ^= i.GetHashCode();\n"); } -void RepeatedEnumFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); - writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); - writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", - name()); +void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if($name$_.Count != other.$name$_.Count) return false;\n" + "for(int ix=0; ix < $name$_.Count; ix++)\n" + " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); } -void RepeatedEnumFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", descriptor_->name(), - name()); +void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print(variables_, + "PrintField(\"$descriptor_name$\", $name$_, writer);\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index c872131c..68c3d6c9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -48,17 +48,17 @@ class RepeatedEnumFieldGenerator : public FieldGeneratorBase { RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedEnumFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 2dfcd402..2ae1d579 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -39,7 +39,6 @@ #include #include -#include namespace google { namespace protobuf { @@ -49,150 +48,177 @@ namespace csharp { RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + variables_["message_or_group"] = message_or_group(); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { } -void RepeatedMessageFieldGenerator::GenerateMembers(Writer* writer) { - writer->WriteLine( - "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", - type_name(), name()); - AddDeprecatedFlag(writer); - writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return $0$_; }", name()); - writer->WriteLine("}"); +void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { + printer->Print( + variables_, + "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public scg::IList<$type_name$> $property_name$List {\n" + " get { return $name$_; }\n" + "}\n"); // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return $0$_.Count; }", name()); - writer->WriteLine("}"); - - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return $0$_[index];", name()); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return $name$_.Count; }\n" + "}\n"); + + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return $name$_[index];\n" + "}\n"); } -void RepeatedMessageFieldGenerator::GenerateBuilderMembers(Writer* writer) { +void RepeatedMessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { // Note: We can return the original list here, because we make it unmodifiable when we build // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(writer); - writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return result.$0$Count; }", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return result.Get$0$(index);", property_name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", - property_name(), type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_[index] = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" + " get { return PrepareBuilder().$name$_; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return result.$property_name$Count; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return result.Get$property_name$(index);\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$(int index, $type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_[index] = value;\n" + " return this;\n" + "}\n"); // Extra overload for builder (just on messages) - AddDeprecatedFlag(writer); - writer->WriteLine( - "public Builder Set$0$(int index, $1$.Builder builderForValue) {", - property_name(), type_name()); - AddNullCheck(writer, "builderForValue"); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_[index] = builderForValue.Build();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Set$property_name$(int index, $type_name$.Builder builderForValue) {\n"); + AddNullCheck(printer, "builderForValue"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_[index] = builderForValue.Build();\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Add$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_.Add(value);\n" + " return this;\n" + "}\n"); // Extra overload for builder (just on messages) - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Add$0$($1$.Builder builderForValue) {", - property_name(), type_name()); - AddNullCheck(writer, "builderForValue"); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(builderForValue.Build());", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine( - "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", - property_name(), type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(values);", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Clear();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Add$property_name$($type_name$.Builder builderForValue) {\n"); + AddNullCheck(printer, "builderForValue"); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_.Add(builderForValue.Build());\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" + " PrepareBuilder();\n" + " result.$name$_.Add(values);\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.$name$_.Clear();\n" + " return this;\n" + "}\n"); } -void RepeatedMessageFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.$0$_.Count != 0) {", name()); - writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); - writer->WriteLine("}"); +void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$name$_.Count != 0) {\n" + " result.$name$_.Add(other.$name$_);\n" + "}\n"); } -void RepeatedMessageFieldGenerator::GenerateBuildingCode(Writer* writer) { - writer->WriteLine("$0$_.MakeReadOnly();", name()); +void RepeatedMessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { + printer->Print(variables_, "$name$_.MakeReadOnly();\n"); } -void RepeatedMessageFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine( - "input.Read$0$Array(tag, field_name, result.$1$_, $2$.DefaultInstance, extensionRegistry);", - message_or_group(), name(), type_name()); +void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print( + variables_, + "input.Read$message_or_group$Array(tag, field_name, result.$name$_, $type_name$.DefaultInstance, extensionRegistry);\n"); } -void RepeatedMessageFieldGenerator::GenerateSerializationCode(Writer* writer) { - writer->WriteLine("if ($0$_.Count > 0) {", name()); - writer->Indent(); - writer->WriteLine("output.Write$0$Array($1$, field_names[$3$], $2$_);", - message_or_group(), number(), name(), field_ordinal()); - writer->Outdent(); - writer->WriteLine("}"); +void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + printer->Print( + variables_, + "if ($name$_.Count > 0) {\n" + " output.Write$message_or_group$Array($number$, field_names[$field_ordinal$], $name$_);\n" + "}\n"); } -void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(Writer* writer) { - writer->WriteLine("foreach ($0$ element in $1$List) {", type_name(), - property_name()); - writer->WriteLine( - " size += pb::CodedOutputStream.Compute$0$Size($1$, element);", - message_or_group(), number()); - writer->WriteLine("}"); +void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + printer->Print( + variables_, + "foreach ($type_name$ element in $property_name$List) {\n" + " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, element);\n" + "}\n"); } -void RepeatedMessageFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); - writer->WriteLine(" hash ^= i.GetHashCode();"); +void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "foreach($type_name$ i in $name$_)\n" + " hash ^= i.GetHashCode();\n"); } -void RepeatedMessageFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); - writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); - writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", - name()); +void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if($name$_.Count != other.$name$_.Count) return false;\n" + "for(int ix=0; ix < $name$_.Count; ix++)\n" + " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); } -void RepeatedMessageFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", - GetFieldName(descriptor_), name()); +void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { + variables_["field_name"] = GetFieldName(descriptor_); + printer->Print( + variables_, + "PrintField(\"$field_name$\", $name$_, writer);\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 104274cb..9db76939 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -48,17 +48,17 @@ class RepeatedMessageFieldGenerator : public FieldGeneratorBase { RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedMessageFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 8b285468..e27458bb 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -40,7 +40,6 @@ #include #include -#include namespace google { namespace protobuf { @@ -56,161 +55,182 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { } -void RepeatedPrimitiveFieldGenerator::GenerateMembers(Writer* writer) { +void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { if (descriptor_->is_packed() && optimize_speed()) { - writer->WriteLine("private int $0$MemoizedSerializedSize;", name()); + printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); } - writer->WriteLine( - "private pbc::PopsicleList<$0$> $1$_ = new pbc::PopsicleList<$0$>();", - type_name(), name()); - AddPublicMemberAttributes(writer); - writer->WriteLine("public scg::IList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return pbc::Lists.AsReadOnly($0$_); }", name()); - writer->WriteLine("}"); + printer->Print(variables_, + "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public scg::IList<$type_name$> $property_name$List {\n" + " get { return pbc::Lists.AsReadOnly($name$_); }\n" + "}\n"); // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return $0$_.Count; }", name()); - writer->WriteLine("}"); - - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return $0$_[index];", name()); - writer->WriteLine("}"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return $name$_.Count; }\n" + "}\n"); + + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return $name$_[index];\n" + "}\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateBuilderMembers(Writer* writer) { +void RepeatedPrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { // Note: We can return the original list here, because we make it unmodifiable when we build // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddPublicMemberAttributes(writer); - writer->WriteLine("public pbc::IPopsicleList<$0$> $1$List {", type_name(), - property_name()); - writer->WriteLine(" get { return PrepareBuilder().$0$_; }", name()); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public int $0$Count {", property_name()); - writer->WriteLine(" get { return result.$0$Count; }", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public $0$ Get$1$(int index) {", type_name(), - property_name()); - writer->WriteLine(" return result.Get$0$(index);", property_name()); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Set$0$(int index, $1$ value) {", - property_name(), type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_[index] = value;", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine("public Builder Add$0$($1$ value) {", property_name(), - type_name()); - AddNullCheck(writer); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(value);", name(), type_name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddPublicMemberAttributes(writer); - writer->WriteLine( - "public Builder AddRange$0$(scg::IEnumerable<$1$> values) {", - property_name(), type_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Add(values);", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); - AddDeprecatedFlag(writer); - writer->WriteLine("public Builder Clear$0$() {", property_name()); - writer->WriteLine(" PrepareBuilder();"); - writer->WriteLine(" result.$0$_.Clear();", name()); - writer->WriteLine(" return this;"); - writer->WriteLine("}"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" + " get { return PrepareBuilder().$name$_; }\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public int $property_name$Count {\n" + " get { return result.$property_name$Count; }\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public $type_name$ Get$property_name$(int index) {\n" + " return result.Get$property_name$(index);\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder Set$property_name$(int index, $type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_[index] = value;\n" + " return this;\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder Add$property_name$($type_name$ value) {\n"); + AddNullCheck(printer); + printer->Print( + variables_, + " PrepareBuilder();\n" + " result.$name$_.Add(value);\n" + " return this;\n" + "}\n"); + AddPublicMemberAttributes(printer); + printer->Print( + variables_, + "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" + " PrepareBuilder();\n" + " result.$name$_.Add(values);\n" + " return this;\n" + "}\n"); + AddDeprecatedFlag(printer); + printer->Print( + variables_, + "public Builder Clear$property_name$() {\n" + " PrepareBuilder();\n" + " result.$name$_.Clear();\n" + " return this;\n" + "}\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(Writer* writer) { - writer->WriteLine("if (other.$0$_.Count != 0) {", name()); - writer->WriteLine(" result.$0$_.Add(other.$0$_);", name()); - writer->WriteLine("}"); +void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { + printer->Print( + variables_, + "if (other.$name$_.Count != 0) {\n" + " result.$name$_.Add(other.$name$_);\n" + "}\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(Writer* writer) { - writer->WriteLine("$0$_.MakeReadOnly();", name()); +void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { + printer->Print(variables_, "$name$_.MakeReadOnly();\n"); } -void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(Writer* writer) { - writer->WriteLine("input.Read$0$Array(tag, field_name, result.$1$_);", - capitalized_type_name(), name()); +void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { + printer->Print(variables_, + "input.Read$capitalized_type_name$Array(tag, field_name, result.$name$_);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( - Writer* writer) { - writer->WriteLine("if ($0$_.Count > 0) {", name()); - writer->Indent(); + io::Printer* printer) { + printer->Print(variables_, "if ($name$_.Count > 0) {\n"); + printer->Indent(); if (descriptor_->is_packed()) { - writer->WriteLine( - "output.WritePacked$0$Array($1$, field_names[$3$], $2$MemoizedSerializedSize, $2$_);", - capitalized_type_name(), number(), name(), field_ordinal()); + printer->Print(variables_, + "output.WritePacked$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); } else { - writer->WriteLine("output.Write$0$Array($1$, field_names[$3$], $2$_);", - capitalized_type_name(), number(), name(), - field_ordinal()); + printer->Print(variables_, + "output.Write$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$_);\n"); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( - Writer* writer) { - writer->WriteLine("{"); - writer->Indent(); - writer->WriteLine("int dataSize = 0;"); + io::Printer* printer) { + printer->Print("{\n"); + printer->Indent(); + printer->Print("int dataSize = 0;\n"); int fixedSize = GetFixedSize(descriptor_->type()); if (fixedSize == -1) { - writer->WriteLine("foreach ($0$ element in $1$List) {", type_name(), - property_name()); - writer->WriteLine( - " dataSize += pb::CodedOutputStream.Compute$0$SizeNoTag(element);", - capitalized_type_name(), number()); - writer->WriteLine("}"); + printer->Print( + variables_, + "foreach ($type_name$ element in $property_name$List) {\n" + " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n" + "}\n"); } else { - writer->WriteLine("dataSize = $0$ * $1$_.Count;", SimpleItoa(fixedSize), name()); + printer->Print( + "dataSize = $size$ * $name$_.Count;\n", + "size", SimpleItoa(fixedSize), "name", name()); } - writer->WriteLine("size += dataSize;"); + printer->Print("size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); if (descriptor_->is_packed()) { - writer->WriteLine("if ($0$_.Count != 0) {", name()); - writer->WriteLine( - " size += $0$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);", - SimpleItoa(tagSize)); - writer->WriteLine("}"); + printer->Print( + "if ($name$_.Count != 0) {\n" + " size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n" + "}\n", + "name", name(), "tag_size", SimpleItoa(tagSize)); } else { - writer->WriteLine("size += $0$ * $1$_.Count;", SimpleItoa(tagSize), name()); + printer->Print( + "size += $tag_size$ * $name$_.Count;\n", + "tag_size", SimpleItoa(tagSize), "name", name()); } // cache the data size for packed fields. if (descriptor_->is_packed()) { - writer->WriteLine("$0$MemoizedSerializedSize = dataSize;", name()); + printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); } - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } -void RepeatedPrimitiveFieldGenerator::WriteHash(Writer* writer) { - writer->WriteLine("foreach($0$ i in $1$_)", type_name(), name()); - writer->WriteLine(" hash ^= i.GetHashCode();"); +void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) { + printer->Print( + variables_, + "foreach($type_name$ i in $name$_)\n" + " hash ^= i.GetHashCode();\n"); } -void RepeatedPrimitiveFieldGenerator::WriteEquals(Writer* writer) { - writer->WriteLine("if($0$_.Count != other.$0$_.Count) return false;", name()); - writer->WriteLine("for(int ix=0; ix < $0$_.Count; ix++)", name()); - writer->WriteLine(" if(!$0$_[ix].Equals(other.$0$_[ix])) return false;", - name()); +void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { + printer->Print( + variables_, + "if($name$_.Count != other.$name$_.Count) return false;\n" + "for(int ix=0; ix < $name$_.Count; ix++)\n" + " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); } -void RepeatedPrimitiveFieldGenerator::WriteToString(Writer* writer) { - writer->WriteLine("PrintField(\"$0$\", $1$_, writer);", descriptor_->name(), - name()); +void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) { + printer->Print(variables_, + "PrintField(\"$descriptor_name$\", $name$_, writer);\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index 07b12015..50af9dda 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -48,17 +48,17 @@ class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedPrimitiveFieldGenerator(); - virtual void GenerateMembers(Writer* writer); - virtual void GenerateBuilderMembers(Writer* writer); - virtual void GenerateMergingCode(Writer* writer); - virtual void GenerateBuildingCode(Writer* writer); - virtual void GenerateParsingCode(Writer* writer); - virtual void GenerateSerializationCode(Writer* writer); - virtual void GenerateSerializedSizeCode(Writer* writer); + virtual void GenerateMembers(io::Printer* printer); + virtual void GenerateBuilderMembers(io::Printer* printer); + virtual void GenerateMergingCode(io::Printer* printer); + virtual void GenerateBuildingCode(io::Printer* printer); + virtual void GenerateParsingCode(io::Printer* printer); + virtual void GenerateSerializationCode(io::Printer* printer); + virtual void GenerateSerializedSizeCode(io::Printer* printer); - virtual void WriteHash(Writer* writer); - virtual void WriteEquals(Writer* writer); - virtual void WriteToString(Writer* writer); + virtual void WriteHash(io::Printer* printer); + virtual void WriteEquals(io::Printer* printer); + virtual void WriteToString(io::Printer* printer); private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index 8dfb41d4..c52f6092 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -39,7 +39,6 @@ #include #include -#include namespace google { namespace protobuf { @@ -61,7 +60,7 @@ SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor) SourceGeneratorBase::~SourceGeneratorBase() { } -void SourceGeneratorBase::WriteGeneratedCodeAttributes(Writer* writer) { +void SourceGeneratorBase::WriteGeneratedCodeAttributes(io::Printer* printer) { // This hook can be used to reintroduce generated code attributes in the future. } diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index 1955394e..61c19511 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -40,8 +40,6 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class SourceGeneratorBase { protected: SourceGeneratorBase(const FileDescriptor* descriptor); @@ -62,7 +60,7 @@ class SourceGeneratorBase { return runtimeSuffix_; } - void WriteGeneratedCodeAttributes(Writer* writer); + void WriteGeneratedCodeAttributes(io::Printer* printer); private: const FileDescriptor* descriptor_; diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc index 358cfa4f..b14bf5e8 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc @@ -42,7 +42,6 @@ #include #include #include -#include namespace google { namespace protobuf { @@ -60,218 +59,224 @@ UmbrellaClassGenerator::UmbrellaClassGenerator(const FileDescriptor* file) UmbrellaClassGenerator::~UmbrellaClassGenerator() { } -void UmbrellaClassGenerator::Generate(Writer* writer) { - WriteIntroduction(writer); - WriteExtensionRegistration(writer); +void UmbrellaClassGenerator::Generate(io::Printer* printer) { + WriteIntroduction(printer); + WriteExtensionRegistration(printer); // write children: Extensions if (file_->extension_count() > 0) { - writer->WriteLine("#region Extensions"); + printer->Print("#region Extensions\n"); for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.Generate(writer); + extensionGenerator.Generate(printer); } - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Print("#endregion\n"); + printer->Print("\n"); } - writer->WriteLine("#region Static variables"); + printer->Print("#region Static variables\n"); for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariables(writer); + messageGenerator.GenerateStaticVariables(printer); } - writer->WriteLine("#endregion"); + printer->Print("#endregion\n"); if (!use_lite_runtime()) { - WriteDescriptor(writer); + WriteDescriptor(printer); } else { - WriteLiteExtensions(writer); + WriteLiteExtensions(printer); } // Close the class declaration. - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); // Close the namespace around the umbrella class if defined if (!umbrellaNamespace_.empty()) { - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } // write children: Enums if (file_->enum_type_count() > 0) { - writer->WriteLine("#region Enums"); + printer->Print("#region Enums\n"); for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator enumGenerator(file_->enum_type(i)); - enumGenerator.Generate(writer); + enumGenerator.Generate(printer); } - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Print("#endregion\n"); + printer->Print("\n"); } // write children: Messages if (file_->message_type_count() > 0) { - writer->WriteLine("#region Messages"); + printer->Print("#region Messages\n"); for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.Generate(writer); + messageGenerator.Generate(printer); } - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Print("#endregion\n"); + printer->Print("\n"); } // TODO(jtattermusch): add insertion point for services. if (!namespace_.empty()) { - writer->Outdent(); - writer->WriteLine("}"); + printer->Outdent(); + printer->Print("}\n"); } - writer->WriteLine(); - writer->WriteLine("#endregion Designer generated code"); + printer->Print("\n"); + printer->Print("#endregion Designer generated code\n"); } -void UmbrellaClassGenerator::WriteIntroduction(Writer* writer) { - writer->WriteLine( - "// Generated by the protocol buffer compiler. DO NOT EDIT!"); - writer->WriteLine("// source: $0$", file_->name()); - writer->WriteLine("#pragma warning disable 1591, 0612, 3021"); - writer->WriteLine("#region Designer generated code"); - - writer->WriteLine(); - writer->WriteLine("using pb = global::Google.ProtocolBuffers;"); - writer->WriteLine("using pbc = global::Google.ProtocolBuffers.Collections;"); - writer->WriteLine("using pbd = global::Google.ProtocolBuffers.Descriptors;"); - writer->WriteLine("using scg = global::System.Collections.Generic;"); +void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) { + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $file_name$\n" + "#pragma warning disable 1591, 0612, 3021\n" + "#region Designer generated code\n" + "\n" + "using pb = global::Google.ProtocolBuffers;\n" + "using pbc = global::Google.ProtocolBuffers.Collections;\n" + "using pbd = global::Google.ProtocolBuffers.Descriptors;\n" + "using scg = global::System.Collections.Generic;\n", + "file_name", file_->name()); if (!namespace_.empty()) { - writer->WriteLine("namespace $0$ {", namespace_); - writer->Indent(); - writer->WriteLine(); + printer->Print("namespace $namespace$ {\n", "namespace", namespace_); + printer->Indent(); + printer->Print("\n"); } // Add the namespace around the umbrella class if defined if (!umbrellaNamespace_.empty()) { - writer->WriteLine("namespace $0$ {", umbrellaNamespace_); - writer->Indent(); - writer->WriteLine(); + printer->Print("namespace $umbrella_namespace$ {\n", + "umbrella_namespace", umbrellaNamespace_); + printer->Indent(); + printer->Print("\n"); } - writer->WriteLine( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]"); - WriteGeneratedCodeAttributes(writer); - writer->WriteLine("$0$ static partial class $1$ {", class_access_level(), - umbrellaClassname_); - writer->WriteLine(); - writer->Indent(); + printer->Print( + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print( + "$access_level$ static partial class $umbrella_class_name$ {\n" + "\n", + "access_level", class_access_level(), + "umbrella_class_name", umbrellaClassname_); + printer->Indent(); } -void UmbrellaClassGenerator::WriteExtensionRegistration(Writer* writer) { - writer->WriteLine("#region Extension registration"); - writer->WriteLine( - "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {"); - writer->Indent(); +void UmbrellaClassGenerator::WriteExtensionRegistration(io::Printer* printer) { + printer->Print( + "#region Extension registration\n" + "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {\n"); + printer->Indent(); for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(writer); + extensionGenerator.GenerateExtensionRegistrationCode(printer); } for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(writer); + messageGenerator.GenerateExtensionRegistrationCode(printer); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("#endregion\n"); } -void UmbrellaClassGenerator::WriteDescriptor(Writer* writer) { - writer->WriteLine("#region Descriptor"); - - writer->WriteLine("public static pbd::FileDescriptor Descriptor {"); - writer->WriteLine(" get { return descriptor; }"); - writer->WriteLine("}"); - writer->WriteLine("private static pbd::FileDescriptor descriptor;"); - writer->WriteLine(); - writer->WriteLine("static $0$() {", umbrellaClassname_); - writer->Indent(); - writer->WriteLine( - "byte[] descriptorData = global::System.Convert.FromBase64String("); - writer->Indent(); - writer->Indent(); - writer->WriteLine("string.Concat("); - writer->Indent(); +void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { + printer->Print( + "#region Descriptor\n" + "public static pbd::FileDescriptor Descriptor {\n" + " get { return descriptor; }\n" + "}\n" + "private static pbd::FileDescriptor descriptor;\n" + "\n" + "static $umbrella_class_name$() {\n", + "umbrella_class_name", umbrellaClassname_); + printer->Indent(); + printer->Print( + "byte[] descriptorData = global::System.Convert.FromBase64String(\n"); + printer->Indent(); + printer->Indent(); + printer->Print("string.Concat(\n"); + printer->Indent(); // TODO(jonskeet): Consider a C#-escaping format here instead of just Base64. std::string base64 = FileDescriptorToBase64(file_); while (base64.size() > 60) { - writer->WriteLine("\"$0$\", ", base64.substr(0, 60)); + printer->Print("\"$base64$\", \n", "base64", base64.substr(0, 60)); base64 = base64.substr(60); } - writer->Outdent(); - writer->WriteLine("\"$0$\"));", base64); - writer->Outdent(); - writer->Outdent(); - writer->WriteLine( - "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {"); - writer->Indent(); - writer->WriteLine("descriptor = root;"); + printer->Outdent(); + printer->Print("\"$base64$\"));\n", "base64", base64); + printer->Outdent(); + printer->Outdent(); + printer->Print( + "pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {\n"); + printer->Indent(); + printer->Print("descriptor = root;\n"); for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(writer); + messageGenerator.GenerateStaticVariableInitializers(printer); } for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(writer); + extensionGenerator.GenerateStaticVariableInitializers(printer); } if (uses_extensions()) { // Must construct an ExtensionRegistry containing all possible extensions // and return it. - writer->WriteLine( - "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();"); - writer->WriteLine("RegisterAllExtensions(registry);"); + printer->Print( + "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();\n"); + printer->Print("RegisterAllExtensions(registry);\n"); for (int i = 0; i < file_->dependency_count(); i++) { - writer->WriteLine("$0$.RegisterAllExtensions(registry);", - GetFullUmbrellaClassName(file_->dependency(i))); + printer->Print("$dependency$.RegisterAllExtensions(registry);\n", + "dependency", GetFullUmbrellaClassName(file_->dependency(i))); } - writer->WriteLine("return registry;"); + printer->Print("return registry;\n"); } else { - writer->WriteLine("return null;"); + printer->Print("return null;\n"); } - writer->Outdent(); - writer->WriteLine("};"); + printer->Outdent(); + printer->Print("};\n"); // ----------------------------------------------------------------- // Invoke internalBuildGeneratedFileFrom() to build the file. - writer->WriteLine( - "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,"); - writer->WriteLine(" new pbd::FileDescriptor[] {"); + printer->Print( + "pbd::FileDescriptor.InternalBuildGeneratedFileFrom(descriptorData,\n"); + printer->Print(" new pbd::FileDescriptor[] {\n"); for (int i = 0; i < file_->dependency_count(); i++) { - writer->WriteLine(" $0$.Descriptor, ", - GetFullUmbrellaClassName(file_->dependency(i))); + printer->Print( + " $full_umbrella_class_name$.Descriptor, \n", + "full_umbrella_class_name", + GetFullUmbrellaClassName(file_->dependency(i))); } - writer->WriteLine(" }, assigner);"); - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Print(" }, assigner);\n"); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("#endregion\n\n"); } -void UmbrellaClassGenerator::WriteLiteExtensions(Writer* writer) { - writer->WriteLine("#region Extensions"); - writer->WriteLine("internal static readonly object Descriptor;"); - writer->WriteLine("static $0$() {", umbrellaClassname_); - writer->Indent(); - writer->WriteLine("Descriptor = null;"); +void UmbrellaClassGenerator::WriteLiteExtensions(io::Printer* printer) { + printer->Print( + "#region Extensions\n" + "internal static readonly object Descriptor;\n" + "static $umbrella_class_name$() {\n", + "umbrella_class_name", umbrellaClassname_); + printer->Indent(); + printer->Print("Descriptor = null;\n"); for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(writer); + messageGenerator.GenerateStaticVariableInitializers(printer); } for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(writer); + extensionGenerator.GenerateStaticVariableInitializers(printer); } - writer->Outdent(); - writer->WriteLine("}"); - writer->WriteLine("#endregion"); - writer->WriteLine(); + printer->Outdent(); + printer->Print("}\n"); + printer->Print("#endregion\n\n"); } bool UmbrellaClassGenerator::uses_extensions() { diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h index 757f8f91..83e1f347 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h @@ -48,7 +48,7 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { UmbrellaClassGenerator(const FileDescriptor* file); ~UmbrellaClassGenerator(); - void Generate(Writer* write); + void Generate(io::Printer* printer); private: const FileDescriptor* file_; @@ -57,10 +57,10 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { std::string umbrellaClassname_; std::string umbrellaNamespace_; - void WriteIntroduction(Writer* writer); - void WriteExtensionRegistration(Writer* writer); - void WriteDescriptor(Writer* writer); - void WriteLiteExtensions(Writer* write); + void WriteIntroduction(io::Printer* printer); + void WriteExtensionRegistration(io::Printer* printer); + void WriteDescriptor(io::Printer* printer); + void WriteLiteExtensions(io::Printer* printer); bool uses_extensions(); -- cgit v1.2.3 From f52426827e4d5e8da7d205af538799740b5199b9 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 5 Jun 2015 20:44:05 +0100 Subject: First stab at new proto3-only code generator --- src/Makefile.am | 6 +- src/google/protobuf/compiler/csharp/csharp_enum.cc | 2 +- .../protobuf/compiler/csharp/csharp_enum_field.cc | 49 +- .../protobuf/compiler/csharp/csharp_extension.cc | 184 ----- .../protobuf/compiler/csharp/csharp_extension.h | 78 -- .../protobuf/compiler/csharp/csharp_field_base.cc | 37 +- .../protobuf/compiler/csharp/csharp_field_base.h | 5 - .../protobuf/compiler/csharp/csharp_message.cc | 855 ++++----------------- .../protobuf/compiler/csharp/csharp_message.h | 14 +- .../compiler/csharp/csharp_message_field.cc | 231 +----- .../compiler/csharp/csharp_message_field.h | 6 - .../compiler/csharp/csharp_primitive_field.cc | 177 +---- .../compiler/csharp/csharp_primitive_field.h | 9 +- .../compiler/csharp/csharp_repeated_enum_field.cc | 131 +--- .../compiler/csharp/csharp_repeated_enum_field.h | 6 +- .../csharp/csharp_repeated_message_field.cc | 120 +-- .../csharp/csharp_repeated_message_field.h | 4 - .../csharp/csharp_repeated_primitive_field.cc | 119 +-- .../csharp/csharp_repeated_primitive_field.h | 4 - .../csharp/csharp_source_generator_base.cc | 8 - .../compiler/csharp/csharp_source_generator_base.h | 17 - .../compiler/csharp/csharp_umbrella_class.cc | 88 +-- .../compiler/csharp/csharp_umbrella_class.h | 7 - .../protobuf/compiler/csharp/csharp_writer.cc | 136 ---- .../protobuf/compiler/csharp/csharp_writer.h | 93 --- vsprojects/libprotoc.vcproj | 4 - 26 files changed, 295 insertions(+), 2095 deletions(-) delete mode 100644 src/google/protobuf/compiler/csharp/csharp_extension.cc delete mode 100644 src/google/protobuf/compiler/csharp/csharp_extension.h delete mode 100644 src/google/protobuf/compiler/csharp/csharp_writer.cc delete mode 100644 src/google/protobuf/compiler/csharp/csharp_writer.h (limited to 'src/google/protobuf/compiler') diff --git a/src/Makefile.am b/src/Makefile.am index 33894dc1..0dc18916 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -369,8 +369,6 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/csharp/csharp_enum.h \ google/protobuf/compiler/csharp/csharp_enum_field.cc \ google/protobuf/compiler/csharp/csharp_enum_field.h \ - google/protobuf/compiler/csharp/csharp_extension.cc \ - google/protobuf/compiler/csharp/csharp_extension.h \ google/protobuf/compiler/csharp/csharp_field_base.cc \ google/protobuf/compiler/csharp/csharp_field_base.h \ google/protobuf/compiler/csharp/csharp_generator.cc \ @@ -391,9 +389,7 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/csharp/csharp_source_generator_base.cc \ google/protobuf/compiler/csharp/csharp_source_generator_base.h \ google/protobuf/compiler/csharp/csharp_umbrella_class.cc \ - google/protobuf/compiler/csharp/csharp_umbrella_class.h \ - google/protobuf/compiler/csharp/csharp_writer.cc \ - google/protobuf/compiler/csharp/csharp_writer.h + google/protobuf/compiler/csharp/csharp_umbrella_class.h bin_PROGRAMS = protoc protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index 0e8f9836..d511bba3 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -58,7 +58,7 @@ EnumGenerator::~EnumGenerator() { void EnumGenerator::Generate(io::Printer* printer) { WriteGeneratedCodeAttributes(printer); - printer->Print("$access_level$ enum $name$ {\n", + printer->Print("$access_level$ enum $name$ : long {\n", "access_level", class_access_level(), "name", descriptor_->name()); printer->Indent(); diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 51a95b9f..8865702d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -55,36 +55,22 @@ EnumFieldGenerator::~EnumFieldGenerator() { void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print(variables_, - "object unknown;\n" - "if(input.ReadEnum(ref result.$name$_, out unknown)) {\n"); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, - " result.has$property_name$ = true;\n"); - } - printer->Print("} else if(unknown is int) {\n"); - if (!use_lite_runtime()) { - printer->Print(variables_, - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); - } - printer->Print("}\n"); + "input.ReadEnum(ref $name$_);\n"); } void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, - "if ($has_property_check$) {\n" - " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" - "}\n"); + "if ($has_property_check$) {\n" + " output.WriteEnum($number$, fieldNames[$field_ordinal$], (long) $property_name$, $property_name$);\n" + "}\n"); } void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( - variables_, - "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" - "}\n"); + variables_, + "if ($has_property_check$) {\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (long) $property_name$);\n" + "}\n"); } EnumOneofFieldGenerator::EnumOneofFieldGenerator(const FieldDescriptor* descriptor, @@ -96,30 +82,21 @@ EnumOneofFieldGenerator::~EnumOneofFieldGenerator() { } void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): What about if we read the default value? printer->Print( variables_, - "object unknown;\n" "$type_name$ enumValue = $default_value$;\n" - "if(input.ReadEnum(ref enumValue, out unknown)) {\n" + "if(input.ReadEnum(ref enumValue)) {\n" " result.$oneof_name$_ = enumValue;\n" " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - "} else if(unknown is int) {\n"); - if (!use_lite_runtime()) { - printer->Print( - variables_, - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)unknown);\n"); - } - printer->Print("}\n"); + "}\n"); } void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, field_names[$field_ordinal$], (int) $property_name$, $property_name$);\n" + " output.WriteEnum($number$, fieldNames[$field_ordinal$], (long) $property_name$, $property_name$);\n" "}\n"); } @@ -127,7 +104,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (long) $property_name$);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.cc b/src/google/protobuf/compiler/csharp/csharp_extension.cc deleted file mode 100644 index 8b665ae4..00000000 --- a/src/google/protobuf/compiler/csharp/csharp_extension.cc +++ /dev/null @@ -1,184 +0,0 @@ -// 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 - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -using google::protobuf::internal::scoped_ptr; - -namespace google { -namespace protobuf { -namespace compiler { -namespace csharp { - -ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) - : FieldGeneratorBase(descriptor, 0) { - if (descriptor_->extension_scope()) { - variables_["scope"] = GetClassName(descriptor_->extension_scope()); - } else { - variables_["scope"] = GetFullUmbrellaClassName(descriptor_->file()); - } - variables_["extends"] = GetClassName(descriptor_->containing_type()); - variables_["capitalized_type_name"] = capitalized_type_name(); - variables_["full_name"] = descriptor_->full_name(); - variables_["access_level"] = class_access_level(); - variables_["index"] = SimpleItoa(descriptor_->index()); - variables_["property_name"] = property_name(); - variables_["type_name"] = type_name(); - if (use_lite_runtime()) { - variables_["generated_extension"] = descriptor_->is_repeated() ? - "GeneratedRepeatExtensionLite" : "GeneratedExtensionLite"; - } else { - variables_["generated_extension"] = descriptor_->is_repeated() ? - "GeneratedRepeatExtension" : "GeneratedExtension"; - } -} - -ExtensionGenerator::~ExtensionGenerator() { -} - -void ExtensionGenerator::Generate(io::Printer* printer) { - printer->Print( - "public const int $constant_name$ = $number$;\n", - "constant_name", GetFieldConstantName(descriptor_), - "number", SimpleItoa(descriptor_->number())); - - if (use_lite_runtime()) { - // TODO(jtattermusch): include the following check - //if (Descriptor.MappedType == MappedType.Message && Descriptor.MessageType.Options.MessageSetWireFormat) - //{ - // throw new ArgumentException( - // "option message_set_wire_format = true; is not supported in Lite runtime extensions."); - //} - - printer->Print( - variables_, - "$access_level$ static pb::$generated_extension$<$extends$, $type_name$> $property_name$;\n"); - } else if (descriptor_->is_repeated()) { - printer->Print( - variables_, - "$access_level$ static pb::GeneratedExtensionBase> $property_name$;\n"); - } else { - printer->Print( - variables_, - "$access_level$ static pb::GeneratedExtensionBase<$type_name$> $property_name$;\n"); - } -} - -void ExtensionGenerator::GenerateStaticVariableInitializers(io::Printer* printer) { - if (use_lite_runtime()) { - printer->Print( - variables_, - "$scope$.$property_name$ = \n"); - printer->Indent(); - printer->Print( - variables_, - "new pb::$generated_extension$<$extends$, $type_name$>(\n"); - printer->Indent(); - printer->Print( - variables_, - "\"$full_name$\",\n" - "$extends$.DefaultInstance,\n"); - if (!descriptor_->is_repeated()) { - std::string default_val; - if (descriptor_->has_default_value()) { - default_val = default_value(); - } else { - default_val = is_nullable_type() ? "null" : ("default(" + type_name() + ")"); - } - printer->Print("$default_val$,\n", "default_val", default_val); - } - printer->Print( - "$message_val$,\n", - "message_val", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_MESSAGE) ? - type_name() + ".DefaultInstance" : "null"); - printer->Print( - "$enum_val$,\n", - "enum_val", - (GetCSharpType(descriptor_->type()) == CSHARPTYPE_ENUM) ? - "new EnumLiteMap<" + type_name() + ">()" : "null"); - printer->Print( - variables_, - "$scope$.$property_name$FieldNumber,\n" - "pbd::FieldType.$capitalized_type_name$"); - if (descriptor_->is_repeated()) { - printer->Print( - ",\n" - "$is_packed$", - "is_packed", descriptor_->is_packed() ? "true" : "false"); - } - printer->Outdent(); - printer->Print(");\n"); - printer->Outdent(); - } - else if (descriptor_->is_repeated()) - { - printer->Print( - variables_, - "$scope$.$property_name$ = pb::GeneratedRepeatExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); - } - else - { - printer->Print( - variables_, - "$scope$.$property_name$ = pb::GeneratedSingleExtension<$type_name$>.CreateInstance($scope$.Descriptor.Extensions[$index$]);\n"); - } -} - -void ExtensionGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { - printer->Print( - variables_, - "registry.Add($scope$.$property_name$);\n"); -} - -void ExtensionGenerator::WriteHash(io::Printer* printer) { -} - -void ExtensionGenerator::WriteEquals(io::Printer* printer) { -} - -void ExtensionGenerator::WriteToString(io::Printer* printer) { -} - -} // namespace csharp -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_extension.h b/src/google/protobuf/compiler/csharp/csharp_extension.h deleted file mode 100644 index f251a21c..00000000 --- a/src/google/protobuf/compiler/csharp/csharp_extension.h +++ /dev/null @@ -1,78 +0,0 @@ -// 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. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ -#define GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ - -#include - -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace csharp { - -class ExtensionGenerator : public FieldGeneratorBase { - public: - ExtensionGenerator(const FieldDescriptor* descriptor); - ~ExtensionGenerator(); - - void GenerateStaticVariableInitializers(io::Printer* printer); - void GenerateExtensionRegistrationCode(io::Printer* printer); - void Generate(io::Printer* printer); - - virtual void WriteHash(io::Printer* printer); - virtual void WriteEquals(io::Printer* printer); - virtual void WriteToString(io::Printer* printer); - - virtual void GenerateMembers(io::Printer* printer) {}; - virtual void GenerateBuilderMembers(io::Printer* printer) {}; - virtual void GenerateMergingCode(io::Printer* printer) {}; - virtual void GenerateBuildingCode(io::Printer* printer) {}; - virtual void GenerateParsingCode(io::Printer* printer) {}; - virtual void GenerateSerializationCode(io::Printer* printer) {}; - virtual void GenerateSerializedSizeCode(io::Printer* printer) {}; - - private: - std::string scope_; - std::string extends_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); -}; - -} // namespace csharp -} // namespace compiler -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_EXTENSION_H__ - diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index c3ce426b..367e54c2 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -263,37 +263,13 @@ bool AllPrintableAscii(const std::string& text) { } std::string FieldGeneratorBase::GetStringDefaultValueInternal() { - if (!descriptor_->has_default_value()) { - return "\"\""; - } - if (AllPrintableAscii(descriptor_->default_value_string())) { - // All chars are ASCII and printable. In this case we only - // need to escape quotes and backslashes. - std::string temp = descriptor_->default_value_string(); - temp = StringReplace(temp, "\\", "\\\\", true); - temp = StringReplace(temp, "'", "\\'", true); - temp = StringReplace(temp, "\"", "\\\"", true); - return "\"" + temp + "\""; - } - if (use_lite_runtime()) { - return "pb::ByteString.FromBase64(\"" - + StringToBase64(descriptor_->default_value_string()) - + "\").ToStringUtf8()"; - } - return "(string) " + GetClassName(descriptor_->containing_type()) - + ".Descriptor.Fields[" + SimpleItoa(descriptor_->index()) - + "].DefaultValue"; + // No other default values needed for proto3... + return "\"\""; } std::string FieldGeneratorBase::GetBytesDefaultValueInternal() { - if (!descriptor_->has_default_value()) { - return "pb::ByteString.Empty"; - } - if (use_lite_runtime()) { - return "pb::ByteString.FromBase64(\"" + StringToBase64(descriptor_->default_value_string()) + "\")"; - } - return "(pb::ByteString) "+ GetClassName(descriptor_->containing_type()) + - ".Descriptor.Fields[" + SimpleItoa(descriptor_->index()) + "].DefaultValue"; + // No other default values needed for proto3... + return "pb::ByteString.Empty"; } std::string FieldGeneratorBase::default_value() { @@ -365,11 +341,6 @@ std::string FieldGeneratorBase::number() { return SimpleItoa(descriptor_->number()); } -std::string FieldGeneratorBase::message_or_group() { - return - (descriptor_->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; -} - std::string FieldGeneratorBase::capitalized_type_name() { switch (descriptor_->type()) { case FieldDescriptor::TYPE_ENUM: diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h index b1570587..1b044a49 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h @@ -42,17 +42,13 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class FieldGeneratorBase : public SourceGeneratorBase { public: FieldGeneratorBase(const FieldDescriptor* descriptor, int fieldOrdinal); ~FieldGeneratorBase(); virtual void GenerateMembers(io::Printer* printer) = 0; - virtual void GenerateBuilderMembers(io::Printer* printer) = 0; virtual void GenerateMergingCode(io::Printer* printer) = 0; - virtual void GenerateBuildingCode(io::Printer* printer) = 0; virtual void GenerateParsingCode(io::Printer* printer) = 0; virtual void GenerateSerializationCode(io::Printer* printer) = 0; virtual void GenerateSerializedSizeCode(io::Printer* printer) = 0; @@ -82,7 +78,6 @@ class FieldGeneratorBase : public SourceGeneratorBase { bool is_nullable_type(); std::string default_value(); std::string number(); - std::string message_or_group(); std::string capitalized_type_name(); std::string field_ordinal(); diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 66b87110..1defcf94 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -43,7 +43,6 @@ #include #include -#include #include #include #include @@ -106,7 +105,7 @@ std::string GetUniqueFileScopeIdentifier(const Descriptor* descriptor) { } void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { - // Because descriptor.proto (Google.ProtocolBuffers.DescriptorProtos) is + // Because descriptor.proto (Google.Protobuf.DescriptorProtos) is // used in the construction of descriptors, we have a tricky bootstrapping // problem. To help control static initialization order, we make sure all // descriptors and other static data that depends on them are members of @@ -115,14 +114,12 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { std::string identifier = GetUniqueFileScopeIdentifier(descriptor_); - if (!use_lite_runtime()) { - // The descriptor for this type. - printer->Print( - "internal static pbd::MessageDescriptor internal__$identifier$__Descriptor;\n" - "internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder> internal__$identifier$__FieldAccessorTable;\n", - "identifier", GetUniqueFileScopeIdentifier(descriptor_), - "full_class_name", full_class_name()); - } + // The descriptor for this type. + printer->Print( + "internal static pbd::MessageDescriptor internal__$identifier$__Descriptor;\n" + "internal static pb::FieldAccess.FieldAccessorTable<$full_class_name$> internal__$identifier$__FieldAccessorTable;\n", + "identifier", GetUniqueFileScopeIdentifier(descriptor_), + "full_class_name", full_class_name()); for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); @@ -139,139 +136,106 @@ void MessageGenerator::GenerateStaticVariableInitializers(io::Printer* printer) vars["parent"] = GetUniqueFileScopeIdentifier( descriptor_->containing_type()); } - if (!use_lite_runtime()) { - printer->Print(vars, "internal__$identifier$__Descriptor = "); + printer->Print(vars, "internal__$identifier$__Descriptor = "); - if (!descriptor_->containing_type()) { - printer->Print(vars, "Descriptor.MessageTypes[$index$];\n"); - } else { - printer->Print(vars, "internal__$parent$__Descriptor.NestedTypes[$index$];\n"); - } + if (!descriptor_->containing_type()) { + printer->Print(vars, "Descriptor.MessageTypes[$index$];\n"); + } else { + printer->Print(vars, "internal__$parent$__Descriptor.NestedTypes[$index$];\n"); + } - printer->Print( - vars, - "internal__$identifier$__FieldAccessorTable = \n" - " new pb::FieldAccess.FieldAccessorTable<$full_class_name$, $full_class_name$.Builder>(internal__$identifier$__Descriptor,\n"); - printer->Print(" new string[] { "); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print("\"$property_name$\", ", - "property_name", GetPropertyName(descriptor_->field(i))); - } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("\"$oneof_name$\", ", - "oneof_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - printer->Print("});\n"); + printer->Print( + vars, + "internal__$identifier$__FieldAccessorTable = \n" + " new pb::FieldAccess.FieldAccessorTable<$full_class_name$>(internal__$identifier$__Descriptor,\n"); + printer->Print(" new string[] { "); + for (int i = 0; i < descriptor_->field_count(); i++) { + printer->Print("\"$property_name$\", ", + "property_name", GetPropertyName(descriptor_->field(i))); + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print("\"$oneof_name$\", ", + "oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); } + printer->Print("});\n"); // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { MessageGenerator messageGenerator(descriptor_->nested_type(i)); messageGenerator.GenerateStaticVariableInitializers(printer); } - - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); - } } void MessageGenerator::Generate(io::Printer* printer) { map vars; vars["class_name"] = class_name(); vars["access_level"] = class_access_level(); - vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? - "Extendable" : "Generated"; - vars["suffix"] = runtime_suffix(); vars["umbrella_class_name"] = GetFullUmbrellaClassName(descriptor_->file()); vars["identifier"] = GetUniqueFileScopeIdentifier(descriptor_); printer->Print( - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); WriteGeneratedCodeAttributes(printer); printer->Print( vars, - "$access_level$ sealed partial class $class_name$ : pb::$extendable_or_generated$Message$suffix$<$class_name$, $class_name$.Builder> {\n"); + "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n"); printer->Indent(); - printer->Print( - vars, - "private $class_name$() { }\n" // Private ctor. - // Must call MakeReadOnly() to make sure all lists are made read-only - "private static readonly $class_name$ defaultInstance = new $class_name$().MakeReadOnly();\n"); - if (optimize_speed()) { - printer->Print( - "private static readonly string[] _$name$FieldNames = " - "new string[] { $slash$$field_names$$slash$ };\n", - "name", UnderscoresToCamelCase(class_name(), false), - "field_names", JoinStrings(field_names(), "\", \""), + // All static fields and properties + printer->Print( + "private static readonly string[] _fieldNames = " + "new string[] { $slash$$field_names$$slash$ };\n", + "field_names", JoinStrings(field_names(), "\", \""), "slash", field_names().size() > 0 ? "\"" : ""); - std::vector tags; - for (int i = 0; i < field_names().size(); i++) { - uint32 tag = internal::WireFormat::MakeTag( - descriptor_->FindFieldByName(field_names()[i])); - tags.push_back(SimpleItoa(tag)); - } - printer->Print( - "private static readonly uint[] _$name$FieldTags = new uint[] { $tags$ };\n", - "name", UnderscoresToCamelCase(class_name(), false), - "tags", JoinStrings(tags, ", ")); + std::vector tags; + for (int i = 0; i < field_names().size(); i++) { + uint32 tag = internal::WireFormat::MakeTag( + descriptor_->FindFieldByName(field_names()[i])); + tags.push_back(SimpleItoa(tag)); } + printer->Print( + "private static readonly uint[] _fieldTags = new uint[] { $tags$ };\n", + "tags", JoinStrings(tags, ", ")); + printer->Print( vars, - "public static $class_name$ DefaultInstance {\n" - " get { return defaultInstance; }\n" + "public static pbd::MessageDescriptor Descriptor {\n" + " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n" "}\n" "\n" - "public override $class_name$ DefaultInstanceForType {\n" - " get { return DefaultInstance; }\n" + "protected override pb::FieldAccess.FieldAccessorTable<$class_name$> InternalFieldAccessors {\n" + " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" "}\n" - "\n" - "protected override $class_name$ ThisMessage {\n" - " get { return this; }\n" - "}\n\n"); + "\n"); - if (!use_lite_runtime()) { - printer->Print( - vars, - "public static pbd::MessageDescriptor Descriptor {\n" - " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n" - "}\n" - "\n" - "protected override pb::FieldAccess.FieldAccessorTable<$class_name$, $class_name$.Builder> InternalFieldAccessors {\n" - " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" - "}\n" - "\n"); - } + // Constructors + printer->Print( + vars, + "public $class_name$() { }\n"); // Public parameterless ctor. - // Extensions don't need to go in an extra nested type - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.Generate(printer); - } + printer->Print( + vars, + "public $class_name$($class_name$ other) {\n" + " MergeWith(other);\n" + "}\n"); // Merge ctor. - if (descriptor_->enum_type_count() + descriptor_->nested_type_count() > 0) { - printer->Print("#region Nested types\n" - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print("public static partial class Types {\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator enumGenerator(descriptor_->enum_type(i)); - enumGenerator.Generate(printer); - } - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.Generate(printer); - } - printer->Outdent(); - printer->Print("}\n" - "#endregion\n" - "\n"); + // Fields/properties + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + + // Rats: we lose the debug comment here :( + printer->Print( + "public const int $field_constant_name$ = $index$;\n", + "field_constant_name", GetFieldConstantName(fieldDescriptor), + "index", SimpleItoa(fieldDescriptor->number())); + scoped_ptr generator( + CreateFieldGeneratorInternal(fieldDescriptor)); + generator->GenerateMembers(printer); + printer->Print("\n"); } - // oneof + // oneof properties for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); @@ -280,13 +244,13 @@ void MessageGenerator::Generate(io::Printer* printer) { "private object $name$_;\n" "public enum $property_name$OneofCase {\n"); printer->Indent(); + printer->Print("None = 0,\n"); for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); printer->Print("$field_property_name$ = $index$,\n", "field_property_name", GetPropertyName(field), "index", SimpleItoa(field->number())); } - printer->Print("None = 0,\n"); printer->Outdent(); printer->Print("}\n"); printer->Print( @@ -294,243 +258,78 @@ void MessageGenerator::Generate(io::Printer* printer) { "private $property_name$OneofCase $name$Case_ = $property_name$OneofCase.None;\n" "public $property_name$OneofCase $property_name$Case {\n" " get { return $name$Case_; }\n" + "}\n\n" + "private Clear$property_name$() {;\n" + " $name$Case_ = $property_name$OneofCase.None;" + " $name$_ = null;" "}\n\n"); } - // Fields - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* fieldDescriptor = descriptor_->field(i); + // TODO(jonskeet): Map properties - // Rats: we lose the debug comment here :( - printer->Print( - "public const int $field_constant_name$ = $index$;\n", - "field_constant_name", GetFieldConstantName(fieldDescriptor), - "index", SimpleItoa(fieldDescriptor->number())); - scoped_ptr generator( - CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateMembers(printer); - printer->Print("\n"); - } + // Standard methods + GenerateMessageSerializationMethods(printer); + GenerateMergingMethods(printer); - if (optimize_speed()) { - if (SupportFieldPresence(descriptor_->file())) { - GenerateIsInitialized(printer); + // Nested messages and enums + if (descriptor_->enum_type_count() + descriptor_->nested_type_count() > 0) { + printer->Print("#region Nested types\n" + "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); + WriteGeneratedCodeAttributes(printer); + printer->Print("public static partial class Types {\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->enum_type_count(); i++) { + EnumGenerator enumGenerator(descriptor_->enum_type(i)); + enumGenerator.Generate(printer); } - GenerateMessageSerializationMethods(printer); - } - if (use_lite_runtime()) { - GenerateLiteRuntimeMethods(printer); - } - - GenerateParseFromMethods(printer); - GenerateBuilder(printer); - - // Force the static initialization code for the file to run, since it may - // initialize static variables declared in this class. - printer->Print(vars, "static $class_name$() {\n"); - // We call object.ReferenceEquals() just to make it a valid statement on its own. - // Another option would be GetType(), but that causes problems in DescriptorProtoFile, - // where the bootstrapping is somewhat recursive - type initializers call - // each other, effectively. We temporarily see Descriptor as null. - printer->Print( - vars, - " object.ReferenceEquals($umbrella_class_name$.Descriptor, null);\n" - "}\n"); - - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - -} - -void MessageGenerator::GenerateLiteRuntimeMethods(io::Printer* printer) { - map vars; - vars["class_name"] = class_name(); - - bool callbase = descriptor_->extension_range_count() > 0; - printer->Print("#region Lite runtime methods\n" - "public override int GetHashCode() {\n"); - printer->Indent(); - printer->Print("int hash = GetType().GetHashCode();\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - if (field->containing_oneof() == NULL) { - scoped_ptr generator( - CreateFieldGeneratorInternal(field)); - generator->WriteHash(printer); + for (int i = 0; i < descriptor_->nested_type_count(); i++) { + MessageGenerator messageGenerator(descriptor_->nested_type(i)); + messageGenerator.Generate(printer); } - } - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print( - "if ($name$Case_ != $property_name$OneofCase.None) {\n" - " hash ^= $name$_.GetHashCode();\n" - "}\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), - "property_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - if (callbase) { - printer->Print("hash ^= base.GetHashCode();\n"); - } - printer->Print("return hash;\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - - printer->Print("public override bool Equals(object obj) {\n"); - printer->Indent(); - printer->Print( - vars, - "$class_name$ other = obj as $class_name$;\n" - "if (other == null) return false;\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->WriteEquals(printer); - } - if (callbase) { - printer->Print("if (!base.Equals(other)) return false;\n"); - } - printer->Print("return true;\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - - printer->Print( - "public override void PrintTo(global::System.IO.TextWriter writer) {\n"); - printer->Indent(); - - for (int i = 0; i < fields_by_number().size(); i++) { - scoped_ptr generator( - CreateFieldGeneratorInternal(fields_by_number()[i])); - generator->WriteToString(printer); + printer->Outdent(); + printer->Print("}\n" + "#endregion\n" + "\n"); } - if (callbase) { - printer->Print("base.PrintTo(writer);\n"); - } printer->Outdent(); printer->Print("}\n"); - printer->Print("#endregion\n"); printer->Print("\n"); -} -bool CompareExtensionRangesStart(const Descriptor::ExtensionRange* r1, - const Descriptor::ExtensionRange* r2) { - return r1->start < r2->start; } void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { - std::vector extension_ranges_sorted; - for (int i = 0; i < descriptor_->extension_range_count(); i++) { - extension_ranges_sorted.push_back(descriptor_->extension_range(i)); - } - std::sort(extension_ranges_sorted.begin(), extension_ranges_sorted.end(), - CompareExtensionRangesStart); - printer->Print( - "public override void WriteTo(pb::ICodedOutputStream output) {\n"); + "public void WriteTo(pb::ICodedOutputStream output) {\n"); printer->Indent(); - // Make sure we've computed the serialized length, so that packed fields are generated correctly. - printer->Print("CalcSerializedSize();\n" - "string[] field_names = _$class_name$FieldNames;\n", - "class_name", UnderscoresToCamelCase(class_name(), false)); - if (descriptor_->extension_range_count()) { - printer->Print( - "pb::ExtendableMessage$runtime_suffix$<$class_name$, $class_name$.Builder>.ExtensionWriter extensionWriter = CreateExtensionWriter(this);\n", - "class_name", class_name(), - "runtime_suffix", runtime_suffix()); - } - - // Merge the fields and the extension ranges, both sorted by field number. - for (int i = 0, j = 0; - i < fields_by_number().size() || j < extension_ranges_sorted.size();) { - if (i == fields_by_number().size()) { - GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); - } else if (j == extension_ranges_sorted.size()) { - GenerateSerializeOneField(printer, fields_by_number()[i++]); - } else if (fields_by_number()[i]->number() - < extension_ranges_sorted[j]->start) { - GenerateSerializeOneField(printer, fields_by_number()[i++]); - } else { - GenerateSerializeOneExtensionRange(printer, extension_ranges_sorted[j++]); - } - } + printer->Print("string[] fieldNames = _fieldNames;\n"); - if (!use_lite_runtime()) { - if (descriptor_->options().message_set_wire_format()) - { - printer->Print("UnknownFields.WriteAsMessageSetTo(output);\n"); - } else { - printer->Print("UnknownFields.WriteTo(output);\n"); - } + // Serialize all the fields + for (int i = 0; i < fields_by_number().size(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(fields_by_number()[i])); + generator->GenerateSerializationCode(printer); } + // TODO(jonskeet): Memoize size of frozen messages? printer->Outdent(); printer->Print( "}\n" "\n" - "private int memoizedSerializedSize = -1;\n" - "public override int SerializedSize {\n"); + "public int CalculateSerializedSize() {\n"); printer->Indent(); - printer->Print("get {\n"); - printer->Indent(); - printer->Print( - "int size = memoizedSerializedSize;\n" - "if (size != -1) return size;\n" - "return CalcSerializedSize();\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - - printer->Print("private int CalcSerializedSize() {\n"); - printer->Indent(); - printer->Print( - "int size = memoizedSerializedSize;\n" - "if (size != -1) return size;\n" - "\n" - "size = 0;\n"); + printer->Print("int size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { scoped_ptr generator( CreateFieldGeneratorInternal(descriptor_->field(i))); generator->GenerateSerializedSizeCode(printer); } - if (descriptor_->extension_range_count() > 0) { - printer->Print("size += ExtensionsSerializedSize;\n"); - } - - if (!use_lite_runtime()) { - if (descriptor_->options().message_set_wire_format()) { - printer->Print("size += UnknownFields.SerializedSizeAsMessageSet;\n"); - } else { - printer->Print("size += UnknownFields.SerializedSize;\n"); - } - } - printer->Print( - "memoizedSerializedSize = size;\n" - "return size;\n"); + printer->Print("return size;\n"); printer->Outdent(); printer->Print("}\n"); } -void MessageGenerator::GenerateSerializeOneField( - io::Printer* printer, const FieldDescriptor* fieldDescriptor) { - scoped_ptr generator( - CreateFieldGeneratorInternal(fieldDescriptor)); - generator->GenerateSerializationCode(printer); -} - -void MessageGenerator::GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* extensionRange) { - printer->Print("extensionWriter.WriteUntil($range_end$, output);\n", - "range_end", SimpleItoa(extensionRange->end)); -} - -void MessageGenerator::GenerateParseFromMethods(io::Printer* printer) { +void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized // for code size. @@ -539,339 +338,72 @@ void MessageGenerator::GenerateParseFromMethods(io::Printer* printer) { printer->Print( vars, - "public static $class_name$ ParseFrom(pb::ByteString data) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ByteString data, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(byte[] data) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(byte[] data, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(data, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(global::System.IO.Stream input) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input) {\n" - " return CreateBuilder().MergeDelimitedFrom(input).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseDelimitedFrom(global::System.IO.Stream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return CreateBuilder().MergeDelimitedFrom(input, extensionRegistry).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ICodedInputStream input) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input)).BuildParsed();\n" - "}\n" - "public static $class_name$ ParseFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n" - " return ((Builder) CreateBuilder().MergeFrom(input, extensionRegistry)).BuildParsed();\n" - "}\n"); -} - -void MessageGenerator::GenerateBuilder(io::Printer* printer) { - map vars; - vars["class_name"] = class_name(); - vars["access_level"] = class_access_level(); - vars["extendable_or_generated"] = descriptor_->extension_range_count() > 0 ? - "Extendable" : "Generated"; - vars["suffix"] = runtime_suffix(); - - printer->Print(vars, "private $class_name$ MakeReadOnly() {\n"); - printer->Indent(); - for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateBuildingCode(printer); - } - printer->Print("return this;\n"); - printer->Outdent(); - printer->Print("}\n\n"); - - printer->Print( - vars, - "public static Builder CreateBuilder() { return new Builder(); }\n" - "public override Builder ToBuilder() { return CreateBuilder(this); }\n" - "public override Builder CreateBuilderForType() { return new Builder(); }\n" - "public static Builder CreateBuilder($class_name$ prototype) {\n" - " return new Builder(prototype);\n" - "}\n" - "\n" - "[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]\n"); - WriteGeneratedCodeAttributes(printer); - printer->Print( - vars, - "$access_level$ sealed partial class Builder : pb::$extendable_or_generated$Builder$suffix$<$class_name$, Builder> {\n"); + "public void MergeWith($class_name$ other) {\n"); printer->Indent(); printer->Print( - "protected override Builder ThisBuilder {\n" - " get { return this; }\n" + "if (other == null) {\n" + " return;\n" "}\n"); - GenerateCommonBuilderMethods(printer); - if (optimize_speed()) { - GenerateBuilderParsingMethods(printer); - } + // TODO(jonskeet): Maps? + // Merge non-oneof fields for (int i = 0; i < descriptor_->field_count(); i++) { - scoped_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - printer->Print("\n"); - // No field comment :( - generator->GenerateBuilderMembers(printer); - } - - // oneof - for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { - printer->Print("\n"); - string name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - string property_name = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print( - "public $property_name$OneofCase $property_name$Case {\n" - " get { return result.$name$Case_; }\n" - "}\n" - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_ = null;\n" - " result.$name$Case_ = $property_name$OneofCase.None;\n" - " return this;\n" - "}\n", - "name", UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false), - "property_name", - UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); - } - - printer->Outdent(); - printer->Print("}\n"); -} - -void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { - map vars; - vars["class_name"] = class_name(); - vars["full_class_name"] = full_class_name(); - vars["suffix"] = runtime_suffix(); - - printer->Print( - vars, - //default constructor - "public Builder() {\n" - //Durring static initialization of message, DefaultInstance is expected to return null. - " result = DefaultInstance;\n" - " resultIsReadOnly = true;\n" - "}\n" - //clone constructor - "internal Builder($class_name$ cloneFrom) {\n" - " result = cloneFrom;\n" - " resultIsReadOnly = true;\n" - "}\n" - "\n" - "private bool resultIsReadOnly;\n" - "private $class_name$ result;\n" - "\n" - "private $class_name$ PrepareBuilder() {\n" - " if (resultIsReadOnly) {\n" - " $class_name$ original = result;\n" - " result = new $class_name$();\n" - " resultIsReadOnly = false;\n" - " MergeFrom(original);\n" - " }\n" - " return result;\n" - "}\n" - "\n" - "public override bool IsInitialized {\n" - " get { return result.IsInitialized; }\n" - "}\n" - "\n" - "protected override $class_name$ MessageBeingBuilt {\n" - " get { return PrepareBuilder(); }\n" - "}\n" - "\n"); - //Not actually expecting that DefaultInstance would ever be null here; however, we will ensure it does not break - printer->Print( - "public override Builder Clear() {\n" - " result = DefaultInstance;\n" - " resultIsReadOnly = true;\n" - " return this;\n" - "}\n" - "\n" - "public override Builder Clone() {\n" - " if (resultIsReadOnly) {\n" - " return new Builder(result);\n" - " } else {\n" - " return new Builder().MergeFrom(result);\n" - " }\n" - "}\n" - "\n"); - if (!use_lite_runtime()) { - printer->Print( - vars, - "public override pbd::MessageDescriptor DescriptorForType {\n" - " get { return $full_class_name$.Descriptor; }\n" - "}\n\n"); + if (!descriptor_->field(i)->containing_oneof()) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->GenerateMergingCode(printer); + } } - printer->Print( - vars, - "public override $class_name$ DefaultInstanceForType {\n" - " get { return $full_class_name$.DefaultInstance; }\n" - "}\n\n"); - - printer->Print( - vars, - "public override $class_name$ BuildPartial() {\n" - " if (resultIsReadOnly) {\n" - " return result;\n" - " }\n" - " resultIsReadOnly = true;\n" - " return result.MakeReadOnly();\n" - "}\n\n"); - - if (optimize_speed()) { - printer->Print( - vars, - "public override Builder MergeFrom(pb::IMessage$suffix$ other) {\n" - " if (other is $class_name$) {\n" - " return MergeFrom(($class_name$) other);\n" - " } else {\n" - " base.MergeFrom(other);\n" - " return this;\n" - " }\n" - "}\n\n"); - - printer->Print(vars,"public override Builder MergeFrom($class_name$ other) {\n"); - // Optimization: If other is the default instance, we know none of its - // fields are set so we can skip the merge. + // Merge oneof fields + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); + vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); + printer->Print(vars, "switch (other.$property_name$Case) {\n"); printer->Indent(); - printer->Print( - vars, - "if (other == $full_class_name$.DefaultInstance) return this;\n" - "PrepareBuilder();\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - if (!descriptor_->field(i)->containing_oneof()) { - scoped_ptr generator( - CreateFieldGeneratorInternal(descriptor_->field(i))); - generator->GenerateMergingCode(printer); - } - } - - // Merge oneof fields - for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { - vars["name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), false); - vars["property_name"] = UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true); - printer->Print(vars, "switch (other.$property_name$Case) {\n"); - printer->Indent(); - for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { - const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); - vars["field_property_name"] = GetPropertyName(field); - printer->Print( - vars, - "case $property_name$OneofCase.$field_property_name$: {\n"); - if (field->type() == FieldDescriptor::TYPE_GROUP || - field->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print( - vars, - " Merge$field_property_name$(other.$field_property_name$);\n"); - } else { - printer->Print( - vars, - " Set$field_property_name$(other.$field_property_name$);\n"); - } - printer->Print(" break;\n"); - printer->Print("}\n"); - } - printer->Print(vars, "case $property_name$OneofCase.None: { break; }\n"); - printer->Outdent(); - printer->Print("}\n"); - } - - // if message type has extensions - if (descriptor_->extension_range_count() > 0) { - printer->Print(" this.MergeExtensionFields(other);\n"); - } - if (!use_lite_runtime()) { - printer->Print("this.MergeUnknownFields(other.UnknownFields);\n"); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + vars["field_property_name"] = GetPropertyName(field); + printer->Print( + vars, + "case $property_name$OneofCase.$field_property_name$:\n" + " $field_property_name$ = other.$field_property_name$;\n" + " break;\n"); } - printer->Print("return this;\n"); printer->Outdent(); printer->Print("}\n\n"); } - -} - -void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { - printer->Print( - "public override Builder MergeFrom(pb::ICodedInputStream input) {\n" - " return MergeFrom(input, pb::ExtensionRegistry.Empty);\n" - "}\n\n"); - - printer->Print( - "public override Builder MergeFrom(pb::ICodedInputStream input, pb::ExtensionRegistry extensionRegistry) {\n"); + printer->Outdent(); + printer->Print("}\n\n"); + printer->Print("public void MergeFrom(pb::ICodedInputStream input) {\n"); printer->Indent(); - printer->Print("PrepareBuilder();\n"); - if (!use_lite_runtime()) { - printer->Print("pb::UnknownFieldSet.Builder unknownFields = null;\n"); - } printer->Print( "uint tag;\n" - "string field_name;\n" - "while (input.ReadTag(out tag, out field_name)) {\n"); + "string fieldName;\n" + "while (input.ReadTag(out tag, out fieldName)) {\n" + " if (tag == 0 && fieldName != null) {"); printer->Indent(); - printer->Print("if(tag == 0 && field_name != null) {\n"); printer->Indent(); - //if you change from StringComparer.Ordinal, the array sort in FieldNames { get; } must also change - printer->Print( - "int field_ordinal = global::System.Array.BinarySearch(_$camel_class_name$FieldNames, field_name, global::System.StringComparer.Ordinal);\n" - "if(field_ordinal >= 0)\n" - " tag = _$camel_class_name$FieldTags[field_ordinal];\n" - "else {\n", - "camel_class_name", UnderscoresToCamelCase(class_name(), false)); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n"); - } printer->Print( - " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", - "prefix", use_lite_runtime() ? "" : "unknownFields, "); - printer->Print(" continue;\n"); - printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); - - printer->Print("switch (tag) {\n"); + "int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.String.String.Ordinal);\n" + "if (fieldOrdinal >= 0) {\n" + " tag = _fieldTags[fieldOrdinal];\n" + "}\n" + "switch(tag) {\n"); printer->Indent(); printer->Print( "case 0: {\n" // 0 signals EOF / limit reached " throw pb::InvalidProtocolBufferException.InvalidTag();\n" "}\n" - "default: {\n" - " if (pb::WireFormat.IsEndGroupTag(tag)) {\n"); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields != null) {\n" - " this.UnknownFields = unknownFields.Build();\n" - " }\n"); - } - printer->Print( - " return this;\n" // it's an endgroup tag - " }\n"); - if (!use_lite_runtime()) { - printer->Print( - " if (unknownFields == null) {\n" // First unknown field - create builder now - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n"); - } - printer->Print( - " ParseUnknownField(input, $prefix$extensionRegistry, tag, field_name);\n", - "prefix", use_lite_runtime() ? "" : "unknownFields, "); - printer->Print(" break;\n"); - printer->Print("}\n"); - + "default:\n" + " if (pb::WireFormat.IsEndGroupTag(tag)) {\n" + " return;\n" + " }\n" + " break;"); // Note: we're ignoring unknown fields here. for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; internal::WireFormatLite::WireType wt = internal::WireFormat::WireTypeForFieldType(field->type()); uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt); + // TODO(jonskeet): Understand what this is trying to do if (field->is_repeated() && (wt == internal::WireFormatLite::WIRETYPE_VARINT || wt == internal::WireFormatLite::WIRETYPE_FIXED32 @@ -894,95 +426,14 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { printer->Outdent(); printer->Print("}\n"); } - - printer->Outdent(); - printer->Print("}\n"); printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); - if (!use_lite_runtime()) { - printer->Print( - "if (unknownFields != null) {\n" - " this.UnknownFields = unknownFields.Build();\n" - "}\n"); - } - printer->Print("return this;\n"); + printer->Print("}\n"); // switch printer->Outdent(); - printer->Print("}\n\n"); -} - -void MessageGenerator::GenerateIsInitialized(io::Printer* printer) { - printer->Print("public override bool IsInitialized {\n"); - printer->Indent(); - printer->Print("get {\n"); - printer->Indent(); - - // Check that all required fields in this message are set. - // TODO(kenton): We can optimize this when we switch to putting all the - // "has" fields into a single bitfield. - for (int i = 0; i < descriptor_->field_count(); i++) { - if (descriptor_->field(i)->is_required()) { - printer->Print("if (!has$property_name$) return false;\n", - "property_name", GetPropertyName(descriptor_->field(i))); - } - } - - // Now check that all embedded messages are initialized. - for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldDescriptor* field = descriptor_->field(i); - - if (field->type() != FieldDescriptor::TYPE_MESSAGE || - !HasRequiredFields(field->message_type())) - { - continue; - } - // TODO(jtattermusch): shouldn't we use GetPropertyName here? - string propertyName = UnderscoresToPascalCase(GetFieldName(field)); - if (field->is_repeated()) - { - printer->Print( - "foreach ($class_name$ element in $property_name$List) {\n" - " if (!element.IsInitialized) return false;\n" - "}\n", - "class_name", GetClassName(field->message_type()), - "property_name", propertyName); - } - else if (field->is_optional()) - { - printer->Print( - "if (Has$property_name$) {\n" - " if (!$property_name$.IsInitialized) return false;\n" - "}\n", - "property_name", propertyName); - } - else - { - printer->Print( - "if (!$property_name$.IsInitialized) return false;\n", - "property_name", propertyName); - } - } - - if (descriptor_->extension_range_count() > 0) { - printer->Print("if (!ExtensionsAreInitialized) return false;\n"); - } - printer->Print("return true;\n"); + printer->Print("}\n"); // if printer->Outdent(); - printer->Print("}\n"); + printer->Print("}\n"); // while printer->Outdent(); - printer->Print("}\n"); - printer->Print("\n"); -} - -void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { - for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(descriptor_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(printer); - } - for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(printer); - } + printer->Print("}\n\n"); // method } int MessageGenerator::GetFieldOrdinal(const FieldDescriptor* descriptor) { diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index ebe58618..f5f41c73 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -43,7 +43,6 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; class FieldGeneratorBase; class MessageGenerator : public SourceGeneratorBase { @@ -53,7 +52,6 @@ class MessageGenerator : public SourceGeneratorBase { void GenerateStaticVariables(io::Printer* printer); void GenerateStaticVariableInitializers(io::Printer* printer); - void GenerateExtensionRegistrationCode(io::Printer* printer); void Generate(io::Printer* printer); private: @@ -61,17 +59,8 @@ class MessageGenerator : public SourceGeneratorBase { std::vector field_names_; std::vector fields_by_number_; - void GenerateLiteRuntimeMethods(io::Printer* printer); void GenerateMessageSerializationMethods(io::Printer* printer); - void GenerateSerializeOneField(io::Printer* printer, - const FieldDescriptor* fieldDescriptor); - void GenerateSerializeOneExtensionRange( - io::Printer* printer, const Descriptor::ExtensionRange* extendsionRange); - void GenerateParseFromMethods(io::Printer* printer); - void GenerateBuilder(io::Printer* printer); - void GenerateCommonBuilderMethods(io::Printer* printer); - void GenerateBuilderParsingMethods(io::Printer* printer); - void GenerateIsInitialized(io::Printer* printer); + void GenerateMergingMethods(io::Printer* printer); int GetFieldOrdinal(const FieldDescriptor* descriptor); FieldGeneratorBase* CreateFieldGeneratorInternal( @@ -95,4 +84,3 @@ class MessageGenerator : public SourceGeneratorBase { } // namespace google #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_H__ - diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 50eb9df6..90aa201b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -49,8 +49,8 @@ namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - variables_["has_property_check"] = "has" + property_name(); - variables_["message_or_group"] = message_or_group(); + variables_["has_property_check"] = property_name() + "_ != null"; + variables_["has_not_property_check"] = property_name() + "_ == null"; } MessageFieldGenerator::~MessageFieldGenerator() { @@ -60,125 +60,42 @@ MessageFieldGenerator::~MessageFieldGenerator() { void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, - "private bool has$property_name$;\n" "private $type_name$ $name$_;\n"); AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return has$property_name$; }\n" - "}\n"); - AddDeprecatedFlag(printer); printer->Print( variables_, "public $type_name$ $property_name$ {\n" - " get { return $name$_ ?? $default_value$; }\n" - "}\n"); -} - -void MessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return result.has$property_name$; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$property_name$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.has$property_name$ = true;\n" - " result.$name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.has$property_name$ = true;\n" - " result.$name$_ = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Merge$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " if (result.has$property_name$ &&\n" - " result.$name$_ != $default_value$) {\n" - " result.$name$_ = $type_name$.CreateBuilder(result.$name$_).MergeFrom(value).BuildPartial();\n" - " } else {\n" - " result.$name$_ = value;\n" - " }\n" - " result.has$property_name$ = true;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.has$property_name$ = false;\n" - " result.$name$_ = null;\n" - " return this;\n" + " get { return $name$_; }\n" + " set { return $name$_ = value; }\n" "}\n"); } void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.Has$property_name$) {\n" - " Merge$property_name$(other.$property_name$);\n" + "if (other.$has_property_check$) {\n" + " if ($has_not_property_check) {\n" + " $name$_ = new $type_name$();\n" + " }\n" + " $property_name$.MergeWith(other.$property_name);\n" "}\n"); } -void MessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - // Nothing to do for singular fields -} - void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" - "if (result.has$property_name$) {\n" - " subBuilder.MergeFrom($property_name$);\n" - "}\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print( - variables_, - "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); - } else { - printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); - } - printer->Print( - variables_, - "$property_name$ = subBuilder.BuildPartial();\n"); + "if ($has_not_property_check) {\n" + " $name$_ = new $type_name$();\n" + "}\n" + "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... } void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + // TODO(jonskeet): Why are we using array access instead of a literal here? printer->Print( variables_, "if ($has_property_check$) {\n" - " output.Write$message_or_group$($number$, field_names[$field_ordinal$], $property_name$);\n" + " output.WriteMessage($number$, fieldNames[$field_ordinal$], $property_name$);\n" "}\n"); } @@ -186,19 +103,19 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, $property_name$);\n" + " size += pb::CodedOutputStream.ComputeMessageSize($number$, $property_name$);\n" "}\n"); } void MessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if (has$property_name$) hash ^= $name$_.GetHashCode();\n"); + "if ($has_property_check$) hash ^= $name$_.GetHashCode();\n"); } void MessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); + "if (!object.Equals($property_name$_, other.$property_name$_)) return false;\n"); } void MessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); @@ -218,118 +135,30 @@ MessageOneofFieldGenerator::~MessageOneofFieldGenerator() { } void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return $has_property_check$; }\n" - "}\n"); - } AddDeprecatedFlag(printer); printer->Print( variables_, "public $type_name$ $property_name$ {\n" - " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - "}\n"); -} - -void MessageOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return result.$has_property_check$; }\n" - "}\n"); - } - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " result.$oneof_name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " result.$oneof_name$_ = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Merge$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " if (result.$has_property_check$ &&\n" - " result.$property_name$ != $default_value$) {\n" - " result.$oneof_name$_ = $type_name$.CreateBuilder(result.$property_name$).MergeFrom(value).BuildPartial();\n" - " } else {\n" - " result.$oneof_name$_ = value;\n" - " }\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " if (result.$has_property_check$) {\n" - " PrepareBuilder();\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" - " result.$oneof_name$_ = null;\n" - " }\n" - " return this;\n" + " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n" + " set { \n" + " $name$_ = value;" + " $oneof_name$Case_ = value == null ? $oneof_property_name$Case.None : $oneof_property_name$Case.$property_name$; }\n" + " } \n" "}\n"); } void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): We may be able to do better than this printer->Print( variables_, - "$type_name$.Builder subBuilder = $type_name$.CreateBuilder();\n" - "if (result.$has_property_check$) {\n" - " subBuilder.MergeFrom($property_name$);\n" - "}\n"); - - if (descriptor_->type() == FieldDescriptor::TYPE_GROUP) { - printer->Print( - variables_, - "input.ReadGroup($number$, subBuilder, extensionRegistry);\n"); - } else { - printer->Print("input.ReadMessage(subBuilder, extensionRegistry);\n"); - } - printer->Print( - variables_, - "result.$oneof_name$_ = subBuilder.BuildPartial();\n" - "result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); + "$type_name$ subBuilder = new type_name$();\n" + "if ($has_property_check$) {\n" + " subBuilder.MergeWith($property_name$);\n" + "}\n" + "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP + "$oneof_property_name$ = subBuilder;\n"); } -void MessageOneofFieldGenerator::WriteEquals(io::Printer* printer) { - printer->Print( - variables_, - "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); -} void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { printer->Print( variables_, diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h index d820908c..02053b4f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h @@ -41,17 +41,13 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class MessageFieldGenerator : public FieldGeneratorBase { public: MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~MessageFieldGenerator(); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); @@ -70,8 +66,6 @@ class MessageOneofFieldGenerator : public MessageFieldGenerator { ~MessageOneofFieldGenerator(); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); - virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index 652eb6b9..bc4858fc 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -49,82 +49,37 @@ namespace csharp { PrimitiveFieldGenerator::PrimitiveFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + // TODO(jonskeet): Make this cleaner... + is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING + && descriptor->type() != FieldDescriptor::TYPE_BYTES; } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { - } void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print(variables_, "private bool has$property_name$;\n"); - } + // TODO(jonskeet): Work out whether we want to prevent the fields from ever being + // null, or whether we just handle it, in the cases of bytes and string. + // (Basically, should null-handling code be in the getter or the setter?) printer->Print( variables_, "private $type_name$ $name_def_message$;\n"); AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return has$property_name$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); printer->Print( variables_, "public $type_name$ $property_name$ {\n" - " get { return $name$_; }\n" - "}\n"); -} - -void PrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return result.has$property_name$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$property_name$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print(" PrepareBuilder();\n"); - if (SupportFieldPresence(descriptor_->file())) { + " get { return $name$_; }\n"); + if (is_value_type) { printer->Print( variables_, - " result.has$property_name$ = true;\n"); - } - printer->Print( - variables_, - " result.$name$_ = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n"); - if (SupportFieldPresence(descriptor_->file())) { + " set { $name$_ = value; }\n"); + + } else { printer->Print( variables_, - " result.has$property_name$ = false;\n"); + " set { $name$_ = value ?? $default_value$; }\n"); } - printer->Print( - variables_, - " result.$name$_ = $default_value$;\n" - " return this;\n" - "}\n"); + printer->Print("}\n\n"); } void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -135,27 +90,17 @@ void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { "}\n"); } -void PrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - // Nothing to do here for primitive types -} - void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "result.has$property_name$ = input.Read$capitalized_type_name$(ref result.$name$_);\n"); - } else { - printer->Print( - variables_, - "input.Read$capitalized_type_name$(ref result.$name$_);\n"); - } + printer->Print( + variables_, + "input.Read$capitalized_type_name$(ref result.$name$_);\n"); } void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.Write$capitalized_type_name$($number$, field_names[$field_ordinal$], $property_name$);\n" + " output.Write$capitalized_type_name$($number$, fieldNames[$field_ordinal$], $property_name$);\n" "}\n"); } @@ -171,24 +116,18 @@ void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " hash ^= $name$_.GetHashCode();\n" + " hash ^= $property_name$.GetHashCode();\n" "}\n"); } void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "if (has$property_name$ != other.has$property_name$ || (has$property_name$ && !$name$_.Equals(other.$name$_))) return false;\n"); - } else { - printer->Print( - variables_, - "if (!$name$_.Equals(other.$name$_)) return false;\n"); - } + printer->Print( + variables_, + "if ($property_name$ != other.$property_name$) return false;\n"); } void PrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print( variables_, - "PrintField(\"$descriptor_name$\", $has_property_check$, $name$_, writer);\n"); + "PrintField(\"$descriptor_name$\", $has_property_check$, $property_name$, writer);\n"); } PrimitiveOneofFieldGenerator::PrimitiveOneofFieldGenerator( @@ -201,79 +140,43 @@ PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() { } void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { + // TODO(jonskeet): What should foo.OneofIntField = 0; do? Clear the oneof? + // Currently foo.OneOfStringField = null will clear the oneof, but foo.OneOfStringField = "" won't. Ick. AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { - printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return $has_property_check$; }\n" - "}\n"); - } - AddPublicMemberAttributes(printer); printer->Print( variables_, "public $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - "}\n"); -} - -void PrimitiveOneofFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - AddDeprecatedFlag(printer); - if (SupportFieldPresence(descriptor_->file())) { + " set {"); + if (is_value_type) { + printer->Print( + variables_, + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = $oneof_property_name$Case.$property_name$;\n"); + } else { + printer->Print( + variables_, + " $oneof_name$_ = value ?? $default_value$;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$Case.None : $oneof_property_name$Case.$property_name$;\n"); + } printer->Print( - variables_, - "public bool Has$property_name$ {\n" - " get { return result.$has_property_check$; }\n" + " }\n" "}\n"); - } - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ $property_name$ {\n" - " get { return result.$has_property_check$ ? ($type_name$) result.$oneof_name$_ : $default_value$; }\n" - " set { Set$property_name$(value); }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$oneof_name$_ = value;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " if (result.$has_property_check$) {\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.None;\n" - " }\n" - " return this;\n" - "}\n"); } -void PrimitiveOneofFieldGenerator::WriteEquals(io::Printer* printer) { - printer->Print( - variables_, - "if (!$property_name$.Equals(other.$property_name$)) return false;\n"); -} void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { printer->Print(variables_, "PrintField(\"$descriptor_name$\", $has_property_check$, $oneof_name$_, writer);\n"); } void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): What if the value we read is the default value for the type? printer->Print( variables_, "$type_name$ value = $default_value$;\n" "if (input.Read$capitalized_type_name$(ref value)) {\n" - " result.$oneof_name$_ = value;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h index 8a2d5020..d6672b6c 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h @@ -41,17 +41,13 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class PrimitiveFieldGenerator : public FieldGeneratorBase { public: PrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~PrimitiveFieldGenerator(); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); @@ -60,6 +56,9 @@ class PrimitiveFieldGenerator : public FieldGeneratorBase { virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); + protected: + bool is_value_type; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; @@ -70,8 +69,6 @@ class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { ~PrimitiveOneofFieldGenerator(); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); - virtual void WriteEquals(io::Printer* printer); virtual void WriteToString(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index f5ebcfb1..f5d5a126 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -56,141 +56,46 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { } void RepeatedEnumFieldGenerator::GenerateMembers(io::Printer* printer) { - if (descriptor_->is_packed() && optimize_speed()) { - printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); - } - printer->Print(variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public scg::IList<$type_name$> $property_name$List {\n" - " get { return pbc::Lists.AsReadOnly($name$_); }\n" - "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" - "}\n"); - - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); printer->Print(variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" + "public pbc::RepeatedField<$type_name$> $property_name$ {\n" + " get { return $name$_; }\n" "}\n"); } void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); -} - -void RepeatedEnumFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); + "$name$_.Add(other.$name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "scg::ICollection unknownItems;\n" - "input.ReadEnumArray<$type_name$>(tag, field_name, result.$name$_, out unknownItems);\n"); - if (!use_lite_runtime()) { - printer->Print( - variables_, - "if (unknownItems != null) {\n" - " if (unknownFields == null) {\n" - " unknownFields = pb::UnknownFieldSet.CreateBuilder(this.UnknownFields);\n" - " }\n" - " foreach (object rawValue in unknownItems)\n" - " if (rawValue is int)\n" - " unknownFields.MergeVarintField($number$, (ulong)(int)rawValue);\n" - "}\n"); - } + "input.ReadEnumArray<$type_name$>(tag, fieldName, result.$name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { - printer->Print(variables_, "if ($name$_.Count > 0) {\n"); - printer->Indent(); + // TODO(jonskeet): Originally, this checked for Count > 0 first. + // The Write* call should make that cheap though - no need to generate it every time. if (descriptor_->is_packed()) { printer->Print( variables_, - "output.WritePackedEnumArray($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); + "output.WritePackedEnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); } else { printer->Print(variables_, - "output.WriteEnumArray($number$, field_names[$field_ordinal$], $name$_);\n"); + "output.WriteEnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); } - printer->Outdent(); printer->Print("}\n"); } void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print("{\n"); printer->Indent(); + // TODO(jonskeet): Move all this code into CodedOutputStream? It's a lot to repeat everywhere... printer->Print( variables_, "int dataSize = 0;\n" @@ -199,7 +104,7 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer printer->Print( variables_, "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" + " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((long) element);\n" "}\n" "size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); @@ -215,11 +120,6 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer } printer->Outdent(); printer->Print("}\n"); - // cache the data size for packed fields. - if (descriptor_->is_packed()) { - printer->Print(variables_, - "$name$MemoizedSerializedSize = dataSize;\n"); - } printer->Outdent(); printer->Print("}\n"); } @@ -227,16 +127,15 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "foreach($type_name$ i in $name$_) {\n" + " hash ^= i.GetHashCode();\n" + "}\n"); } void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$)) return false;\n"); } void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h index 68c3d6c9..92f265c5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h @@ -41,17 +41,15 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - +// TODO(jonskeet): Refactor repeated field support; all the implementations are *really* similar. We +// should probably have a RepeatedFieldGeneratorBase. class RepeatedEnumFieldGenerator : public FieldGeneratorBase { public: RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedEnumFieldGenerator(); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 2ae1d579..2a6a01f5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -48,7 +48,6 @@ namespace csharp { RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - variables_["message_or_group"] = message_or_group(); } RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { @@ -58,11 +57,11 @@ RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() { void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public scg::IList<$type_name$> $property_name$List {\n" + "public pbc::RepeatedField<$type_name$> $property_name$ {\n" " get { return $name$_; }\n" "}\n"); @@ -82,137 +81,46 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { "}\n"); } -void RepeatedMessageFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - // Extra overload for builder (just on messages) - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = builderForValue.Build();\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - // Extra overload for builder (just on messages) - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$.Builder builderForValue) {\n"); - AddNullCheck(printer, "builderForValue"); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(builderForValue.Build());\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" - "}\n"); -} - void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); -} - -void RepeatedMessageFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); + "$name$_.Add(other.$name$_);\n"); } void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.Read$message_or_group$Array(tag, field_name, result.$name$_, $type_name$.DefaultInstance, extensionRegistry);\n"); + "input.ReadMessageArray(tag, fieldName, $name$_);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { + // TODO(jonskeet): Originally, this checked for Count > 0 first. + // The Write* call should make that cheap though - no need to generate it every time. printer->Print( variables_, - "if ($name$_.Count > 0) {\n" - " output.Write$message_or_group$Array($number$, field_names[$field_ordinal$], $name$_);\n" - "}\n"); + "output.WriteMessageArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + // TODO(jonskeet): Put this into CodedOutputStream. printer->Print( variables_, - "foreach ($type_name$ element in $property_name$List) {\n" - " size += pb::CodedOutputStream.Compute$message_or_group$Size($number$, element);\n" + "foreach ($type_name$ element in $property_name$) {\n" + " size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n" "}\n"); } void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "foreach($type_name$ i in $name$_) {\n" + " hash ^= i.GetHashCode();\n" + "}\n"); } void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$)) return false;\n"); } void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h index 9db76939..b8582800 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h @@ -41,17 +41,13 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class RepeatedMessageFieldGenerator : public FieldGeneratorBase { public: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedMessageFieldGenerator(); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index e27458bb..2001b849 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -56,129 +56,43 @@ RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { } void RepeatedPrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { - if (descriptor_->is_packed() && optimize_speed()) { - printer->Print(variables_, "private int $name$MemoizedSerializedSize;\n"); - } printer->Print(variables_, - "private pbc::PopsicleList<$type_name$> $name$_ = new pbc::PopsicleList<$type_name$>();\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public scg::IList<$type_name$> $property_name$List {\n" - " get { return pbc::Lists.AsReadOnly($name$_); }\n" - "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. + "private readonly pbc::RepeatedField<$type_name$> $name$_ = new pbc::RepeatedField<$type_name$>();\n"); AddDeprecatedFlag(printer); printer->Print( variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" - "}\n"); - - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateBuilderMembers(io::Printer* printer) { - // Note: We can return the original list here, because we make it unmodifiable when we build - // We return it via IPopsicleList so that collection initializers work more pleasantly. - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public pbc::IPopsicleList<$type_name$> $property_name$List {\n" - " get { return PrepareBuilder().$name$_; }\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return result.$property_name$Count; }\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return result.Get$property_name$(index);\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Set$property_name$(int index, $type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_[index] = value;\n" - " return this;\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder Add$property_name$($type_name$ value) {\n"); - AddNullCheck(printer); - printer->Print( - variables_, - " PrepareBuilder();\n" - " result.$name$_.Add(value);\n" - " return this;\n" - "}\n"); - AddPublicMemberAttributes(printer); - printer->Print( - variables_, - "public Builder AddRange$property_name$(scg::IEnumerable<$type_name$> values) {\n" - " PrepareBuilder();\n" - " result.$name$_.Add(values);\n" - " return this;\n" - "}\n"); - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public Builder Clear$property_name$() {\n" - " PrepareBuilder();\n" - " result.$name$_.Clear();\n" - " return this;\n" + "public pbc::RepeatedField<$type_name$> $property_name$ {\n" + " get { return $name$_; }\n" "}\n"); } void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, - "if (other.$name$_.Count != 0) {\n" - " result.$name$_.Add(other.$name$_);\n" - "}\n"); -} - -void RepeatedPrimitiveFieldGenerator::GenerateBuildingCode(io::Printer* printer) { - printer->Print(variables_, "$name$_.MakeReadOnly();\n"); + "$name$_.Add(other.$name$_);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print(variables_, - "input.Read$capitalized_type_name$Array(tag, field_name, result.$name$_);\n"); + "input.Read$capitalized_type_name$Array(tag, fieldName, $name$_);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( io::Printer* printer) { - printer->Print(variables_, "if ($name$_.Count > 0) {\n"); - printer->Indent(); + // TODO(jonskeet): Originally, this checked for Count > 0 first. + // The Write* call should make that cheap though - no need to generate it every time. if (descriptor_->is_packed()) { printer->Print(variables_, - "output.WritePacked$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$MemoizedSerializedSize, $name$_);\n"); + "output.WritePacked$capitalized_type_name$Array($number$, fieldNames[$field_ordinal$], $name$_);\n"); } else { printer->Print(variables_, - "output.Write$capitalized_type_name$Array($number$, field_names[$field_ordinal$], $name$_);\n"); + "output.Write$capitalized_type_name$Array($number$, fieldNames[$field_ordinal$], $name$_);\n"); } - printer->Outdent(); - printer->Print("}\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( io::Printer* printer) { + // TODO(jonskeet): Get rid of most of this - move it into the runtime. printer->Print("{\n"); printer->Indent(); printer->Print("int dataSize = 0;\n"); @@ -207,10 +121,6 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( "size += $tag_size$ * $name$_.Count;\n", "tag_size", SimpleItoa(tagSize), "name", name()); } - // cache the data size for packed fields. - if (descriptor_->is_packed()) { - printer->Print(variables_, "$name$MemoizedSerializedSize = dataSize;\n"); - } printer->Outdent(); printer->Print("}\n"); } @@ -218,15 +128,14 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n" - " hash ^= i.GetHashCode();\n"); + "foreach($type_name$ i in $name$_)\n {" + " hash ^= i.GetHashCode();\n" + "}\n"); } void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if($name$_.Count != other.$name$_.Count) return false;\n" - "for(int ix=0; ix < $name$_.Count; ix++)\n" - " if(!$name$_[ix].Equals(other.$name$_[ix])) return false;\n"); + "if(!$name$_.Equals(other.$name$)) return false;\n"); } void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print(variables_, diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h index 50af9dda..29d437d7 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h @@ -41,17 +41,13 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class RepeatedPrimitiveFieldGenerator : public FieldGeneratorBase { public: RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal); ~RepeatedPrimitiveFieldGenerator(); virtual void GenerateMembers(io::Printer* printer); - virtual void GenerateBuilderMembers(io::Printer* printer); virtual void GenerateMergingCode(io::Printer* printer); - virtual void GenerateBuildingCode(io::Printer* printer); virtual void GenerateParsingCode(io::Printer* printer); virtual void GenerateSerializationCode(io::Printer* printer); virtual void GenerateSerializedSizeCode(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc index c52f6092..c666c820 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc @@ -47,14 +47,6 @@ namespace csharp { SourceGeneratorBase::SourceGeneratorBase(const FileDescriptor* descriptor) : descriptor_(descriptor) { - optimizeSize_ = (descriptor->options().optimize_for() - == FileOptions::CODE_SIZE); - optimizeSpeed_ = (descriptor->options().optimize_for() == FileOptions::SPEED); - useLiteRuntime_ = (descriptor->options().optimize_for() - == FileOptions::LITE_RUNTIME); - - optimizeSpeed_ |= useLiteRuntime_; - runtimeSuffix_ = useLiteRuntime_ ? "Lite" : ""; } SourceGeneratorBase::~SourceGeneratorBase() { diff --git a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h index 61c19511..6caef171 100644 --- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h +++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h @@ -47,27 +47,10 @@ class SourceGeneratorBase { std::string class_access_level(); - bool optimize_size() { - return optimizeSize_; - } - bool optimize_speed() { - return optimizeSpeed_; - } - bool use_lite_runtime() { - return useLiteRuntime_; - } - std::string runtime_suffix() { - return runtimeSuffix_; - } - void WriteGeneratedCodeAttributes(io::Printer* printer); private: const FileDescriptor* descriptor_; - bool optimizeSize_; - bool optimizeSpeed_; - bool useLiteRuntime_; - std::string runtimeSuffix_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceGeneratorBase); }; diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc index b14bf5e8..03a3b8df 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.cc @@ -39,7 +39,6 @@ #include #include -#include #include #include @@ -61,18 +60,6 @@ UmbrellaClassGenerator::~UmbrellaClassGenerator() { void UmbrellaClassGenerator::Generate(io::Printer* printer) { WriteIntroduction(printer); - WriteExtensionRegistration(printer); - - // write children: Extensions - if (file_->extension_count() > 0) { - printer->Print("#region Extensions\n"); - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.Generate(printer); - } - printer->Print("#endregion\n"); - printer->Print("\n"); - } printer->Print("#region Static variables\n"); for (int i = 0; i < file_->message_type_count(); i++) { @@ -80,11 +67,7 @@ void UmbrellaClassGenerator::Generate(io::Printer* printer) { messageGenerator.GenerateStaticVariables(printer); } printer->Print("#endregion\n"); - if (!use_lite_runtime()) { - WriteDescriptor(printer); - } else { - WriteLiteExtensions(printer); - } + WriteDescriptor(printer); // Close the class declaration. printer->Outdent(); printer->Print("}\n"); @@ -134,9 +117,9 @@ void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) { "#pragma warning disable 1591, 0612, 3021\n" "#region Designer generated code\n" "\n" - "using pb = global::Google.ProtocolBuffers;\n" - "using pbc = global::Google.ProtocolBuffers.Collections;\n" - "using pbd = global::Google.ProtocolBuffers.Descriptors;\n" + "using pb = global::Google.Protobuf;\n" + "using pbc = global::Google.Protobuf.Collections;\n" + "using pbd = global::Google.Protobuf.Descriptors;\n" "using scg = global::System.Collections.Generic;\n", "file_name", file_->name()); @@ -165,24 +148,6 @@ void UmbrellaClassGenerator::WriteIntroduction(io::Printer* printer) { printer->Indent(); } -void UmbrellaClassGenerator::WriteExtensionRegistration(io::Printer* printer) { - printer->Print( - "#region Extension registration\n" - "public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {\n"); - printer->Indent(); - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateExtensionRegistrationCode(printer); - } - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateExtensionRegistrationCode(printer); - } - printer->Outdent(); - printer->Print("}\n"); - printer->Print("#endregion\n"); -} - void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { printer->Print( "#region Descriptor\n" @@ -219,25 +184,7 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { MessageGenerator messageGenerator(file_->message_type(i)); messageGenerator.GenerateStaticVariableInitializers(printer); } - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); - } - if (uses_extensions()) { - // Must construct an ExtensionRegistry containing all possible extensions - // and return it. - printer->Print( - "pb::ExtensionRegistry registry = pb::ExtensionRegistry.CreateInstance();\n"); - printer->Print("RegisterAllExtensions(registry);\n"); - for (int i = 0; i < file_->dependency_count(); i++) { - printer->Print("$dependency$.RegisterAllExtensions(registry);\n", - "dependency", GetFullUmbrellaClassName(file_->dependency(i))); - } - printer->Print("return registry;\n"); - } else { - printer->Print("return null;\n"); - } printer->Outdent(); printer->Print("};\n"); @@ -258,33 +205,6 @@ void UmbrellaClassGenerator::WriteDescriptor(io::Printer* printer) { printer->Print("#endregion\n\n"); } -void UmbrellaClassGenerator::WriteLiteExtensions(io::Printer* printer) { - printer->Print( - "#region Extensions\n" - "internal static readonly object Descriptor;\n" - "static $umbrella_class_name$() {\n", - "umbrella_class_name", umbrellaClassname_); - printer->Indent(); - printer->Print("Descriptor = null;\n"); - for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateStaticVariableInitializers(printer); - } - for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator extensionGenerator(file_->extension(i)); - extensionGenerator.GenerateStaticVariableInitializers(printer); - } - printer->Outdent(); - printer->Print("}\n"); - printer->Print("#endregion\n\n"); -} - -bool UmbrellaClassGenerator::uses_extensions() { - // TODO(jtattermusch): implement recursive descent that looks for extensions. - // For now, we conservatively assume that extensions are used. - return true; -} - } // namespace csharp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h index 83e1f347..f7533d2d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h +++ b/src/google/protobuf/compiler/csharp/csharp_umbrella_class.h @@ -41,8 +41,6 @@ namespace protobuf { namespace compiler { namespace csharp { -class Writer; - class UmbrellaClassGenerator : public SourceGeneratorBase { public: UmbrellaClassGenerator(const FileDescriptor* file); @@ -58,11 +56,7 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { std::string umbrellaNamespace_; void WriteIntroduction(io::Printer* printer); - void WriteExtensionRegistration(io::Printer* printer); void WriteDescriptor(io::Printer* printer); - void WriteLiteExtensions(io::Printer* printer); - - bool uses_extensions(); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UmbrellaClassGenerator); }; @@ -73,4 +67,3 @@ class UmbrellaClassGenerator : public SourceGeneratorBase { } // namespace google #endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_UMBRELLA_CLASS_H__ - diff --git a/src/google/protobuf/compiler/csharp/csharp_writer.cc b/src/google/protobuf/compiler/csharp/csharp_writer.cc deleted file mode 100644 index 2bcafde5..00000000 --- a/src/google/protobuf/compiler/csharp/csharp_writer.cc +++ /dev/null @@ -1,136 +0,0 @@ -// 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. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace csharp { - -Writer::Writer(google::protobuf::io::Printer* printer) - : printer_(printer), - newline_("\n") { - // TODO(jtattermusch): make newline customizable. -} - -Writer::~Writer() { -} - -void Writer::Indent() { - printer_->Indent(); -} - -void Writer::Outdent() { - printer_->Outdent(); -} - -void Writer::Write(const char* text) { - printer_->Print(text); -} - -void Writer::Write(const char* text, const string& value0) { - printer_->Print(text, "0", value0); -} - -void Writer::Write(const char* text, const string& value0, - const string& value1) { - printer_->Print(text, "0", value0, "1", value1); -} - -void Writer::Write(const char* text, const string& value0, const string& value1, - const string& value2) { - printer_->Print(text, "0", value0, "1", value1, "2", value2); -} - -void Writer::Write(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3) { - printer_->Print(text, "0", value0, "1", value1, "2", value2, "3", value3); -} - -void Writer::WriteLine() { - printer_->Print(newline_); -} - -void Writer::WriteLine(const char* text) { - Write(text); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0) { - Write(text, value0); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1) { - Write(text, value0, value1); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1, const string& value2) { - Write(text, value0, value1, value2); - WriteLine(); -} - -void Writer::WriteLine(const char* text, const string& value0, - const string& value1, const string& value2, - const string& value3) { - Write(text, value0, value1, value2, value3); - WriteLine(); -} - -} // namespace java -} // namespace compiler -} // namespace protobuf -} // namespace google diff --git a/src/google/protobuf/compiler/csharp/csharp_writer.h b/src/google/protobuf/compiler/csharp/csharp_writer.h deleted file mode 100644 index 26c59b31..00000000 --- a/src/google/protobuf/compiler/csharp/csharp_writer.h +++ /dev/null @@ -1,93 +0,0 @@ -// 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. - -// Author: kenton@google.com (Kenton Varda) -// Based on original Protocol Buffers design by -// Sanjay Ghemawat, Jeff Dean, and others. - -#ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ -#define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ - -#include -#include -#include -#include -#include - -namespace google { -namespace protobuf { -namespace compiler { -namespace csharp { - -// Simple wrapper around Printer that supports customizable line endings -// and number-based variables (e.g. $0$). -class Writer { - public: - Writer(io::Printer* printer); - ~Writer(); - - void Indent(); - void Outdent(); - - void Write(const char* text); - - void Write(const char* text, const string& value0); - - void Write(const char* text, const string& value0, const string& value1); - - void Write(const char* text, const string& value0, const string& value1, - const string& value2); - - void Write(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3); - - void WriteLine(); - - void WriteLine(const char* text); - - void WriteLine(const char* text, const string& value0); - - void WriteLine(const char* text, const string& value0, const string& value1); - - void WriteLine(const char* text, const string& value0, const string& value1, - const string& value2); - - void WriteLine(const char* text, const string& value0, const string& value1, - const string& value2, const string& value3); - private: - io::Printer* printer_; - const char* newline_; -}; - -} // namespace csharp -} // namespace compiler -} // namespace protobuf -} // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_CSHARP_WRITER_H__ diff --git a/vsprojects/libprotoc.vcproj b/vsprojects/libprotoc.vcproj index 515a6096..c530ef0a 100644 --- a/vsprojects/libprotoc.vcproj +++ b/vsprojects/libprotoc.vcproj @@ -169,7 +169,6 @@ - @@ -181,7 +180,6 @@ - @@ -269,7 +267,6 @@ - @@ -281,7 +278,6 @@ - -- cgit v1.2.3 From 307af628e646cd67e659f327e549542c0f5e31b7 Mon Sep 17 00:00:00 2001 From: Austin Schuh Date: Fri, 5 Jun 2015 22:46:01 -0700 Subject: Marked another compiler literal unsigned. When compiling a protobuf with gcc 4.1.2 for powerpc, I ran into another of the following warning message: INFO: From Compiling my_proto.pb.cc powerpc-603e-linux-gcc: bazel-out/local_linux-dbg/genfiles/my_proto.pb.cc: In member function `virtual void MyProto::Clear()': bazel-out/local_linux-dbg/genfiles/my_proto.pb.cc:223: warning: this decimal constant is unsigned only in ISO C90 The line in the proto file that was triggering it was: if (_has_bits_[24 / 32] & 4278190080) { ZR_(field1_, field2_); } _has_bits_ is a uint32. The constant mask should therefore be unsigned. This change updates the constant to be generated as unsigned. --- src/google/protobuf/compiler/cpp/cpp_message.cc | 2 +- src/google/protobuf/compiler/plugin.pb.cc | 2 +- src/google/protobuf/descriptor.pb.cc | 34 ++++++++++++------------- 3 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 212fe2e1..af85919a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -3510,7 +3510,7 @@ GenerateByteSize(io::Printer* printer) { } else { if (HasFieldPresence(descriptor_->file())) { printer->Print( - "if (_has_bits_[$index$ / 32] & $mask$) {\n", + "if (_has_bits_[$index$ / 32] & $mask$u) {\n", "index", SimpleItoa(i), "mask", SimpleItoa(mask)); printer->Indent(); diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 344ed450..e7890fae 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -913,7 +913,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( int CodeGeneratorResponse_File::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 7) { + if (_has_bits_[0 / 32] & 7u) { // optional string name = 1; if (has_name()) { total_size += 1 + diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 755c2617..fc13d8dc 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -1648,7 +1648,7 @@ void FileDescriptorProto::SerializeWithCachedSizes( int FileDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -1664,7 +1664,7 @@ int FileDescriptorProto::ByteSize() const { } } - if (_has_bits_[9 / 32] & 3584) { + if (_has_bits_[9 / 32] & 3584u) { // optional .google.protobuf.FileOptions options = 8; if (has_options()) { total_size += 1 + @@ -2534,7 +2534,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( int DescriptorProto_ExtensionRange::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional int32 start = 1; if (has_start()) { total_size += 1 + @@ -2817,7 +2817,7 @@ void DescriptorProto_ReservedRange::SerializeWithCachedSizes( int DescriptorProto_ReservedRange::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional int32 start = 1; if (has_start()) { total_size += 1 + @@ -3373,7 +3373,7 @@ void DescriptorProto::SerializeWithCachedSizes( int DescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 129) { + if (_has_bits_[0 / 32] & 129u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -4558,7 +4558,7 @@ void FieldDescriptorProto::SerializeWithCachedSizes( int FieldDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 255) { + if (_has_bits_[0 / 32] & 255u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -5633,7 +5633,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes( int EnumDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 5) { + if (_has_bits_[0 / 32] & 5u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -6102,7 +6102,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( int EnumValueDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 7) { + if (_has_bits_[0 / 32] & 7u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -6569,7 +6569,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( int ServiceDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 5) { + if (_has_bits_[0 / 32] & 5u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -7165,7 +7165,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( int MethodDescriptorProto::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 63) { + if (_has_bits_[0 / 32] & 63u) { // optional string name = 1; if (has_name()) { total_size += 1 + @@ -8240,7 +8240,7 @@ void FileOptions::SerializeWithCachedSizes( int FileOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 255) { + if (_has_bits_[0 / 32] & 255u) { // optional string java_package = 1; if (has_java_package()) { total_size += 1 + @@ -8289,7 +8289,7 @@ int FileOptions::ByteSize() const { } } - if (_has_bits_[8 / 32] & 16128) { + if (_has_bits_[8 / 32] & 16128u) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; @@ -9279,7 +9279,7 @@ void MessageOptions::SerializeWithCachedSizes( int MessageOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 15) { + if (_has_bits_[0 / 32] & 15u) { // optional bool message_set_wire_format = 1 [default = false]; if (has_message_set_wire_format()) { total_size += 1 + 1; @@ -9939,7 +9939,7 @@ void FieldOptions::SerializeWithCachedSizes( int FieldOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 63) { + if (_has_bits_[0 / 32] & 63u) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (has_ctype()) { total_size += 1 + @@ -10498,7 +10498,7 @@ void EnumOptions::SerializeWithCachedSizes( int EnumOptions::ByteSize() const { int total_size = 0; - if (_has_bits_[0 / 32] & 3) { + if (_has_bits_[0 / 32] & 3u) { // optional bool allow_alias = 2; if (has_allow_alias()) { total_size += 1 + 1; @@ -12410,7 +12410,7 @@ void UninterpretedOption::SerializeWithCachedSizes( int UninterpretedOption::ByteSize() const { int total_size = 0; - if (_has_bits_[1 / 32] & 126) { + if (_has_bits_[1 / 32] & 126u) { // optional string identifier_value = 3; if (has_identifier_value()) { total_size += 1 + @@ -13248,7 +13248,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( int SourceCodeInfo_Location::ByteSize() const { int total_size = 0; - if (_has_bits_[2 / 32] & 12) { + if (_has_bits_[2 / 32] & 12u) { // optional string leading_comments = 3; if (has_leading_comments()) { total_size += 1 + -- cgit v1.2.3 From d846b0b059b4d867536b98aa29475a387aa09114 Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Mon, 8 Jun 2015 16:24:57 -0400 Subject: Beta quality drop of Objective C Support. - Add more to the ObjC dir readme. - Merge the ExtensionField and ExtensionDescriptor to reduce overhead. - Fix an initialization race. - Clean up the Xcode schemes. - Remove the class/enum filter. - Remove some forced inline that were bloating things without proof of performance wins. - Rename some internal types to avoid conflicts with the well know types protos. - Drop the use of ApplyFunctions to the compiler/optimizer can do what it wants. - Better document some possible future improvements. - Add missing support for parsing repeated primitive fields in packed or unpacked forms. - Improve -hash. - Add *Count for repeated and map<> fields to avoid auto create when checking for them being set. --- Makefile.am | 18 +- objectivec/DevTools/compile_testing_protos.sh | 113 + objectivec/DevTools/full_mac_build.sh | 2 +- objectivec/GPBArray.h | 2 +- objectivec/GPBCodedInputStream.h | 2 +- objectivec/GPBCodedInputStream.m | 26 +- objectivec/GPBCodedInputStream_PackagePrivate.h | 4 +- objectivec/GPBCodedOutputStream.h | 118 +- objectivec/GPBCodedOutputStream.m | 126 +- objectivec/GPBDescriptor.h | 14 +- objectivec/GPBDescriptor.m | 307 +- objectivec/GPBDescriptor_PackagePrivate.h | 50 +- objectivec/GPBDictionary.h | 2 +- objectivec/GPBDictionary.m | 1750 +++++---- objectivec/GPBDictionary_PackagePrivate.h | 31 +- objectivec/GPBExtensionField.h | 51 - objectivec/GPBExtensionField.m | 525 --- objectivec/GPBExtensionField_PackagePrivate.h | 51 - objectivec/GPBExtensionInternals.h | 50 + objectivec/GPBExtensionInternals.m | 380 ++ objectivec/GPBExtensionRegistry.h | 8 +- objectivec/GPBExtensionRegistry.m | 32 +- objectivec/GPBField.h | 56 - objectivec/GPBField.m | 328 -- objectivec/GPBField_PackagePrivate.h | 49 - objectivec/GPBMessage.h | 14 +- objectivec/GPBMessage.m | 4067 ++++++-------------- objectivec/GPBMessage_PackagePrivate.h | 4 +- objectivec/GPBProtocolBuffers.h | 3 +- objectivec/GPBProtocolBuffers.m | 17 +- objectivec/GPBProtocolBuffers_RuntimeSupport.h | 3 +- objectivec/GPBRootObject.m | 7 +- objectivec/GPBRootObject_PackagePrivate.h | 4 +- objectivec/GPBRuntimeTypes.h | 102 + objectivec/GPBTypes.h | 102 - objectivec/GPBUnknownField.h | 56 + objectivec/GPBUnknownField.m | 326 ++ objectivec/GPBUnknownFieldSet.h | 6 +- objectivec/GPBUnknownFieldSet.m | 55 +- objectivec/GPBUnknownField_PackagePrivate.h | 49 + objectivec/GPBUtilities.h | 263 +- objectivec/GPBUtilities.m | 598 +-- objectivec/GPBUtilities_PackagePrivate.h | 145 +- objectivec/GPBWireFormat.h | 4 +- objectivec/GPBWireFormat.m | 40 +- .../ProtocolBuffers_OSX.xcodeproj/project.pbxproj | 276 +- .../xcschemes/PerformanceTests.xcscheme | 219 +- .../xcschemes/ProtocolBuffers.xcscheme | 2 +- .../ProtocolBuffers_iOS.xcodeproj/project.pbxproj | 285 +- .../xcschemes/PerformanceTests.xcscheme | 222 +- .../xcschemes/ProtocolBuffers.xcscheme | 2 +- objectivec/README.md | 93 +- objectivec/Tests/Filter1.txt | 40 - objectivec/Tests/Filter2.txt | 35 - objectivec/Tests/GPBARCUnittestProtos.m | 3 +- objectivec/Tests/GPBCodedInputStreamTests.m | 2 +- objectivec/Tests/GPBConcurrencyTests.m | 3 +- objectivec/Tests/GPBFilteredMessageTests.m | 98 - objectivec/Tests/GPBMessageTests+Runtime.m | 142 +- objectivec/Tests/GPBMessageTests+Serialization.m | 136 +- objectivec/Tests/GPBMessageTests.m | 49 +- objectivec/Tests/GPBTestUtilities.h | 6 + objectivec/Tests/GPBTestUtilities.m | 386 +- objectivec/Tests/GPBUnittestProtos.m | 3 +- objectivec/Tests/GPBUnknownFieldSetTest.m | 47 +- objectivec/Tests/GPBUtilitiesTests.m | 190 - objectivec/Tests/GPBWireFormatTests.m | 12 +- objectivec/Tests/unittest_filter.proto | 71 - objectivec/Tests/unittest_name_mangling.proto | 37 - objectivec/Tests/unittest_objc_startup.proto | 49 + objectivec/google/protobuf/Any.pbobjc.m | 52 +- objectivec/google/protobuf/Api.pbobjc.h | 3 + objectivec/google/protobuf/Api.pbobjc.m | 151 +- objectivec/google/protobuf/Descriptor.pbobjc.h | 30 + objectivec/google/protobuf/Descriptor.pbobjc.m | 1451 +++---- objectivec/google/protobuf/Duration.pbobjc.m | 50 +- objectivec/google/protobuf/Empty.pbobjc.m | 40 +- objectivec/google/protobuf/FieldMask.pbobjc.h | 1 + objectivec/google/protobuf/FieldMask.pbobjc.m | 46 +- objectivec/google/protobuf/SourceContext.pbobjc.m | 44 +- objectivec/google/protobuf/Struct.pbobjc.h | 2 + objectivec/google/protobuf/Struct.pbobjc.m | 162 +- objectivec/google/protobuf/Timestamp.pbobjc.m | 50 +- objectivec/google/protobuf/Type.pbobjc.h | 7 + objectivec/google/protobuf/Type.pbobjc.m | 334 +- objectivec/google/protobuf/Wrappers.pbobjc.m | 372 +- src/Makefile.am | 2 +- .../compiler/objectivec/objectivec_enum_field.cc | 12 +- .../compiler/objectivec/objectivec_extension.cc | 39 +- .../compiler/objectivec/objectivec_extension.h | 6 +- .../compiler/objectivec/objectivec_field.cc | 91 +- .../compiler/objectivec/objectivec_file.cc | 293 +- .../protobuf/compiler/objectivec/objectivec_file.h | 4 - .../compiler/objectivec/objectivec_generator.cc | 4 - .../compiler/objectivec/objectivec_helpers.cc | 63 +- .../compiler/objectivec/objectivec_helpers.h | 5 +- .../objectivec/objectivec_helpers_unittest.cc | 8 + .../compiler/objectivec/objectivec_message.cc | 369 +- .../compiler/objectivec/objectivec_message.h | 11 +- .../objectivec/objectivec_message_field.cc | 2 +- 100 files changed, 7482 insertions(+), 8590 deletions(-) create mode 100755 objectivec/DevTools/compile_testing_protos.sh delete mode 100644 objectivec/GPBExtensionField.h delete mode 100644 objectivec/GPBExtensionField.m delete mode 100644 objectivec/GPBExtensionField_PackagePrivate.h create mode 100644 objectivec/GPBExtensionInternals.h create mode 100644 objectivec/GPBExtensionInternals.m delete mode 100644 objectivec/GPBField.h delete mode 100644 objectivec/GPBField.m delete mode 100644 objectivec/GPBField_PackagePrivate.h create mode 100644 objectivec/GPBRuntimeTypes.h delete mode 100644 objectivec/GPBTypes.h create mode 100644 objectivec/GPBUnknownField.h create mode 100644 objectivec/GPBUnknownField.m create mode 100644 objectivec/GPBUnknownField_PackagePrivate.h delete mode 100644 objectivec/Tests/Filter1.txt delete mode 100644 objectivec/Tests/Filter2.txt delete mode 100644 objectivec/Tests/GPBFilteredMessageTests.m delete mode 100644 objectivec/Tests/unittest_filter.proto delete mode 100644 objectivec/Tests/unittest_name_mangling.proto create mode 100644 objectivec/Tests/unittest_objc_startup.proto (limited to 'src/google/protobuf/compiler') diff --git a/Makefile.am b/Makefile.am index 084fca6b..6180f6cd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -506,14 +506,10 @@ objectivec_EXTRA_DIST= \ objectivec/GPBDictionary.h \ objectivec/GPBDictionary.m \ objectivec/GPBDictionary_PackagePrivate.h \ - objectivec/GPBExtensionField.h \ - objectivec/GPBExtensionField.m \ - objectivec/GPBExtensionField_PackagePrivate.h \ + objectivec/GPBExtensionInternals.h \ + objectivec/GPBExtensionInternals.m \ objectivec/GPBExtensionRegistry.h \ objectivec/GPBExtensionRegistry.m \ - objectivec/GPBField.h \ - objectivec/GPBField.m \ - objectivec/GPBField_PackagePrivate.h \ objectivec/GPBMessage.h \ objectivec/GPBMessage.m \ objectivec/GPBMessage_PackagePrivate.h \ @@ -523,7 +519,10 @@ objectivec_EXTRA_DIST= \ objectivec/GPBRootObject.h \ objectivec/GPBRootObject.m \ objectivec/GPBRootObject_PackagePrivate.h \ - objectivec/GPBTypes.h \ + objectivec/GPBRuntimeTypes.h \ + objectivec/GPBUnknownField.h \ + objectivec/GPBUnknownField.m \ + objectivec/GPBUnknownField_PackagePrivate.h \ objectivec/GPBUnknownFieldSet.h \ objectivec/GPBUnknownFieldSet.m \ objectivec/GPBUnknownFieldSet_PackagePrivate.h \ @@ -547,8 +546,6 @@ objectivec_EXTRA_DIST= \ objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \ objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \ objectivec/README.md \ - objectivec/Tests/Filter1.txt \ - objectivec/Tests/Filter2.txt \ objectivec/Tests/golden_message \ objectivec/Tests/golden_packed_fields_message \ objectivec/Tests/GPBARCUnittestProtos.m \ @@ -564,7 +561,6 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/GPBDictionaryTests+UInt32.m \ objectivec/Tests/GPBDictionaryTests+UInt64.m \ objectivec/Tests/GPBDictionaryTests.pddm \ - objectivec/Tests/GPBFilteredMessageTests.m \ objectivec/Tests/GPBMessageTests+Merge.m \ objectivec/Tests/GPBMessageTests+Runtime.m \ objectivec/Tests/GPBMessageTests+Serialization.m \ @@ -596,8 +592,6 @@ objectivec_EXTRA_DIST= \ objectivec/Tests/text_format_map_unittest_data.txt \ objectivec/Tests/text_format_unittest_data.txt \ objectivec/Tests/unittest_cycle.proto \ - objectivec/Tests/unittest_filter.proto \ - objectivec/Tests/unittest_name_mangling.proto \ objectivec/Tests/unittest_objc.proto \ objectivec/Tests/unittest_runtime_proto2.proto \ objectivec/Tests/unittest_runtime_proto3.proto \ diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh new file mode 100755 index 00000000..f414bd87 --- /dev/null +++ b/objectivec/DevTools/compile_testing_protos.sh @@ -0,0 +1,113 @@ +#!/bin/bash + +# Invoked by the Xcode projects to build the protos needed for the unittests. + +set -eu + +readonly OUTPUT_DIR="${PROJECT_DERIVED_FILE_DIR}/protos" + +# Helper for bailing. +die() { + echo "Error: $1" + exit 2 +} + +# What to do. +case "${ACTION}" in + "") + # Build, fall thru + ;; + "clean") + rm -rf "${OUTPUT_DIR}" + exit 0 + ;; + *) + die "Unknown action requested: ${ACTION}" + ;; +esac + +# Move to the top of the protobuf directories. +cd "${SRCROOT}/.." + +[[ -x src/protoc ]] || \ + die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)." + +RUN_PROTOC=no +if [[ ! -d "${OUTPUT_DIR}" ]] ; then + RUN_PROTOC=yes +else + # Find the newest input file (protos, compiler, and this script). + # (these patterns catch some extra stuff, but better to over sample than + # under) + readonly NewestInput=$(find \ + src/google/protobuf/*.proto \ + objectivec/Tests/*.proto \ + src/.libs src/*.la src/protoc \ + objectivec/DevTools/compile_testing_protos.sh \ + -type f -print0 \ + | xargs -0 stat -f "%m %N" \ + | sort -n | tail -n1 | cut -f2- -d" ") + # Find the oldest output file. + readonly OldestOutput=$(find \ + "${OUTPUT_DIR}" \ + -type f -print0 \ + | xargs -0 stat -f "%m %N" \ + | sort -n -r | tail -n1 | cut -f2- -d" ") + # If the newest input is newer than the oldest output, regenerate. + if [[ "${NewestInput}" -nt "${OldestOutput}" ]] ; then + RUN_PROTOC=yes + fi +fi + +if [[ "${RUN_PROTOC}" != "yes" ]] ; then + # Up to date. + exit 0 +fi + +# Ensure the output dir exists +mkdir -p "${OUTPUT_DIR}/google/protobuf" + +CORE_PROTO_FILES=( \ + src/google/protobuf/unittest_custom_options.proto \ + src/google/protobuf/unittest_enormous_descriptor.proto \ + src/google/protobuf/unittest_embed_optimize_for.proto \ + src/google/protobuf/unittest_empty.proto \ + src/google/protobuf/unittest_import.proto \ + src/google/protobuf/unittest_import_lite.proto \ + src/google/protobuf/unittest_lite.proto \ + src/google/protobuf/unittest_mset.proto \ + src/google/protobuf/unittest_no_generic_services.proto \ + src/google/protobuf/unittest_optimize_for.proto \ + src/google/protobuf/unittest.proto \ + src/google/protobuf/unittest_import_public.proto \ + src/google/protobuf/unittest_import_public_lite.proto \ + src/google/protobuf/unittest_drop_unknown_fields.proto \ + src/google/protobuf/unittest_preserve_unknown_enum.proto \ + src/google/protobuf/map_lite_unittest.proto \ + src/google/protobuf/map_proto2_unittest.proto \ + src/google/protobuf/map_unittest.proto \ +) + +compile_proto() { + src/protoc \ + --objc_out="${OUTPUT_DIR}/google/protobuf" \ + --proto_path=src/google/protobuf/ \ + --proto_path=src \ + $* +} + +for a_proto in "${CORE_PROTO_FILES[@]}" ; do + compile_proto "${a_proto}" +done + +OBJC_PROTO_FILES=( \ + objectivec/Tests/unittest_cycle.proto \ + objectivec/Tests/unittest_runtime_proto2.proto \ + objectivec/Tests/unittest_runtime_proto3.proto \ + objectivec/Tests/unittest_objc.proto \ + objectivec/Tests/unittest_objc_startup.proto \ +) + +for a_proto in "${OBJC_PROTO_FILES[@]}" ; do + compile_proto --proto_path="objectivec/Tests" "${a_proto}" +done diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh index 57c4f438..2192b760 100755 --- a/objectivec/DevTools/full_mac_build.sh +++ b/objectivec/DevTools/full_mac_build.sh @@ -162,7 +162,7 @@ wrapped_make -j "${NUM_MAKE_JOBS}" all wrapped_make -j "${NUM_MAKE_JOBS}" check header "Ensuring the ObjC descriptors are current." -# Find the newest input file (protos, compiler, and this script). +# Find the newest input file (protos, compiler, and the generator script). # (these patterns catch some extra stuff, but better to over sample than under) readonly NewestInput=$(find \ src/google/protobuf/*.proto \ diff --git a/objectivec/GPBArray.h b/objectivec/GPBArray.h index 3fcba7af..b486f27b 100644 --- a/objectivec/GPBArray.h +++ b/objectivec/GPBArray.h @@ -30,7 +30,7 @@ #import -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" // These classes are used for repeated fields of basic data types. They are used because // they perform better than boxing into NSNumbers in NSArrays. diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h index e9b27e22..b71ee871 100644 --- a/objectivec/GPBCodedInputStream.h +++ b/objectivec/GPBCodedInputStream.h @@ -60,7 +60,7 @@ - (int64_t)readSInt64; - (BOOL)readBool; - (NSString *)readString; -- (NSData *)readData; +- (NSData *)readBytes; // Read an embedded message field value from the stream. - (void)readMessage:(GPBMessage *)message diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m index 79d31fc7..71758baa 100644 --- a/objectivec/GPBCodedInputStream.m +++ b/objectivec/GPBCodedInputStream.m @@ -38,7 +38,7 @@ static const NSUInteger kDefaultRecursionLimit = 64; -static inline void CheckSize(GPBCodedInputStreamState *state, size_t size) { +static void CheckSize(GPBCodedInputStreamState *state, size_t size) { size_t newSize = state->bufferPos + size; if (newSize > state->bufferSize) { [NSException raise:NSParseErrorException format:@""]; @@ -50,26 +50,26 @@ static inline void CheckSize(GPBCodedInputStreamState *state, size_t size) { } } -static inline int8_t ReadRawByte(GPBCodedInputStreamState *state) { +static int8_t ReadRawByte(GPBCodedInputStreamState *state) { CheckSize(state, sizeof(int8_t)); return ((int8_t *)state->bytes)[state->bufferPos++]; } -static inline int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) { +static int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) { CheckSize(state, sizeof(int32_t)); int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos); state->bufferPos += sizeof(int32_t); return value; } -static inline int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) { +static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) { CheckSize(state, sizeof(int64_t)); int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos); state->bufferPos += sizeof(int64_t); return value; } -static inline int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { +static int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { int8_t tmp = ReadRawByte(state); if (tmp >= 0) { return tmp; @@ -104,7 +104,7 @@ static inline int32_t ReadRawVarint32(GPBCodedInputStreamState *state) { return result; } -static inline int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { +static int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { int32_t shift = 0; int64_t result = 0; while (shift < 64) { @@ -119,7 +119,7 @@ static inline int64_t ReadRawVarint64(GPBCodedInputStreamState *state) { return 0; } -static inline void SkipRawData(GPBCodedInputStreamState *state, size_t size) { +static void SkipRawData(GPBCodedInputStreamState *state, size_t size) { CheckSize(state, size); state->bufferPos += size; } @@ -222,7 +222,7 @@ NSString *GPBCodedInputStreamReadRetainedString( return result; } -NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state) { +NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) { int32_t size = ReadRawVarint32(state); if (size < 0) return nil; CheckSize(state, size); @@ -232,7 +232,7 @@ NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state) { return result; } -NSData *GPBCodedInputStreamReadRetainedDataNoCopy( +NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( GPBCodedInputStreamState *state) { int32_t size = ReadRawVarint32(state); if (size < 0) return nil; @@ -453,8 +453,8 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, GPBCodedInputStreamPopLimit(&state_, oldLimit); } -- (NSData *)readData { - return [GPBCodedInputStreamReadRetainedData(&state_) autorelease]; +- (NSData *)readBytes { + return [GPBCodedInputStreamReadRetainedBytes(&state_) autorelease]; } - (uint32_t)readUInt32 { @@ -499,7 +499,7 @@ void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, // Returns true if the passed in bytes are 7 bit ascii. // This routine needs to be fast. -static inline bool AreBytesIn7BitASCII(const uint8_t *bytes, NSUInteger len) { +static bool AreBytesIn7BitASCII(const uint8_t *bytes, NSUInteger len) { // In the loops below, it's more efficient to collect rather than do // conditional at every step. #if __LP64__ @@ -587,7 +587,7 @@ static inline bool AreBytesIn7BitASCII(const uint8_t *bytes, NSUInteger len) { return true; } -static inline void GPBStringInitStringValue(GPBString *string) { +static void GPBStringInitStringValue(GPBString *string) { OSSpinLockLock(&string->lock_); GPBStringInitStringValueAlreadyLocked(string); OSSpinLockUnlock(&string->lock_); diff --git a/objectivec/GPBCodedInputStream_PackagePrivate.h b/objectivec/GPBCodedInputStream_PackagePrivate.h index ba6471ef..e482b4c9 100644 --- a/objectivec/GPBCodedInputStream_PackagePrivate.h +++ b/objectivec/GPBCodedInputStream_PackagePrivate.h @@ -114,9 +114,9 @@ int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state); BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state); NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); -NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state) +NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); -NSData *GPBCodedInputStreamReadRetainedDataNoCopy( +NSData *GPBCodedInputStreamReadRetainedBytesNoCopy( GPBCodedInputStreamState *state) __attribute((ns_returns_retained)); size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h index 1f1eb38a..9a237b6e 100644 --- a/objectivec/GPBCodedOutputStream.h +++ b/objectivec/GPBCodedOutputStream.h @@ -30,7 +30,7 @@ #import -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" #import "GPBWireFormat.h" @class GPBBoolArray; @@ -84,110 +84,110 @@ // This block of code is generated, do not edit it directly. - (void)writeDouble:(int32_t)fieldNumber value:(double)value; -- (void)writeDoubles:(int32_t)fieldNumber - values:(GPBDoubleArray *)values - tag:(uint32_t)tag; +- (void)writeDoubleArray:(int32_t)fieldNumber + values:(GPBDoubleArray *)values + tag:(uint32_t)tag; - (void)writeDoubleNoTag:(double)value; - (void)writeFloat:(int32_t)fieldNumber value:(float)value; -- (void)writeFloats:(int32_t)fieldNumber - values:(GPBFloatArray *)values - tag:(uint32_t)tag; +- (void)writeFloatArray:(int32_t)fieldNumber + values:(GPBFloatArray *)values + tag:(uint32_t)tag; - (void)writeFloatNoTag:(float)value; - (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value; -- (void)writeUInt64s:(int32_t)fieldNumber - values:(GPBUInt64Array *)values - tag:(uint32_t)tag; +- (void)writeUInt64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag; - (void)writeUInt64NoTag:(uint64_t)value; - (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value; -- (void)writeInt64s:(int32_t)fieldNumber - values:(GPBInt64Array *)values - tag:(uint32_t)tag; +- (void)writeInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; - (void)writeInt64NoTag:(int64_t)value; - (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value; -- (void)writeInt32s:(int32_t)fieldNumber - values:(GPBInt32Array *)values - tag:(uint32_t)tag; +- (void)writeInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; - (void)writeInt32NoTag:(int32_t)value; - (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value; -- (void)writeUInt32s:(int32_t)fieldNumber - values:(GPBUInt32Array *)values - tag:(uint32_t)tag; +- (void)writeUInt32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag; - (void)writeUInt32NoTag:(uint32_t)value; - (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value; -- (void)writeFixed64s:(int32_t)fieldNumber - values:(GPBUInt64Array *)values - tag:(uint32_t)tag; +- (void)writeFixed64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag; - (void)writeFixed64NoTag:(uint64_t)value; - (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value; -- (void)writeFixed32s:(int32_t)fieldNumber - values:(GPBUInt32Array *)values - tag:(uint32_t)tag; +- (void)writeFixed32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag; - (void)writeFixed32NoTag:(uint32_t)value; - (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value; -- (void)writeSInt32s:(int32_t)fieldNumber - values:(GPBInt32Array *)values - tag:(uint32_t)tag; +- (void)writeSInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; - (void)writeSInt32NoTag:(int32_t)value; - (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value; -- (void)writeSInt64s:(int32_t)fieldNumber - values:(GPBInt64Array *)values - tag:(uint32_t)tag; +- (void)writeSInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; - (void)writeSInt64NoTag:(int64_t)value; - (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value; -- (void)writeSFixed64s:(int32_t)fieldNumber - values:(GPBInt64Array *)values - tag:(uint32_t)tag; +- (void)writeSFixed64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag; - (void)writeSFixed64NoTag:(int64_t)value; - (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value; -- (void)writeSFixed32s:(int32_t)fieldNumber - values:(GPBInt32Array *)values - tag:(uint32_t)tag; +- (void)writeSFixed32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag; - (void)writeSFixed32NoTag:(int32_t)value; - (void)writeBool:(int32_t)fieldNumber value:(BOOL)value; -- (void)writeBools:(int32_t)fieldNumber - values:(GPBBoolArray *)values - tag:(uint32_t)tag; +- (void)writeBoolArray:(int32_t)fieldNumber + values:(GPBBoolArray *)values + tag:(uint32_t)tag; - (void)writeBoolNoTag:(BOOL)value; - (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value; -- (void)writeEnums:(int32_t)fieldNumber - values:(GPBEnumArray *)values - tag:(uint32_t)tag; +- (void)writeEnumArray:(int32_t)fieldNumber + values:(GPBEnumArray *)values + tag:(uint32_t)tag; - (void)writeEnumNoTag:(int32_t)value; - (void)writeString:(int32_t)fieldNumber value:(NSString *)value; -- (void)writeStrings:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values; - (void)writeStringNoTag:(NSString *)value; - (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value; -- (void)writeMessages:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values; - (void)writeMessageNoTag:(GPBMessage *)value; -- (void)writeData:(int32_t)fieldNumber value:(NSData *)value; -- (void)writeDatas:(int32_t)fieldNumber values:(NSArray *)values; -- (void)writeDataNoTag:(NSData *)value; +- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value; +- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeBytesNoTag:(NSData *)value; - (void)writeGroup:(int32_t)fieldNumber value:(GPBMessage *)value; -- (void)writeGroups:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values; - (void)writeGroupNoTag:(int32_t)fieldNumber value:(GPBMessage *)value; - (void)writeUnknownGroup:(int32_t)fieldNumber value:(GPBUnknownFieldSet *)value; -- (void)writeUnknownGroups:(int32_t)fieldNumber values:(NSArray *)values; +- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values; - (void)writeUnknownGroupNoTag:(int32_t)fieldNumber value:(GPBUnknownFieldSet *)value; @@ -230,7 +230,7 @@ size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, __attribute__((const)); size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) __attribute__((const)); -size_t GPBComputeDataSize(int32_t fieldNumber, NSData *value) +size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) __attribute__((const)); size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) __attribute__((const)); @@ -243,7 +243,7 @@ size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) __attribute__((const)); size_t GPBComputeTagSize(int32_t fieldNumber) __attribute__((const)); -size_t GPBComputeWireFormatTagSize(int field_number, GPBType type) +size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) __attribute__((const)); size_t GPBComputeDoubleSizeNoTag(double value) __attribute__((const)); @@ -259,7 +259,7 @@ size_t GPBComputeGroupSizeNoTag(GPBMessage *value) __attribute__((const)); size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) __attribute__((const)); size_t GPBComputeMessageSizeNoTag(GPBMessage *value) __attribute__((const)); -size_t GPBComputeDataSizeNoTag(NSData *value) __attribute__((const)); +size_t GPBComputeBytesSizeNoTag(NSData *value) __attribute__((const)); size_t GPBComputeUInt32SizeNoTag(int32_t value) __attribute__((const)); size_t GPBComputeEnumSizeNoTag(int32_t value) __attribute__((const)); size_t GPBComputeSFixed32SizeNoTag(int32_t value) __attribute__((const)); @@ -297,22 +297,22 @@ CF_EXTERN_C_END // Write methods for types that can be in packed arrays. //%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE) //%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value; -//%- (void)write##NAME##s:(int32_t)fieldNumber -//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values -//% NAME$S tag:(uint32_t)tag; +//%- (void)write##NAME##Array:(int32_t)fieldNumber +//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values +//% NAME$S tag:(uint32_t)tag; //%- (void)write##NAME##NoTag:(TYPE)value; //% // Write methods for types that aren't in packed arrays. //%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE) //%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value; -//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values; +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values; //%- (void)write##NAME##NoTag:(TYPE)value; //% // Special write methods for Groups. //%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE) //%- (void)write##NAME:(int32_t)fieldNumber //% NAME$S value:(TYPE)value; -//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values; +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values; //%- (void)write##NAME##NoTag:(int32_t)fieldNumber //% NAME$S value:(TYPE)value; //% @@ -335,6 +335,6 @@ CF_EXTERN_C_END //%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t) //%_WRITE_UNPACKABLE_DECLS(String, NSString *) //%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage *) -//%_WRITE_UNPACKABLE_DECLS(Data, NSData *) +//%_WRITE_UNPACKABLE_DECLS(Bytes, NSData *) //%_WRITE_GROUP_DECLS(Group, GPBMessage *) //%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet *) diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m index 9604c128..eb4900f6 100644 --- a/objectivec/GPBCodedOutputStream.m +++ b/objectivec/GPBCodedOutputStream.m @@ -372,14 +372,14 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, [self writeMessageNoTag:value]; } -- (void)writeDataNoTag:(NSData *)value { +- (void)writeBytesNoTag:(NSData *)value { GPBWriteRawVarint32(&state_, (int32_t)[value length]); [self writeRawData:value]; } -- (void)writeData:(int32_t)fieldNumber value:(NSData *)value { +- (void)writeBytes:(int32_t)fieldNumber value:(NSData *)value { GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited); - [self writeDataNoTag:value]; + [self writeBytesNoTag:value]; } - (void)writeUInt32NoTag:(uint32_t)value { @@ -436,9 +436,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, } //%PDDM-DEFINE WRITE_PACKABLE_DEFNS(NAME, ARRAY_TYPE, TYPE, ACCESSOR_NAME) -//%- (void)write##NAME##s:(int32_t)fieldNumber -//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values -//% NAME$S tag:(uint32_t)tag { +//%- (void)write##NAME##Array:(int32_t)fieldNumber +//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values +//% NAME$S tag:(uint32_t)tag { //% if (tag != 0) { //% if (values.count == 0) return; //% __block size_t dataSize = 0; @@ -461,7 +461,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%} //% //%PDDM-DEFINE WRITE_UNPACKABLE_DEFNS(NAME, TYPE) -//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values { +//%- (void)write##NAME##Array:(int32_t)fieldNumber values:(NSArray *)values { //% for (TYPE *value in values) { //% [self write##NAME:fieldNumber value:value]; //% } @@ -470,9 +470,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, ) // This block of code is generated, do not edit it directly. -- (void)writeDoubles:(int32_t)fieldNumber - values:(GPBDoubleArray *)values - tag:(uint32_t)tag { +- (void)writeDoubleArray:(int32_t)fieldNumber + values:(GPBDoubleArray *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -497,9 +497,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, ) // This block of code is generated, do not edit it directly. -- (void)writeFloats:(int32_t)fieldNumber - values:(GPBFloatArray *)values - tag:(uint32_t)tag { +- (void)writeFloatArray:(int32_t)fieldNumber + values:(GPBFloatArray *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -524,9 +524,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, ) // This block of code is generated, do not edit it directly. -- (void)writeUInt64s:(int32_t)fieldNumber - values:(GPBUInt64Array *)values - tag:(uint32_t)tag { +- (void)writeUInt64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -551,9 +551,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, ) // This block of code is generated, do not edit it directly. -- (void)writeInt64s:(int32_t)fieldNumber - values:(GPBInt64Array *)values - tag:(uint32_t)tag { +- (void)writeInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -578,9 +578,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, ) // This block of code is generated, do not edit it directly. -- (void)writeInt32s:(int32_t)fieldNumber - values:(GPBInt32Array *)values - tag:(uint32_t)tag { +- (void)writeInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -605,9 +605,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, ) // This block of code is generated, do not edit it directly. -- (void)writeUInt32s:(int32_t)fieldNumber - values:(GPBUInt32Array *)values - tag:(uint32_t)tag { +- (void)writeUInt32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -632,9 +632,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, ) // This block of code is generated, do not edit it directly. -- (void)writeFixed64s:(int32_t)fieldNumber - values:(GPBUInt64Array *)values - tag:(uint32_t)tag { +- (void)writeFixed64Array:(int32_t)fieldNumber + values:(GPBUInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -659,9 +659,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, ) // This block of code is generated, do not edit it directly. -- (void)writeFixed32s:(int32_t)fieldNumber - values:(GPBUInt32Array *)values - tag:(uint32_t)tag { +- (void)writeFixed32Array:(int32_t)fieldNumber + values:(GPBUInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -686,9 +686,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, ) // This block of code is generated, do not edit it directly. -- (void)writeSInt32s:(int32_t)fieldNumber - values:(GPBInt32Array *)values - tag:(uint32_t)tag { +- (void)writeSInt32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -713,9 +713,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, ) // This block of code is generated, do not edit it directly. -- (void)writeSInt64s:(int32_t)fieldNumber - values:(GPBInt64Array *)values - tag:(uint32_t)tag { +- (void)writeSInt64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -740,9 +740,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, ) // This block of code is generated, do not edit it directly. -- (void)writeSFixed64s:(int32_t)fieldNumber - values:(GPBInt64Array *)values - tag:(uint32_t)tag { +- (void)writeSFixed64Array:(int32_t)fieldNumber + values:(GPBInt64Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -767,9 +767,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, ) // This block of code is generated, do not edit it directly. -- (void)writeSFixed32s:(int32_t)fieldNumber - values:(GPBInt32Array *)values - tag:(uint32_t)tag { +- (void)writeSFixed32Array:(int32_t)fieldNumber + values:(GPBInt32Array *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -794,9 +794,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, ) // This block of code is generated, do not edit it directly. -- (void)writeBools:(int32_t)fieldNumber - values:(GPBBoolArray *)values - tag:(uint32_t)tag { +- (void)writeBoolArray:(int32_t)fieldNumber + values:(GPBBoolArray *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -821,9 +821,9 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw) // This block of code is generated, do not edit it directly. -- (void)writeEnums:(int32_t)fieldNumber - values:(GPBEnumArray *)values - tag:(uint32_t)tag { +- (void)writeEnumArray:(int32_t)fieldNumber + values:(GPBEnumArray *)values + tag:(uint32_t)tag { if (tag != 0) { if (values.count == 0) return; __block size_t dataSize = 0; @@ -848,7 +848,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString) // This block of code is generated, do not edit it directly. -- (void)writeStrings:(int32_t)fieldNumber values:(NSArray *)values { +- (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values { for (NSString *value in values) { [self writeString:fieldNumber value:value]; } @@ -857,25 +857,25 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage) // This block of code is generated, do not edit it directly. -- (void)writeMessages:(int32_t)fieldNumber values:(NSArray *)values { +- (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBMessage *value in values) { [self writeMessage:fieldNumber value:value]; } } -//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Data, NSData) +//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData) // This block of code is generated, do not edit it directly. -- (void)writeDatas:(int32_t)fieldNumber values:(NSArray *)values { +- (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values { for (NSData *value in values) { - [self writeData:fieldNumber value:value]; + [self writeBytes:fieldNumber value:value]; } } //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage) // This block of code is generated, do not edit it directly. -- (void)writeGroups:(int32_t)fieldNumber values:(NSArray *)values { +- (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBMessage *value in values) { [self writeGroup:fieldNumber value:value]; } @@ -884,7 +884,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet) // This block of code is generated, do not edit it directly. -- (void)writeUnknownGroups:(int32_t)fieldNumber values:(NSArray *)values { +- (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values { for (GPBUnknownFieldSet *value in values) { [self writeUnknownGroup:fieldNumber value:value]; } @@ -906,7 +906,7 @@ static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, GPBWireFormatStartGroup); GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber); - [self writeData:GPBWireFormatMessageSetMessage value:value]; + [self writeBytes:GPBWireFormatMessageSetMessage value:value]; GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, GPBWireFormatEndGroup); } @@ -1062,7 +1062,7 @@ size_t GPBComputeMessageSizeNoTag(GPBMessage *value) { return GPBComputeRawVarint32SizeForInteger(size) + size; } -size_t GPBComputeDataSizeNoTag(NSData *value) { +size_t GPBComputeBytesSizeNoTag(NSData *value) { NSUInteger valueLength = [value length]; return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength; } @@ -1143,8 +1143,8 @@ size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) { return GPBComputeTagSize(fieldNumber) + GPBComputeMessageSizeNoTag(value); } -size_t GPBComputeDataSize(int32_t fieldNumber, NSData *value) { - return GPBComputeTagSize(fieldNumber) + GPBComputeDataSizeNoTag(value); +size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) { + return GPBComputeTagSize(fieldNumber) + GPBComputeBytesSizeNoTag(value); } size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) { @@ -1183,7 +1183,7 @@ size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, NSData *value) { return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 + GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) + - GPBComputeDataSize(GPBWireFormatMessageSetMessage, value); + GPBComputeBytesSize(GPBWireFormatMessageSetMessage, value); } size_t GPBComputeTagSize(int32_t fieldNumber) { @@ -1191,9 +1191,9 @@ size_t GPBComputeTagSize(int32_t fieldNumber) { GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint)); } -size_t GPBComputeWireFormatTagSize(int field_number, GPBType type) { +size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) { size_t result = GPBComputeTagSize(field_number); - if (type == GPBTypeGroup) { + if (dataType == GPBDataTypeGroup) { // Groups have both a start and an end tag. return result * 2; } else { diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h index 97b46b3c..aeac9029 100644 --- a/objectivec/GPBDescriptor.h +++ b/objectivec/GPBDescriptor.h @@ -30,7 +30,7 @@ #import -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" @class GPBEnumDescriptor; @class GPBFieldDescriptor; @@ -89,14 +89,14 @@ typedef NS_ENUM(NSInteger, GPBFieldType) { @property(nonatomic, readonly, copy) NSString *name; @property(nonatomic, readonly) uint32_t number; -@property(nonatomic, readonly) GPBType type; +@property(nonatomic, readonly) GPBDataType dataType; @property(nonatomic, readonly) BOOL hasDefaultValue; -@property(nonatomic, readonly) GPBValue defaultValue; +@property(nonatomic, readonly) GPBGenericValue defaultValue; @property(nonatomic, readonly, getter=isRequired) BOOL required; @property(nonatomic, readonly, getter=isOptional) BOOL optional; @property(nonatomic, readonly) GPBFieldType fieldType; // If it is a map, the value type is in -type. -@property(nonatomic, readonly) GPBType mapKeyType; +@property(nonatomic, readonly) GPBDataType mapKeyDataType; @property(nonatomic, readonly, getter=isPackable) BOOL packable; @property(nonatomic, readonly, assign) GPBOneofDescriptor *containingOneof; @@ -129,12 +129,14 @@ typedef NS_ENUM(NSInteger, GPBFieldType) { @end -@interface GPBExtensionDescriptor : NSObject +@interface GPBExtensionDescriptor : NSObject @property(nonatomic, readonly) uint32_t fieldNumber; -@property(nonatomic, readonly) GPBType type; +@property(nonatomic, readonly) Class containingMessageClass; +@property(nonatomic, readonly) GPBDataType dataType; @property(nonatomic, readonly, getter=isRepeated) BOOL repeated; @property(nonatomic, readonly, getter=isPackable) BOOL packable; @property(nonatomic, readonly, assign) Class msgClass; @property(nonatomic, readonly) NSString *singletonName; @property(nonatomic, readonly, strong) GPBEnumDescriptor *enumDescriptor; +@property(nonatomic, readonly) id defaultValue; @end diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m index b955018c..bae9187e 100644 --- a/objectivec/GPBDescriptor.m +++ b/objectivec/GPBDescriptor.m @@ -369,16 +369,26 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { GPBWireFormat format; if ((description->flags & GPBFieldMapKeyMask) != 0) { // Maps are repeated messages on the wire. - format = GPBWireFormatForType(GPBTypeMessage, NO); + format = GPBWireFormatForType(GPBDataTypeMessage, NO); } else { - format = GPBWireFormatForType(description->type, - description->flags & GPBFieldPacked); + format = GPBWireFormatForType(description->dataType, + ((description->flags & GPBFieldPacked) != 0)); } return GPBWireFormatMakeTag(description->number, format); } +uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) { + GPBMessageFieldDescription *description = self->description_; + NSCAssert((description->flags & GPBFieldRepeated) != 0, + @"Only valid on repeated fields"); + GPBWireFormat format = + GPBWireFormatForType(description->dataType, + ((description->flags & GPBFieldPacked) == 0)); + return GPBWireFormatMakeTag(description->number, format); +} + @implementation GPBFieldDescriptor { - GPBValue defaultValue_; + GPBGenericValue defaultValue_; GPBFieldOptions *fieldOptions_; // Message ivars @@ -416,12 +426,66 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { getSel_ = sel_getUid(description->name); setSel_ = SelFromStrings("set", description->name, NULL, YES); + GPBDataType dataType = description->dataType; + BOOL isMessage = GPBDataTypeIsMessage(dataType); + BOOL isMapOrArray = GPBFieldIsMapOrArray(self); + + if (isMapOrArray) { + // map<>/repeated fields get a *Count property (inplace of a has*) to + // support checking if there are any entries without triggering + // autocreation. + hasOrCountSel_ = SelFromStrings(NULL, description->name, "_Count", NO); + } else { + // If there is a positive hasIndex, then: + // - All fields types for proto2 messages get has* selectors. + // - Only message fields for proto3 messages get has* selectors. + // Note: the positive check is to handle oneOfs, we can't check + // containingOneof_ because it isn't set until after initialization. + if ((description->hasIndex >= 0) && + (description->hasIndex != GPBNoHasBit) && + ((syntax != GPBFileSyntaxProto3) || isMessage)) { + hasOrCountSel_ = SelFromStrings("has", description->name, NULL, NO); + setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES); + } + } + + // Extra type specific data. + if (isMessage) { + const char *className = description->dataTypeSpecific.className; + msgClass_ = objc_getClass(className); + NSAssert(msgClass_, @"Class %s not defined", className); + } else if (dataType == GPBDataTypeEnum) { + if ((description_->flags & GPBFieldHasEnumDescriptor) != 0) { + enumHandling_.enumDescriptor_ = + description->dataTypeSpecific.enumDescFunc(); + } else { + enumHandling_.enumVerifier_ = + description->dataTypeSpecific.enumVerifier; + } + } + + // Non map<>/repeated fields can have defaults. + if (!isMapOrArray) { + defaultValue_ = description->defaultValue; + if (dataType == GPBDataTypeBytes) { + // Data stored as a length prefixed (network byte order) c-string in + // descriptor structure. + const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; + if (bytes) { + uint32_t length = *((uint32_t *)bytes); + length = ntohl(length); + bytes += sizeof(length); + defaultValue_.valueData = + [[NSData alloc] initWithBytes:bytes length:length]; + } + } + } + + // FieldOptions stored as a length prefixed (network byte order) c-escaped + // string in descriptor records. if (description->fieldOptions) { - // FieldOptions stored as a length prefixed c-escaped string in descriptor - // records. uint8_t *optionsBytes = (uint8_t *)description->fieldOptions; uint32_t optionsLength = *((uint32_t *)optionsBytes); - // The length is stored in network byte order. optionsLength = ntohl(optionsLength); if (optionsLength > 0) { optionsBytes += sizeof(optionsLength); @@ -434,69 +498,20 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { error:NULL] retain]; } } - - GPBType type = description->type; - BOOL isMessage = GPBTypeIsMessage(type); - if (isMessage) { - // No has* for repeated/map or something in a oneof (we can't check - // containingOneof_ because it isn't set until after initialization). - if ((description->hasIndex >= 0) && - (description->hasIndex != GPBNoHasBit)) { - hasSel_ = SelFromStrings("has", description->name, NULL, NO); - setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES); - } - const char *className = description->typeSpecific.className; - msgClass_ = objc_getClass(className); - NSAssert1(msgClass_, @"Class %s not defined", className); - // The defaultValue_ is fetched directly in -defaultValue to avoid - // initialization order issues. - } else { - if (!GPBFieldIsMapOrArray(self)) { - defaultValue_ = description->defaultValue; - if (type == GPBTypeData) { - // Data stored as a length prefixed c-string in descriptor records. - const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData; - if (bytes) { - uint32_t length = *((uint32_t *)bytes); - // The length is stored in network byte order. - length = ntohl(length); - bytes += sizeof(length); - defaultValue_.valueData = - [[NSData alloc] initWithBytes:bytes length:length]; - } - } - // No has* methods for proto3 or if our hasIndex is < 0 because it - // means the field is in a oneof (we can't check containingOneof_ - // because it isn't set until after initialization). - if ((syntax != GPBFileSyntaxProto3) && (description->hasIndex >= 0) && - (description->hasIndex != GPBNoHasBit)) { - hasSel_ = SelFromStrings("has", description->name, NULL, NO); - setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES); - } - } - if (GPBTypeIsEnum(type)) { - if (description_->flags & GPBFieldHasEnumDescriptor) { - enumHandling_.enumDescriptor_ = - description->typeSpecific.enumDescFunc(); - } else { - enumHandling_.enumVerifier_ = description->typeSpecific.enumVerifier; - } - } - } } return self; } - (void)dealloc { - if (description_->type == GPBTypeData && + if (description_->dataType == GPBDataTypeBytes && !(description_->flags & GPBFieldRepeated)) { [defaultValue_.valueData release]; } [super dealloc]; } -- (GPBType)type { - return description_->type; +- (GPBDataType)dataType { + return description_->dataType; } - (BOOL)hasDefaultValue { @@ -530,36 +545,36 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } } -- (GPBType)mapKeyType { +- (GPBDataType)mapKeyDataType { switch (description_->flags & GPBFieldMapKeyMask) { case GPBFieldMapKeyInt32: - return GPBTypeInt32; + return GPBDataTypeInt32; case GPBFieldMapKeyInt64: - return GPBTypeInt64; + return GPBDataTypeInt64; case GPBFieldMapKeyUInt32: - return GPBTypeUInt32; + return GPBDataTypeUInt32; case GPBFieldMapKeyUInt64: - return GPBTypeUInt64; + return GPBDataTypeUInt64; case GPBFieldMapKeySInt32: - return GPBTypeSInt32; + return GPBDataTypeSInt32; case GPBFieldMapKeySInt64: - return GPBTypeSInt64; + return GPBDataTypeSInt64; case GPBFieldMapKeyFixed32: - return GPBTypeFixed32; + return GPBDataTypeFixed32; case GPBFieldMapKeyFixed64: - return GPBTypeFixed64; + return GPBDataTypeFixed64; case GPBFieldMapKeySFixed32: - return GPBTypeSFixed32; + return GPBDataTypeSFixed32; case GPBFieldMapKeySFixed64: - return GPBTypeSFixed64; + return GPBDataTypeSFixed64; case GPBFieldMapKeyBool: - return GPBTypeBool; + return GPBDataTypeBool; case GPBFieldMapKeyString: - return GPBTypeString; + return GPBDataTypeString; default: NSAssert(0, @"Not a map type"); - return GPBTypeInt32; // For lack of anything better. + return GPBDataTypeInt32; // For lack of anything better. } } @@ -568,8 +583,8 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } - (BOOL)isValidEnumValue:(int32_t)value { - NSAssert(description_->type == GPBTypeEnum, - @"Field Must be of type GPBTypeEnum"); + NSAssert(description_->dataType == GPBDataTypeEnum, + @"Field Must be of type GPBDataTypeEnum"); if (description_->flags & GPBFieldHasEnumDescriptor) { return enumHandling_.enumDescriptor_.enumVerifier(value); } else { @@ -585,18 +600,18 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } } -- (GPBValue)defaultValue { +- (GPBGenericValue)defaultValue { // Depends on the fact that defaultValue_ is initialized either to "0/nil" or // to an actual defaultValue in our initializer. - GPBValue value = defaultValue_; + GPBGenericValue value = defaultValue_; if (!(description_->flags & GPBFieldRepeated)) { // We special handle data and strings. If they are nil, we replace them // with empty string/empty data. - GPBType type = description_->type; - if (type == GPBTypeData && value.valueData == nil) { + GPBDataType type = description_->dataType; + if (type == GPBDataTypeBytes && value.valueData == nil) { value.valueData = GPBEmptyNSData(); - } else if (type == GPBTypeString && value.valueString == nil) { + } else if (type == GPBDataTypeString && value.valueString == nil) { value.valueString = @""; } } @@ -635,7 +650,7 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } // Groups vs. other fields. - if (description_->type == GPBTypeGroup) { + if (description_->dataType == GPBDataTypeGroup) { // Just capitalize the first letter. unichar firstChar = [name characterAtIndex:0]; if (firstChar >= 'a' && firstChar <= 'z') { @@ -811,16 +826,70 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { @end -@implementation GPBExtensionDescriptor +@implementation GPBExtensionDescriptor { + GPBGenericValue defaultValue_; +} + +@synthesize containingMessageClass = containingMessageClass_; - (instancetype)initWithExtensionDescription: (GPBExtensionDescription *)description { if ((self = [super init])) { description_ = description; + +#if DEBUG + const char *className = description->messageOrGroupClassName; + if (className) { + NSAssert(objc_lookUpClass(className) != Nil, + @"Class %s not defined", className); + } +#endif + + if (description->extendedClass) { + Class containingClass = objc_lookUpClass(description->extendedClass); + NSAssert(containingClass, @"Class %s not defined", + description->extendedClass); + containingMessageClass_ = containingClass; + } + + GPBDataType type = description_->dataType; + if (type == GPBDataTypeBytes) { + // Data stored as a length prefixed c-string in descriptor records. + const uint8_t *bytes = + (const uint8_t *)description->defaultValue.valueData; + if (bytes) { + uint32_t length = *((uint32_t *)bytes); + // The length is stored in network byte order. + length = ntohl(length); + bytes += sizeof(length); + defaultValue_.valueData = + [[NSData alloc] initWithBytes:bytes length:length]; + } + } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) { + // The default is looked up in -defaultValue instead since extensions + // aren't common, we avoid the hit startup hit and it avoid initialization + // order issues. + } else { + defaultValue_ = description->defaultValue; + } } return self; } +- (void)dealloc { + if ((description_->dataType == GPBDataTypeBytes) && + !GPBExtensionIsRepeated(description_)) { + [defaultValue_.valueData release]; + } + [super dealloc]; +} + +- (instancetype)copyWithZone:(NSZone *)zone { +#pragma unused(zone) + // Immutable. + return [self retain]; +} + - (NSString *)singletonName { return @(description_->singletonName); } @@ -833,12 +902,24 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { return description_->fieldNumber; } -- (GPBType)type { - return description_->type; +- (GPBDataType)dataType { + return description_->dataType; +} + +- (GPBWireFormat)wireType { + return GPBWireFormatForType(description_->dataType, + GPBExtensionIsPacked(description_)); +} + +- (GPBWireFormat)alternateWireType { + NSAssert(GPBExtensionIsRepeated(description_), + @"Only valid on repeated extensions"); + return GPBWireFormatForType(description_->dataType, + !GPBExtensionIsPacked(description_)); } - (BOOL)isRepeated { - return (description_->options & GPBExtensionRepeated) != 0; + return GPBExtensionIsRepeated(description_); } - (BOOL)isMap { @@ -846,7 +927,7 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } - (BOOL)isPackable { - return (description_->options & GPBExtensionPacked) != 0; + return GPBExtensionIsPacked(description_); } - (Class)msgClass { @@ -854,11 +935,63 @@ uint32_t GPBFieldTag(GPBFieldDescriptor *self) { } - (GPBEnumDescriptor *)enumDescriptor { - if (GPBTypeIsEnum(description_->type)) { + if (description_->dataType == GPBDataTypeEnum) { GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc(); return enumDescriptor; } return nil; } +- (id)defaultValue { + if (GPBExtensionIsRepeated(description_)) { + return nil; + } + + switch (description_->dataType) { + case GPBDataTypeBool: + return @(defaultValue_.valueBool); + case GPBDataTypeFloat: + return @(defaultValue_.valueFloat); + case GPBDataTypeDouble: + return @(defaultValue_.valueDouble); + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeSFixed32: + return @(defaultValue_.valueInt32); + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeSFixed64: + return @(defaultValue_.valueInt64); + case GPBDataTypeUInt32: + case GPBDataTypeFixed32: + return @(defaultValue_.valueUInt32); + case GPBDataTypeUInt64: + case GPBDataTypeFixed64: + return @(defaultValue_.valueUInt64); + case GPBDataTypeBytes: + // Like message fields, the default is zero length data. + return (defaultValue_.valueData ? defaultValue_.valueData + : GPBEmptyNSData()); + case GPBDataTypeString: + // Like message fields, the default is zero length string. + return (defaultValue_.valueString ? defaultValue_.valueString : @""); + case GPBDataTypeGroup: + case GPBDataTypeMessage: + return nil; + } +} + +- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other { + int32_t selfNumber = description_->fieldNumber; + int32_t otherNumber = other->description_->fieldNumber; + if (selfNumber < otherNumber) { + return NSOrderedAscending; + } else if (selfNumber == otherNumber) { + return NSOrderedSame; + } else { + return NSOrderedDescending; + } +} + @end diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h index b289a48b..7987d928 100644 --- a/objectivec/GPBDescriptor_PackagePrivate.h +++ b/objectivec/GPBDescriptor_PackagePrivate.h @@ -33,6 +33,7 @@ // subject to change at any time without notice. #import "GPBDescriptor.h" +#import "GPBWireFormat.h" // Describes attributes of the field. typedef NS_OPTIONS(uint32_t, GPBFieldFlags) { @@ -66,8 +67,6 @@ typedef NS_OPTIONS(uint32_t, GPBFieldFlags) { // set, the name can be derived from the ObjC name. GPBFieldTextFormatNameCustom = 1 << 16, // Indicates the field has an enum descriptor. - // TODO(thomasvl): Output the CPP check to use descFunc or validator based - // on final compile. This will then get added based on that. GPBFieldHasEnumDescriptor = 1 << 17, }; @@ -84,21 +83,21 @@ typedef struct GPBMessageFieldDescription { int32_t hasIndex; // Field flags. Use accessor functions below. GPBFieldFlags flags; - // Type of the ivar. - GPBType type; + // Data type of the ivar. + GPBDataType dataType; // Offset of the variable into it's structure struct. size_t offset; // FieldOptions protobuf, serialized as string. const char *fieldOptions; - GPBValue defaultValue; // Default value for the ivar. + GPBGenericValue defaultValue; // Default value for the ivar. union { const char *className; // Name for message class. // For enums only: If EnumDescriptors are compiled in, it will be that, // otherwise it will be the verifier. GPBEnumDescriptorFunc enumDescFunc; GPBEnumValidationFunc enumVerifier; - } typeSpecific; + } dataTypeSpecific; } GPBMessageFieldDescription; // Describes a oneof. @@ -133,10 +132,10 @@ typedef NS_OPTIONS(uint32_t, GPBExtensionOptions) { // An extension typedef struct GPBExtensionDescription { const char *singletonName; - GPBType type; + GPBDataType dataType; const char *extendedClass; int32_t fieldNumber; - GPBValue defaultValue; + GPBGenericValue defaultValue; const char *messageOrGroupClassName; GPBExtensionOptions options; GPBEnumDescriptorFunc enumDescriptorFunc; @@ -217,7 +216,7 @@ typedef struct GPBExtensionDescription { SEL getSel_; SEL setSel_; - SEL hasSel_; + SEL hasOrCountSel_; // *Count for map<>/repeated fields, has* otherwise. SEL setHasSel_; } @@ -254,10 +253,18 @@ typedef struct GPBExtensionDescription { @package GPBExtensionDescription *description_; } +@property(nonatomic, readonly) GPBWireFormat wireType; + +// For repeated extensions, alternateWireType is the wireType with the opposite +// value for the packable property. i.e. - if the extension was marked packed +// it would be the wire type for unpacked; if the extension was marked unpacked, +// it would be the wire type for packed. +@property(nonatomic, readonly) GPBWireFormat alternateWireType; // description has to be long lived, it is held as a raw pointer. - (instancetype)initWithExtensionDescription: - (GPBExtensionDescription *)description; + (GPBExtensionDescription *)description; +- (NSComparisonResult)compareByFieldNumber:(GPBExtensionDescriptor *)other; @end CF_EXTERN_C_BEGIN @@ -267,8 +274,8 @@ GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) { (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0; } -GPB_INLINE GPBType GPBGetFieldType(GPBFieldDescriptor *field) { - return field->description_->type; +GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) { + return field->description_->dataType; } GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) { @@ -281,6 +288,12 @@ GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) { uint32_t GPBFieldTag(GPBFieldDescriptor *self); +// For repeated fields, alternateWireType is the wireType with the opposite +// value for the packable property. i.e. - if the field was marked packed it +// would be the wire type for unpacked; if the field was marked unpacked, it +// would be the wire type for packed. +uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self); + GPB_INLINE BOOL GPBPreserveUnknownFields(GPBFileSyntax syntax) { return syntax != GPBFileSyntaxProto3; } @@ -289,4 +302,17 @@ GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) { return syntax == GPBFileSyntaxProto3; } +GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) { + return (description->options & GPBExtensionRepeated) != 0; +} + +GPB_INLINE BOOL GPBExtensionIsPacked(GPBExtensionDescription *description) { + return (description->options & GPBExtensionPacked) != 0; +} + +GPB_INLINE BOOL GPBExtensionIsWireFormat(GPBExtensionDescription *description) { + return (description->options & GPBExtensionSetWireFormat) != 0; +} + + CF_EXTERN_C_END diff --git a/objectivec/GPBDictionary.h b/objectivec/GPBDictionary.h index 72873ad2..e5bd4750 100644 --- a/objectivec/GPBDictionary.h +++ b/objectivec/GPBDictionary.h @@ -30,7 +30,7 @@ #import -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" // These classes are used for map fields of basic data types. They are used because // they perform better than boxing into NSNumbers in NSDictionaries. diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m index 3769c697..df634279 100644 --- a/objectivec/GPBDictionary.m +++ b/objectivec/GPBDictionary.m @@ -55,64 +55,64 @@ static BOOL DictDefault_IsValidValue(int32_t value) { return (value != kGPBUnrecognizedEnumeratorValue); } -//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBTYPE_NAME1, GPBTYPE_NAME2) -//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) { -//% if (wireType == GPBType##GPBTYPE_NAME1) { -//% return GPBCompute##GPBTYPE_NAME1##Size(fieldNum, value); -//% } else if (wireType == GPBType##GPBTYPE_NAME2) { -//% return GPBCompute##GPBTYPE_NAME2##Size(fieldNum, value); +//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value); //% } else { -//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% NSCAssert(NO, @"Unexpected type %d", dataType); //% return 0; //% } //%} //% -//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) { -//% if (wireType == GPBType##GPBTYPE_NAME1) { -//% [stream write##GPBTYPE_NAME1##:fieldNum value:value]; -//% } else if (wireType == GPBType##GPBTYPE_NAME2) { -//% [stream write##GPBTYPE_NAME2##:fieldNum value:value]; +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% [stream write##GPBDATATYPE_NAME1##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% [stream write##GPBDATATYPE_NAME2##:fieldNum value:value]; //% } else { -//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% NSCAssert(NO, @"Unexpected type %d", dataType); //% } //%} //% -//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBTYPE_NAME1, GPBTYPE_NAME2, GPBTYPE_NAME3) -//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) { -//% if (wireType == GPBType##GPBTYPE_NAME1) { -//% return GPBCompute##GPBTYPE_NAME1##Size(fieldNum, value); -//% } else if (wireType == GPBType##GPBTYPE_NAME2) { -//% return GPBCompute##GPBTYPE_NAME2##Size(fieldNum, value); -//% } else if (wireType == GPBType##GPBTYPE_NAME3) { -//% return GPBCompute##GPBTYPE_NAME3##Size(fieldNum, value); +//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2, GPBDATATYPE_NAME3) +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% return GPBCompute##GPBDATATYPE_NAME1##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% return GPBCompute##GPBDATATYPE_NAME2##Size(fieldNum, value); +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) { +//% return GPBCompute##GPBDATATYPE_NAME3##Size(fieldNum, value); //% } else { -//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% NSCAssert(NO, @"Unexpected type %d", dataType); //% return 0; //% } //%} //% -//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) { -//% if (wireType == GPBType##GPBTYPE_NAME1) { -//% [stream write##GPBTYPE_NAME1##:fieldNum value:value]; -//% } else if (wireType == GPBType##GPBTYPE_NAME2) { -//% [stream write##GPBTYPE_NAME2##:fieldNum value:value]; -//% } else if (wireType == GPBType##GPBTYPE_NAME3) { -//% [stream write##GPBTYPE_NAME3##:fieldNum value:value]; +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) { +//% if (dataType == GPBDataType##GPBDATATYPE_NAME1) { +//% [stream write##GPBDATATYPE_NAME1##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME2) { +//% [stream write##GPBDATATYPE_NAME2##:fieldNum value:value]; +//% } else if (dataType == GPBDataType##GPBDATATYPE_NAME3) { +//% [stream write##GPBDATATYPE_NAME3##:fieldNum value:value]; //% } else { -//% NSCAssert(NO, @"Unexpected type %d", wireType); +//% NSCAssert(NO, @"Unexpected type %d", dataType); //% } //%} //% //%PDDM-DEFINE SIMPLE_SERIALIZE_SUPPORT(VALUE_NAME, VALUE_TYPE, VisP) -//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBType wireType) { -//% NSCAssert(wireType == GPBType##VALUE_NAME, @"bad type: %d", wireType); -//% #pragma unused(wireType) // For when asserts are off in release. +//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) { +//% NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType); +//% #pragma unused(dataType) // For when asserts are off in release. //% return GPBCompute##VALUE_NAME##Size(fieldNum, value); //%} //% -//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBType wireType) { -//% NSCAssert(wireType == GPBType##VALUE_NAME, @"bad type: %d", wireType); -//% #pragma unused(wireType) // For when asserts are off in release. +//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) { +//% NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType); +//% #pragma unused(dataType) // For when asserts are off in release. //% [stream write##VALUE_NAME##:fieldNum value:value]; //%} //% @@ -126,191 +126,191 @@ static BOOL DictDefault_IsValidValue(int32_t value) { //%SIMPLE_SERIALIZE_SUPPORT(Float, float, ) //%SIMPLE_SERIALIZE_SUPPORT(Double, double, ) //%SIMPLE_SERIALIZE_SUPPORT(String, NSString, *) -//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Data) +//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Bytes) //%PDDM-EXPAND SERIALIZE_SUPPORT_HELPERS() // This block of code is generated, do not edit it directly. -GPB_INLINE size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeInt32) { +static size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt32) { return GPBComputeInt32Size(fieldNum, value); - } else if (wireType == GPBTypeSInt32) { + } else if (dataType == GPBDataTypeSInt32) { return GPBComputeSInt32Size(fieldNum, value); - } else if (wireType == GPBTypeSFixed32) { + } else if (dataType == GPBDataTypeSFixed32) { return GPBComputeSFixed32Size(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeInt32) { +static void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt32) { [stream writeInt32:fieldNum value:value]; - } else if (wireType == GPBTypeSInt32) { + } else if (dataType == GPBDataTypeSInt32) { [stream writeSInt32:fieldNum value:value]; - } else if (wireType == GPBTypeSFixed32) { + } else if (dataType == GPBDataTypeSFixed32) { [stream writeSFixed32:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } -GPB_INLINE size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeUInt32) { +static size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt32) { return GPBComputeUInt32Size(fieldNum, value); - } else if (wireType == GPBTypeFixed32) { + } else if (dataType == GPBDataTypeFixed32) { return GPBComputeFixed32Size(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeUInt32) { +static void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt32) { [stream writeUInt32:fieldNum value:value]; - } else if (wireType == GPBTypeFixed32) { + } else if (dataType == GPBDataTypeFixed32) { [stream writeFixed32:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } -GPB_INLINE size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeInt64) { +static size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt64) { return GPBComputeInt64Size(fieldNum, value); - } else if (wireType == GPBTypeSInt64) { + } else if (dataType == GPBDataTypeSInt64) { return GPBComputeSInt64Size(fieldNum, value); - } else if (wireType == GPBTypeSFixed64) { + } else if (dataType == GPBDataTypeSFixed64) { return GPBComputeSFixed64Size(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeInt64) { +static void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeInt64) { [stream writeInt64:fieldNum value:value]; - } else if (wireType == GPBTypeSInt64) { + } else if (dataType == GPBDataTypeSInt64) { [stream writeSInt64:fieldNum value:value]; - } else if (wireType == GPBTypeSFixed64) { + } else if (dataType == GPBDataTypeSFixed64) { [stream writeSFixed64:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } -GPB_INLINE size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeUInt64) { +static size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt64) { return GPBComputeUInt64Size(fieldNum, value); - } else if (wireType == GPBTypeFixed64) { + } else if (dataType == GPBDataTypeFixed64) { return GPBComputeFixed64Size(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeUInt64) { +static void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeUInt64) { [stream writeUInt64:fieldNum value:value]; - } else if (wireType == GPBTypeFixed64) { + } else if (dataType == GPBDataTypeFixed64) { [stream writeFixed64:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } -GPB_INLINE size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeBoolSize(fieldNum, value); } -GPB_INLINE void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeBool:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeEnum, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeEnumSize(fieldNum, value); } -GPB_INLINE void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeEnum, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeEnum:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeFloatSize(fieldNum, value); } -GPB_INLINE void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeFloat:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeDoubleSize(fieldNum, value); } -GPB_INLINE void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeDouble:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. return GPBComputeStringSize(fieldNum, value); } -GPB_INLINE void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBType wireType) { - NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType); - #pragma unused(wireType) // For when asserts are off in release. +static void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBDataType dataType) { + NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType); + #pragma unused(dataType) // For when asserts are off in release. [stream writeString:fieldNum value:value]; } -GPB_INLINE size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeMessage) { +static size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeMessage) { return GPBComputeMessageSize(fieldNum, value); - } else if (wireType == GPBTypeString) { + } else if (dataType == GPBDataTypeString) { return GPBComputeStringSize(fieldNum, value); - } else if (wireType == GPBTypeData) { - return GPBComputeDataSize(fieldNum, value); + } else if (dataType == GPBDataTypeBytes) { + return GPBComputeBytesSize(fieldNum, value); } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); return 0; } } -GPB_INLINE void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBType wireType) { - if (wireType == GPBTypeMessage) { +static void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBDataType dataType) { + if (dataType == GPBDataTypeMessage) { [stream writeMessage:fieldNum value:value]; - } else if (wireType == GPBTypeString) { + } else if (dataType == GPBDataTypeString) { [stream writeString:fieldNum value:value]; - } else if (wireType == GPBTypeData) { - [stream writeData:fieldNum value:value]; + } else if (dataType == GPBDataTypeBytes) { + [stream writeBytes:fieldNum value:value]; } else { - NSCAssert(NO, @"Unexpected type %d", wireType); + NSCAssert(NO, @"Unexpected type %d", dataType); } } //%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS() size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { - GPBType mapValueType = GPBGetFieldType(field); + GPBDataType mapValueType = GPBGetFieldDataType(field); __block size_t result = 0; [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { #pragma unused(stop) @@ -318,7 +318,7 @@ size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescri msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * dict.count; return result; } @@ -326,8 +326,8 @@ size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescri void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream, NSDictionary *dict, GPBFieldDescriptor *field) { - NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type"); - GPBType mapValueType = GPBGetFieldType(field); + NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type"); + GPBDataType mapValueType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) { #pragma unused(stop) @@ -345,8 +345,8 @@ void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream } BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) { - NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type"); - NSCAssert(GPBGetFieldType(field) == GPBTypeMessage, @"Unexpected value type"); + NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type"); + NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeMessage, @"Unexpected value type"); #pragma unused(field) // For when asserts are off in release. for (GPBMessage *msg in [dict objectEnumerator]) { if (!msg.initialized) { @@ -358,69 +358,69 @@ BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescri // Note: if the type is an object, it the retain pass back to the caller. static void ReadValue(GPBCodedInputStream *stream, - GPBValue *valueToFill, - GPBType type, + GPBGenericValue *valueToFill, + GPBDataType type, GPBExtensionRegistry *registry, GPBFieldDescriptor *field) { switch (type) { - case GPBTypeBool: + case GPBDataTypeBool: valueToFill->valueBool = GPBCodedInputStreamReadBool(&stream->state_); break; - case GPBTypeFixed32: + case GPBDataTypeFixed32: valueToFill->valueUInt32 = GPBCodedInputStreamReadFixed32(&stream->state_); break; - case GPBTypeSFixed32: + case GPBDataTypeSFixed32: valueToFill->valueInt32 = GPBCodedInputStreamReadSFixed32(&stream->state_); break; - case GPBTypeFloat: + case GPBDataTypeFloat: valueToFill->valueFloat = GPBCodedInputStreamReadFloat(&stream->state_); break; - case GPBTypeFixed64: + case GPBDataTypeFixed64: valueToFill->valueUInt64 = GPBCodedInputStreamReadFixed64(&stream->state_); break; - case GPBTypeSFixed64: + case GPBDataTypeSFixed64: valueToFill->valueInt64 = GPBCodedInputStreamReadSFixed64(&stream->state_); break; - case GPBTypeDouble: + case GPBDataTypeDouble: valueToFill->valueDouble = GPBCodedInputStreamReadDouble(&stream->state_); break; - case GPBTypeInt32: + case GPBDataTypeInt32: valueToFill->valueInt32 = GPBCodedInputStreamReadInt32(&stream->state_); break; - case GPBTypeInt64: + case GPBDataTypeInt64: valueToFill->valueInt64 = GPBCodedInputStreamReadInt32(&stream->state_); break; - case GPBTypeSInt32: + case GPBDataTypeSInt32: valueToFill->valueInt32 = GPBCodedInputStreamReadSInt32(&stream->state_); break; - case GPBTypeSInt64: + case GPBDataTypeSInt64: valueToFill->valueInt64 = GPBCodedInputStreamReadSInt64(&stream->state_); break; - case GPBTypeUInt32: + case GPBDataTypeUInt32: valueToFill->valueUInt32 = GPBCodedInputStreamReadUInt32(&stream->state_); break; - case GPBTypeUInt64: + case GPBDataTypeUInt64: valueToFill->valueUInt64 = GPBCodedInputStreamReadUInt64(&stream->state_); break; - case GPBTypeData: + case GPBDataTypeBytes: [valueToFill->valueData release]; - valueToFill->valueData = GPBCodedInputStreamReadRetainedData(&stream->state_); + valueToFill->valueData = GPBCodedInputStreamReadRetainedBytes(&stream->state_); break; - case GPBTypeString: + case GPBDataTypeString: [valueToFill->valueString release]; valueToFill->valueString = GPBCodedInputStreamReadRetainedString(&stream->state_); break; - case GPBTypeMessage: { + case GPBDataTypeMessage: { GPBMessage *message = [[field.msgClass alloc] init]; [stream readMessage:message extensionRegistry:registry]; [valueToFill->valueMessage release]; valueToFill->valueMessage = message; break; } - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"Can't happen"); break; - case GPBTypeEnum: + case GPBDataTypeEnum: valueToFill->valueEnum = GPBCodedInputStreamReadEnum(&stream->state_); break; } @@ -431,30 +431,30 @@ void GPBDictionaryReadEntry(id mapDictionary, GPBExtensionRegistry *registry, GPBFieldDescriptor *field, GPBMessage *parentMessage) { - GPBType keyType = field.mapKeyType; - GPBType valueType = GPBGetFieldType(field); + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); - GPBValue key; - GPBValue value; + GPBGenericValue key; + GPBGenericValue value; // Zero them (but pick up any enum default for proto2). key.valueString = value.valueString = nil; - if (valueType == GPBTypeEnum) { + if (valueDataType == GPBDataTypeEnum) { value = field.defaultValue; } GPBCodedInputStreamState *state = &stream->state_; uint32_t keyTag = - GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyType, NO)); + GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyDataType, NO)); uint32_t valueTag = - GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueType, NO)); + GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueDataType, NO)); BOOL hitError = NO; while (YES) { uint32_t tag = GPBCodedInputStreamReadTag(state); if (tag == keyTag) { - ReadValue(stream, &key, keyType, registry, field); + ReadValue(stream, &key, keyDataType, registry, field); } else if (tag == valueTag) { - ReadValue(stream, &value, valueType, registry, field); + ReadValue(stream, &value, valueDataType, registry, field); } else if (tag == 0) { // zero signals EOF / limit reached break; @@ -468,18 +468,18 @@ void GPBDictionaryReadEntry(id mapDictionary, if (!hitError) { // Handle the special defaults and/or missing key/value. - if ((keyType == GPBTypeString) && (key.valueString == nil)) { + if ((keyDataType == GPBDataTypeString) && (key.valueString == nil)) { key.valueString = [@"" retain]; } - if (GPBTypeIsObject(valueType) && value.valueString == nil) { - switch (valueType) { - case GPBTypeString: + if (GPBDataTypeIsObject(valueDataType) && value.valueString == nil) { + switch (valueDataType) { + case GPBDataTypeString: value.valueString = [@"" retain]; break; - case GPBTypeData: + case GPBDataTypeBytes: value.valueData = [GPBEmptyNSData() retain]; break; - case GPBTypeMessage: { + case GPBDataTypeMessage: { value.valueMessage = [[field.msgClass alloc] init]; break; } @@ -489,30 +489,30 @@ void GPBDictionaryReadEntry(id mapDictionary, } } - if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) { + if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) { // mapDictionary is an NSMutableDictionary [mapDictionary setObject:value.valueString forKey:key.valueString]; } else { - if (valueType == GPBTypeEnum) { + if (valueDataType == GPBDataTypeEnum) { if (GPBHasPreservingUnknownEnumSemantics([parentMessage descriptor].file.syntax) || [field isValidEnumValue:value.valueEnum]) { - [mapDictionary setGPBValue:&value forGPBValueKey:&key]; + [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key]; } else { NSData *data = [mapDictionary serializedDataForUnknownValue:value.valueEnum forKey:&key - keyType:keyType]; + keyDataType:keyDataType]; [parentMessage addUnknownMapEntry:GPBFieldNumber(field) value:data]; } } else { - [mapDictionary setGPBValue:&value forGPBValueKey:&key]; + [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key]; } } } - if (GPBTypeIsObject(keyType)) { + if (GPBDataTypeIsObject(keyDataType)) { [key.valueString release]; } - if (GPBTypeIsObject(valueType)) { + if (GPBDataTypeIsObject(valueDataType)) { [value.valueString release]; } } @@ -834,26 +834,26 @@ void GPBDictionaryReadEntry(id mapDictionary, //% return 0; //% } //% -//% GPBType valueType = GPBGetFieldType(field); -//% GPBType keyType = field.mapKeyType; +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% GPBDataType keyDataType = field.mapKeyDataType; //% __block size_t result = 0; //% [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey, //% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue, //% BOOL *stop) { //% #pragma unused(stop) -//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType); -//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType); +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType); //% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; //% }]; -//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); +//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); //% result += tagSize * count; //% return result; //%} //% //%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream //% asField:(GPBFieldDescriptor *)field { -//% GPBType valueType = GPBGetFieldType(field); -//% GPBType keyType = field.mapKeyType; +//% GPBDataType valueDataType = GPBGetFieldDataType(field); +//% GPBDataType keyDataType = field.mapKeyDataType; //% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); //% [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey, //% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue, @@ -862,16 +862,17 @@ void GPBDictionaryReadEntry(id mapDictionary, //% // Write the tag. //% [outputStream writeInt32NoTag:tag]; //% // Write the size of the message. -//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType); -//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType); +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType); //% [outputStream writeInt32NoTag:(int32_t)msgSize]; //% // Write the fields. -//% WriteDict##KEY_NAME##Field(outputStream, UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType); -//% WriteDict##VALUE_NAME##Field(outputStream, UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType); +//% WriteDict##KEY_NAME##Field(outputStream, UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyDataType); +//% WriteDict##VALUE_NAME##Field(outputStream, UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueDataType); //% }]; //%} //% -//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { //% [_dictionary setObject:WRAPPED##VHELPER(value->##GPBVALUE_##VHELPER(VALUE_NAME)##) forKey:WRAPPED##KHELPER(key->value##KEY_NAME)]; //%} //% @@ -1036,37 +1037,37 @@ void GPBDictionaryReadEntry(id mapDictionary, //%} //% //%BOOL_EXTRA_METHODS_##HELPER(Bool, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { -//% GPBType valueType = GPBGetFieldType(field); +//% GPBDataType valueDataType = GPBGetFieldDataType(field); //% NSUInteger count = 0; //% size_t result = 0; //% for (int i = 0; i < 2; ++i) { //% if (BOOL_DICT_HAS##HELPER(i, )) { //% ++count; -//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); -//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueType); +//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType); //% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; //% } //% } -//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); +//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); //% result += tagSize * count; //% return result; //%} //% //%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream //% asField:(GPBFieldDescriptor *)field { -//% GPBType valueType = GPBGetFieldType(field); +//% GPBDataType valueDataType = GPBGetFieldDataType(field); //% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); //% for (int i = 0; i < 2; ++i) { //% if (BOOL_DICT_HAS##HELPER(i, )) { //% // Write the tag. //% [outputStream writeInt32NoTag:tag]; //% // Write the size of the message. -//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); -//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueType); +//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueDataType); //% [outputStream writeInt32NoTag:(int32_t)msgSize]; //% // Write the fields. -//% WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); -//% WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueType); +//% WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); +//% WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); //% } //% } //%} @@ -1149,14 +1150,14 @@ void GPBDictionaryReadEntry(id mapDictionary, // Empty //%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Enum(KEY_NAME) //%- (NSData *)serializedDataForUnknownValue:(int32_t)value -//% forKey:(GPBValue *)key -//% keyType:(GPBType)keyType { -//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyType); -//% msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); +//% forKey:(GPBGenericValue *)key +//% keyDataType:(GPBDataType)keyDataType { +//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); +//% msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); //% NSMutableData *data = [NSMutableData dataWithLength:msgSize]; //% GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; -//% WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyType); -//% WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); +//% WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyDataType); +//% WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); //% [outputStream release]; //% return data; //%} @@ -1221,7 +1222,8 @@ void GPBDictionaryReadEntry(id mapDictionary, //% return NO; //%} //%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE, VisP) -//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +//%- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { //% int idx = (key->valueBool ? 1 : 0); //% _values[idx] = value->value##VALUE_NAME; //% _valueSet[idx] = YES; @@ -1401,7 +1403,8 @@ void GPBDictionaryReadEntry(id mapDictionary, //% return _values[key ? 1 : 0]; //%} //%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_OBJECT(VALUE_NAME, VALUE_TYPE, VisP) -//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +//%- (void)setGPBGenericValue:(GPBGenericValue *)value +//% forGPBGenericValueKey:(GPBGenericValue *)key { //% int idx = (key->valueBool ? 1 : 0); //% [_values[idx] release]; //% _values[idx] = [value->valueString retain]; @@ -1573,26 +1576,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -1601,16 +1604,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt32)]; } @@ -1778,26 +1782,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -1806,16 +1810,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt32)]; } @@ -1983,26 +1988,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2011,16 +2016,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt32)]; } @@ -2188,26 +2194,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2216,16 +2222,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt32)]; } @@ -2393,26 +2400,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2421,16 +2428,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt32)]; } @@ -2598,26 +2606,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2626,16 +2634,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt32)]; } @@ -2803,26 +2812,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -2831,16 +2840,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt32)]; } @@ -3036,26 +3046,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -3064,28 +3074,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt32)]; } @@ -3315,26 +3326,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, @@ -3343,16 +3354,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType); - WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType); + WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:value->valueString forKey:@(key->valueUInt32)]; } @@ -3520,26 +3532,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -3548,16 +3560,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt32)]; } @@ -3725,26 +3738,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -3753,16 +3766,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt32)]; } @@ -3930,26 +3944,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -3958,16 +3972,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt32)]; } @@ -4135,26 +4150,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -4163,16 +4178,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt32)]; } @@ -4340,26 +4356,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -4368,16 +4384,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt32)]; } @@ -4545,26 +4562,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -4573,16 +4590,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt32)]; } @@ -4750,26 +4768,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -4778,16 +4796,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt32)]; } @@ -4983,26 +5002,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -5011,28 +5030,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt32)]; } @@ -5262,26 +5282,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, @@ -5290,16 +5310,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType); - WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType); + WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:value->valueString forKey:@(key->valueInt32)]; } @@ -5467,26 +5488,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -5495,16 +5516,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt64)]; } @@ -5672,26 +5694,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -5700,16 +5722,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt64)]; } @@ -5877,26 +5900,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -5905,16 +5928,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt64)]; } @@ -6082,26 +6106,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6110,16 +6134,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt64)]; } @@ -6287,26 +6312,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6315,16 +6340,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt64)]; } @@ -6492,26 +6518,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6520,16 +6546,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt64)]; } @@ -6697,26 +6724,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6725,16 +6752,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt64)]; } @@ -6930,26 +6958,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -6958,28 +6986,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt64)]; } @@ -7209,26 +7238,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, @@ -7237,16 +7266,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType); - WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType); + WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:value->valueString forKey:@(key->valueUInt64)]; } @@ -7414,26 +7444,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -7442,16 +7472,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt64)]; } @@ -7619,26 +7650,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -7647,16 +7678,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt64)]; } @@ -7824,26 +7856,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -7852,16 +7884,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt64)]; } @@ -8029,26 +8062,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8057,16 +8090,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt64)]; } @@ -8234,26 +8268,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8262,16 +8296,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt64)]; } @@ -8439,26 +8474,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8467,16 +8502,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt64)]; } @@ -8644,26 +8680,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8672,16 +8708,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt64)]; } @@ -8877,26 +8914,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, NSNumber *aValue, @@ -8905,28 +8942,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt64)]; } @@ -9156,26 +9194,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey, id aValue, @@ -9184,16 +9222,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType); - msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType); - WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType); + WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyDataType); + WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:value->valueString forKey:@(key->valueInt64)]; } @@ -9361,26 +9400,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -9389,16 +9428,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt32) forKey:key->valueString]; } @@ -9566,26 +9606,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -9594,16 +9634,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt32) forKey:key->valueString]; } @@ -9771,26 +9812,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -9799,16 +9840,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueUInt64) forKey:key->valueString]; } @@ -9976,26 +10018,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10004,16 +10046,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueInt64) forKey:key->valueString]; } @@ -10181,26 +10224,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10209,16 +10252,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueBool) forKey:key->valueString]; } @@ -10386,26 +10430,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10414,16 +10458,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueFloat) forKey:key->valueString]; } @@ -10591,26 +10636,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10619,16 +10664,17 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueDataType); }]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueDouble) forKey:key->valueString]; } @@ -10824,26 +10870,26 @@ void GPBDictionaryReadEntry(id mapDictionary, return 0; } - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; __block size_t result = 0; [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, BOOL *stop) { #pragma unused(stop) - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; }]; - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); - GPBType keyType = field.mapKeyType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + GPBDataType keyDataType = field.mapKeyDataType; uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey, NSNumber *aValue, @@ -10852,28 +10898,29 @@ void GPBDictionaryReadEntry(id mapDictionary, // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType); + WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueDataType); }]; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { [_dictionary setObject:@(value->valueEnum) forKey:key->valueString]; } @@ -11104,7 +11151,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueUInt32; _valueSet[idx] = YES; @@ -11131,37 +11179,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -11344,7 +11392,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueInt32; _valueSet[idx] = YES; @@ -11371,37 +11420,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -11584,7 +11633,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueUInt64; _valueSet[idx] = YES; @@ -11611,37 +11661,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -11824,7 +11874,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueInt64; _valueSet[idx] = YES; @@ -11851,37 +11902,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -12064,7 +12115,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueBool; _valueSet[idx] = YES; @@ -12091,37 +12143,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -12304,7 +12356,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueFloat; _valueSet[idx] = YES; @@ -12331,37 +12384,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -12544,7 +12597,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return NO; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueDouble; _valueSet[idx] = YES; @@ -12571,37 +12625,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -12772,7 +12826,8 @@ void GPBDictionaryReadEntry(id mapDictionary, return _values[key ? 1 : 0]; } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); [_values[idx] release]; _values[idx] = [value->valueString retain]; @@ -12820,37 +12875,37 @@ void GPBDictionaryReadEntry(id mapDictionary, } - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_values[i] != nil) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_values[i] != nil) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -13115,14 +13170,14 @@ void GPBDictionaryReadEntry(id mapDictionary, // This block of code is generated, do not edit it directly. - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType { - size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyType); - msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum); + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType { + size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyDataType); + msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBDataTypeEnum); NSMutableData *data = [NSMutableData dataWithLength:msgSize]; GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data]; - WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyType); - WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum); + WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyDataType); + WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBDataTypeEnum); [outputStream release]; return data; } @@ -13130,37 +13185,37 @@ void GPBDictionaryReadEntry(id mapDictionary, //%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool) - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); NSUInteger count = 0; size_t result = 0; for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { ++count; - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize; } } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage); + size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBDataTypeMessage); result += tagSize * count; return result; } - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field { - GPBType valueType = GPBGetFieldType(field); + GPBDataType valueDataType = GPBGetFieldDataType(field); uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited); for (int i = 0; i < 2; ++i) { if (_valueSet[i]) { // Write the tag. [outputStream writeInt32NoTag:tag]; // Write the size of the message. - size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool); - msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType); + size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueDataType); [outputStream writeInt32NoTag:(int32_t)msgSize]; // Write the fields. - WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool); - WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType); + WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBDataTypeBool); + WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueDataType); } } } @@ -13174,7 +13229,8 @@ void GPBDictionaryReadEntry(id mapDictionary, } } -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key { +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key { int idx = (key->valueBool ? 1 : 0); _values[idx] = value->valueInt32; _valueSet[idx] = YES; diff --git a/objectivec/GPBDictionary_PackagePrivate.h b/objectivec/GPBDictionary_PackagePrivate.h index 9c3c5915..7b921e8e 100644 --- a/objectivec/GPBDictionary_PackagePrivate.h +++ b/objectivec/GPBDictionary_PackagePrivate.h @@ -41,7 +41,8 @@ - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field; - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream asField:(GPBFieldDescriptor *)field; -- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key; +- (void)setGPBGenericValue:(GPBGenericValue *)value + forGPBGenericValueKey:(GPBGenericValue *)key; - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block; @end @@ -75,8 +76,8 @@ //% //%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Enum() //%- (NSData *)serializedDataForUnknownValue:(int32_t)value -//% forKey:(GPBValue *)key -//% keyType:(GPBType)keyType; +//% forKey:(GPBGenericValue *)key +//% keyDataType:(GPBDataType)keyDataType; //% //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32) @@ -129,8 +130,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBUInt32ObjectDictionary () { @@ -192,8 +193,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBInt32ObjectDictionary () { @@ -255,8 +256,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBUInt64ObjectDictionary () { @@ -318,8 +319,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBInt64ObjectDictionary () { @@ -381,8 +382,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end @interface GPBBoolObjectDictionary () { @@ -444,8 +445,8 @@ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator; } - (NSData *)serializedDataForUnknownValue:(int32_t)value - forKey:(GPBValue *)key - keyType:(GPBType)keyType; + forKey:(GPBGenericValue *)key + keyDataType:(GPBDataType)keyDataType; @end //%PDDM-EXPAND-END (6 expansions) diff --git a/objectivec/GPBExtensionField.h b/objectivec/GPBExtensionField.h deleted file mode 100644 index e5ba1561..00000000 --- a/objectivec/GPBExtensionField.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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. - -#import - -#import "GPBWireFormat.h" -#import "GPBTypes.h" - -@class GPBCodedInputStream; -@class GPBCodedOutputStream; -@class GPBExtensionRegistry; -@class GPBDescriptor; -@class GPBExtensionDescriptor; - -@interface GPBExtensionField : NSObject - -@property(nonatomic, readonly) int32_t fieldNumber; -@property(nonatomic, readonly) GPBWireFormat wireType; -@property(nonatomic, readonly) BOOL isRepeated; -@property(nonatomic, readonly) GPBDescriptor *containingType; -@property(nonatomic, readonly) id defaultValue; -@property(nonatomic, readonly) GPBExtensionDescriptor *descriptor; - -@end diff --git a/objectivec/GPBExtensionField.m b/objectivec/GPBExtensionField.m deleted file mode 100644 index bbb36d7f..00000000 --- a/objectivec/GPBExtensionField.m +++ /dev/null @@ -1,525 +0,0 @@ -// 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. - -#import "GPBExtensionField_PackagePrivate.h" - -#import - -#import "GPBCodedInputStream_PackagePrivate.h" -#import "GPBCodedOutputStream.h" -#import "GPBDescriptor_PackagePrivate.h" -#import "GPBMessage_PackagePrivate.h" -#import "GPBUtilities_PackagePrivate.h" - -GPB_INLINE size_t TypeSize(GPBType type) { - switch (type) { - case GPBTypeBool: - return 1; - case GPBTypeFixed32: - case GPBTypeSFixed32: - case GPBTypeFloat: - return 4; - case GPBTypeFixed64: - case GPBTypeSFixed64: - case GPBTypeDouble: - return 8; - default: - return 0; - } -} - -GPB_INLINE BOOL ExtensionIsRepeated(GPBExtensionDescription *description) { - return (description->options & GPBExtensionRepeated) != 0; -} - -GPB_INLINE BOOL ExtensionIsPacked(GPBExtensionDescription *description) { - return (description->options & GPBExtensionPacked) != 0; -} - -GPB_INLINE BOOL ExtensionIsWireFormat(GPBExtensionDescription *description) { - return (description->options & GPBExtensionSetWireFormat) != 0; -} - -static size_t ComputePBSerializedSizeNoTagOfObject(GPBType type, id object) { -#define FIELD_CASE(TYPE, ACCESSOR) \ - case GPBType##TYPE: \ - return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]); -#define FIELD_CASE2(TYPE) \ - case GPBType##TYPE: \ - return GPBCompute##TYPE##SizeNoTag(object); - switch (type) { - FIELD_CASE(Bool, boolValue) - FIELD_CASE(Float, floatValue) - FIELD_CASE(Double, doubleValue) - FIELD_CASE(Int32, intValue) - FIELD_CASE(SFixed32, intValue) - FIELD_CASE(SInt32, intValue) - FIELD_CASE(Enum, intValue) - FIELD_CASE(Int64, longLongValue) - FIELD_CASE(SInt64, longLongValue) - FIELD_CASE(SFixed64, longLongValue) - FIELD_CASE(UInt32, unsignedIntValue) - FIELD_CASE(Fixed32, unsignedIntValue) - FIELD_CASE(UInt64, unsignedLongLongValue) - FIELD_CASE(Fixed64, unsignedLongLongValue) - FIELD_CASE2(Data) - FIELD_CASE2(String) - FIELD_CASE2(Message) - FIELD_CASE2(Group) - } -#undef FIELD_CASE -#undef FIELD_CASE2 -} - -static size_t ComputeSerializedSizeIncludingTagOfObject( - GPBExtensionDescription *description, id object) { -#define FIELD_CASE(TYPE, ACCESSOR) \ - case GPBType##TYPE: \ - return GPBCompute##TYPE##Size(description->fieldNumber, \ - [(NSNumber *)object ACCESSOR]); -#define FIELD_CASE2(TYPE) \ - case GPBType##TYPE: \ - return GPBCompute##TYPE##Size(description->fieldNumber, object); - switch (description->type) { - FIELD_CASE(Bool, boolValue) - FIELD_CASE(Float, floatValue) - FIELD_CASE(Double, doubleValue) - FIELD_CASE(Int32, intValue) - FIELD_CASE(SFixed32, intValue) - FIELD_CASE(SInt32, intValue) - FIELD_CASE(Enum, intValue) - FIELD_CASE(Int64, longLongValue) - FIELD_CASE(SInt64, longLongValue) - FIELD_CASE(SFixed64, longLongValue) - FIELD_CASE(UInt32, unsignedIntValue) - FIELD_CASE(Fixed32, unsignedIntValue) - FIELD_CASE(UInt64, unsignedLongLongValue) - FIELD_CASE(Fixed64, unsignedLongLongValue) - FIELD_CASE2(Data) - FIELD_CASE2(String) - FIELD_CASE2(Group) - case GPBTypeMessage: - if (ExtensionIsWireFormat(description)) { - return GPBComputeMessageSetExtensionSize(description->fieldNumber, - object); - } else { - return GPBComputeMessageSize(description->fieldNumber, object); - } - } -#undef FIELD_CASE -#undef FIELD_CASE2 -} - -static size_t ComputeSerializedSizeIncludingTagOfArray( - GPBExtensionDescription *description, NSArray *values) { - if (ExtensionIsPacked(description)) { - size_t size = 0; - size_t typeSize = TypeSize(description->type); - if (typeSize != 0) { - size = values.count * typeSize; - } else { - for (id value in values) { - size += ComputePBSerializedSizeNoTagOfObject(description->type, value); - } - } - return size + GPBComputeTagSize(description->fieldNumber) + - GPBComputeRawVarint32SizeForInteger(size); - } else { - size_t size = 0; - for (id value in values) { - size += ComputeSerializedSizeIncludingTagOfObject(description, value); - } - return size; - } -} - -static void WriteObjectIncludingTagToCodedOutputStream( - id object, GPBExtensionDescription *description, - GPBCodedOutputStream *output) { -#define FIELD_CASE(TYPE, ACCESSOR) \ - case GPBType##TYPE: \ - [output write##TYPE:description->fieldNumber \ - value:[(NSNumber *)object ACCESSOR]]; \ - return; -#define FIELD_CASE2(TYPE) \ - case GPBType##TYPE: \ - [output write##TYPE:description->fieldNumber value:object]; \ - return; - switch (description->type) { - FIELD_CASE(Bool, boolValue) - FIELD_CASE(Float, floatValue) - FIELD_CASE(Double, doubleValue) - FIELD_CASE(Int32, intValue) - FIELD_CASE(SFixed32, intValue) - FIELD_CASE(SInt32, intValue) - FIELD_CASE(Enum, intValue) - FIELD_CASE(Int64, longLongValue) - FIELD_CASE(SInt64, longLongValue) - FIELD_CASE(SFixed64, longLongValue) - FIELD_CASE(UInt32, unsignedIntValue) - FIELD_CASE(Fixed32, unsignedIntValue) - FIELD_CASE(UInt64, unsignedLongLongValue) - FIELD_CASE(Fixed64, unsignedLongLongValue) - FIELD_CASE2(Data) - FIELD_CASE2(String) - FIELD_CASE2(Group) - case GPBTypeMessage: - if (ExtensionIsWireFormat(description)) { - [output writeMessageSetExtension:description->fieldNumber value:object]; - } else { - [output writeMessage:description->fieldNumber value:object]; - } - return; - } -#undef FIELD_CASE -#undef FIELD_CASE2 -} - -static void WriteObjectNoTagToCodedOutputStream( - id object, GPBExtensionDescription *description, - GPBCodedOutputStream *output) { -#define FIELD_CASE(TYPE, ACCESSOR) \ - case GPBType##TYPE: \ - [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \ - return; -#define FIELD_CASE2(TYPE) \ - case GPBType##TYPE: \ - [output write##TYPE##NoTag:object]; \ - return; - switch (description->type) { - FIELD_CASE(Bool, boolValue) - FIELD_CASE(Float, floatValue) - FIELD_CASE(Double, doubleValue) - FIELD_CASE(Int32, intValue) - FIELD_CASE(SFixed32, intValue) - FIELD_CASE(SInt32, intValue) - FIELD_CASE(Enum, intValue) - FIELD_CASE(Int64, longLongValue) - FIELD_CASE(SInt64, longLongValue) - FIELD_CASE(SFixed64, longLongValue) - FIELD_CASE(UInt32, unsignedIntValue) - FIELD_CASE(Fixed32, unsignedIntValue) - FIELD_CASE(UInt64, unsignedLongLongValue) - FIELD_CASE(Fixed64, unsignedLongLongValue) - FIELD_CASE2(Data) - FIELD_CASE2(String) - FIELD_CASE2(Message) - case GPBTypeGroup: - [output writeGroupNoTag:description->fieldNumber value:object]; - return; - } -#undef FIELD_CASE -#undef FIELD_CASE2 -} - -static void WriteArrayIncludingTagsToCodedOutputStream( - NSArray *values, GPBExtensionDescription *description, - GPBCodedOutputStream *output) { - if (ExtensionIsPacked(description)) { - [output writeTag:description->fieldNumber - format:GPBWireFormatLengthDelimited]; - size_t dataSize = 0; - size_t typeSize = TypeSize(description->type); - if (typeSize != 0) { - dataSize = values.count * typeSize; - } else { - for (id value in values) { - dataSize += - ComputePBSerializedSizeNoTagOfObject(description->type, value); - } - } - [output writeRawVarintSizeTAs32:dataSize]; - for (id value in values) { - WriteObjectNoTagToCodedOutputStream(value, description, output); - } - } else { - for (id value in values) { - WriteObjectIncludingTagToCodedOutputStream(value, description, output); - } - } -} - -@implementation GPBExtensionField { - GPBExtensionDescription *description_; - GPBExtensionDescriptor *descriptor_; - GPBValue defaultValue_; -} - -@synthesize containingType = containingType_; -@synthesize descriptor = descriptor_; - -- (instancetype)init { - // Throw an exception if people attempt to not use the designated initializer. - self = [super init]; - if (self != nil) { - [self doesNotRecognizeSelector:_cmd]; - self = nil; - } - return self; -} - -- (instancetype)initWithDescription:(GPBExtensionDescription *)description { - if ((self = [super init])) { - description_ = description; - if (description->extendedClass) { - Class containingClass = objc_lookUpClass(description->extendedClass); - NSAssert1(containingClass, @"Class %s not defined", - description->extendedClass); - containingType_ = [containingClass descriptor]; - } -#if DEBUG - const char *className = description->messageOrGroupClassName; - if (className) { - NSAssert1(objc_lookUpClass(className) != Nil, @"Class %s not defined", - className); - } -#endif - descriptor_ = [[GPBExtensionDescriptor alloc] - initWithExtensionDescription:description]; - GPBType type = description_->type; - if (type == GPBTypeData) { - // Data stored as a length prefixed c-string in descriptor records. - const uint8_t *bytes = - (const uint8_t *)description->defaultValue.valueData; - if (bytes) { - uint32_t length = *((uint32_t *)bytes); - // The length is stored in network byte order. - length = ntohl(length); - bytes += sizeof(length); - defaultValue_.valueData = - [[NSData alloc] initWithBytes:bytes length:length]; - } - } else if (type == GPBTypeMessage || type == GPBTypeGroup) { - // The default is looked up in -defaultValue instead since extensions - // aren't - // common, we avoid the hit startup hit and it avoid initialization order - // issues. - } else { - defaultValue_ = description->defaultValue; - } - } - return self; -} - -- (void)dealloc { - if ((description_->type == GPBTypeData) && - !ExtensionIsRepeated(description_)) { - [defaultValue_.valueData release]; - } - [descriptor_ release]; - [super dealloc]; -} - -- (NSString *)description { - return [NSString stringWithFormat:@"<%@ %p> FieldNumber:%d ContainingType:%@", - [self class], self, self.fieldNumber, - self.containingType]; -} - -- (id)copyWithZone:(NSZone *)__unused zone { - return [self retain]; -} - -#pragma mark Properties - -- (int32_t)fieldNumber { - return description_->fieldNumber; -} - -- (GPBWireFormat)wireType { - return GPBWireFormatForType(description_->type, - ExtensionIsPacked(description_)); -} - -- (BOOL)isRepeated { - return ExtensionIsRepeated(description_); -} - -- (id)defaultValue { - if (ExtensionIsRepeated(description_)) { - return nil; - } - - switch (description_->type) { - case GPBTypeBool: - return @(defaultValue_.valueBool); - case GPBTypeFloat: - return @(defaultValue_.valueFloat); - case GPBTypeDouble: - return @(defaultValue_.valueDouble); - case GPBTypeInt32: - case GPBTypeSInt32: - case GPBTypeEnum: - case GPBTypeSFixed32: - return @(defaultValue_.valueInt32); - case GPBTypeInt64: - case GPBTypeSInt64: - case GPBTypeSFixed64: - return @(defaultValue_.valueInt64); - case GPBTypeUInt32: - case GPBTypeFixed32: - return @(defaultValue_.valueUInt32); - case GPBTypeUInt64: - case GPBTypeFixed64: - return @(defaultValue_.valueUInt64); - case GPBTypeData: - // Like message fields, the default is zero length data. - return (defaultValue_.valueData ? defaultValue_.valueData - : GPBEmptyNSData()); - case GPBTypeString: - // Like message fields, the default is zero length string. - return (defaultValue_.valueString ? defaultValue_.valueString : @""); - case GPBTypeGroup: - case GPBTypeMessage: - NSAssert(0, @"Shouldn't get here"); - return nil; - } -} - -#pragma mark Internals - -- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry - message:(GPBMessage *)message { - GPBCodedInputStreamState *state = &input->state_; - if (ExtensionIsPacked(description_)) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - id value = [self newSingleValueFromCodedInputStream:input - extensionRegistry:extensionRegistry - existingValue:nil]; - [message addExtension:self value:value]; - [value release]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - id existingValue = nil; - BOOL isRepeated = ExtensionIsRepeated(description_); - if (!isRepeated && GPBTypeIsMessage(description_->type)) { - existingValue = [message getExistingExtension:self]; - } - id value = [self newSingleValueFromCodedInputStream:input - extensionRegistry:extensionRegistry - existingValue:existingValue]; - if (isRepeated) { - [message addExtension:self value:value]; - } else { - [message setExtension:self value:value]; - } - [value release]; - } -} - -- (void)writeValue:(id)value - includingTagToCodedOutputStream:(GPBCodedOutputStream *)output { - if (ExtensionIsRepeated(description_)) { - WriteArrayIncludingTagsToCodedOutputStream(value, description_, output); - } else { - WriteObjectIncludingTagToCodedOutputStream(value, description_, output); - } -} - -- (size_t)computeSerializedSizeIncludingTag:(id)value { - if (ExtensionIsRepeated(description_)) { - return ComputeSerializedSizeIncludingTagOfArray(description_, value); - } else { - return ComputeSerializedSizeIncludingTagOfObject(description_, value); - } -} - -// Note that this returns a retained value intentionally. -- (id)newSingleValueFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry - existingValue:(GPBMessage *)existingValue { - GPBCodedInputStreamState *state = &input->state_; - switch (description_->type) { - case GPBTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)]; - case GPBTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)]; - case GPBTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)]; - case GPBTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)]; - case GPBTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)]; - case GPBTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)]; - case GPBTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)]; - case GPBTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)]; - case GPBTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)]; - case GPBTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)]; - case GPBTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)]; - case GPBTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)]; - case GPBTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)]; - case GPBTypeData: return GPBCodedInputStreamReadRetainedData(state); - case GPBTypeString: return GPBCodedInputStreamReadRetainedString(state); - case GPBTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)]; - case GPBTypeGroup: - case GPBTypeMessage: { - GPBMessage *message; - if (existingValue) { - message = [existingValue retain]; - } else { - GPBDescriptor *decriptor = [descriptor_.msgClass descriptor]; - message = [[decriptor.messageClass alloc] init]; - } - - if (description_->type == GPBTypeGroup) { - [input readGroup:description_->fieldNumber - message:message - extensionRegistry:extensionRegistry]; - } else { - // description_->type == GPBTypeMessage - if (ExtensionIsWireFormat(description_)) { - // For MessageSet fields the message length will have already been - // read. - [message mergeFromCodedInputStream:input - extensionRegistry:extensionRegistry]; - } else { - [input readMessage:message extensionRegistry:extensionRegistry]; - } - } - - return message; - } - } - - return nil; -} - -- (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other { - int32_t selfNumber = description_->fieldNumber; - int32_t otherNumber = other->description_->fieldNumber; - if (selfNumber < otherNumber) { - return NSOrderedAscending; - } else if (selfNumber == otherNumber) { - return NSOrderedSame; - } else { - return NSOrderedDescending; - } -} - -@end diff --git a/objectivec/GPBExtensionField_PackagePrivate.h b/objectivec/GPBExtensionField_PackagePrivate.h deleted file mode 100644 index 6256b9a7..00000000 --- a/objectivec/GPBExtensionField_PackagePrivate.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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. - -#import - -#import "GPBExtensionField.h" - -struct GPBExtensionDescription; - -@interface GPBExtensionField () - -- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input - extensionRegistry:(GPBExtensionRegistry *)extensionRegistry - message:(GPBMessage *)message; - -- (instancetype)initWithDescription:(struct GPBExtensionDescription *)description; - -- (size_t)computeSerializedSizeIncludingTag:(id)value; -- (void)writeValue:(id)value - includingTagToCodedOutputStream:(GPBCodedOutputStream *)output; - -- (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other; - -@end diff --git a/objectivec/GPBExtensionInternals.h b/objectivec/GPBExtensionInternals.h new file mode 100644 index 00000000..2b980aef --- /dev/null +++ b/objectivec/GPBExtensionInternals.h @@ -0,0 +1,50 @@ +// 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. + +#import + +#import "GPBDescriptor.h" + +@class GPBCodedInputStream; +@class GPBCodedOutputStream; +@class GPBExtensionRegistry; + +void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, + BOOL isPackedOnStream, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *message); + +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value); + +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, + GPBCodedOutputStream *output); diff --git a/objectivec/GPBExtensionInternals.m b/objectivec/GPBExtensionInternals.m new file mode 100644 index 00000000..634c3369 --- /dev/null +++ b/objectivec/GPBExtensionInternals.m @@ -0,0 +1,380 @@ +// 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. + +#import "GPBExtensionInternals.h" + +#import + +#import "GPBCodedInputStream_PackagePrivate.h" +#import "GPBCodedOutputStream.h" +#import "GPBDescriptor_PackagePrivate.h" +#import "GPBMessage_PackagePrivate.h" +#import "GPBUtilities_PackagePrivate.h" + +static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *existingValue) + __attribute__((ns_returns_retained)); + +GPB_INLINE size_t DataTypeSize(GPBDataType dataType) { + switch (dataType) { + case GPBDataTypeBool: + return 1; + case GPBDataTypeFixed32: + case GPBDataTypeSFixed32: + case GPBDataTypeFloat: + return 4; + case GPBDataTypeFixed64: + case GPBDataTypeSFixed64: + case GPBDataTypeDouble: + return 8; + default: + return 0; + } +} + +static size_t ComputePBSerializedSizeNoTagOfObject(GPBDataType dataType, id object) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]); +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##SizeNoTag(object); + switch (dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Message) + FIELD_CASE2(Group) + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static size_t ComputeSerializedSizeIncludingTagOfObject( + GPBExtensionDescription *description, id object) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##Size(description->fieldNumber, \ + [(NSNumber *)object ACCESSOR]); +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + return GPBCompute##TYPE##Size(description->fieldNumber, object); + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Group) + case GPBDataTypeMessage: + if (GPBExtensionIsWireFormat(description)) { + return GPBComputeMessageSetExtensionSize(description->fieldNumber, + object); + } else { + return GPBComputeMessageSize(description->fieldNumber, object); + } + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static size_t ComputeSerializedSizeIncludingTagOfArray( + GPBExtensionDescription *description, NSArray *values) { + if (GPBExtensionIsPacked(description)) { + size_t size = 0; + size_t typeSize = DataTypeSize(description->dataType); + if (typeSize != 0) { + size = values.count * typeSize; + } else { + for (id value in values) { + size += + ComputePBSerializedSizeNoTagOfObject(description->dataType, value); + } + } + return size + GPBComputeTagSize(description->fieldNumber) + + GPBComputeRawVarint32SizeForInteger(size); + } else { + size_t size = 0; + for (id value in values) { + size += ComputeSerializedSizeIncludingTagOfObject(description, value); + } + return size; + } +} + +static void WriteObjectIncludingTagToCodedOutputStream( + id object, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + [output write##TYPE:description->fieldNumber \ + value:[(NSNumber *)object ACCESSOR]]; \ + return; +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + [output write##TYPE:description->fieldNumber value:object]; \ + return; + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Group) + case GPBDataTypeMessage: + if (GPBExtensionIsWireFormat(description)) { + [output writeMessageSetExtension:description->fieldNumber value:object]; + } else { + [output writeMessage:description->fieldNumber value:object]; + } + return; + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static void WriteObjectNoTagToCodedOutputStream( + id object, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { +#define FIELD_CASE(TYPE, ACCESSOR) \ + case GPBDataType##TYPE: \ + [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \ + return; +#define FIELD_CASE2(TYPE) \ + case GPBDataType##TYPE: \ + [output write##TYPE##NoTag:object]; \ + return; + switch (description->dataType) { + FIELD_CASE(Bool, boolValue) + FIELD_CASE(Float, floatValue) + FIELD_CASE(Double, doubleValue) + FIELD_CASE(Int32, intValue) + FIELD_CASE(SFixed32, intValue) + FIELD_CASE(SInt32, intValue) + FIELD_CASE(Enum, intValue) + FIELD_CASE(Int64, longLongValue) + FIELD_CASE(SInt64, longLongValue) + FIELD_CASE(SFixed64, longLongValue) + FIELD_CASE(UInt32, unsignedIntValue) + FIELD_CASE(Fixed32, unsignedIntValue) + FIELD_CASE(UInt64, unsignedLongLongValue) + FIELD_CASE(Fixed64, unsignedLongLongValue) + FIELD_CASE2(Bytes) + FIELD_CASE2(String) + FIELD_CASE2(Message) + case GPBDataTypeGroup: + [output writeGroupNoTag:description->fieldNumber value:object]; + return; + } +#undef FIELD_CASE +#undef FIELD_CASE2 +} + +static void WriteArrayIncludingTagsToCodedOutputStream( + NSArray *values, GPBExtensionDescription *description, + GPBCodedOutputStream *output) { + if (GPBExtensionIsPacked(description)) { + [output writeTag:description->fieldNumber + format:GPBWireFormatLengthDelimited]; + size_t dataSize = 0; + size_t typeSize = DataTypeSize(description->dataType); + if (typeSize != 0) { + dataSize = values.count * typeSize; + } else { + for (id value in values) { + dataSize += + ComputePBSerializedSizeNoTagOfObject(description->dataType, value); + } + } + [output writeRawVarintSizeTAs32:dataSize]; + for (id value in values) { + WriteObjectNoTagToCodedOutputStream(value, description, output); + } + } else { + for (id value in values) { + WriteObjectIncludingTagToCodedOutputStream(value, description, output); + } + } +} + +void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, + BOOL isPackedOnStream, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *message) { + GPBExtensionDescription *description = extension->description_; + GPBCodedInputStreamState *state = &input->state_; + if (isPackedOnStream) { + NSCAssert(GPBExtensionIsRepeated(description), + @"How was it packed if it isn't repeated?"); + int32_t length = GPBCodedInputStreamReadInt32(state); + size_t limit = GPBCodedInputStreamPushLimit(state, length); + while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { + id value = NewSingleValueFromInputStream(extension, + input, + extensionRegistry, + nil); + [message addExtension:extension value:value]; + [value release]; + } + GPBCodedInputStreamPopLimit(state, limit); + } else { + id existingValue = nil; + BOOL isRepeated = GPBExtensionIsRepeated(description); + if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) { + existingValue = [message getExistingExtension:extension]; + } + id value = NewSingleValueFromInputStream(extension, + input, + extensionRegistry, + existingValue); + if (isRepeated) { + [message addExtension:extension value:value]; + } else { + [message setExtension:extension value:value]; + } + [value release]; + } +} + +void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, + id value, + GPBCodedOutputStream *output) { + GPBExtensionDescription *description = extension->description_; + if (GPBExtensionIsRepeated(description)) { + WriteArrayIncludingTagsToCodedOutputStream(value, description, output); + } else { + WriteObjectIncludingTagToCodedOutputStream(value, description, output); + } +} + +size_t GPBComputeExtensionSerializedSizeIncludingTag( + GPBExtensionDescriptor *extension, id value) { + GPBExtensionDescription *description = extension->description_; + if (GPBExtensionIsRepeated(description)) { + return ComputeSerializedSizeIncludingTagOfArray(description, value); + } else { + return ComputeSerializedSizeIncludingTagOfObject(description, value); + } +} + +// Note that this returns a retained value intentionally. +static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension, + GPBCodedInputStream *input, + GPBExtensionRegistry *extensionRegistry, + GPBMessage *existingValue) { + GPBExtensionDescription *description = extension->description_; + GPBCodedInputStreamState *state = &input->state_; + switch (description->dataType) { + case GPBDataTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)]; + case GPBDataTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)]; + case GPBDataTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)]; + case GPBDataTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)]; + case GPBDataTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)]; + case GPBDataTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)]; + case GPBDataTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)]; + case GPBDataTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)]; + case GPBDataTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)]; + case GPBDataTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)]; + case GPBDataTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)]; + case GPBDataTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)]; + case GPBDataTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)]; + case GPBDataTypeBytes: return GPBCodedInputStreamReadRetainedBytes(state); + case GPBDataTypeString: return GPBCodedInputStreamReadRetainedString(state); + case GPBDataTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)]; + case GPBDataTypeGroup: + case GPBDataTypeMessage: { + GPBMessage *message; + if (existingValue) { + message = [existingValue retain]; + } else { + GPBDescriptor *decriptor = [extension.msgClass descriptor]; + message = [[decriptor.messageClass alloc] init]; + } + + if (description->dataType == GPBDataTypeGroup) { + [input readGroup:description->fieldNumber + message:message + extensionRegistry:extensionRegistry]; + } else { + // description->dataType == GPBDataTypeMessage + if (GPBExtensionIsWireFormat(description)) { + // For MessageSet fields the message length will have already been + // read. + [message mergeFromCodedInputStream:input + extensionRegistry:extensionRegistry]; + } else { + [input readMessage:message extensionRegistry:extensionRegistry]; + } + } + + return message; + } + } + + return nil; +} diff --git a/objectivec/GPBExtensionRegistry.h b/objectivec/GPBExtensionRegistry.h index e382971c..07a99e42 100644 --- a/objectivec/GPBExtensionRegistry.h +++ b/objectivec/GPBExtensionRegistry.h @@ -31,7 +31,7 @@ #import @class GPBDescriptor; -@class GPBExtensionField; +@class GPBExtensionDescriptor; // A table of known extensions, searchable by name or field number. When // parsing a protocol message that might have extensions, you must provide an @@ -54,10 +54,10 @@ // @interface GPBExtensionRegistry : NSObject -- (void)addExtension:(GPBExtensionField *)extension; +- (void)addExtension:(GPBExtensionDescriptor *)extension; - (void)addExtensions:(GPBExtensionRegistry *)registry; -- (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType - fieldNumber:(NSInteger)fieldNumber; +- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor + fieldNumber:(NSInteger)fieldNumber; @end diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m index 4f234f55..df61a17b 100644 --- a/objectivec/GPBExtensionRegistry.m +++ b/objectivec/GPBExtensionRegistry.m @@ -32,7 +32,6 @@ #import "GPBBootstrap.h" #import "GPBDescriptor.h" -#import "GPBExtensionField.h" @implementation GPBExtensionRegistry { // TODO(dmaclach): Reimplement with CFDictionaries that don't use @@ -60,31 +59,34 @@ return result; } -- (NSMutableDictionary *)extensionMapForContainingType: - (GPBDescriptor *)containingType { +- (NSMutableDictionary *)extensionMapForContainingMessageClass: + (Class)containingMessageClass { NSMutableDictionary *extensionMap = - [mutableClassMap_ objectForKey:containingType]; + [mutableClassMap_ objectForKey:containingMessageClass]; if (extensionMap == nil) { extensionMap = [NSMutableDictionary dictionary]; - [mutableClassMap_ setObject:extensionMap forKey:containingType]; + [mutableClassMap_ setObject:extensionMap + forKey:(id)containingMessageClass]; } return extensionMap; } -- (void)addExtension:(GPBExtensionField *)extension { +- (void)addExtension:(GPBExtensionDescriptor *)extension { if (extension == nil) { return; } - GPBDescriptor *containingType = [extension containingType]; + Class containingMessageClass = extension.containingMessageClass; NSMutableDictionary *extensionMap = - [self extensionMapForContainingType:containingType]; - [extensionMap setObject:extension forKey:@([extension fieldNumber])]; + [self extensionMapForContainingMessageClass:containingMessageClass]; + [extensionMap setObject:extension forKey:@(extension.fieldNumber)]; } -- (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType - fieldNumber:(NSInteger)fieldNumber { - NSDictionary *extensionMap = [mutableClassMap_ objectForKey:containingType]; +- (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor + fieldNumber:(NSInteger)fieldNumber { + Class messageClass = descriptor.messageClass; + NSDictionary *extensionMap = + [mutableClassMap_ objectForKey:messageClass]; return [extensionMap objectForKey:@(fieldNumber)]; } @@ -94,11 +96,11 @@ return; } NSMutableDictionary *otherClassMap = registry->mutableClassMap_; - for (GPBDescriptor *containingType in otherClassMap) { + for (Class containingMessageClass in otherClassMap) { NSMutableDictionary *extensionMap = - [self extensionMapForContainingType:containingType]; + [self extensionMapForContainingMessageClass:containingMessageClass]; NSMutableDictionary *otherExtensionMap = - [registry extensionMapForContainingType:containingType]; + [registry extensionMapForContainingMessageClass:containingMessageClass]; [extensionMap addEntriesFromDictionary:otherExtensionMap]; } } diff --git a/objectivec/GPBField.h b/objectivec/GPBField.h deleted file mode 100644 index 041a242f..00000000 --- a/objectivec/GPBField.h +++ /dev/null @@ -1,56 +0,0 @@ -// 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. - -#import - -@class GPBCodedOutputStream; -@class GPBUInt32Array; -@class GPBUInt64Array; -@class GPBUnknownFieldSet; - -@interface GPBField : NSObject - -@property(nonatomic, readonly, assign) int32_t number; - -// Only one of these will be set. -@property(nonatomic, readonly, strong) GPBUInt64Array *varintList; -@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List; -@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List; -@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList; -@property(nonatomic, readonly, strong) NSArray *groupList; - -// Only one of these should be used per Field. -- (void)addVarint:(uint64_t)value; -- (void)addFixed32:(uint32_t)value; -- (void)addFixed64:(uint64_t)value; -- (void)addLengthDelimited:(NSData *)value; -- (void)addGroup:(GPBUnknownFieldSet *)value; - -@end diff --git a/objectivec/GPBField.m b/objectivec/GPBField.m deleted file mode 100644 index c390ae9e..00000000 --- a/objectivec/GPBField.m +++ /dev/null @@ -1,328 +0,0 @@ -// 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. - -#import "GPBField_PackagePrivate.h" - -#import "GPBArray.h" -#import "GPBCodedOutputStream.h" - -@interface GPBField () { - @protected - int32_t number_; - GPBUInt64Array *mutableVarintList_; - GPBUInt32Array *mutableFixed32List_; - GPBUInt64Array *mutableFixed64List_; - NSMutableArray *mutableLengthDelimitedList_; - NSMutableArray *mutableGroupList_; -} -@end - -@implementation GPBField - -@synthesize number = number_; -@synthesize varintList = mutableVarintList_; -@synthesize fixed32List = mutableFixed32List_; -@synthesize fixed64List = mutableFixed64List_; -@synthesize lengthDelimitedList = mutableLengthDelimitedList_; -@synthesize groupList = mutableGroupList_; - -- (instancetype)initWithNumber:(int32_t)number { - if ((self = [super init])) { - number_ = number; - } - return self; -} - -- (void)dealloc { - [mutableVarintList_ release]; - [mutableFixed32List_ release]; - [mutableFixed64List_ release]; - [mutableLengthDelimitedList_ release]; - [mutableGroupList_ release]; - - [super dealloc]; -} - -- (id)copyWithZone:(NSZone *)zone { - GPBField *result = [[GPBField allocWithZone:zone] initWithNumber:number_]; - result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone]; - result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone]; - result->mutableLengthDelimitedList_ = - [mutableLengthDelimitedList_ copyWithZone:zone]; - result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone]; - if (mutableGroupList_.count) { - result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone] - initWithCapacity:mutableGroupList_.count]; - for (GPBUnknownFieldSet *group in mutableGroupList_) { - GPBUnknownFieldSet *copied = [group copyWithZone:zone]; - [result->mutableGroupList_ addObject:copied]; - [copied release]; - } - } - return result; -} - -- (BOOL)isEqual:(id)object { - if (self == object) return YES; - if (![object isKindOfClass:[GPBField class]]) return NO; - GPBField *field = (GPBField *)object; - BOOL equalVarint = - (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) || - [mutableVarintList_ isEqual:field->mutableVarintList_]; - if (!equalVarint) return NO; - BOOL equalFixed32 = (mutableFixed32List_.count == 0 && - field->mutableFixed32List_.count == 0) || - [mutableFixed32List_ isEqual:field->mutableFixed32List_]; - if (!equalFixed32) return NO; - BOOL equalFixed64 = (mutableFixed64List_.count == 0 && - field->mutableFixed64List_.count == 0) || - [mutableFixed64List_ isEqual:field->mutableFixed64List_]; - if (!equalFixed64) return NO; - BOOL equalLDList = - (mutableLengthDelimitedList_.count == 0 && - field->mutableLengthDelimitedList_.count == 0) || - [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_]; - if (!equalLDList) return NO; - BOOL equalGroupList = - (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) || - [mutableGroupList_ isEqual:field->mutableGroupList_]; - if (!equalGroupList) return NO; - return YES; -} - -- (NSUInteger)hash { - // Just mix the hashes of the possible sub arrays. - const int prime = 31; - NSUInteger result = prime + [mutableVarintList_ hash]; - result = prime * result + [mutableFixed32List_ hash]; - result = prime * result + [mutableFixed64List_ hash]; - result = prime * result + [mutableLengthDelimitedList_ hash]; - result = prime * result + [mutableGroupList_ hash]; - return result; -} - -- (void)writeToOutput:(GPBCodedOutputStream *)output { - NSUInteger count = mutableVarintList_.count; - if (count > 0) { - [output writeUInt64s:number_ values:mutableVarintList_ tag:0]; - } - count = mutableFixed32List_.count; - if (count > 0) { - [output writeFixed32s:number_ values:mutableFixed32List_ tag:0]; - } - count = mutableFixed64List_.count; - if (count > 0) { - [output writeFixed64s:number_ values:mutableFixed64List_ tag:0]; - } - count = mutableLengthDelimitedList_.count; - if (count > 0) { - [output writeDatas:number_ values:mutableLengthDelimitedList_]; - } - count = mutableGroupList_.count; - if (count > 0) { - [output writeUnknownGroups:number_ values:mutableGroupList_]; - } -} - -- (size_t)serializedSize { - __block size_t result = 0; - int32_t number = number_; - [mutableVarintList_ - enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { -#pragma unused(idx, stop) - result += GPBComputeUInt64Size(number, value); - }]; - - [mutableFixed32List_ - enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { -#pragma unused(idx, stop) - result += GPBComputeFixed32Size(number, value); - }]; - - [mutableFixed64List_ - enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { -#pragma unused(idx, stop) - result += GPBComputeFixed64Size(number, value); - }]; - - for (NSData *data in mutableLengthDelimitedList_) { - result += GPBComputeDataSize(number, data); - } - - for (GPBUnknownFieldSet *set in mutableGroupList_) { - result += GPBComputeUnknownGroupSize(number, set); - } - - return result; -} - -- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output { - for (NSData *data in mutableLengthDelimitedList_) { - [output writeRawMessageSetExtension:number_ value:data]; - } -} - -- (size_t)serializedSizeAsMessageSetExtension { - size_t result = 0; - for (NSData *data in mutableLengthDelimitedList_) { - result += GPBComputeRawMessageSetExtensionSize(number_, data); - } - return result; -} - -- (NSString *)description { - NSMutableString *description = [NSMutableString - stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_]; - [mutableVarintList_ - enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { -#pragma unused(idx, stop) - [description appendFormat:@"\t%llu\n", value]; - }]; - - [mutableFixed32List_ - enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { -#pragma unused(idx, stop) - [description appendFormat:@"\t%u\n", value]; - }]; - - [mutableFixed64List_ - enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { -#pragma unused(idx, stop) - [description appendFormat:@"\t%llu\n", value]; - }]; - - for (NSData *data in mutableLengthDelimitedList_) { - [description appendFormat:@"\t%@\n", data]; - } - - for (GPBUnknownFieldSet *set in mutableGroupList_) { - [description appendFormat:@"\t%@\n", set]; - } - [description appendString:@"}"]; - return description; -} - -- (void)mergeFromField:(GPBField *)other { - GPBUInt64Array *otherVarintList = other.varintList; - if (otherVarintList.count > 0) { - if (mutableVarintList_ == nil) { - mutableVarintList_ = [otherVarintList copy]; - } else { - [mutableVarintList_ addValuesFromArray:otherVarintList]; - } - } - - GPBUInt32Array *otherFixed32List = other.fixed32List; - if (otherFixed32List.count > 0) { - if (mutableFixed32List_ == nil) { - mutableFixed32List_ = [otherFixed32List copy]; - } else { - [mutableFixed32List_ addValuesFromArray:otherFixed32List]; - } - } - - GPBUInt64Array *otherFixed64List = other.fixed64List; - if (otherFixed64List.count > 0) { - if (mutableFixed64List_ == nil) { - mutableFixed64List_ = [otherFixed64List copy]; - } else { - [mutableFixed64List_ addValuesFromArray:otherFixed64List]; - } - } - - NSArray *otherLengthDelimitedList = other.lengthDelimitedList; - if (otherLengthDelimitedList.count > 0) { - if (mutableLengthDelimitedList_ == nil) { - mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy]; - } else { - [mutableLengthDelimitedList_ - addObjectsFromArray:otherLengthDelimitedList]; - } - } - - NSArray *otherGroupList = other.groupList; - if (otherGroupList.count > 0) { - if (mutableGroupList_ == nil) { - mutableGroupList_ = - [[NSMutableArray alloc] initWithCapacity:otherGroupList.count]; - } - // Make our own mutable copies. - for (GPBUnknownFieldSet *group in otherGroupList) { - GPBUnknownFieldSet *copied = [group copy]; - [mutableGroupList_ addObject:copied]; - [copied release]; - } - } -} - -- (void)addVarint:(uint64_t)value { - if (mutableVarintList_ == nil) { - mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1]; - } else { - [mutableVarintList_ addValue:value]; - } -} - -- (void)addFixed32:(uint32_t)value { - if (mutableFixed32List_ == nil) { - mutableFixed32List_ = - [[GPBUInt32Array alloc] initWithValues:&value count:1]; - } else { - [mutableFixed32List_ addValue:value]; - } -} - -- (void)addFixed64:(uint64_t)value { - if (mutableFixed64List_ == nil) { - mutableFixed64List_ = - [[GPBUInt64Array alloc] initWithValues:&value count:1]; - } else { - [mutableFixed64List_ addValue:value]; - } -} - -- (void)addLengthDelimited:(NSData *)value { - if (mutableLengthDelimitedList_ == nil) { - mutableLengthDelimitedList_ = - [[NSMutableArray alloc] initWithObjects:&value count:1]; - } else { - [mutableLengthDelimitedList_ addObject:value]; - } -} - -- (void)addGroup:(GPBUnknownFieldSet *)value { - if (mutableGroupList_ == nil) { - mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1]; - } else { - [mutableGroupList_ addObject:value]; - } -} - -@end diff --git a/objectivec/GPBField_PackagePrivate.h b/objectivec/GPBField_PackagePrivate.h deleted file mode 100644 index 73c1fa80..00000000 --- a/objectivec/GPBField_PackagePrivate.h +++ /dev/null @@ -1,49 +0,0 @@ -// 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. - -#import - -#import "GPBField.h" - -@class GPBCodedOutputStream; - -@interface GPBField () - -- (instancetype)initWithNumber:(int32_t)number; - -- (void)writeToOutput:(GPBCodedOutputStream *)output; -- (size_t)serializedSize; - -- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output; -- (size_t)serializedSizeAsMessageSetExtension; - -- (void)mergeFromField:(GPBField *)other; - -@end diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h index 1c6c091d..64d3ba1e 100644 --- a/objectivec/GPBMessage.h +++ b/objectivec/GPBMessage.h @@ -35,7 +35,7 @@ @class GPBDescriptor; @class GPBCodedInputStream; @class GPBCodedOutputStream; -@class GPBExtensionField; +@class GPBExtensionDescriptor; @class GPBExtensionRegistry; @class GPBFieldDescriptor; @class GPBUnknownFieldSet; @@ -148,14 +148,14 @@ CF_EXTERN_C_END // Extensions use boxed values (NSNumbers) for PODs, NSMutableArrays for // repeated. If the extension is a Message one will be auto created for you // and returned similar to fields. -- (BOOL)hasExtension:(GPBExtensionField *)extension; -- (id)getExtension:(GPBExtensionField *)extension; -- (void)setExtension:(GPBExtensionField *)extension value:(id)value; -- (void)addExtension:(GPBExtensionField *)extension value:(id)value; -- (void)setExtension:(GPBExtensionField *)extension +- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension; +- (id)getExtension:(GPBExtensionDescriptor *)extension; +- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value; +- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value; +- (void)setExtension:(GPBExtensionDescriptor *)extension index:(NSUInteger)index value:(id)value; -- (void)clearExtension:(GPBExtensionField *)extension; +- (void)clearExtension:(GPBExtensionDescriptor *)extension; - (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields; diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m index bd3235f1..c655edd3 100644 --- a/objectivec/GPBMessage.m +++ b/objectivec/GPBMessage.m @@ -38,7 +38,7 @@ #import "GPBCodedOutputStream.h" #import "GPBDescriptor_PackagePrivate.h" #import "GPBDictionary_PackagePrivate.h" -#import "GPBExtensionField_PackagePrivate.h" +#import "GPBExtensionInternals.h" #import "GPBExtensionRegistry.h" #import "GPBRootObject_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h" @@ -54,6 +54,13 @@ NSString *const GPBExceptionMessageKey = static NSString *const kGPBDataCoderKey = @"GPBData"; +#ifndef _GPBCompileAssert +#define _GPBCompileAssertSymbolInner(line, msg) _GPBCompileAssert ## line ## __ ## msg +#define _GPBCompileAssertSymbol(line, msg) _GPBCompileAssertSymbolInner(line, msg) +#define _GPBCompileAssert(test, msg) \ + typedef char _GPBCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] +#endif // _GPBCompileAssert + // // PLEASE REMEMBER: // @@ -73,7 +80,7 @@ static NSString *const kGPBDataCoderKey = @"GPBData"; // mutated, we can inform the creator to make our field visible. GPBMessage *autocreator_; GPBFieldDescriptor *autocreatorField_; - GPBExtensionField *autocreatorExtension_; + GPBExtensionDescriptor *autocreatorExtension_; } @end @@ -110,13 +117,14 @@ static NSError *MessageErrorWithReason(NSInteger code, NSString *reason) { } -static void CheckExtension(GPBMessage *self, GPBExtensionField *extension) { - if ([[self class] descriptor] != [extension containingType]) { +static void CheckExtension(GPBMessage *self, + GPBExtensionDescriptor *extension) { + if ([self class] != extension.containingMessageClass) { [NSException raise:NSInvalidArgumentException format:@"Extension %@ used on wrong class (%@ instead of %@)", - extension.descriptor.singletonName, - [[self class] descriptor].name, [extension containingType].name]; + extension.singletonName, + [self class], extension.containingMessageClass]; } } @@ -128,12 +136,11 @@ static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone] initWithCapacity:extensionMap.count]; - for (GPBExtensionField *field in extensionMap) { - id value = [extensionMap objectForKey:field]; - GPBExtensionDescriptor *fieldDescriptor = field.descriptor; - BOOL isMessageExtension = GPBExtensionIsMessage(fieldDescriptor); + for (GPBExtensionDescriptor *extension in extensionMap) { + id value = [extensionMap objectForKey:extension]; + BOOL isMessageExtension = GPBExtensionIsMessage(extension); - if ([field isRepeated]) { + if (extension.repeated) { if (isMessageExtension) { NSMutableArray *list = [[NSMutableArray alloc] initWithCapacity:[value count]]; @@ -142,20 +149,20 @@ static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, [list addObject:copiedValue]; [copiedValue release]; } - [result setObject:list forKey:field]; + [result setObject:list forKey:extension]; [list release]; } else { NSMutableArray *copiedValue = [value mutableCopyWithZone:zone]; - [result setObject:copiedValue forKey:field]; + [result setObject:copiedValue forKey:extension]; [copiedValue release]; } } else { if (isMessageExtension) { GPBMessage *copiedValue = [value copyWithZone:zone]; - [result setObject:copiedValue forKey:field]; + [result setObject:copiedValue forKey:extension]; [copiedValue release]; } else { - [result setObject:value forKey:field]; + [result setObject:value forKey:extension]; } } } @@ -166,45 +173,45 @@ static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator) { id result; - GPBType fieldDataType = GPBGetFieldType(field); + GPBDataType fieldDataType = GPBGetFieldDataType(field); switch (fieldDataType) { - case GPBTypeBool: + case GPBDataTypeBool: result = [[GPBBoolArray alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBUInt32Array alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBInt32Array alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBUInt64Array alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBInt64Array alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBFloatArray alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBDoubleArray alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBEnumArray alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeGroup: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: + case GPBDataTypeString: if (autocreator) { result = [[GPBAutocreatedArray alloc] init]; } else { @@ -214,7 +221,7 @@ static id CreateArrayForField(GPBFieldDescriptor *field, } if (autocreator) { - if (GPBTypeIsObject(fieldDataType)) { + if (GPBDataTypeIsObject(fieldDataType)) { GPBAutocreatedArray *autoArray = result; autoArray->_autocreator = autocreator; } else { @@ -229,290 +236,291 @@ static id CreateArrayForField(GPBFieldDescriptor *field, static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) { id result; - GPBType keyType = field.mapKeyType; - GPBType valueType = GPBGetFieldType(field); - switch (keyType) { - case GPBTypeBool: - switch (valueType) { - case GPBTypeBool: + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + switch (keyDataType) { + case GPBDataTypeBool: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBBoolBoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBBoolUInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBBoolInt32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBBoolUInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBBoolInt64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBBoolFloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBBoolDoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBBoolEnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBBoolObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeFixed32: - case GPBTypeUInt32: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBUInt32BoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBUInt32UInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBUInt32Int32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBUInt32UInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBUInt32Int64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBUInt32FloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBUInt32DoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBUInt32ObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBInt32BoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBInt32UInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBInt32Int32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBInt32UInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBInt32Int64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBInt32FloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBInt32DoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBInt32EnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBInt32ObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeFixed64: - case GPBTypeUInt64: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBUInt64BoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBUInt64UInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBUInt64Int32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBUInt64UInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBUInt64Int64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBUInt64FloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBUInt64DoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBUInt64ObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBInt64BoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBInt64UInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBInt64Int32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBInt64UInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBInt64Int64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBInt64FloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBInt64DoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBInt64EnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: result = [[GPBInt64ObjectDictionary alloc] init]; break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeString: - switch (valueType) { - case GPBTypeBool: + case GPBDataTypeString: + switch (valueDataType) { + case GPBDataTypeBool: result = [[GPBStringBoolDictionary alloc] init]; break; - case GPBTypeFixed32: - case GPBTypeUInt32: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: result = [[GPBStringUInt32Dictionary alloc] init]; break; - case GPBTypeInt32: - case GPBTypeSFixed32: - case GPBTypeSInt32: + case GPBDataTypeInt32: + case GPBDataTypeSFixed32: + case GPBDataTypeSInt32: result = [[GPBStringInt32Dictionary alloc] init]; break; - case GPBTypeFixed64: - case GPBTypeUInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: result = [[GPBStringUInt64Dictionary alloc] init]; break; - case GPBTypeInt64: - case GPBTypeSFixed64: - case GPBTypeSInt64: + case GPBDataTypeInt64: + case GPBDataTypeSFixed64: + case GPBDataTypeSInt64: result = [[GPBStringInt64Dictionary alloc] init]; break; - case GPBTypeFloat: + case GPBDataTypeFloat: result = [[GPBStringFloatDictionary alloc] init]; break; - case GPBTypeDouble: + case GPBDataTypeDouble: result = [[GPBStringDoubleDictionary alloc] init]; break; - case GPBTypeEnum: + case GPBDataTypeEnum: result = [[GPBStringEnumDictionary alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier]; break; - case GPBTypeData: - case GPBTypeMessage: - case GPBTypeString: + case GPBDataTypeBytes: + case GPBDataTypeMessage: + case GPBDataTypeString: if (autocreator) { result = [[GPBAutocreatedDictionary alloc] init]; } else { result = [[NSMutableDictionary alloc] init]; } break; - case GPBTypeGroup: + case GPBDataTypeGroup: NSCAssert(NO, @"shouldn't happen"); return nil; } break; - case GPBTypeFloat: - case GPBTypeDouble: - case GPBTypeEnum: - case GPBTypeData: - case GPBTypeGroup: - case GPBTypeMessage: + case GPBDataTypeFloat: + case GPBDataTypeDouble: + case GPBDataTypeEnum: + case GPBDataTypeBytes: + case GPBDataTypeGroup: + case GPBDataTypeMessage: NSCAssert(NO, @"shouldn't happen"); return nil; } if (autocreator) { - if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) { + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { GPBAutocreatedDictionary *autoDict = result; autoDict->_autocreator = autocreator; } else { @@ -608,11 +616,12 @@ GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, } static GPBMessage *CreateMessageWithAutocreatorForExtension( - Class msgClass, GPBMessage *autocreator, GPBExtensionField *extension) + Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension) __attribute__((ns_returns_retained)); static GPBMessage *CreateMessageWithAutocreatorForExtension( - Class msgClass, GPBMessage *autocreator, GPBExtensionField *extension) { + Class msgClass, GPBMessage *autocreator, + GPBExtensionDescriptor *extension) { GPBMessage *message = [[msgClass alloc] init]; message->autocreator_ = autocreator; message->autocreatorExtension_ = [extension retain]; @@ -647,7 +656,7 @@ void GPBAutocreatedArrayModified(GPBMessage *self, id array) { if (field.fieldType == GPBFieldTypeRepeated) { id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (curArray == array) { - if (GPBFieldTypeIsObject(field)) { + if (GPBFieldDataTypeIsObject(field)) { GPBAutocreatedArray *autoArray = array; autoArray->_autocreator = nil; } else { @@ -669,8 +678,8 @@ void GPBAutocreatedDictionaryModified(GPBMessage *self, id dictionary) { if (field.fieldType == GPBFieldTypeMap) { id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (curDict == dictionary) { - if ((field.mapKeyType == GPBTypeString) && - GPBFieldTypeIsObject(field)) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { GPBAutocreatedDictionary *autoDict = dictionary; autoDict->_autocreator = nil; } else { @@ -812,6 +821,9 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if ((self = [self init])) { @try { [self mergeFromData:data extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } } @catch (NSException *exception) { [self release]; @@ -841,6 +853,9 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if ((self = [self init])) { @try { [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } } @catch (NSException *exception) { [self release]; @@ -885,7 +900,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { // We need to copy the array/map, but the catch is for message fields, // we also need to ensure all the messages as those need copying also. id newValue; - if (GPBFieldTypeIsMessage(field)) { + if (GPBFieldDataTypeIsMessage(field)) { if (field.fieldType == GPBFieldTypeRepeated) { NSArray *existingArray = (NSArray *)value; NSMutableArray *newArray = @@ -897,7 +912,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { [copiedMsg release]; } } else { - if (field.mapKeyType == GPBTypeString) { + if (field.mapKeyDataType == GPBDataTypeString) { // Map is an NSDictionary. NSDictionary *existingDict = value; NSMutableDictionary *newDict = [[NSMutableDictionary alloc] @@ -921,7 +936,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { // Not messages (but is a map/array)... if (field.fieldType == GPBFieldTypeRepeated) { - if (GPBFieldTypeIsObject(field)) { + if (GPBFieldDataTypeIsObject(field)) { // NSArray newValue = [value mutableCopyWithZone:zone]; } else { @@ -929,7 +944,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { newValue = [value copyWithZone:zone]; } } else { - if (field.mapKeyType == GPBTypeString) { + if (field.mapKeyDataType == GPBDataTypeString) { // NSDictionary newValue = [value mutableCopyWithZone:zone]; } else { @@ -946,7 +961,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, syntax); } - } else if (GPBFieldTypeIsMessage(field)) { + } else if (GPBFieldDataTypeIsMessage(field)) { // For object types, if we have a value, copy it. If we don't, // zero it to remove the pointer to something that was autocreated // (and the ptr just got memcpyed). @@ -963,7 +978,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { id *typePtr = (id *)&storage[field->description_->offset]; *typePtr = NULL; } - } else if (GPBFieldTypeIsObject(field) && GPBGetHasIvarField(self, field)) { + } else if (GPBFieldDataTypeIsObject(field) && + GPBGetHasIvarField(self, field)) { // A set string/data value (message picked off above), copy it. id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); id newValue = [value copyWithZone:zone]; @@ -973,7 +989,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue, syntax); } else { - // memcpy took care of the rest of the primative fields if they were set. + // memcpy took care of the rest of the primitive fields if they were set. } } // for (field in descriptor->fields_) } @@ -1000,7 +1016,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (arrayOrMap) { if (field.fieldType == GPBFieldTypeRepeated) { - if (GPBFieldTypeIsObject(field)) { + if (GPBFieldDataTypeIsObject(field)) { GPBAutocreatedArray *autoArray = arrayOrMap; if (autoArray->_autocreator == self) { autoArray->_autocreator = nil; @@ -1013,8 +1029,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } } } else { - if ((field.mapKeyType == GPBTypeString) && - GPBFieldTypeIsObject(field)) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBFieldDataTypeIsObject(field)) { GPBAutocreatedDictionary *autoDict = arrayOrMap; if (autoDict->_autocreator == self) { autoDict->_autocreator = nil; @@ -1029,11 +1045,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } [arrayOrMap release]; } - } else if (GPBFieldTypeIsMessage(field)) { + } else if (GPBFieldDataTypeIsMessage(field)) { GPBClearAutocreatedMessageIvarWithField(self, field); GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field); [value release]; - } else if (GPBFieldTypeIsObject(field) && GPBGetHasIvarField(self, field)) { + } else if (GPBFieldDataTypeIsObject(field) && + GPBGetHasIvarField(self, field)) { id value = GPBGetObjectIvarWithField(self, field); [value release]; } @@ -1076,11 +1093,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { return NO; } } - if (GPBFieldTypeIsMessage(field)) { + if (GPBFieldDataTypeIsMessage(field)) { GPBFieldType fieldType = field.fieldType; if (fieldType == GPBFieldTypeSingle) { if (field.isRequired) { - GPBMessage *message = GPBGetMessageIvarWithField(self, field); + GPBMessage *message = GPBGetMessageMessageField(self, field); if (!message.initialized) { return NO; } @@ -1089,7 +1106,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { @"%@: Single message field %@ not required or optional?", [self class], field.name); if (GPBGetHasIvarField(self, field)) { - GPBMessage *message = GPBGetMessageIvarWithField(self, field); + GPBMessage *message = GPBGetMessageMessageField(self, field); if (!message.initialized) { return NO; } @@ -1103,7 +1120,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } } } else { // fieldType == GPBFieldTypeMap - if (field.mapKeyType == GPBTypeString) { + if (field.mapKeyDataType == GPBDataTypeString) { NSDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, field); if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) { @@ -1123,11 +1140,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { __block BOOL result = YES; [extensionMap_ - enumerateKeysAndObjectsUsingBlock:^(GPBExtensionField *extension, id obj, + enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, + id obj, BOOL *stop) { - GPBExtensionDescriptor *extDesc = extension.descriptor; - if (GPBExtensionIsMessage(extDesc)) { - if (extDesc.isRepeated) { + if (GPBExtensionIsMessage(extension)) { + if (extension.isRepeated) { for (GPBMessage *msg in obj) { if (!msg.initialized) { result = NO; @@ -1259,15 +1276,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE) //%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE) //%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE) -//% case GPBType##TYPE: +//% case GPBDataType##TYPE: //% if (fieldType == GPBFieldTypeRepeated) { //% uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; //% GPB##ARRAY_TYPE##Array *array = //% GPBGetObjectIvarWithFieldNoAutocreate(self, field); -//% [output write##TYPE##s:fieldNumber values:array tag:tag]; +//% [output write##TYPE##Array:fieldNumber values:array tag:tag]; //% } else if (fieldType == GPBFieldTypeSingle) { //% [output write##TYPE:fieldNumber -//% TYPE$S value:GPBGet##REAL_TYPE##IvarWithField(self, field)]; +//% TYPE$S value:GPBGetMessage##REAL_TYPE##Field(self, field)]; //% } else { // fieldType == GPBFieldTypeMap //% // Exact type here doesn't matter. //% GPBInt32##ARRAY_TYPE##Dictionary *dict = @@ -1277,10 +1294,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //% break; //% //%PDDM-DEFINE FIELD_CASE2(TYPE) -//% case GPBType##TYPE: +//% case GPBDataType##TYPE: //% if (fieldType == GPBFieldTypeRepeated) { //% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); -//% [output write##TYPE##s:fieldNumber values:array]; +//% [output write##TYPE##Array:fieldNumber values:array]; //% } else if (fieldType == GPBFieldTypeSingle) { //% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check //% // again. @@ -1289,8 +1306,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //% } else { // fieldType == GPBFieldTypeMap //% // Exact type here doesn't matter. //% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); -//% GPBType mapKeyType = field.mapKeyType; -//% if (mapKeyType == GPBTypeString) { +//% GPBDataType mapKeyDataType = field.mapKeyDataType; +//% if (mapKeyDataType == GPBDataTypeString) { //% GPBDictionaryWriteToStreamInternalHelper(output, dict, field); //% } else { //% [dict writeToCodedOutputStream:output asField:field]; @@ -1299,20 +1316,20 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //% break; //% - switch (GPBGetFieldType(field)) { + switch (GPBGetFieldDataType(field)) { //%PDDM-EXPAND FIELD_CASE(Bool, Bool) // This block of code is generated, do not edit it directly. - case GPBTypeBool: + case GPBDataTypeBool: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBBoolArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeBools:fieldNumber values:array tag:tag]; + [output writeBoolArray:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeBool:fieldNumber - value:GPBGetBoolIvarWithField(self, field)]; + value:GPBGetMessageBoolField(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32BoolDictionary *dict = @@ -1324,15 +1341,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32) // This block of code is generated, do not edit it directly. - case GPBTypeFixed32: + case GPBDataTypeFixed32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBUInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeFixed32s:fieldNumber values:array tag:tag]; + [output writeFixed32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeFixed32:fieldNumber - value:GPBGetUInt32IvarWithField(self, field)]; + value:GPBGetMessageUInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32UInt32Dictionary *dict = @@ -1344,15 +1361,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(SFixed32, Int32) // This block of code is generated, do not edit it directly. - case GPBTypeSFixed32: + case GPBDataTypeSFixed32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeSFixed32s:fieldNumber values:array tag:tag]; + [output writeSFixed32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeSFixed32:fieldNumber - value:GPBGetInt32IvarWithField(self, field)]; + value:GPBGetMessageInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int32Dictionary *dict = @@ -1364,15 +1381,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Float, Float) // This block of code is generated, do not edit it directly. - case GPBTypeFloat: + case GPBDataTypeFloat: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBFloatArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeFloats:fieldNumber values:array tag:tag]; + [output writeFloatArray:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeFloat:fieldNumber - value:GPBGetFloatIvarWithField(self, field)]; + value:GPBGetMessageFloatField(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32FloatDictionary *dict = @@ -1384,15 +1401,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64) // This block of code is generated, do not edit it directly. - case GPBTypeFixed64: + case GPBDataTypeFixed64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBUInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeFixed64s:fieldNumber values:array tag:tag]; + [output writeFixed64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeFixed64:fieldNumber - value:GPBGetUInt64IvarWithField(self, field)]; + value:GPBGetMessageUInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32UInt64Dictionary *dict = @@ -1404,15 +1421,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(SFixed64, Int64) // This block of code is generated, do not edit it directly. - case GPBTypeSFixed64: + case GPBDataTypeSFixed64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeSFixed64s:fieldNumber values:array tag:tag]; + [output writeSFixed64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeSFixed64:fieldNumber - value:GPBGetInt64IvarWithField(self, field)]; + value:GPBGetMessageInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int64Dictionary *dict = @@ -1424,15 +1441,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Double, Double) // This block of code is generated, do not edit it directly. - case GPBTypeDouble: + case GPBDataTypeDouble: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBDoubleArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeDoubles:fieldNumber values:array tag:tag]; + [output writeDoubleArray:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeDouble:fieldNumber - value:GPBGetDoubleIvarWithField(self, field)]; + value:GPBGetMessageDoubleField(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32DoubleDictionary *dict = @@ -1444,15 +1461,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Int32, Int32) // This block of code is generated, do not edit it directly. - case GPBTypeInt32: + case GPBDataTypeInt32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeInt32s:fieldNumber values:array tag:tag]; + [output writeInt32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeInt32:fieldNumber - value:GPBGetInt32IvarWithField(self, field)]; + value:GPBGetMessageInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int32Dictionary *dict = @@ -1464,15 +1481,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(Int64, Int64) // This block of code is generated, do not edit it directly. - case GPBTypeInt64: + case GPBDataTypeInt64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeInt64s:fieldNumber values:array tag:tag]; + [output writeInt64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeInt64:fieldNumber - value:GPBGetInt64IvarWithField(self, field)]; + value:GPBGetMessageInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int64Dictionary *dict = @@ -1484,15 +1501,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(SInt32, Int32) // This block of code is generated, do not edit it directly. - case GPBTypeSInt32: + case GPBDataTypeSInt32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeSInt32s:fieldNumber values:array tag:tag]; + [output writeSInt32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeSInt32:fieldNumber - value:GPBGetInt32IvarWithField(self, field)]; + value:GPBGetMessageInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int32Dictionary *dict = @@ -1504,15 +1521,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(SInt64, Int64) // This block of code is generated, do not edit it directly. - case GPBTypeSInt64: + case GPBDataTypeSInt64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeSInt64s:fieldNumber values:array tag:tag]; + [output writeSInt64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeSInt64:fieldNumber - value:GPBGetInt64IvarWithField(self, field)]; + value:GPBGetMessageInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32Int64Dictionary *dict = @@ -1524,15 +1541,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(UInt32, UInt32) // This block of code is generated, do not edit it directly. - case GPBTypeUInt32: + case GPBDataTypeUInt32: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBUInt32Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeUInt32s:fieldNumber values:array tag:tag]; + [output writeUInt32Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeUInt32:fieldNumber - value:GPBGetUInt32IvarWithField(self, field)]; + value:GPBGetMessageUInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32UInt32Dictionary *dict = @@ -1544,15 +1561,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE(UInt64, UInt64) // This block of code is generated, do not edit it directly. - case GPBTypeUInt64: + case GPBDataTypeUInt64: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBUInt64Array *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeUInt64s:fieldNumber values:array tag:tag]; + [output writeUInt64Array:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeUInt64:fieldNumber - value:GPBGetUInt64IvarWithField(self, field)]; + value:GPBGetMessageUInt64Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32UInt64Dictionary *dict = @@ -1564,15 +1581,15 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum) // This block of code is generated, do not edit it directly. - case GPBTypeEnum: + case GPBDataTypeEnum: if (fieldType == GPBFieldTypeRepeated) { uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0; GPBEnumArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeEnums:fieldNumber values:array tag:tag]; + [output writeEnumArray:fieldNumber values:array tag:tag]; } else if (fieldType == GPBFieldTypeSingle) { [output writeEnum:fieldNumber - value:GPBGetInt32IvarWithField(self, field)]; + value:GPBGetMessageInt32Field(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. GPBInt32EnumDictionary *dict = @@ -1581,23 +1598,23 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } break; -//%PDDM-EXPAND FIELD_CASE2(Data) +//%PDDM-EXPAND FIELD_CASE2(Bytes) // This block of code is generated, do not edit it directly. - case GPBTypeData: + case GPBDataTypeBytes: if (fieldType == GPBFieldTypeRepeated) { NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeDatas:fieldNumber values:array]; + [output writeBytesArray:fieldNumber values:array]; } else if (fieldType == GPBFieldTypeSingle) { // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check // again. - [output writeData:fieldNumber - value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; + [output writeBytes:fieldNumber + value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)]; } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { GPBDictionaryWriteToStreamInternalHelper(output, dict, field); } else { [dict writeToCodedOutputStream:output asField:field]; @@ -1608,10 +1625,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE2(String) // This block of code is generated, do not edit it directly. - case GPBTypeString: + case GPBDataTypeString: if (fieldType == GPBFieldTypeRepeated) { NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeStrings:fieldNumber values:array]; + [output writeStringArray:fieldNumber values:array]; } else if (fieldType == GPBFieldTypeSingle) { // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check // again. @@ -1620,8 +1637,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { GPBDictionaryWriteToStreamInternalHelper(output, dict, field); } else { [dict writeToCodedOutputStream:output asField:field]; @@ -1632,10 +1649,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE2(Message) // This block of code is generated, do not edit it directly. - case GPBTypeMessage: + case GPBDataTypeMessage: if (fieldType == GPBFieldTypeRepeated) { NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeMessages:fieldNumber values:array]; + [output writeMessageArray:fieldNumber values:array]; } else if (fieldType == GPBFieldTypeSingle) { // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check // again. @@ -1644,8 +1661,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { GPBDictionaryWriteToStreamInternalHelper(output, dict, field); } else { [dict writeToCodedOutputStream:output asField:field]; @@ -1656,10 +1673,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { //%PDDM-EXPAND FIELD_CASE2(Group) // This block of code is generated, do not edit it directly. - case GPBTypeGroup: + case GPBDataTypeGroup: if (fieldType == GPBFieldTypeRepeated) { NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - [output writeGroups:fieldNumber values:array]; + [output writeGroupArray:fieldNumber values:array]; } else if (fieldType == GPBFieldTypeSingle) { // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check // again. @@ -1668,8 +1685,8 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { } else { // fieldType == GPBFieldTypeMap // Exact type here doesn't matter. id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { + GPBDataType mapKeyDataType = field.mapKeyDataType; + if (mapKeyDataType == GPBDataTypeString) { GPBDictionaryWriteToStreamInternalHelper(output, dict, field); } else { [dict writeToCodedOutputStream:output asField:field]; @@ -1683,22 +1700,20 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { #pragma mark - Extensions -- (id)getExtension:(GPBExtensionField *)extension { +- (id)getExtension:(GPBExtensionDescriptor *)extension { CheckExtension(self, extension); id value = [extensionMap_ objectForKey:extension]; if (value != nil) { return value; } - GPBExtensionDescriptor *extDesc = extension.descriptor; - // No default for repeated. - if (extDesc.isRepeated) { + if (extension.isRepeated) { return nil; } // Non messages get their default. - if (!GPBExtensionIsMessage(extDesc)) { - return [extension defaultValue]; + if (!GPBExtensionIsMessage(extension)) { + return extension.defaultValue; } // Check for an autocreated value. @@ -1706,7 +1721,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { value = [autocreatedExtensionMap_ objectForKey:extension]; if (!value) { // Auto create the message extensions to match normal fields. - value = CreateMessageWithAutocreatorForExtension(extDesc.msgClass, self, + value = CreateMessageWithAutocreatorForExtension(extension.msgClass, self, extension); if (autocreatedExtensionMap_ == nil) { @@ -1723,12 +1738,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { return value; } -- (id)getExistingExtension:(GPBExtensionField *)extension { +- (id)getExistingExtension:(GPBExtensionDescriptor *)extension { // This is an internal method so we don't need to call CheckExtension(). return [extensionMap_ objectForKey:extension]; } -- (BOOL)hasExtension:(GPBExtensionField *)extension { +- (BOOL)hasExtension:(GPBExtensionDescriptor *)extension { #if DEBUG CheckExtension(self, extension); #endif // DEBUG @@ -1745,11 +1760,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; uint32_t start = range.start; uint32_t end = range.end; - for (GPBExtensionField *extension in sortedExtensions) { - uint32_t fieldNumber = [extension fieldNumber]; + for (GPBExtensionDescriptor *extension in sortedExtensions) { + uint32_t fieldNumber = extension.fieldNumber; if (fieldNumber >= start && fieldNumber < end) { id value = [extensionMap_ objectForKey:extension]; - [extension writeValue:value includingTagToCodedOutputStream:output]; + GPBWriteExtensionValueToOutputStream(extension, value, output); } } } @@ -1759,7 +1774,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { sortedArrayUsingSelector:@selector(compareByFieldNumber:)]; } -- (void)setExtension:(GPBExtensionField *)extension value:(id)value { +- (void)setExtension:(GPBExtensionDescriptor *)extension value:(id)value { if (!value) { [self clearExtension:extension]; return; @@ -1767,7 +1782,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { CheckExtension(self, extension); - if ([extension isRepeated]) { + if (extension.repeated) { [NSException raise:NSInvalidArgumentException format:@"Must call addExtension() for repeated types."]; } @@ -1778,7 +1793,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { [extensionMap_ setObject:value forKey:extension]; - GPBExtensionDescriptor *descriptor = extension.descriptor; + GPBExtensionDescriptor *descriptor = extension; if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) { GPBMessage *autocreatedValue = @@ -1793,10 +1808,10 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBBecomeVisibleToAutocreator(self); } -- (void)addExtension:(GPBExtensionField *)extension value:(id)value { +- (void)addExtension:(GPBExtensionDescriptor *)extension value:(id)value { CheckExtension(self, extension); - if (![extension isRepeated]) { + if (!extension.repeated) { [NSException raise:NSInvalidArgumentException format:@"Must call setExtension() for singular types."]; } @@ -1814,12 +1829,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBBecomeVisibleToAutocreator(self); } -- (void)setExtension:(GPBExtensionField *)extension +- (void)setExtension:(GPBExtensionDescriptor *)extension index:(NSUInteger)idx value:(id)value { CheckExtension(self, extension); - if (![extension isRepeated]) { + if (!extension.repeated) { [NSException raise:NSInvalidArgumentException format:@"Must call setExtension() for singular types."]; } @@ -1834,7 +1849,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { GPBBecomeVisibleToAutocreator(self); } -- (void)clearExtension:(GPBExtensionField *)extension { +- (void)clearExtension:(GPBExtensionDescriptor *)extension { CheckExtension(self, extension); // Only become visible if there was actually a value to clear. @@ -1862,7 +1877,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if (GPBCodedInputStreamIsAtEnd(state)) { return; } - NSData *data = GPBCodedInputStreamReadRetainedDataNoCopy(state); + NSData *data = GPBCodedInputStreamReadRetainedBytesNoCopy(state); if (data == nil) { return; } @@ -1903,6 +1918,9 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { @try { [message mergeDelimitedFromCodedInputStream:input extensionRegistry:extensionRegistry]; + if (errorPtr) { + *errorPtr = nil; + } } @catch (NSException *exception) { [message release]; @@ -1942,7 +1960,7 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { uint32_t typeId = 0; NSData *rawBytes = nil; - GPBExtensionField *extension = nil; + GPBExtensionDescriptor *extension = nil; GPBCodedInputStreamState *state = &input->state_; while (true) { uint32_t tag = GPBCodedInputStreamReadTag(state); @@ -1953,11 +1971,12 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if (tag == GPBWireFormatMessageSetTypeIdTag) { typeId = GPBCodedInputStreamReadUInt32(state); if (typeId != 0) { - extension = [extensionRegistry getExtension:[self descriptor] - fieldNumber:typeId]; + extension = [extensionRegistry extensionForDescriptor:[self descriptor] + fieldNumber:typeId]; } } else if (tag == GPBWireFormatMessageSetMessageTag) { - rawBytes = [GPBCodedInputStreamReadRetainedDataNoCopy(state) autorelease]; + rawBytes = + [GPBCodedInputStreamReadRetainedBytesNoCopy(state) autorelease]; } else { if (![input skipField:tag]) { break; @@ -1971,9 +1990,11 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { if (extension != nil) { GPBCodedInputStream *newInput = [[GPBCodedInputStream alloc] initWithData:rawBytes]; - [extension mergeFromCodedInputStream:newInput - extensionRegistry:extensionRegistry - message:self]; + GPBExtensionMergeFromInputStream(extension, + extension.packable, + newInput, + extensionRegistry, + self); [newInput release]; } else { GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); @@ -1989,19 +2010,33 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag); GPBDescriptor *descriptor = [self descriptor]; - GPBExtensionField *extension = - [extensionRegistry getExtension:descriptor fieldNumber:fieldNumber]; - + GPBExtensionDescriptor *extension = + [extensionRegistry extensionForDescriptor:descriptor + fieldNumber:fieldNumber]; if (extension == nil) { if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) { [self parseMessageSet:input extensionRegistry:extensionRegistry]; return YES; } } else { - if ([extension wireType] == wireType) { - [extension mergeFromCodedInputStream:input - extensionRegistry:extensionRegistry - message:self]; + if (extension.wireType == wireType) { + GPBExtensionMergeFromInputStream(extension, + extension.packable, + input, + extensionRegistry, + self); + return YES; + } + // Primitive, repeated types can be packed on unpacked on the wire, and are + // parsed either way. + if ([extension isRepeated] && + !GPBDataTypeIsObject(extension->description_->dataType) && + (extension.alternateWireType == wireType)) { + GPBExtensionMergeFromInputStream(extension, + !extension.packable, + input, + extensionRegistry, + self); return YES; } } @@ -2020,1077 +2055,455 @@ static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) { #pragma mark - MergeFromCodedInputStream Support -typedef struct MergeFromCodedInputStreamContext { - GPBMessage *self; - GPBCodedInputStream *stream; - GPBMessage *result; - GPBExtensionRegistry *registry; - uint32_t tag; - GPBFileSyntax syntax; -} MergeFromCodedInputStreamContext; - -//%PDDM-DEFINE MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(NAME, TYPE, ARRAY_TYPE) -//%static BOOL DynamicMergeFromCodedInputStream##NAME(GPBFieldDescriptor *field, -//% NAME$S void *voidContext) { -//% MergeFromCodedInputStreamContext *context = -//% (MergeFromCodedInputStreamContext *)voidContext; -//% GPBCodedInputStreamState *state = &context->stream->state_; -//% GPBFieldType fieldType = field.fieldType; -//% if (fieldType == GPBFieldTypeRepeated) { -//% GPB##ARRAY_TYPE##Array *array = -//% GetOrCreateArrayIvarWithField(context->result, field, context->syntax); -//% if (field.isPackable) { -//% int32_t length = GPBCodedInputStreamReadInt32(state); -//% size_t limit = GPBCodedInputStreamPushLimit(state, length); -//% while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { -//% TYPE val = GPBCodedInputStreamRead##NAME(state); -//% [array addValue:val]; -//% } -//% GPBCodedInputStreamPopLimit(state, limit); -//% } else { -//% TYPE val = GPBCodedInputStreamRead##NAME(state); -//% [array addValue:val]; -//% } -//% } else if (fieldType == GPBFieldTypeSingle) { -//% TYPE val = GPBCodedInputStreamRead##NAME(state); -//% GPBSet##ARRAY_TYPE##IvarWithFieldInternal(context->result, field, val, -//% ARRAY_TYPE$S context->syntax); -//% } else { // fieldType == GPBFieldTypeMap -//% // The exact type doesn't matter, just need to know it is a GPB*Dictionary. -//% GPBInt32Int32Dictionary *map = -//% GetOrCreateMapIvarWithField(context->result, field, context->syntax); -//% [context->stream readMapEntry:map -//% extensionRegistry:nil -//% field:field -//% parentMessage:context->result]; -//% } -//% return NO; -//%} -//% -//%PDDM-DEFINE MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(NAME) -//%static BOOL DynamicMergeFromCodedInputStream##NAME(GPBFieldDescriptor *field, -//% NAME$S void *voidContext) { -//% MergeFromCodedInputStreamContext *context = voidContext; -//% GPBCodedInputStreamState *state = &context->stream->state_; -//% GPBFieldType fieldType = field.fieldType; -//% if (fieldType == GPBFieldTypeMap) { -//% // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point. -//% id map = -//% GetOrCreateMapIvarWithField(context->result, field, context->syntax); -//% [context->stream readMapEntry:map -//% extensionRegistry:nil -//% field:field -//% parentMessage:context->result]; -//% } else { -//% id val = GPBCodedInputStreamReadRetained##NAME(state); -//% if (fieldType == GPBFieldTypeRepeated) { -//% NSMutableArray *array = -//% GetOrCreateArrayIvarWithField(context->result, field, context->syntax); -//% [array addObject:val]; -//% [val release]; -//% } else { // fieldType == GPBFieldTypeSingle -//% GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val, -//% context->syntax); -//% } -//% } -//% return NO; -//%} -//% - -static BOOL DynamicMergeFromCodedInputStreamGroup(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - int number = GPBFieldNumber(field); - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBMessage *message = [[field.msgClass alloc] init]; - NSMutableArray *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - [context->stream readGroup:number - message:message - extensionRegistry:context->registry]; - [array addObject:message]; - [message release]; - } else if (fieldType == GPBFieldTypeSingle) { - BOOL has = GPBGetHasIvarField(context->result, field); - if (has) { - // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check - // again. - GPBMessage *message = - GPBGetObjectIvarWithFieldNoAutocreate(context->result, field); - [context->stream readGroup:number - message:message - extensionRegistry:context->registry]; - } else { - GPBMessage *message = [[field.msgClass alloc] init]; - [context->stream readGroup:number - message:message - extensionRegistry:context->registry]; - GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message, - context->syntax); - } - } else { // fieldType == GPBFieldTypeMap - NSCAssert(NO, @"Shouldn't happen"); - return YES; - } - return NO; -} - -static BOOL DynamicMergeFromCodedInputStreamMessage(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBMessage *message = [[field.msgClass alloc] init]; - NSMutableArray *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - [context->stream readMessage:message extensionRegistry:context->registry]; - [array addObject:message]; - [message release]; - } else if (fieldType == GPBFieldTypeSingle) { - BOOL has = GPBGetHasIvarField(context->result, field); - if (has) { - // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check - // again. - GPBMessage *message = - GPBGetObjectIvarWithFieldNoAutocreate(context->result, field); - [context->stream readMessage:message extensionRegistry:context->registry]; - } else { - GPBMessage *message = [[field.msgClass alloc] init]; - [context->stream readMessage:message extensionRegistry:context->registry]; - GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message, - context->syntax); - } - } else { // fieldType == GPBFieldTypeMap - // GPB*Dictionary or NSDictionary, exact type doesn't matter. - id map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:context->registry - field:field - parentMessage:context->result]; - } - return NO; -} - -static BOOL DynamicMergeFromCodedInputStreamEnum(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - int number = GPBFieldNumber(field); - BOOL hasPreservingUnknownEnumSemantics = - GPBHasPreservingUnknownEnumSemantics(context->syntax); - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBEnumArray *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - int32_t val = GPBCodedInputStreamReadEnum(state); - if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) { - [array addRawValue:val]; - } else { - GPBUnknownFieldSet *unknownFields = - GetOrMakeUnknownFields(context->self); - [unknownFields mergeVarintField:number value:val]; - } - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - int32_t val = GPBCodedInputStreamReadEnum(state); - if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) { - [array addRawValue:val]; +static void MergeSingleFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(&input->state_); \ + GPBSet##FUNC_TYPE##IvarWithFieldInternal(self, field, val, syntax); \ + break; \ + } +#define CASE_SINGLE_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id val = GPBCodedInputStreamReadRetained##NAME(&input->state_); \ + GPBSetRetainedObjectIvarWithFieldInternal(self, field, val, syntax); \ + break; \ + } + CASE_SINGLE_POD(Bool, BOOL, Bool) + CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) + CASE_SINGLE_POD(SFixed32, int32_t, Int32) + CASE_SINGLE_POD(Float, float, Float) + CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) + CASE_SINGLE_POD(SFixed64, int64_t, Int64) + CASE_SINGLE_POD(Double, double, Double) + CASE_SINGLE_POD(Int32, int32_t, Int32) + CASE_SINGLE_POD(Int64, int64_t, Int64) + CASE_SINGLE_POD(SInt32, int32_t, Int32) + CASE_SINGLE_POD(SInt64, int64_t, Int64) + CASE_SINGLE_POD(UInt32, uint32_t, UInt32) + CASE_SINGLE_POD(UInt64, uint64_t, UInt64) + CASE_SINGLE_OBJECT(Bytes) + CASE_SINGLE_OBJECT(String) +#undef CASE_SINGLE_POD +#undef CASE_SINGLE_OBJECT + + case GPBDataTypeMessage: { + if (GPBGetHasIvarField(self, field)) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has + // check again. + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [input readMessage:message extensionRegistry:extensionRegistry]; } else { - GPBUnknownFieldSet *unknownFields = - GetOrMakeUnknownFields(context->self); - [unknownFields mergeVarintField:number value:val]; - } - } - } else if (fieldType == GPBFieldTypeSingle) { - int32_t val = GPBCodedInputStreamReadEnum(state); - if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) { - GPBSetInt32IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { - GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(context->self); - [unknownFields mergeVarintField:number value:val]; - } - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a - // GPB*EnumDictionary. - GPBInt32EnumDictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:context->registry - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Bool, BOOL, Bool) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamBool(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBBoolArray *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - BOOL val = GPBCodedInputStreamReadBool(state); - [array addValue:val]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - BOOL val = GPBCodedInputStreamReadBool(state); - [array addValue:val]; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL val = GPBCodedInputStreamReadBool(state); - GPBSetBoolIvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Int32, int32_t, Int32) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamInt32(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt32Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - int32_t val = GPBCodedInputStreamReadInt32(state); - [array addValue:val]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - int32_t val = GPBCodedInputStreamReadInt32(state); - [array addValue:val]; - } - } else if (fieldType == GPBFieldTypeSingle) { - int32_t val = GPBCodedInputStreamReadInt32(state); - GPBSetInt32IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SInt32, int32_t, Int32) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamSInt32(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt32Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - int32_t val = GPBCodedInputStreamReadSInt32(state); - [array addValue:val]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - int32_t val = GPBCodedInputStreamReadSInt32(state); - [array addValue:val]; - } - } else if (fieldType == GPBFieldTypeSingle) { - int32_t val = GPBCodedInputStreamReadSInt32(state); - GPBSetInt32IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SFixed32, int32_t, Int32) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamSFixed32(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt32Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - int32_t val = GPBCodedInputStreamReadSFixed32(state); - [array addValue:val]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - int32_t val = GPBCodedInputStreamReadSFixed32(state); - [array addValue:val]; - } - } else if (fieldType == GPBFieldTypeSingle) { - int32_t val = GPBCodedInputStreamReadSFixed32(state); - GPBSetInt32IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(UInt32, uint32_t, UInt32) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamUInt32(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBUInt32Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - uint32_t val = GPBCodedInputStreamReadUInt32(state); - [array addValue:val]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - uint32_t val = GPBCodedInputStreamReadUInt32(state); - [array addValue:val]; - } - } else if (fieldType == GPBFieldTypeSingle) { - uint32_t val = GPBCodedInputStreamReadUInt32(state); - GPBSetUInt32IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Fixed32, uint32_t, UInt32) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamFixed32(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBUInt32Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - uint32_t val = GPBCodedInputStreamReadFixed32(state); - [array addValue:val]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - uint32_t val = GPBCodedInputStreamReadFixed32(state); - [array addValue:val]; - } - } else if (fieldType == GPBFieldTypeSingle) { - uint32_t val = GPBCodedInputStreamReadFixed32(state); - GPBSetUInt32IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Int64, int64_t, Int64) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamInt64(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt64Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - int64_t val = GPBCodedInputStreamReadInt64(state); - [array addValue:val]; + GPBMessage *message = [[field.msgClass alloc] init]; + [input readMessage:message extensionRegistry:extensionRegistry]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); } - GPBCodedInputStreamPopLimit(state, limit); - } else { - int64_t val = GPBCodedInputStreamReadInt64(state); - [array addValue:val]; + break; } - } else if (fieldType == GPBFieldTypeSingle) { - int64_t val = GPBCodedInputStreamReadInt64(state); - GPBSetInt64IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SFixed64, int64_t, Int64) -// This block of code is generated, do not edit it directly. -static BOOL DynamicMergeFromCodedInputStreamSFixed64(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt64Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - int64_t val = GPBCodedInputStreamReadSFixed64(state); - [array addValue:val]; + case GPBDataTypeGroup: { + if (GPBGetHasIvarField(self, field)) { + // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has + // check again. + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + } else { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, syntax); } - GPBCodedInputStreamPopLimit(state, limit); - } else { - int64_t val = GPBCodedInputStreamReadSFixed64(state); - [array addValue:val]; + break; } - } else if (fieldType == GPBFieldTypeSingle) { - int64_t val = GPBCodedInputStreamReadSFixed64(state); - GPBSetInt64IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SInt64, int64_t, Int64) -// This block of code is generated, do not edit it directly. -static BOOL DynamicMergeFromCodedInputStreamSInt64(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt64Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - int64_t val = GPBCodedInputStreamReadSInt64(state); - [array addValue:val]; + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(&input->state_); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + GPBSetInt32IvarWithFieldInternal(self, field, val, syntax); + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; } - GPBCodedInputStreamPopLimit(state, limit); - } else { - int64_t val = GPBCodedInputStreamReadSInt64(state); - [array addValue:val]; } - } else if (fieldType == GPBFieldTypeSingle) { - int64_t val = GPBCodedInputStreamReadSInt64(state); - GPBSetInt64IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; + } // switch } -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(UInt64, uint64_t, UInt64) -// This block of code is generated, do not edit it directly. +static void MergeRepeatedPackedFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + GPBCodedInputStreamState *state = &input->state_; + id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + int32_t length = GPBCodedInputStreamReadInt32(state); + size_t limit = GPBCodedInputStreamPushLimit(state, length); + while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { + switch (fieldDataType) { +#define CASE_REPEATED_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(state); \ + [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ + break; \ + } + CASE_REPEATED_PACKED_POD(Bool, BOOL, Bool) + CASE_REPEATED_PACKED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_PACKED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(Float, float, Float) + CASE_REPEATED_PACKED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_PACKED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(Double, double, Double) + CASE_REPEATED_PACKED_POD(Int32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(Int64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_PACKED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_PACKED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_PACKED_POD(UInt64, uint64_t, UInt64) +#undef CASE_REPEATED_PACKED_POD + + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + NSCAssert(NO, @"Non primitive types can't be packed"); + break; -static BOOL DynamicMergeFromCodedInputStreamUInt64(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBUInt64Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - uint64_t val = GPBCodedInputStreamReadUInt64(state); - [array addValue:val]; + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(state); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + [(GPBEnumArray*)genericArray addRawValue:val]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; + } + break; } - GPBCodedInputStreamPopLimit(state, limit); - } else { - uint64_t val = GPBCodedInputStreamReadUInt64(state); - [array addValue:val]; - } - } else if (fieldType == GPBFieldTypeSingle) { - uint64_t val = GPBCodedInputStreamReadUInt64(state); - GPBSetUInt64IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; + } // switch + } // while(BytesUntilLimit() > 0) + GPBCodedInputStreamPopLimit(state, limit); } -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Fixed64, uint64_t, UInt64) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamFixed64(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBUInt64Array *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - uint64_t val = GPBCodedInputStreamReadFixed64(state); - [array addValue:val]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - uint64_t val = GPBCodedInputStreamReadFixed64(state); - [array addValue:val]; +static void MergeRepeatedNotPackedFieldFromCodedInputStream( + GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax, + GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) { + GPBCodedInputStreamState *state = &input->state_; + id genericArray = GetOrCreateArrayIvarWithField(self, field, syntax); + switch (GPBGetFieldDataType(field)) { +#define CASE_REPEATED_NOT_PACKED_POD(NAME, TYPE, ARRAY_TYPE) \ + case GPBDataType##NAME: { \ + TYPE val = GPBCodedInputStreamRead##NAME(state); \ + [(GPB##ARRAY_TYPE##Array *)genericArray addValue:val]; \ + break; \ + } +#define CASE_REPEATED_NOT_PACKED_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id val = GPBCodedInputStreamReadRetained##NAME(state); \ + [(NSMutableArray*)genericArray addObject:val]; \ + [val release]; \ + break; \ + } + CASE_REPEATED_NOT_PACKED_POD(Bool, BOOL, Bool) + CASE_REPEATED_NOT_PACKED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_NOT_PACKED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(Float, float, Float) + CASE_REPEATED_NOT_PACKED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_NOT_PACKED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(Double, double, Double) + CASE_REPEATED_NOT_PACKED_POD(Int32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(Int64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_NOT_PACKED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_NOT_PACKED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_NOT_PACKED_POD(UInt64, uint64_t, UInt64) + CASE_REPEATED_NOT_PACKED_OBJECT(Bytes) + CASE_REPEATED_NOT_PACKED_OBJECT(String) +#undef CASE_REPEATED_NOT_PACKED_POD +#undef CASE_NOT_PACKED_OBJECT + case GPBDataTypeMessage: { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readMessage:message extensionRegistry:extensionRegistry]; + [(NSMutableArray*)genericArray addObject:message]; + [message release]; + break; } - } else if (fieldType == GPBFieldTypeSingle) { - uint64_t val = GPBCodedInputStreamReadFixed64(state); - GPBSetUInt64IvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Float, float, Float) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamFloat(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBFloatArray *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - float val = GPBCodedInputStreamReadFloat(state); - [array addValue:val]; - } - GPBCodedInputStreamPopLimit(state, limit); - } else { - float val = GPBCodedInputStreamReadFloat(state); - [array addValue:val]; + case GPBDataTypeGroup: { + GPBMessage *message = [[field.msgClass alloc] init]; + [input readGroup:GPBFieldNumber(field) + message:message + extensionRegistry:extensionRegistry]; + [(NSMutableArray*)genericArray addObject:message]; + [message release]; + break; } - } else if (fieldType == GPBFieldTypeSingle) { - float val = GPBCodedInputStreamReadFloat(state); - GPBSetFloatIvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Double, double, Double) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamDouble(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = - (MergeFromCodedInputStreamContext *)voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBDoubleArray *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - if (field.isPackable) { - int32_t length = GPBCodedInputStreamReadInt32(state); - size_t limit = GPBCodedInputStreamPushLimit(state, length); - while (GPBCodedInputStreamBytesUntilLimit(state) > 0) { - double val = GPBCodedInputStreamReadDouble(state); - [array addValue:val]; + case GPBDataTypeEnum: { + int32_t val = GPBCodedInputStreamReadEnum(state); + if (GPBHasPreservingUnknownEnumSemantics(syntax) || + [field isValidEnumValue:val]) { + [(GPBEnumArray*)genericArray addRawValue:val]; + } else { + GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self); + [unknownFields mergeVarintField:GPBFieldNumber(field) value:val]; } - GPBCodedInputStreamPopLimit(state, limit); - } else { - double val = GPBCodedInputStreamReadDouble(state); - [array addValue:val]; - } - } else if (fieldType == GPBFieldTypeSingle) { - double val = GPBCodedInputStreamReadDouble(state); - GPBSetDoubleIvarWithFieldInternal(context->result, field, val, - context->syntax); - } else { // fieldType == GPBFieldTypeMap - // The exact type doesn't matter, just need to know it is a GPB*Dictionary. - GPBInt32Int32Dictionary *map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(String) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamString(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeMap) { - // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point. - id map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } else { - id val = GPBCodedInputStreamReadRetainedString(state); - if (fieldType == GPBFieldTypeRepeated) { - NSMutableArray *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - [array addObject:val]; - [val release]; - } else { // fieldType == GPBFieldTypeSingle - GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val, - context->syntax); - } - } - return NO; -} - -//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(Data) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicMergeFromCodedInputStreamData(GPBFieldDescriptor *field, - void *voidContext) { - MergeFromCodedInputStreamContext *context = voidContext; - GPBCodedInputStreamState *state = &context->stream->state_; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeMap) { - // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point. - id map = - GetOrCreateMapIvarWithField(context->result, field, context->syntax); - [context->stream readMapEntry:map - extensionRegistry:nil - field:field - parentMessage:context->result]; - } else { - id val = GPBCodedInputStreamReadRetainedData(state); - if (fieldType == GPBFieldTypeRepeated) { - NSMutableArray *array = - GetOrCreateArrayIvarWithField(context->result, field, context->syntax); - [array addObject:val]; - [val release]; - } else { // fieldType == GPBFieldTypeSingle - GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val, - context->syntax); + break; } - } - return NO; + } // switch } -//%PDDM-EXPAND-END (15 expansions) - - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input extensionRegistry:(GPBExtensionRegistry *)extensionRegistry { GPBDescriptor *descriptor = [self descriptor]; GPBFileSyntax syntax = descriptor.file.syntax; - MergeFromCodedInputStreamContext context = { - self, input, self, extensionRegistry, 0, syntax - }; - GPBApplyStrictFunctions funcs = - GPBAPPLY_STRICT_FUNCTIONS_INIT(DynamicMergeFromCodedInputStream); + GPBCodedInputStreamState *state = &input->state_; + uint32_t tag = 0; NSUInteger startingIndex = 0; NSArray *fields = descriptor->fields_; - NSUInteger count = fields.count; + NSUInteger numFields = fields.count; while (YES) { BOOL merged = NO; - context.tag = GPBCodedInputStreamReadTag(&input->state_); - for (NSUInteger i = 0; i < count; ++i) { - if (startingIndex >= count) startingIndex = 0; + tag = GPBCodedInputStreamReadTag(state); + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; - if (GPBFieldTag(fieldDescriptor) == context.tag) { - GPBApplyFunction function = funcs[GPBGetFieldType(fieldDescriptor)]; - function(fieldDescriptor, &context); + if (GPBFieldTag(fieldDescriptor) == tag) { + GPBFieldType fieldType = fieldDescriptor.fieldType; + if (fieldType == GPBFieldTypeSingle) { + MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax, + input, extensionRegistry); + // Well formed protos will only have a single field once, advance + // the starting index to the next field. + startingIndex += 1; + } else if (fieldType == GPBFieldTypeRepeated) { + if (fieldDescriptor.isPackable) { + MergeRepeatedPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. + startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input, extensionRegistry); + } + } else { // fieldType == GPBFieldTypeMap + // GPB*Dictionary or NSDictionary, exact type doesn't matter at this + // point. + id map = GetOrCreateMapIvarWithField(self, fieldDescriptor, syntax); + [input readMapEntry:map + extensionRegistry:extensionRegistry + field:fieldDescriptor + parentMessage:self]; + } merged = YES; break; } else { startingIndex += 1; } + } // for(i < numFields) + + if (!merged) { + // Primitive, repeated types can be packed on unpacked on the wire, and + // are parsed either way. The above loop covered tag in the preferred + // for, so this need to check the alternate form. + for (NSUInteger i = 0; i < numFields; ++i) { + if (startingIndex >= numFields) startingIndex = 0; + GPBFieldDescriptor *fieldDescriptor = fields[startingIndex]; + if ((fieldDescriptor.fieldType == GPBFieldTypeRepeated) && + !GPBFieldDataTypeIsObject(fieldDescriptor) && + (GPBFieldAlternateTag(fieldDescriptor) == tag)) { + BOOL alternateIsPacked = !fieldDescriptor.isPackable; + if (alternateIsPacked) { + MergeRepeatedPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input); + // Well formed protos will only have a repeated field that is + // packed once, advance the starting index to the next field. + startingIndex += 1; + } else { + MergeRepeatedNotPackedFieldFromCodedInputStream( + self, fieldDescriptor, syntax, input, extensionRegistry); + } + merged = YES; + break; + } else { + startingIndex += 1; + } + } } + if (!merged) { - if (context.tag == 0) { + if (tag == 0) { // zero signals EOF / limit reached return; } else { if (GPBPreserveUnknownFields(syntax)) { if (![self parseUnknownField:input extensionRegistry:extensionRegistry - tag:context.tag]) { + tag:tag]) { // it's an endgroup tag return; } } else { - if (![input skipField:context.tag]) { + if (![input skipField:tag]) { return; } } } - } - } -} - -#pragma mark - MergeFrom Support - -typedef struct MergeFromContext { - GPBMessage *other; - GPBMessage *result; - GPBFileSyntax syntax; -} MergeFromContext; - -//%PDDM-DEFINE GPB_MERGE_FROM_FUNC(NAME) -//%static BOOL MergeFrom##NAME(GPBFieldDescriptor *field, void *voidContext) { -//% MergeFromContext *context = (MergeFromContext *)voidContext; -//% BOOL otherHas = GPBGetHasIvarField(context->other, field); -//% if (otherHas) { -//% GPBSet##NAME##IvarWithFieldInternal( -//% context->result, field, GPBGet##NAME##IvarWithField(context->other, field), -//% context->syntax); -//% } -//% return YES; -//%} -//% -//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Bool) -// This block of code is generated, do not edit it directly. + } // if(!merged) -static BOOL MergeFromBool(GPBFieldDescriptor *field, void *voidContext) { - MergeFromContext *context = (MergeFromContext *)voidContext; - BOOL otherHas = GPBGetHasIvarField(context->other, field); - if (otherHas) { - GPBSetBoolIvarWithFieldInternal( - context->result, field, GPBGetBoolIvarWithField(context->other, field), - context->syntax); - } - return YES; -} - -//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Int32) -// This block of code is generated, do not edit it directly. - -static BOOL MergeFromInt32(GPBFieldDescriptor *field, void *voidContext) { - MergeFromContext *context = (MergeFromContext *)voidContext; - BOOL otherHas = GPBGetHasIvarField(context->other, field); - if (otherHas) { - GPBSetInt32IvarWithFieldInternal( - context->result, field, GPBGetInt32IvarWithField(context->other, field), - context->syntax); - } - return YES; + } // while(YES) } -//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(UInt32) -// This block of code is generated, do not edit it directly. - -static BOOL MergeFromUInt32(GPBFieldDescriptor *field, void *voidContext) { - MergeFromContext *context = (MergeFromContext *)voidContext; - BOOL otherHas = GPBGetHasIvarField(context->other, field); - if (otherHas) { - GPBSetUInt32IvarWithFieldInternal( - context->result, field, GPBGetUInt32IvarWithField(context->other, field), - context->syntax); - } - return YES; -} - -//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Int64) -// This block of code is generated, do not edit it directly. +#pragma mark - MergeFrom Support -static BOOL MergeFromInt64(GPBFieldDescriptor *field, void *voidContext) { - MergeFromContext *context = (MergeFromContext *)voidContext; - BOOL otherHas = GPBGetHasIvarField(context->other, field); - if (otherHas) { - GPBSetInt64IvarWithFieldInternal( - context->result, field, GPBGetInt64IvarWithField(context->other, field), - context->syntax); +- (void)mergeFrom:(GPBMessage *)other { + Class selfClass = [self class]; + Class otherClass = [other class]; + if (!([selfClass isSubclassOfClass:otherClass] || + [otherClass isSubclassOfClass:selfClass])) { + [NSException raise:NSInvalidArgumentException + format:@"Classes must match %@ != %@", selfClass, otherClass]; } - return YES; -} -//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(UInt64) -// This block of code is generated, do not edit it directly. + // We assume something will be done and become visible. + GPBBecomeVisibleToAutocreator(self); -static BOOL MergeFromUInt64(GPBFieldDescriptor *field, void *voidContext) { - MergeFromContext *context = (MergeFromContext *)voidContext; - BOOL otherHas = GPBGetHasIvarField(context->other, field); - if (otherHas) { - GPBSetUInt64IvarWithFieldInternal( - context->result, field, GPBGetUInt64IvarWithField(context->other, field), - context->syntax); - } - return YES; -} + GPBDescriptor *descriptor = [[self class] descriptor]; + GPBFileSyntax syntax = descriptor.file.syntax; -//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Float) -// This block of code is generated, do not edit it directly. - -static BOOL MergeFromFloat(GPBFieldDescriptor *field, void *voidContext) { - MergeFromContext *context = (MergeFromContext *)voidContext; - BOOL otherHas = GPBGetHasIvarField(context->other, field); - if (otherHas) { - GPBSetFloatIvarWithFieldInternal( - context->result, field, GPBGetFloatIvarWithField(context->other, field), - context->syntax); - } - return YES; -} - -//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Double) -// This block of code is generated, do not edit it directly. - -static BOOL MergeFromDouble(GPBFieldDescriptor *field, void *voidContext) { - MergeFromContext *context = (MergeFromContext *)voidContext; - BOOL otherHas = GPBGetHasIvarField(context->other, field); - if (otherHas) { - GPBSetDoubleIvarWithFieldInternal( - context->result, field, GPBGetDoubleIvarWithField(context->other, field), - context->syntax); - } - return YES; -} - -//%PDDM-EXPAND-END (7 expansions) - -static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) { - MergeFromContext *context = (MergeFromContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - // In the case of a list, they need to be appended, and there is no - // _hasIvar to worry about setting. - id otherArray = - GPBGetObjectIvarWithFieldNoAutocreate(context->other, field); - if (otherArray) { - GPBType fieldDataType = field->description_->type; - if (GPBTypeIsObject(fieldDataType)) { - NSMutableArray *resultArray = GetOrCreateArrayIvarWithField( - context->result, field, context->syntax); - [resultArray addObjectsFromArray:otherArray]; - } else if (fieldDataType == GPBTypeEnum) { - GPBEnumArray *resultArray = GetOrCreateArrayIvarWithField( - context->result, field, context->syntax); - [resultArray addRawValuesFromArray:otherArray]; - } else { - // The array type doesn't matter, that all implment - // -addValuesFromArray:. - GPBInt32Array *resultArray = GetOrCreateArrayIvarWithField( - context->result, field, context->syntax); - [resultArray addValuesFromArray:otherArray]; + for (GPBFieldDescriptor *field in descriptor->fields_) { + GPBFieldType fieldType = field.fieldType; + if (fieldType == GPBFieldTypeSingle) { + int32_t hasIndex = GPBFieldHasIndex(field); + uint32_t fieldNumber = GPBFieldNumber(field); + if (!GPBGetHasIvar(other, hasIndex, fieldNumber)) { + // Other doesn't have the field set, on to the next. + continue; + } + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { + case GPBDataTypeBool: + GPBSetBoolIvarWithFieldInternal( + self, field, GPBGetMessageBoolField(other, field), syntax); + break; + case GPBDataTypeSFixed32: + case GPBDataTypeEnum: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + GPBSetInt32IvarWithFieldInternal( + self, field, GPBGetMessageInt32Field(other, field), syntax); + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + GPBSetUInt32IvarWithFieldInternal( + self, field, GPBGetMessageUInt32Field(other, field), syntax); + break; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + GPBSetInt64IvarWithFieldInternal( + self, field, GPBGetMessageInt64Field(other, field), syntax); + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + GPBSetUInt64IvarWithFieldInternal( + self, field, GPBGetMessageUInt64Field(other, field), syntax); + break; + case GPBDataTypeFloat: + GPBSetFloatIvarWithFieldInternal( + self, field, GPBGetMessageFloatField(other, field), syntax); + break; + case GPBDataTypeDouble: + GPBSetDoubleIvarWithFieldInternal( + self, field, GPBGetMessageDoubleField(other, field), syntax); + break; + case GPBDataTypeBytes: + case GPBDataTypeString: { + id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + GPBSetObjectIvarWithFieldInternal(self, field, otherVal, syntax); + break; + } + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (GPBGetHasIvar(self, hasIndex, fieldNumber)) { + GPBMessage *message = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + [message mergeFrom:otherVal]; + } else { + GPBMessage *message = [otherVal copy]; + GPBSetRetainedObjectIvarWithFieldInternal(self, field, message, + syntax); + } + break; + } + } // switch() + } else if (fieldType == GPBFieldTypeRepeated) { + // In the case of a list, they need to be appended, and there is no + // _hasIvar to worry about setting. + id otherArray = + GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (otherArray) { + GPBDataType fieldDataType = field->description_->dataType; + if (GPBDataTypeIsObject(fieldDataType)) { + NSMutableArray *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addObjectsFromArray:otherArray]; + } else if (fieldDataType == GPBDataTypeEnum) { + GPBEnumArray *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addRawValuesFromArray:otherArray]; + } else { + // The array type doesn't matter, that all implment + // -addValuesFromArray:. + GPBInt32Array *resultArray = + GetOrCreateArrayIvarWithField(self, field, syntax); + [resultArray addValuesFromArray:otherArray]; + } } - } - return YES; - } - if (fieldType == GPBFieldTypeMap) { - // In the case of a map, they need to be merged, and there is no - // _hasIvar to worry about setting. - id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(context->other, field); - if (otherDict) { - GPBType keyType = field.mapKeyType; - GPBType valueType = field->description_->type; - if (GPBTypeIsObject(keyType) && GPBTypeIsObject(valueType)) { - NSMutableDictionary *resultDict = GetOrCreateMapIvarWithField( - context->result, field, context->syntax); - [resultDict addEntriesFromDictionary:otherDict]; - } else if (valueType == GPBTypeEnum) { - // The exact type doesn't matter, just need to know it is a - // GPB*EnumDictionary. - GPBInt32EnumDictionary *resultDict = GetOrCreateMapIvarWithField( - context->result, field, context->syntax); - [resultDict addRawEntriesFromDictionary:otherDict]; - } else { - // The exact type doesn't matter, they all implement - // -addEntriesFromDictionary:. - GPBInt32Int32Dictionary *resultDict = GetOrCreateMapIvarWithField( - context->result, field, context->syntax); - [resultDict addEntriesFromDictionary:otherDict]; + } else { // fieldType = GPBFieldTypeMap + // In the case of a map, they need to be merged, and there is no + // _hasIvar to worry about setting. + id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(other, field); + if (otherDict) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = field->description_->dataType; + if (GPBDataTypeIsObject(keyDataType) && + GPBDataTypeIsObject(valueDataType)) { + NSMutableDictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addEntriesFromDictionary:otherDict]; + } else if (valueDataType == GPBDataTypeEnum) { + // The exact type doesn't matter, just need to know it is a + // GPB*EnumDictionary. + GPBInt32EnumDictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addRawEntriesFromDictionary:otherDict]; + } else { + // The exact type doesn't matter, they all implement + // -addEntriesFromDictionary:. + GPBInt32Int32Dictionary *resultDict = + GetOrCreateMapIvarWithField(self, field, syntax); + [resultDict addEntriesFromDictionary:otherDict]; + } } - } - return YES; - } - - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNumber = GPBFieldNumber(field); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNumber); - if (!otherHas) { - return YES; - } - // GPBGetObjectIvarWithFieldNoAutocreate skips the has check, faster. - id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(context->other, field); - if (GPBFieldTypeIsMessage(field)) { - if (GPBGetHasIvar(context->result, hasIndex, fieldNumber)) { - GPBMessage *message = - GPBGetObjectIvarWithFieldNoAutocreate(context->result, field); - [message mergeFrom:otherVal]; - } else { - GPBMessage *message = [otherVal copy]; - GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message, - context->syntax); - } - } else { - GPBSetObjectIvarWithFieldInternal(context->result, field, otherVal, - context->syntax); - } - return YES; -} - -- (void)mergeFrom:(GPBMessage *)other { - Class selfClass = [self class]; - Class otherClass = [other class]; - if (!([selfClass isSubclassOfClass:otherClass] || - [otherClass isSubclassOfClass:selfClass])) { - [NSException raise:NSInvalidArgumentException - format:@"Classes must match %@ != %@", selfClass, otherClass]; - } - - GPBApplyFunctions funcs = GPBAPPLY_FUNCTIONS_INIT(MergeFrom); - GPBFileSyntax syntax = [self descriptor].file.syntax; - MergeFromContext context = {other, self, syntax}; - GPBApplyFunctionsToMessageFields(&funcs, self, &context); - - // We assume someting got done, and become visible. - GPBBecomeVisibleToAutocreator(self); + } // if (fieldType)..else if...else + } // for(fields) // Unknown fields. if (!unknownFields_) { - [self setUnknownFields:context.other.unknownFields]; + [self setUnknownFields:other.unknownFields]; } else { - [unknownFields_ mergeUnknownFields:context.other.unknownFields]; + [unknownFields_ mergeUnknownFields:other.unknownFields]; } + // Extensions + if (other->extensionMap_.count == 0) { return; } @@ -3099,17 +2512,16 @@ static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) { extensionMap_ = CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self)); } else { - for (GPBExtensionField *thisField in other->extensionMap_) { - id otherValue = [other->extensionMap_ objectForKey:thisField]; - id value = [extensionMap_ objectForKey:thisField]; - GPBExtensionDescriptor *thisFieldDescriptor = thisField.descriptor; - BOOL isMessageExtension = GPBExtensionIsMessage(thisFieldDescriptor); + for (GPBExtensionDescriptor *extension in other->extensionMap_) { + id otherValue = [other->extensionMap_ objectForKey:extension]; + id value = [extensionMap_ objectForKey:extension]; + BOOL isMessageExtension = GPBExtensionIsMessage(extension); - if ([thisField isRepeated]) { + if (extension.repeated) { NSMutableArray *list = value; if (list == nil) { list = [[NSMutableArray alloc] init]; - [extensionMap_ setObject:list forKey:thisField]; + [extensionMap_ setObject:list forKey:extension]; [list release]; } if (isMessageExtension) { @@ -3127,20 +2539,20 @@ static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) { [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue]; } else { GPBMessage *copiedValue = [otherValue copy]; - [extensionMap_ setObject:copiedValue forKey:thisField]; + [extensionMap_ setObject:copiedValue forKey:extension]; [copiedValue release]; } } else { - [extensionMap_ setObject:otherValue forKey:thisField]; + [extensionMap_ setObject:otherValue forKey:extension]; } } - if (isMessageExtension && !thisFieldDescriptor.isRepeated) { + if (isMessageExtension && !extension.isRepeated) { GPBMessage *autocreatedValue = - [[autocreatedExtensionMap_ objectForKey:thisField] retain]; + [[autocreatedExtensionMap_ objectForKey:extension] retain]; // Must remove from the map before calling GPBClearMessageAutocreator() // so that GPBClearMessageAutocreator() knows its safe to clear. - [autocreatedExtensionMap_ removeObjectForKey:thisField]; + [autocreatedExtensionMap_ removeObjectForKey:extension]; GPBClearMessageAutocreator(autocreatedValue); [autocreatedValue release]; } @@ -3148,259 +2560,7 @@ static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) { } } -#pragma mark - IsEqual Support - -typedef struct IsEqualContext { - GPBMessage *other; - GPBMessage *self; - BOOL outIsEqual; -} IsEqualContext; - -// If both self and other "has" a value then compare. -//%PDDM-DEFINE IS_EQUAL_FUNC(NAME, TYPE) -//%static BOOL IsEqual##NAME(GPBFieldDescriptor *field, void *voidContext) { -//% IsEqualContext *context = (IsEqualContext *)voidContext; -//% int32_t hasIndex = GPBFieldHasIndex(field); -//% uint32_t fieldNum = GPBFieldNumber(field); -//% BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); -//% BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); -//% if (selfHas != otherHas) { -//% context->outIsEqual = NO; -//% return NO; -//% } -//% if (!selfHas) { -//% return YES; -//% } -//% TYPE selfVal = GPBGet##NAME##IvarWithField(context->self, field); -//% TYPE otherVal = GPBGet##NAME##IvarWithField(context->other, field); -//% if (selfVal != otherVal) { -//% context->outIsEqual = NO; -//% return NO; -//% } -//% return YES; -//%} -//% -//%PDDM-EXPAND IS_EQUAL_FUNC(Bool, BOOL) -// This block of code is generated, do not edit it directly. - -static BOOL IsEqualBool(GPBFieldDescriptor *field, void *voidContext) { - IsEqualContext *context = (IsEqualContext *)voidContext; - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNum = GPBFieldNumber(field); - BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); - if (selfHas != otherHas) { - context->outIsEqual = NO; - return NO; - } - if (!selfHas) { - return YES; - } - BOOL selfVal = GPBGetBoolIvarWithField(context->self, field); - BOOL otherVal = GPBGetBoolIvarWithField(context->other, field); - if (selfVal != otherVal) { - context->outIsEqual = NO; - return NO; - } - return YES; -} - -//%PDDM-EXPAND IS_EQUAL_FUNC(Int32, int32_t) -// This block of code is generated, do not edit it directly. - -static BOOL IsEqualInt32(GPBFieldDescriptor *field, void *voidContext) { - IsEqualContext *context = (IsEqualContext *)voidContext; - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNum = GPBFieldNumber(field); - BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); - if (selfHas != otherHas) { - context->outIsEqual = NO; - return NO; - } - if (!selfHas) { - return YES; - } - int32_t selfVal = GPBGetInt32IvarWithField(context->self, field); - int32_t otherVal = GPBGetInt32IvarWithField(context->other, field); - if (selfVal != otherVal) { - context->outIsEqual = NO; - return NO; - } - return YES; -} - -//%PDDM-EXPAND IS_EQUAL_FUNC(UInt32, uint32_t) -// This block of code is generated, do not edit it directly. - -static BOOL IsEqualUInt32(GPBFieldDescriptor *field, void *voidContext) { - IsEqualContext *context = (IsEqualContext *)voidContext; - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNum = GPBFieldNumber(field); - BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); - if (selfHas != otherHas) { - context->outIsEqual = NO; - return NO; - } - if (!selfHas) { - return YES; - } - uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field); - uint32_t otherVal = GPBGetUInt32IvarWithField(context->other, field); - if (selfVal != otherVal) { - context->outIsEqual = NO; - return NO; - } - return YES; -} - -//%PDDM-EXPAND IS_EQUAL_FUNC(Int64, int64_t) -// This block of code is generated, do not edit it directly. - -static BOOL IsEqualInt64(GPBFieldDescriptor *field, void *voidContext) { - IsEqualContext *context = (IsEqualContext *)voidContext; - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNum = GPBFieldNumber(field); - BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); - if (selfHas != otherHas) { - context->outIsEqual = NO; - return NO; - } - if (!selfHas) { - return YES; - } - int64_t selfVal = GPBGetInt64IvarWithField(context->self, field); - int64_t otherVal = GPBGetInt64IvarWithField(context->other, field); - if (selfVal != otherVal) { - context->outIsEqual = NO; - return NO; - } - return YES; -} - -//%PDDM-EXPAND IS_EQUAL_FUNC(UInt64, uint64_t) -// This block of code is generated, do not edit it directly. - -static BOOL IsEqualUInt64(GPBFieldDescriptor *field, void *voidContext) { - IsEqualContext *context = (IsEqualContext *)voidContext; - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNum = GPBFieldNumber(field); - BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); - if (selfHas != otherHas) { - context->outIsEqual = NO; - return NO; - } - if (!selfHas) { - return YES; - } - uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field); - uint64_t otherVal = GPBGetUInt64IvarWithField(context->other, field); - if (selfVal != otherVal) { - context->outIsEqual = NO; - return NO; - } - return YES; -} - -//%PDDM-EXPAND IS_EQUAL_FUNC(Float, float) -// This block of code is generated, do not edit it directly. - -static BOOL IsEqualFloat(GPBFieldDescriptor *field, void *voidContext) { - IsEqualContext *context = (IsEqualContext *)voidContext; - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNum = GPBFieldNumber(field); - BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); - if (selfHas != otherHas) { - context->outIsEqual = NO; - return NO; - } - if (!selfHas) { - return YES; - } - float selfVal = GPBGetFloatIvarWithField(context->self, field); - float otherVal = GPBGetFloatIvarWithField(context->other, field); - if (selfVal != otherVal) { - context->outIsEqual = NO; - return NO; - } - return YES; -} - -//%PDDM-EXPAND IS_EQUAL_FUNC(Double, double) -// This block of code is generated, do not edit it directly. - -static BOOL IsEqualDouble(GPBFieldDescriptor *field, void *voidContext) { - IsEqualContext *context = (IsEqualContext *)voidContext; - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNum = GPBFieldNumber(field); - BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); - if (selfHas != otherHas) { - context->outIsEqual = NO; - return NO; - } - if (!selfHas) { - return YES; - } - double selfVal = GPBGetDoubleIvarWithField(context->self, field); - double otherVal = GPBGetDoubleIvarWithField(context->other, field); - if (selfVal != otherVal) { - context->outIsEqual = NO; - return NO; - } - return YES; -} - -//%PDDM-EXPAND-END (7 expansions) - -static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { - IsEqualContext *context = (IsEqualContext *)voidContext; - if (GPBFieldIsMapOrArray(field)) { - // In the case of a list/map, there is no _hasIvar to worry about checking. - // NOTE: These are NSArray/GPB*Array/NSDictionary/GPB*Dictionary, but the - // type doesn't really matter as the object just has to support - // -count/-isEqual:. - NSArray *resultMapOrArray = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSArray *otherMapOrArray = - GPBGetObjectIvarWithFieldNoAutocreate(context->other, field); - context->outIsEqual = - (resultMapOrArray.count == 0 && otherMapOrArray.count == 0) || - [resultMapOrArray isEqual:otherMapOrArray]; - return context->outIsEqual; - } - int32_t hasIndex = GPBFieldHasIndex(field); - uint32_t fieldNum = GPBFieldNumber(field); - BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum); - BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum); - if (selfHas != otherHas) { - context->outIsEqual = NO; - return NO; - } - if (!selfHas) { - return YES; - } - // GPBGetObjectIvarWithFieldNoAutocreate skips the has check, faster. - NSObject *selfVal = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSObject *otherVal = - GPBGetObjectIvarWithFieldNoAutocreate(context->other, field); - - // This covers case where selfVal is set to nil, as well as shortcuts the call - // to isEqual: in common cases. - if (selfVal == otherVal) { - return YES; - } - if (![selfVal isEqual:otherVal]) { - context->outIsEqual = NO; - return NO; - } - return YES; -} +#pragma mark - isEqual: & hash Support - (BOOL)isEqual:(GPBMessage *)other { if (other == self) { @@ -3410,12 +2570,97 @@ static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { ![self isKindOfClass:[other class]]) { return NO; } - GPBApplyFunctions funcs = GPBAPPLY_FUNCTIONS_INIT(IsEqual); - IsEqualContext context = {other, self, YES}; - GPBApplyFunctionsToMessageFields(&funcs, self, &context); - if (!context.outIsEqual) { - return NO; - } + + GPBDescriptor *descriptor = [[self class] descriptor]; + uint8_t *selfStorage = (uint8_t *)messageStorage_; + uint8_t *otherStorage = (uint8_t *)other->messageStorage_; + + for (GPBFieldDescriptor *field in descriptor->fields_) { + if (GPBFieldIsMapOrArray(field)) { + // In the case of a list or map, there is no _hasIvar to worry about. + // NOTE: These are NSArray/GPB*Array or NSDictionary/GPB*Dictionary, but + // the type doesn't really matter as the objects all support -count and + // -isEqual:. + NSArray *resultMapOrArray = + GPBGetObjectIvarWithFieldNoAutocreate(self, field); + NSArray *otherMapOrArray = + GPBGetObjectIvarWithFieldNoAutocreate(other, field); + // nil and empty are equal + if (resultMapOrArray.count != 0 || otherMapOrArray.count != 0) { + if (![resultMapOrArray isEqual:otherMapOrArray]) { + return NO; + } + } + } else { // Single field + int32_t hasIndex = GPBFieldHasIndex(field); + uint32_t fieldNum = GPBFieldNumber(field); + BOOL selfHas = GPBGetHasIvar(self, hasIndex, fieldNum); + BOOL otherHas = GPBGetHasIvar(other, hasIndex, fieldNum); + if (selfHas != otherHas) { + return NO; // Differing has values, not equal. + } + if (!selfHas) { + // Same has values, was no, nothing else to check for this field. + continue; + } + // Now compare the values. + GPBDataType fieldDataType = GPBGetFieldDataType(field); + size_t fieldOffset = field->description_->offset; + switch (fieldDataType) { + case GPBDataTypeBool: { + BOOL *selfValPtr = (BOOL *)&selfStorage[fieldOffset]; + BOOL *otherValPtr = (BOOL *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + case GPBDataTypeFloat: { + _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); + // These are all 32bit, signed/unsigned doesn't matter for equality. + uint32_t *selfValPtr = (uint32_t *)&selfStorage[fieldOffset]; + uint32_t *otherValPtr = (uint32_t *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + case GPBDataTypeDouble: { + _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); + // These are all 64bit, signed/unsigned doesn't matter for equality. + uint64_t *selfValPtr = (uint64_t *)&selfStorage[fieldOffset]; + uint64_t *otherValPtr = (uint64_t *)&otherStorage[fieldOffset]; + if (*selfValPtr != *otherValPtr) { + return NO; + } + break; + } + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + // Type doesn't matter here, they all implement -isEqual:. + id *selfValPtr = (id *)&selfStorage[fieldOffset]; + id *otherValPtr = (id *)&otherStorage[fieldOffset]; + if (![*selfValPtr isEqual:*otherValPtr]) { + return NO; + } + break; + } + } // switch() + } // if(mapOrArray)...else + } // for(fields) // nil and empty are equal if (extensionMap_.count != 0 || other->extensionMap_.count != 0) { @@ -3425,13 +2670,14 @@ static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { } // nil and empty are equal - GPBUnknownFieldSet *otherUnknowns = other.unknownFields; + GPBUnknownFieldSet *otherUnknowns = other->unknownFields_; if ([unknownFields_ countOfFields] != 0 || [otherUnknowns countOfFields] != 0) { if (![unknownFields_ isEqual:otherUnknowns]) { return NO; } } + return YES; } @@ -3449,22 +2695,88 @@ static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { - (NSUInteger)hash { GPBDescriptor *descriptor = [[self class] descriptor]; const NSUInteger prime = 19; + uint8_t *storage = (uint8_t *)messageStorage_; - // Start with the descriptor and then mix it with the field numbers that - // are set. Hopefully that will give a spread based on classes and what - // fields are set. + // Start with the descriptor and then mix it with some instance info. + // Hopefully that will give a spread based on classes and what fields are set. NSUInteger result = (NSUInteger)descriptor; + for (GPBFieldDescriptor *field in descriptor->fields_) { if (GPBFieldIsMapOrArray(field)) { // Exact type doesn't matter, just check if there are any elements. NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field); - if (mapOrArray.count) { + NSUInteger count = mapOrArray.count; + if (count) { + // NSArray/NSDictionary use count, use the field number and the count. result = prime * result + GPBFieldNumber(field); + result = prime * result + count; } } else if (GPBGetHasIvarField(self, field)) { - result = prime * result + GPBFieldNumber(field); + // Just using the field number seemed simple/fast, but then a small + // message class where all the same fields are always set (to different + // things would end up all with the same hash, so pull in some data). + GPBDataType fieldDataType = GPBGetFieldDataType(field); + size_t fieldOffset = field->description_->offset; + switch (fieldDataType) { + case GPBDataTypeBool: { + BOOL *valPtr = (BOOL *)&storage[fieldOffset]; + result = prime * result + *valPtr; + break; + } + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + case GPBDataTypeEnum: + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + case GPBDataTypeFloat: { + _GPBCompileAssert(sizeof(float) == sizeof(uint32_t), float_not_32_bits); + // These are all 32bit, just mix it in. + uint32_t *valPtr = (uint32_t *)&storage[fieldOffset]; + result = prime * result + *valPtr; + break; + } + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + case GPBDataTypeDouble: { + _GPBCompileAssert(sizeof(double) == sizeof(uint64_t), double_not_64_bits); + // These are all 64bit, just mix what fits into an NSUInteger in. + uint64_t *valPtr = (uint64_t *)&storage[fieldOffset]; + result = prime * result + (NSUInteger)(*valPtr); + break; + } + case GPBDataTypeBytes: + case GPBDataTypeString: { + // Type doesn't matter here, they both implement -hash:. + id *valPtr = (id *)&storage[fieldOffset]; + result = prime * result + [*valPtr hash]; + break; + } + + case GPBDataTypeMessage: + case GPBDataTypeGroup: { + GPBMessage **valPtr = (GPBMessage **)&storage[fieldOffset]; + // Could call -hash on the sub message, but that could recurse pretty + // deep; follow the lead of NSArray/NSDictionary and don't really + // recurse for hash, instead use the field number and the descriptor + // of the sub message. Yes, this could suck for a bunch of messages + // where they all only differ in the sub messages, but if you are + // using a message with sub messages for something that needs -hash, + // odds are you are also copying them as keys, and that deep copy + // will also suck. + result = prime * result + GPBFieldNumber(field); + result = prime * result + (NSUInteger)[[*valPtr class] descriptor]; + break; + } + } // switch() } } + + // Unknowns and extensions are not included. + return result; } @@ -3487,1325 +2799,245 @@ static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) { #endif // DEBUG -#pragma mark - SerializedSize Support - -// Serialized size is only calculated once, and then is stored into -// memoizedSerializedSize. - -typedef struct SerializedSizeContext { - GPBMessage *self; - size_t outSize; -} SerializedSizeContext; - -//%PDDM-DEFINE SERIALIZED_SIZE_POD_FUNC(NAME, TYPE, REAL_TYPE) -//%SERIALIZED_SIZE_POD_FUNC_FULL(NAME, TYPE, REAL_TYPE, REAL_TYPE, ) -//%PDDM-DEFINE SERIALIZED_SIZE_POD_FUNC_FULL(NAME, TYPE, REAL_TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) -//%static BOOL DynamicSerializedSize##NAME(GPBFieldDescriptor *field, -//% NAME$S void *voidContext) { -//% SerializedSizeContext *context = (SerializedSizeContext *)voidContext; -//% GPBFieldType fieldType = field.fieldType; -//% if (fieldType == GPBFieldTypeRepeated) { -//% GPB##ARRAY_TYPE##Array *array = -//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); -//% NSUInteger count = array.count; -//% if (count == 0) return YES; -//% __block size_t dataSize = 0; -//% [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { -//% #pragma unused(idx, stop) -//% dataSize += GPBCompute##NAME##SizeNoTag(value); -//% }]; -//% context->outSize += dataSize; -//% size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); -//% if (field.isPackable) { -//% context->outSize += tagSize; -//% context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); -//% } else { -//% context->outSize += count * tagSize; -//% } -//% } else if (fieldType == GPBFieldTypeSingle) { -//% BOOL selfHas = GPBGetHasIvarField(context->self, field); -//% if (selfHas) { -//% TYPE selfVal = GPBGet##REAL_TYPE##IvarWithField(context->self, field); -//% context->outSize += GPBCompute##NAME##Size(GPBFieldNumber(field), selfVal); -//% } -//% } else { // fieldType == GPBFieldTypeMap -//% // Type will be GPB*##REAL_TYPE##Dictionary, exact type doesn't matter. -//% GPBInt32##REAL_TYPE##Dictionary *map = -//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); -//% context->outSize += [map computeSerializedSizeAsField:field]; -//% } -//% return YES; -//%} -//% -//%PDDM-DEFINE SERIALIZED_SIZE_OBJECT_FUNC(NAME) -//%static BOOL DynamicSerializedSize##NAME(GPBFieldDescriptor *field, -//% NAME$S void *voidContext) { -//% SerializedSizeContext *context = (SerializedSizeContext *)voidContext; -//% GPBFieldType fieldType = field.fieldType; -//% if (fieldType == GPBFieldTypeRepeated) { -//% NSArray *array = -//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); -//% for (id value in array) { -//% context->outSize += GPBCompute##NAME##SizeNoTag(value); -//% } -//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), -//% GPBGetFieldType(field)); -//% context->outSize += array.count * tagSize; -//% } else if (fieldType == GPBFieldTypeSingle) { -//% BOOL selfHas = GPBGetHasIvarField(context->self, field); -//% if (selfHas) { -//% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check -//% // again. -//% id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); -//% context->outSize += GPBCompute##NAME##Size(GPBFieldNumber(field), selfVal); -//% } -//% } else { // fieldType == GPBFieldTypeMap -//% GPBType mapKeyType = field.mapKeyType; -//% if (mapKeyType == GPBTypeString) { -//% // If key type was string, then the map is an NSDictionary. -//% NSDictionary *map = -//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); -//% context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field); -//% } else { -//% // Type will be GPB*##NAME##Dictionary, exact type doesn't matter. -//% GPBInt32ObjectDictionary *map = -//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); -//% context->outSize += [map computeSerializedSizeAsField:field]; -//% } -//% } -//% return YES; -//%} -//% -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Bool, BOOL, Bool) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeBool(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBBoolArray *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeBoolSizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - BOOL selfVal = GPBGetBoolIvarWithField(context->self, field); - context->outSize += GPBComputeBoolSize(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*BoolDictionary, exact type doesn't matter. - GPBInt32BoolDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} +#pragma mark - SerializedSize -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Int32, int32_t, Int32) -// This block of code is generated, do not edit it directly. +- (size_t)serializedSize { + GPBDescriptor *descriptor = [[self class] descriptor]; + size_t result = 0; -static BOOL DynamicSerializedSizeInt32(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt32Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeInt32SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - int32_t selfVal = GPBGetInt32IvarWithField(context->self, field); - context->outSize += GPBComputeInt32Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*Int32Dictionary, exact type doesn't matter. - GPBInt32Int32Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} + // Has check is done explicitly, so GPBGetObjectIvarWithFieldNoAutocreate() + // avoids doing the has check again. -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SInt32, int32_t, Int32) -// This block of code is generated, do not edit it directly. + // Fields. + for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) { + GPBFieldType fieldType = fieldDescriptor.fieldType; + GPBDataType fieldDataType = GPBGetFieldDataType(fieldDescriptor); -static BOOL DynamicSerializedSizeSInt32(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt32Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeSInt32SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - int32_t selfVal = GPBGetInt32IvarWithField(context->self, field); - context->outSize += GPBComputeSInt32Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*Int32Dictionary, exact type doesn't matter. - GPBInt32Int32Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} + // Single Fields + if (fieldType == GPBFieldTypeSingle) { + BOOL selfHas = GPBGetHasIvarField(self, fieldDescriptor); + if (!selfHas) { + continue; // Nothing to do. + } -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SFixed32, int32_t, Int32) -// This block of code is generated, do not edit it directly. + uint32_t fieldNumber = GPBFieldNumber(fieldDescriptor); -static BOOL DynamicSerializedSizeSFixed32(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt32Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeSFixed32SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - int32_t selfVal = GPBGetInt32IvarWithField(context->self, field); - context->outSize += GPBComputeSFixed32Size(GPBFieldNumber(field), selfVal); + switch (fieldDataType) { +#define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE) \ + case GPBDataType##NAME: { \ + TYPE fieldVal = GPBGetMessage##FUNC_TYPE##Field(self, fieldDescriptor); \ + result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ + break; \ + } +#define CASE_SINGLE_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + id fieldVal = GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); \ + result += GPBCompute##NAME##Size(fieldNumber, fieldVal); \ + break; \ + } + CASE_SINGLE_POD(Bool, BOOL, Bool) + CASE_SINGLE_POD(Fixed32, uint32_t, UInt32) + CASE_SINGLE_POD(SFixed32, int32_t, Int32) + CASE_SINGLE_POD(Float, float, Float) + CASE_SINGLE_POD(Fixed64, uint64_t, UInt64) + CASE_SINGLE_POD(SFixed64, int64_t, Int64) + CASE_SINGLE_POD(Double, double, Double) + CASE_SINGLE_POD(Int32, int32_t, Int32) + CASE_SINGLE_POD(Int64, int64_t, Int64) + CASE_SINGLE_POD(SInt32, int32_t, Int32) + CASE_SINGLE_POD(SInt64, int64_t, Int64) + CASE_SINGLE_POD(UInt32, uint32_t, UInt32) + CASE_SINGLE_POD(UInt64, uint64_t, UInt64) + CASE_SINGLE_OBJECT(Bytes) + CASE_SINGLE_OBJECT(String) + CASE_SINGLE_OBJECT(Message) + CASE_SINGLE_OBJECT(Group) + CASE_SINGLE_POD(Enum, int32_t, Int32) +#undef CASE_SINGLE_POD +#undef CASE_SINGLE_OBJECT + } + + // Repeated Fields + } else if (fieldType == GPBFieldTypeRepeated) { + id genericArray = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + NSUInteger count = [genericArray count]; + if (count == 0) { + continue; // Nothing to add. + } + __block size_t dataSize = 0; + + switch (fieldDataType) { +#define CASE_REPEATED_POD(NAME, TYPE, ARRAY_TYPE) \ + CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ) +#define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME) \ + case GPBDataType##NAME: { \ + GPB##ARRAY_TYPE##Array *array = genericArray; \ + [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \ + _Pragma("unused(idx, stop)"); \ + dataSize += GPBCompute##NAME##SizeNoTag(value); \ + }]; \ + break; \ + } +#define CASE_REPEATED_OBJECT(NAME) \ + case GPBDataType##NAME: { \ + for (id value in genericArray) { \ + dataSize += GPBCompute##NAME##SizeNoTag(value); \ + } \ + break; \ + } + CASE_REPEATED_POD(Bool, BOOL, Bool) + CASE_REPEATED_POD(Fixed32, uint32_t, UInt32) + CASE_REPEATED_POD(SFixed32, int32_t, Int32) + CASE_REPEATED_POD(Float, float, Float) + CASE_REPEATED_POD(Fixed64, uint64_t, UInt64) + CASE_REPEATED_POD(SFixed64, int64_t, Int64) + CASE_REPEATED_POD(Double, double, Double) + CASE_REPEATED_POD(Int32, int32_t, Int32) + CASE_REPEATED_POD(Int64, int64_t, Int64) + CASE_REPEATED_POD(SInt32, int32_t, Int32) + CASE_REPEATED_POD(SInt64, int64_t, Int64) + CASE_REPEATED_POD(UInt32, uint32_t, UInt32) + CASE_REPEATED_POD(UInt64, uint64_t, UInt64) + CASE_REPEATED_OBJECT(Bytes) + CASE_REPEATED_OBJECT(String) + CASE_REPEATED_OBJECT(Message) + CASE_REPEATED_OBJECT(Group) + CASE_REPEATED_POD_EXTRA(Enum, int32_t, Enum, Raw) +#undef CASE_REPEATED_POD +#undef CASE_REPEATED_POD_EXTRA +#undef CASE_REPEATED_OBJECT + } // switch + result += dataSize; + size_t tagSize = GPBComputeTagSize(GPBFieldNumber(fieldDescriptor)); + if (fieldDataType == GPBDataTypeGroup) { + // Groups have both a start and an end tag. + tagSize *= 2; + } + if (fieldDescriptor.isPackable) { + result += tagSize; + result += GPBComputeSizeTSizeAsInt32NoTag(dataSize); + } else { + result += count * tagSize; + } + + // Map<> Fields + } else { // fieldType == GPBFieldTypeMap + if (GPBDataTypeIsObject(fieldDataType) && + (fieldDescriptor.mapKeyDataType == GPBDataTypeString)) { + // If key type was string, then the map is an NSDictionary. + NSDictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + if (map) { + result += GPBDictionaryComputeSizeInternalHelper(map, fieldDescriptor); + } + } else { + // Type will be GPB*GroupDictionary, exact type doesn't matter. + GPBInt32Int32Dictionary *map = + GPBGetObjectIvarWithFieldNoAutocreate(self, fieldDescriptor); + result += [map computeSerializedSizeAsField:fieldDescriptor]; + } } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*Int32Dictionary, exact type doesn't matter. - GPBInt32Int32Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} + } // for(fields) -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC_FULL(Enum, int32_t, Int32, Enum, Raw) -// This block of code is generated, do not edit it directly. + // Add any unknown fields. + if (descriptor.wireFormat) { + result += [unknownFields_ serializedSizeAsMessageSet]; + } else { + result += [unknownFields_ serializedSize]; + } -static BOOL DynamicSerializedSizeEnum(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBEnumArray *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeEnumSizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - int32_t selfVal = GPBGetInt32IvarWithField(context->self, field); - context->outSize += GPBComputeEnumSize(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*Int32Dictionary, exact type doesn't matter. - GPBInt32Int32Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; + // Add any extensions. + for (GPBExtensionDescriptor *extension in extensionMap_) { + id value = [extensionMap_ objectForKey:extension]; + result += GPBComputeExtensionSerializedSizeIncludingTag(extension, value); } - return YES; + + return result; } -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(UInt32, uint32_t, UInt32) -// This block of code is generated, do not edit it directly. +#pragma mark - Resolve Methods Support -static BOOL DynamicSerializedSizeUInt32(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBUInt32Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeUInt32SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field); - context->outSize += GPBComputeUInt32Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*UInt32Dictionary, exact type doesn't matter. - GPBInt32UInt32Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Fixed32, uint32_t, UInt32) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeFixed32(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBUInt32Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeFixed32SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field); - context->outSize += GPBComputeFixed32Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*UInt32Dictionary, exact type doesn't matter. - GPBInt32UInt32Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Int64, int64_t, Int64) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeInt64(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt64Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeInt64SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - int64_t selfVal = GPBGetInt64IvarWithField(context->self, field); - context->outSize += GPBComputeInt64Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*Int64Dictionary, exact type doesn't matter. - GPBInt32Int64Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SFixed64, int64_t, Int64) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeSFixed64(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt64Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeSFixed64SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - int64_t selfVal = GPBGetInt64IvarWithField(context->self, field); - context->outSize += GPBComputeSFixed64Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*Int64Dictionary, exact type doesn't matter. - GPBInt32Int64Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SInt64, int64_t, Int64) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeSInt64(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBInt64Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeSInt64SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - int64_t selfVal = GPBGetInt64IvarWithField(context->self, field); - context->outSize += GPBComputeSInt64Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*Int64Dictionary, exact type doesn't matter. - GPBInt32Int64Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(UInt64, uint64_t, UInt64) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeUInt64(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBUInt64Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeUInt64SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field); - context->outSize += GPBComputeUInt64Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*UInt64Dictionary, exact type doesn't matter. - GPBInt32UInt64Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Fixed64, uint64_t, UInt64) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeFixed64(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBUInt64Array *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeFixed64SizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field); - context->outSize += GPBComputeFixed64Size(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*UInt64Dictionary, exact type doesn't matter. - GPBInt32UInt64Dictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Float, float, Float) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeFloat(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBFloatArray *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeFloatSizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - float selfVal = GPBGetFloatIvarWithField(context->self, field); - context->outSize += GPBComputeFloatSize(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*FloatDictionary, exact type doesn't matter. - GPBInt32FloatDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Double, double, Double) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeDouble(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - GPBDoubleArray *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - NSUInteger count = array.count; - if (count == 0) return YES; - __block size_t dataSize = 0; - [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) { - #pragma unused(idx, stop) - dataSize += GPBComputeDoubleSizeNoTag(value); - }]; - context->outSize += dataSize; - size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field)); - if (field.isPackable) { - context->outSize += tagSize; - context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize); - } else { - context->outSize += count * tagSize; - } - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - double selfVal = GPBGetDoubleIvarWithField(context->self, field); - context->outSize += GPBComputeDoubleSize(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - // Type will be GPB*DoubleDictionary, exact type doesn't matter. - GPBInt32DoubleDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(String) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeString(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - NSArray *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - for (id value in array) { - context->outSize += GPBComputeStringSizeNoTag(value); - } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), - GPBGetFieldType(field)); - context->outSize += array.count * tagSize; - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check - // again. - id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += GPBComputeStringSize(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { - // If key type was string, then the map is an NSDictionary. - NSDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field); - } else { - // Type will be GPB*StringDictionary, exact type doesn't matter. - GPBInt32ObjectDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Data) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeData(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - NSArray *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - for (id value in array) { - context->outSize += GPBComputeDataSizeNoTag(value); - } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), - GPBGetFieldType(field)); - context->outSize += array.count * tagSize; - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check - // again. - id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += GPBComputeDataSize(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { - // If key type was string, then the map is an NSDictionary. - NSDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field); - } else { - // Type will be GPB*DataDictionary, exact type doesn't matter. - GPBInt32ObjectDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Message) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeMessage(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - NSArray *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - for (id value in array) { - context->outSize += GPBComputeMessageSizeNoTag(value); - } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), - GPBGetFieldType(field)); - context->outSize += array.count * tagSize; - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check - // again. - id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += GPBComputeMessageSize(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { - // If key type was string, then the map is an NSDictionary. - NSDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field); - } else { - // Type will be GPB*MessageDictionary, exact type doesn't matter. - GPBInt32ObjectDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - } - return YES; -} - -//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Group) -// This block of code is generated, do not edit it directly. - -static BOOL DynamicSerializedSizeGroup(GPBFieldDescriptor *field, - void *voidContext) { - SerializedSizeContext *context = (SerializedSizeContext *)voidContext; - GPBFieldType fieldType = field.fieldType; - if (fieldType == GPBFieldTypeRepeated) { - NSArray *array = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - for (id value in array) { - context->outSize += GPBComputeGroupSizeNoTag(value); - } - size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), - GPBGetFieldType(field)); - context->outSize += array.count * tagSize; - } else if (fieldType == GPBFieldTypeSingle) { - BOOL selfHas = GPBGetHasIvarField(context->self, field); - if (selfHas) { - // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check - // again. - id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += GPBComputeGroupSize(GPBFieldNumber(field), selfVal); - } - } else { // fieldType == GPBFieldTypeMap - GPBType mapKeyType = field.mapKeyType; - if (mapKeyType == GPBTypeString) { - // If key type was string, then the map is an NSDictionary. - NSDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field); - } else { - // Type will be GPB*GroupDictionary, exact type doesn't matter. - GPBInt32ObjectDictionary *map = - GPBGetObjectIvarWithFieldNoAutocreate(context->self, field); - context->outSize += [map computeSerializedSizeAsField:field]; - } - } - return YES; -} - -//%PDDM-EXPAND-END (18 expansions) - -- (size_t)serializedSize { - // Fields. - SerializedSizeContext context = {self, 0}; - GPBApplyStrictFunctions funcs = - GPBAPPLY_STRICT_FUNCTIONS_INIT(DynamicSerializedSize); - GPBApplyStrictFunctionsToMessageFields(&funcs, self, &context); - // Add any unknown fields. - const GPBDescriptor *descriptor = [self descriptor]; - if (descriptor.wireFormat) { - context.outSize += [unknownFields_ serializedSizeAsMessageSet]; - } else { - context.outSize += [unknownFields_ serializedSize]; - } - // Add any extensions. - for (GPBExtensionField *extension in extensionMap_) { - id value = [extensionMap_ objectForKey:extension]; - context.outSize += [extension computeSerializedSizeIncludingTag:value]; - } - - return context.outSize; -} - -#pragma mark - Resolve Methods Support - -typedef struct IvarAccessorMethodContext { - GPBFileSyntax syntax; +typedef struct ResolveIvarAccessorMethodResult { IMP impToAdd; SEL encodingSelector; -} IvarAccessorMethodContext; - -//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, TRUE_NAME) -//%static BOOL IvarGet##NAME(GPBFieldDescriptor *field, void *voidContext) { -//% IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; -//% context->impToAdd = imp_implementationWithBlock(^(id obj) { -//% return GPBGet##TRUE_NAME##IvarWithField(obj, field); -//% }); -//% context->encodingSelector = @selector(get##NAME); -//% return NO; -//%} -//% -//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_OBJECT(NAME, TYPE) -//%IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, Object) -//%static BOOL IvarSet##NAME(GPBFieldDescriptor *field, void *voidContext) { -//% IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; -//% // Local for syntax so the block doesn't capture context and use random -//% // memory in the future. -//% const GPBFileSyntax syntax = context->syntax; -//% context->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { -//% return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); -//% }); -//% context->encodingSelector = @selector(set##NAME:); -//% return NO; -//%} -//% -//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_PER_VERSION(NAME, TYPE) -//%IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(NAME, TYPE, NAME) -//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(NAME, TYPE, TRUE_NAME) -//%IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, TRUE_NAME) -//%static BOOL IvarSet##NAME(GPBFieldDescriptor *field, void *voidContext) { -//% IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; -//% // Local for syntax so the block doesn't capture context and use random -//% // memory in the future. -//% const GPBFileSyntax syntax = context->syntax; -//% context->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { -//% return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); -//% }); -//% context->encodingSelector = @selector(set##NAME:); -//% return NO; -//%} -//% -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Bool, BOOL) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetBool(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetBoolIvarWithField(obj, field); - }); - context->encodingSelector = @selector(getBool); - return NO; -} - -static BOOL IvarSetBool(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { - return GPBSetBoolIvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setBool:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Int32, int32_t) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetInt32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetInt32IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getInt32); - return NO; -} - -static BOOL IvarSetInt32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) { - return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setInt32:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SInt32, int32_t, Int32) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetSInt32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetInt32IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getSInt32); - return NO; -} - -static BOOL IvarSetSInt32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) { - return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setSInt32:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SFixed32, int32_t, Int32) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetSFixed32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetInt32IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getSFixed32); - return NO; -} - -static BOOL IvarSetSFixed32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) { - return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setSFixed32:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(UInt32, uint32_t) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetUInt32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetUInt32IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getUInt32); - return NO; -} - -static BOOL IvarSetUInt32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, uint32_t value) { - return GPBSetUInt32IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setUInt32:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(Fixed32, uint32_t, UInt32) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetFixed32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetUInt32IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getFixed32); - return NO; -} - -static BOOL IvarSetFixed32(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, uint32_t value) { - return GPBSetUInt32IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setFixed32:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Int64, int64_t) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetInt64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetInt64IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getInt64); - return NO; -} - -static BOOL IvarSetInt64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) { - return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setInt64:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SFixed64, int64_t, Int64) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetSFixed64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetInt64IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getSFixed64); - return NO; -} - -static BOOL IvarSetSFixed64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) { - return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setSFixed64:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SInt64, int64_t, Int64) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetSInt64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetInt64IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getSInt64); - return NO; -} - -static BOOL IvarSetSInt64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) { - return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setSInt64:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(UInt64, uint64_t) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetUInt64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetUInt64IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getUInt64); - return NO; -} - -static BOOL IvarSetUInt64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, uint64_t value) { - return GPBSetUInt64IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setUInt64:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(Fixed64, uint64_t, UInt64) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetFixed64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetUInt64IvarWithField(obj, field); - }); - context->encodingSelector = @selector(getFixed64); - return NO; -} - -static BOOL IvarSetFixed64(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, uint64_t value) { - return GPBSetUInt64IvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setFixed64:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Float, float) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetFloat(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetFloatIvarWithField(obj, field); - }); - context->encodingSelector = @selector(getFloat); - return NO; -} - -static BOOL IvarSetFloat(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, float value) { - return GPBSetFloatIvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setFloat:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Double, double) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetDouble(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetDoubleIvarWithField(obj, field); - }); - context->encodingSelector = @selector(getDouble); - return NO; -} - -static BOOL IvarSetDouble(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, double value) { - return GPBSetDoubleIvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setDouble:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(String, id) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetString(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetObjectIvarWithField(obj, field); - }); - context->encodingSelector = @selector(getString); - return NO; -} - -static BOOL IvarSetString(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, id value) { - return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setString:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Data, id) -// This block of code is generated, do not edit it directly. +} ResolveIvarAccessorMethodResult; -static BOOL IvarGetData(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetObjectIvarWithField(obj, field); - }); - context->encodingSelector = @selector(getData); - return NO; -} - -static BOOL IvarSetData(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, id value) { - return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setData:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Message, id) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetMessage(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetObjectIvarWithField(obj, field); - }); - context->encodingSelector = @selector(getMessage); - return NO; -} - -static BOOL IvarSetMessage(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, id value) { - return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setMessage:); - return NO; -} - -//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Group, id) -// This block of code is generated, do not edit it directly. - -static BOOL IvarGetGroup(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetObjectIvarWithField(obj, field); - }); - context->encodingSelector = @selector(getGroup); - return NO; -} - -static BOOL IvarSetGroup(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, id value) { - return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setGroup:); - return NO; -} - -//%PDDM-EXPAND-END (17 expansions) - -// Enum gets custom hooks because get needs the syntax to Get. - -static BOOL IvarGetEnum(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj) { - return GPBGetEnumIvarWithFieldInternal(obj, field, syntax); - }); - context->encodingSelector = @selector(getEnum); - return NO; -} - -static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) { - IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext; - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context->syntax; - context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) { - return GPBSetEnumIvarWithFieldInternal(obj, field, value, syntax); - }); - context->encodingSelector = @selector(setEnum:); - return NO; +static void ResolveIvarGet(GPBFieldDescriptor *field, + ResolveIvarAccessorMethodResult *result) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_GET(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj) { \ + return GPBGetMessage##TRUE_NAME##Field(obj, field); \ + }); \ + result->encodingSelector = @selector(get##NAME); \ + break; \ + } +#define CASE_GET_OBJECT(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj) { \ + return GPBGetObjectIvarWithField(obj, field); \ + }); \ + result->encodingSelector = @selector(get##NAME); \ + break; \ + } + CASE_GET(Bool, BOOL, Bool) + CASE_GET(Fixed32, uint32_t, UInt32) + CASE_GET(SFixed32, int32_t, Int32) + CASE_GET(Float, float, Float) + CASE_GET(Fixed64, uint64_t, UInt64) + CASE_GET(SFixed64, int64_t, Int64) + CASE_GET(Double, double, Double) + CASE_GET(Int32, int32_t, Int32) + CASE_GET(Int64, int64_t, Int64) + CASE_GET(SInt32, int32_t, Int32) + CASE_GET(SInt64, int64_t, Int64) + CASE_GET(UInt32, uint32_t, UInt32) + CASE_GET(UInt64, uint64_t, UInt64) + CASE_GET_OBJECT(Bytes, id, Object) + CASE_GET_OBJECT(String, id, Object) + CASE_GET_OBJECT(Message, id, Object) + CASE_GET_OBJECT(Group, id, Object) + CASE_GET(Enum, int32_t, Enum) +#undef CASE_GET + } +} + +static void ResolveIvarSet(GPBFieldDescriptor *field, + GPBFileSyntax syntax, + ResolveIvarAccessorMethodResult *result) { + GPBDataType fieldDataType = GPBGetFieldDataType(field); + switch (fieldDataType) { +#define CASE_SET(NAME, TYPE, TRUE_NAME) \ + case GPBDataType##NAME: { \ + result->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) { \ + return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax); \ + }); \ + result->encodingSelector = @selector(set##NAME:); \ + break; \ + } + CASE_SET(Bool, BOOL, Bool) + CASE_SET(Fixed32, uint32_t, UInt32) + CASE_SET(SFixed32, int32_t, Int32) + CASE_SET(Float, float, Float) + CASE_SET(Fixed64, uint64_t, UInt64) + CASE_SET(SFixed64, int64_t, Int64) + CASE_SET(Double, double, Double) + CASE_SET(Int32, int32_t, Int32) + CASE_SET(Int64, int64_t, Int64) + CASE_SET(SInt32, int32_t, Int32) + CASE_SET(SInt64, int64_t, Int64) + CASE_SET(UInt32, uint32_t, UInt32) + CASE_SET(UInt64, uint64_t, UInt64) + CASE_SET(Bytes, id, Object) + CASE_SET(String, id, Object) + CASE_SET(Message, id, Object) + CASE_SET(Group, id, Object) + CASE_SET(Enum, int32_t, Enum) +#undef CASE_SET + } } + (BOOL)resolveInstanceMethod:(SEL)sel { @@ -4814,29 +3046,31 @@ static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) { return NO; } - // NOTE: hasSel_/setHasSel_ will be NULL if the field for the given message - // should not have has support (done in GPBDescriptor.m), so there is no need - // for checks here to see if has*/setHas* are allowed. + // NOTE: hasOrCountSel_/setHasSel_ will be NULL if the field for the given + // message should not have has support (done in GPBDescriptor.m), so there is + // no need for checks here to see if has*/setHas* are allowed. - IvarAccessorMethodContext context = {descriptor.file.syntax, NULL, NULL}; + ResolveIvarAccessorMethodResult result = {NULL, NULL}; for (GPBFieldDescriptor *field in descriptor->fields_) { BOOL isMapOrArray = GPBFieldIsMapOrArray(field); if (!isMapOrArray) { + // Single fields. if (sel == field->getSel_) { - static const GPBApplyStrictFunctions funcs = - GPBAPPLY_STRICT_FUNCTIONS_INIT(IvarGet); - funcs[GPBGetFieldType(field)](field, &context); + ResolveIvarGet(field, &result); + break; + } else if (sel == field->setSel_) { + ResolveIvarSet(field, descriptor.file.syntax, &result); break; - } else if (sel == field->hasSel_) { + } else if (sel == field->hasOrCountSel_) { int32_t index = GPBFieldHasIndex(field); uint32_t fieldNum = GPBFieldNumber(field); - context.impToAdd = imp_implementationWithBlock(^(id obj) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { return GPBGetHasIvar(obj, index, fieldNum); }); - context.encodingSelector = @selector(getBool); + result.encodingSelector = @selector(getBool); break; } else if (sel == field->setHasSel_) { - context.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { + result.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) { if (value) { [NSException raise:NSInvalidArgumentException format:@"%@: %@ can only be set to NO (to clear field).", @@ -4845,53 +3079,60 @@ static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) { } GPBClearMessageField(obj, field); }); - context.encodingSelector = @selector(setBool:); - break; - } else if (sel == field->setSel_) { - GPBApplyStrictFunctions funcs = GPBAPPLY_STRICT_FUNCTIONS_INIT(IvarSet); - funcs[GPBGetFieldType(field)](field, &context); + result.encodingSelector = @selector(setBool:); break; } else { GPBOneofDescriptor *oneof = field->containingOneof_; if (oneof && (sel == oneof->caseSel_)) { int32_t index = oneof->oneofDescription_->index; - context.impToAdd = imp_implementationWithBlock(^(id obj) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { return GPBGetHasOneof(obj, index); }); - context.encodingSelector = @selector(getEnum); + result.encodingSelector = @selector(getEnum); break; } } } else { + // map<>/repeated fields. if (sel == field->getSel_) { if (field.fieldType == GPBFieldTypeRepeated) { - context.impToAdd = imp_implementationWithBlock(^(id obj) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { return GetArrayIvarWithField(obj, field); }); } else { - context.impToAdd = imp_implementationWithBlock(^(id obj) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { return GetMapIvarWithField(obj, field); }); } - context.encodingSelector = @selector(getArray); + result.encodingSelector = @selector(getArray); break; } else if (sel == field->setSel_) { - // Local for syntax so the block doesn't capture context and use random - // memory in the future. - const GPBFileSyntax syntax = context.syntax; - context.impToAdd = imp_implementationWithBlock(^(id obj, id value) { + // Local for syntax so the block can directly capture it and not the + // full lookup. + const GPBFileSyntax syntax = descriptor.file.syntax; + result.impToAdd = imp_implementationWithBlock(^(id obj, id value) { return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax); }); - context.encodingSelector = @selector(setArray:); + result.encodingSelector = @selector(setArray:); + break; + } else if (sel == field->hasOrCountSel_) { + result.impToAdd = imp_implementationWithBlock(^(id obj) { + // Type doesn't matter, all *Array and *Dictionary types support + // -count. + NSArray *arrayOrMap = + GPBGetObjectIvarWithFieldNoAutocreate(obj, field); + return [arrayOrMap count]; + }); + result.encodingSelector = @selector(getArrayCount); break; } } } - if (context.impToAdd) { + if (result.impToAdd) { const char *encoding = - GPBMessageEncodingForSelector(context.encodingSelector, YES); + GPBMessageEncodingForSelector(result.encodingSelector, YES); BOOL methodAdded = class_addMethod(descriptor.messageClass, sel, - context.impToAdd, encoding); + result.impToAdd, encoding); return methodAdded; } return [super resolveInstanceMethod:sel]; diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h index c437c55b..d4c3501a 100644 --- a/objectivec/GPBMessage_PackagePrivate.h +++ b/objectivec/GPBMessage_PackagePrivate.h @@ -67,9 +67,9 @@ typedef struct GPBMessage_Storage *GPBMessage_StoragePtr; // Gets an extension value without autocreating the result if not found. (i.e. // returns nil if the extension is not set) -- (id)getExistingExtension:(GPBExtensionField *)extension; +- (id)getExistingExtension:(GPBExtensionDescriptor *)extension; -// Returns an array of GPBExtensionField* for all the extensions currently +// Returns an array of GPBExtensionDescriptor* for all the extensions currently // in use on the message. They are sorted by field number. - (NSArray *)sortedExtensionsInUse; diff --git a/objectivec/GPBProtocolBuffers.h b/objectivec/GPBProtocolBuffers.h index 436c9836..a66f295e 100644 --- a/objectivec/GPBProtocolBuffers.h +++ b/objectivec/GPBProtocolBuffers.h @@ -35,11 +35,10 @@ #import "GPBCodedOutputStream.h" #import "GPBDescriptor.h" #import "GPBDictionary.h" -#import "GPBExtensionField.h" #import "GPBExtensionRegistry.h" -#import "GPBField.h" #import "GPBMessage.h" #import "GPBRootObject.h" +#import "GPBUnknownField.h" #import "GPBUnknownFieldSet.h" #import "GPBUtilities.h" #import "GPBWireFormat.h" diff --git a/objectivec/GPBProtocolBuffers.m b/objectivec/GPBProtocolBuffers.m index 96eeb1d3..e9cbfb42 100644 --- a/objectivec/GPBProtocolBuffers.m +++ b/objectivec/GPBProtocolBuffers.m @@ -36,14 +36,27 @@ #import "GPBCodedOutputStream.m" #import "GPBDescriptor.m" #import "GPBDictionary.m" -#import "GPBExtensionField.m" +#import "GPBExtensionInternals.m" #import "GPBExtensionRegistry.m" -#import "GPBField.m" #import "GPBMessage.m" #import "GPBRootObject.m" +#import "GPBUnknownField.m" #import "GPBUnknownFieldSet.m" #import "GPBUtilities.m" #import "GPBWellKnownTypes.m" #import "GPBWireFormat.m" #import "google/protobuf/Descriptor.pbobjc.m" + +// Duration and Timestamp are #imported into GPBWellKnownTypes.m to the +// Objective C categories added will always be linked in with the classes. +#import "google/protobuf/Any.pbobjc.m" +#import "google/protobuf/Api.pbobjc.m" +// #import "google/protobuf/Duration.pbobjc.m" +#import "google/protobuf/Empty.pbobjc.m" +#import "google/protobuf/FieldMask.pbobjc.m" +#import "google/protobuf/SourceContext.pbobjc.m" +#import "google/protobuf/Struct.pbobjc.m" +// #import "google/protobuf/Timestamp.pbobjc.m" +#import "google/protobuf/Type.pbobjc.m" +#import "google/protobuf/Wrappers.pbobjc.m" diff --git a/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/objectivec/GPBProtocolBuffers_RuntimeSupport.h index 7fd7b4c8..fea75b93 100644 --- a/objectivec/GPBProtocolBuffers_RuntimeSupport.h +++ b/objectivec/GPBProtocolBuffers_RuntimeSupport.h @@ -34,8 +34,7 @@ #import "GPBProtocolBuffers.h" #import "GPBDescriptor_PackagePrivate.h" -#import "GPBExtensionField_PackagePrivate.h" -#import "GPBExtensionRegistry.h" +#import "GPBExtensionInternals.h" #import "GPBMessage_PackagePrivate.h" #import "GPBRootObject_PackagePrivate.h" #import "GPBUtilities_PackagePrivate.h" diff --git a/objectivec/GPBRootObject.m b/objectivec/GPBRootObject.m index 38dab665..3f648257 100644 --- a/objectivec/GPBRootObject.m +++ b/objectivec/GPBRootObject.m @@ -36,7 +36,6 @@ #import #import "GPBDescriptor.h" -#import "GPBExtensionField.h" #import "GPBUtilities_PackagePrivate.h" @interface GPBExtensionDescriptor (GPBRootObject) @@ -130,14 +129,14 @@ static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL; return nil; } -+ (void)globallyRegisterExtension:(GPBExtensionField *)field { - const char *key = [field.descriptor singletonNameC]; ++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field { + const char *key = [field singletonNameC]; OSSpinLockLock(&gExtensionSingletonDictionaryLock_); CFDictionarySetValue(gExtensionSingletonDictionary, key, field); OSSpinLockUnlock(&gExtensionSingletonDictionaryLock_); } -GPB_INLINE id ExtensionForName(id self, SEL _cmd) { +static id ExtensionForName(id self, SEL _cmd) { // Really fast way of doing "classname_selName". // This came up as a hotspot (creation of NSString *) when accessing a // lot of extensions. diff --git a/objectivec/GPBRootObject_PackagePrivate.h b/objectivec/GPBRootObject_PackagePrivate.h index f1cfe990..3c8f09c8 100644 --- a/objectivec/GPBRootObject_PackagePrivate.h +++ b/objectivec/GPBRootObject_PackagePrivate.h @@ -32,12 +32,12 @@ #import "GPBRootObject.h" -@class GPBExtensionField; +@class GPBExtensionDescriptor; @interface GPBRootObject () // Globally register. -+ (void)globallyRegisterExtension:(GPBExtensionField *)field; ++ (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field; @end diff --git a/objectivec/GPBRuntimeTypes.h b/objectivec/GPBRuntimeTypes.h new file mode 100644 index 00000000..e91d86a6 --- /dev/null +++ b/objectivec/GPBRuntimeTypes.h @@ -0,0 +1,102 @@ +// 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. + +#import + +#import "GPBBootstrap.h" + +@class GPBEnumDescriptor; +@class GPBMessage; +@class GPBInt32Array; + +// Function used to verify that a given value can be represented by an +// enum type. +typedef BOOL (*GPBEnumValidationFunc)(int32_t); + +// Function used to fetch an EnumDescriptor. +typedef GPBEnumDescriptor *(*GPBEnumDescriptorFunc)(void); + +// Magic values used for when an the at runtime to indicate an enum value +// that wasn't know at compile time. +enum { + kGPBUnrecognizedEnumeratorValue = (int32_t)0xFBADBEEF, +}; + +// A union for storing all possible Protobuf values. +// Note that owner is responsible for memory management of object types. +typedef union { + BOOL valueBool; + int32_t valueInt32; + int64_t valueInt64; + uint32_t valueUInt32; + uint64_t valueUInt64; + float valueFloat; + double valueDouble; + GPB_UNSAFE_UNRETAINED NSData *valueData; + GPB_UNSAFE_UNRETAINED NSString *valueString; + GPB_UNSAFE_UNRETAINED GPBMessage *valueMessage; + int32_t valueEnum; +} GPBGenericValue; + +// Do not change the order of this enum (or add things to it) without thinking +// about it very carefully. There are several things that depend on the order. +typedef enum { + GPBDataTypeBool = 0, + GPBDataTypeFixed32, + GPBDataTypeSFixed32, + GPBDataTypeFloat, + GPBDataTypeFixed64, + GPBDataTypeSFixed64, + GPBDataTypeDouble, + GPBDataTypeInt32, + GPBDataTypeInt64, + GPBDataTypeSInt32, + GPBDataTypeSInt64, + GPBDataTypeUInt32, + GPBDataTypeUInt64, + GPBDataTypeBytes, + GPBDataTypeString, + GPBDataTypeMessage, + GPBDataTypeGroup, + GPBDataTypeEnum, +} GPBDataType; + +enum { + // A count of the number of types in GPBDataType. Separated out from the + // GPBDataType enum to avoid warnings regarding not handling + // GPBDataType_Count in switch statements. + GPBDataType_Count = GPBDataTypeEnum + 1 +}; + +// An extension range. +typedef struct GPBExtensionRange { + uint32_t start; // inclusive + uint32_t end; // exclusive +} GPBExtensionRange; diff --git a/objectivec/GPBTypes.h b/objectivec/GPBTypes.h deleted file mode 100644 index 49c2b9e4..00000000 --- a/objectivec/GPBTypes.h +++ /dev/null @@ -1,102 +0,0 @@ -// 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. - -#import - -#import "GPBBootstrap.h" - -@class GPBEnumDescriptor; -@class GPBMessage; -@class GPBInt32Array; - -// Function used to verify that a given value can be represented by an -// enum type. -typedef BOOL (*GPBEnumValidationFunc)(int32_t); - -// Function used to fetch an EnumDescriptor. -typedef GPBEnumDescriptor *(*GPBEnumDescriptorFunc)(void); - -// Magic values used for when an the at runtime to indicate an enum value -// that wasn't know at compile time. -enum { - kGPBUnrecognizedEnumeratorValue = (int32_t)0xFBADBEEF, -}; - -// A union for storing all possible Protobuf values. -// Note that owner is responsible for memory management of object types. -typedef union { - BOOL valueBool; - int32_t valueInt32; - int64_t valueInt64; - uint32_t valueUInt32; - uint64_t valueUInt64; - float valueFloat; - double valueDouble; - GPB_UNSAFE_UNRETAINED NSData *valueData; - GPB_UNSAFE_UNRETAINED NSString *valueString; - GPB_UNSAFE_UNRETAINED GPBMessage *valueMessage; - int32_t valueEnum; -} GPBValue; - -// Do not change the order of this enum (or add things to it) without thinking -// about it very carefully. There are several things that depend on the order. -typedef enum { - GPBTypeBool = 0, - GPBTypeFixed32, - GPBTypeSFixed32, - GPBTypeFloat, - GPBTypeFixed64, - GPBTypeSFixed64, - GPBTypeDouble, - GPBTypeInt32, - GPBTypeInt64, - GPBTypeSInt32, - GPBTypeSInt64, - GPBTypeUInt32, - GPBTypeUInt64, - GPBTypeData, // Maps to Bytes Protobuf type - GPBTypeString, - GPBTypeMessage, - GPBTypeGroup, - GPBTypeEnum, -} GPBType; - -enum { - // A count of the number of types in GPBType. Separated out from the GPBType - // enum to avoid warnings regarding not handling GPBTypeCount in switch - // statements. - GPBTypeCount = GPBTypeEnum + 1 -}; - -// An extension range. -typedef struct GPBExtensionRange { - uint32_t start; // inclusive - uint32_t end; // exclusive -} GPBExtensionRange; diff --git a/objectivec/GPBUnknownField.h b/objectivec/GPBUnknownField.h new file mode 100644 index 00000000..f86d8249 --- /dev/null +++ b/objectivec/GPBUnknownField.h @@ -0,0 +1,56 @@ +// 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. + +#import + +@class GPBCodedOutputStream; +@class GPBUInt32Array; +@class GPBUInt64Array; +@class GPBUnknownFieldSet; + +@interface GPBUnknownField : NSObject + +@property(nonatomic, readonly, assign) int32_t number; + +// Only one of these will be set. +@property(nonatomic, readonly, strong) GPBUInt64Array *varintList; +@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List; +@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List; +@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList; // NSData +@property(nonatomic, readonly, strong) NSArray *groupList; // GPBUnknownFieldSet + +// Only one of these should be used per Field. +- (void)addVarint:(uint64_t)value; +- (void)addFixed32:(uint32_t)value; +- (void)addFixed64:(uint64_t)value; +- (void)addLengthDelimited:(NSData *)value; +- (void)addGroup:(GPBUnknownFieldSet *)value; + +@end diff --git a/objectivec/GPBUnknownField.m b/objectivec/GPBUnknownField.m new file mode 100644 index 00000000..c49c0dfc --- /dev/null +++ b/objectivec/GPBUnknownField.m @@ -0,0 +1,326 @@ +// 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. + +#import "GPBUnknownField_PackagePrivate.h" + +#import "GPBArray.h" +#import "GPBCodedOutputStream.h" + +@implementation GPBUnknownField { + @protected + int32_t number_; + GPBUInt64Array *mutableVarintList_; + GPBUInt32Array *mutableFixed32List_; + GPBUInt64Array *mutableFixed64List_; + NSMutableArray *mutableLengthDelimitedList_; + NSMutableArray *mutableGroupList_; +} + +@synthesize number = number_; +@synthesize varintList = mutableVarintList_; +@synthesize fixed32List = mutableFixed32List_; +@synthesize fixed64List = mutableFixed64List_; +@synthesize lengthDelimitedList = mutableLengthDelimitedList_; +@synthesize groupList = mutableGroupList_; + +- (instancetype)initWithNumber:(int32_t)number { + if ((self = [super init])) { + number_ = number; + } + return self; +} + +- (void)dealloc { + [mutableVarintList_ release]; + [mutableFixed32List_ release]; + [mutableFixed64List_ release]; + [mutableLengthDelimitedList_ release]; + [mutableGroupList_ release]; + + [super dealloc]; +} + +- (id)copyWithZone:(NSZone *)zone { + GPBUnknownField *result = + [[GPBUnknownField allocWithZone:zone] initWithNumber:number_]; + result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone]; + result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone]; + result->mutableLengthDelimitedList_ = + [mutableLengthDelimitedList_ copyWithZone:zone]; + result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone]; + if (mutableGroupList_.count) { + result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone] + initWithCapacity:mutableGroupList_.count]; + for (GPBUnknownFieldSet *group in mutableGroupList_) { + GPBUnknownFieldSet *copied = [group copyWithZone:zone]; + [result->mutableGroupList_ addObject:copied]; + [copied release]; + } + } + return result; +} + +- (BOOL)isEqual:(id)object { + if (self == object) return YES; + if (![object isKindOfClass:[GPBUnknownField class]]) return NO; + GPBUnknownField *field = (GPBUnknownField *)object; + BOOL equalVarint = + (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) || + [mutableVarintList_ isEqual:field->mutableVarintList_]; + if (!equalVarint) return NO; + BOOL equalFixed32 = (mutableFixed32List_.count == 0 && + field->mutableFixed32List_.count == 0) || + [mutableFixed32List_ isEqual:field->mutableFixed32List_]; + if (!equalFixed32) return NO; + BOOL equalFixed64 = (mutableFixed64List_.count == 0 && + field->mutableFixed64List_.count == 0) || + [mutableFixed64List_ isEqual:field->mutableFixed64List_]; + if (!equalFixed64) return NO; + BOOL equalLDList = + (mutableLengthDelimitedList_.count == 0 && + field->mutableLengthDelimitedList_.count == 0) || + [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_]; + if (!equalLDList) return NO; + BOOL equalGroupList = + (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) || + [mutableGroupList_ isEqual:field->mutableGroupList_]; + if (!equalGroupList) return NO; + return YES; +} + +- (NSUInteger)hash { + // Just mix the hashes of the possible sub arrays. + const int prime = 31; + NSUInteger result = prime + [mutableVarintList_ hash]; + result = prime * result + [mutableFixed32List_ hash]; + result = prime * result + [mutableFixed64List_ hash]; + result = prime * result + [mutableLengthDelimitedList_ hash]; + result = prime * result + [mutableGroupList_ hash]; + return result; +} + +- (void)writeToOutput:(GPBCodedOutputStream *)output { + NSUInteger count = mutableVarintList_.count; + if (count > 0) { + [output writeUInt64Array:number_ values:mutableVarintList_ tag:0]; + } + count = mutableFixed32List_.count; + if (count > 0) { + [output writeFixed32Array:number_ values:mutableFixed32List_ tag:0]; + } + count = mutableFixed64List_.count; + if (count > 0) { + [output writeFixed64Array:number_ values:mutableFixed64List_ tag:0]; + } + count = mutableLengthDelimitedList_.count; + if (count > 0) { + [output writeBytesArray:number_ values:mutableLengthDelimitedList_]; + } + count = mutableGroupList_.count; + if (count > 0) { + [output writeUnknownGroupArray:number_ values:mutableGroupList_]; + } +} + +- (size_t)serializedSize { + __block size_t result = 0; + int32_t number = number_; + [mutableVarintList_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeUInt64Size(number, value); + }]; + + [mutableFixed32List_ + enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeFixed32Size(number, value); + }]; + + [mutableFixed64List_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + result += GPBComputeFixed64Size(number, value); + }]; + + for (NSData *data in mutableLengthDelimitedList_) { + result += GPBComputeBytesSize(number, data); + } + + for (GPBUnknownFieldSet *set in mutableGroupList_) { + result += GPBComputeUnknownGroupSize(number, set); + } + + return result; +} + +- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output { + for (NSData *data in mutableLengthDelimitedList_) { + [output writeRawMessageSetExtension:number_ value:data]; + } +} + +- (size_t)serializedSizeAsMessageSetExtension { + size_t result = 0; + for (NSData *data in mutableLengthDelimitedList_) { + result += GPBComputeRawMessageSetExtensionSize(number_, data); + } + return result; +} + +- (NSString *)description { + NSMutableString *description = [NSMutableString + stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_]; + [mutableVarintList_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%llu\n", value]; + }]; + + [mutableFixed32List_ + enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%u\n", value]; + }]; + + [mutableFixed64List_ + enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) { +#pragma unused(idx, stop) + [description appendFormat:@"\t%llu\n", value]; + }]; + + for (NSData *data in mutableLengthDelimitedList_) { + [description appendFormat:@"\t%@\n", data]; + } + + for (GPBUnknownFieldSet *set in mutableGroupList_) { + [description appendFormat:@"\t%@\n", set]; + } + [description appendString:@"}"]; + return description; +} + +- (void)mergeFromField:(GPBUnknownField *)other { + GPBUInt64Array *otherVarintList = other.varintList; + if (otherVarintList.count > 0) { + if (mutableVarintList_ == nil) { + mutableVarintList_ = [otherVarintList copy]; + } else { + [mutableVarintList_ addValuesFromArray:otherVarintList]; + } + } + + GPBUInt32Array *otherFixed32List = other.fixed32List; + if (otherFixed32List.count > 0) { + if (mutableFixed32List_ == nil) { + mutableFixed32List_ = [otherFixed32List copy]; + } else { + [mutableFixed32List_ addValuesFromArray:otherFixed32List]; + } + } + + GPBUInt64Array *otherFixed64List = other.fixed64List; + if (otherFixed64List.count > 0) { + if (mutableFixed64List_ == nil) { + mutableFixed64List_ = [otherFixed64List copy]; + } else { + [mutableFixed64List_ addValuesFromArray:otherFixed64List]; + } + } + + NSArray *otherLengthDelimitedList = other.lengthDelimitedList; + if (otherLengthDelimitedList.count > 0) { + if (mutableLengthDelimitedList_ == nil) { + mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy]; + } else { + [mutableLengthDelimitedList_ + addObjectsFromArray:otherLengthDelimitedList]; + } + } + + NSArray *otherGroupList = other.groupList; + if (otherGroupList.count > 0) { + if (mutableGroupList_ == nil) { + mutableGroupList_ = + [[NSMutableArray alloc] initWithCapacity:otherGroupList.count]; + } + // Make our own mutable copies. + for (GPBUnknownFieldSet *group in otherGroupList) { + GPBUnknownFieldSet *copied = [group copy]; + [mutableGroupList_ addObject:copied]; + [copied release]; + } + } +} + +- (void)addVarint:(uint64_t)value { + if (mutableVarintList_ == nil) { + mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1]; + } else { + [mutableVarintList_ addValue:value]; + } +} + +- (void)addFixed32:(uint32_t)value { + if (mutableFixed32List_ == nil) { + mutableFixed32List_ = + [[GPBUInt32Array alloc] initWithValues:&value count:1]; + } else { + [mutableFixed32List_ addValue:value]; + } +} + +- (void)addFixed64:(uint64_t)value { + if (mutableFixed64List_ == nil) { + mutableFixed64List_ = + [[GPBUInt64Array alloc] initWithValues:&value count:1]; + } else { + [mutableFixed64List_ addValue:value]; + } +} + +- (void)addLengthDelimited:(NSData *)value { + if (mutableLengthDelimitedList_ == nil) { + mutableLengthDelimitedList_ = + [[NSMutableArray alloc] initWithObjects:&value count:1]; + } else { + [mutableLengthDelimitedList_ addObject:value]; + } +} + +- (void)addGroup:(GPBUnknownFieldSet *)value { + if (mutableGroupList_ == nil) { + mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1]; + } else { + [mutableGroupList_ addObject:value]; + } +} + +@end diff --git a/objectivec/GPBUnknownFieldSet.h b/objectivec/GPBUnknownFieldSet.h index 48824f10..ab8ee5e5 100644 --- a/objectivec/GPBUnknownFieldSet.h +++ b/objectivec/GPBUnknownFieldSet.h @@ -30,15 +30,15 @@ #import -@class GPBField; +@class GPBUnknownField; @interface GPBUnknownFieldSet : NSObject - (BOOL)hasField:(int32_t)number; -- (GPBField *)getField:(int32_t)number; +- (GPBUnknownField *)getField:(int32_t)number; - (NSUInteger)countOfFields; -- (void)addField:(GPBField *)field; +- (void)addField:(GPBUnknownField *)field; // Returns an NSArray of the GPBFields sorted by the field numbers. - (NSArray *)sortedFields; diff --git a/objectivec/GPBUnknownFieldSet.m b/objectivec/GPBUnknownFieldSet.m index d7154dc8..4ddc0d2a 100644 --- a/objectivec/GPBUnknownFieldSet.m +++ b/objectivec/GPBUnknownFieldSet.m @@ -32,7 +32,7 @@ #import "GPBCodedInputStream_PackagePrivate.h" #import "GPBCodedOutputStream.h" -#import "GPBField_PackagePrivate.h" +#import "GPBUnknownField_PackagePrivate.h" #import "GPBUtilities.h" #import "GPBWireFormat.h" @@ -85,10 +85,10 @@ static void checkNumber(int32_t number) { static void CopyWorker(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; GPBUnknownFieldSet *result = context; - GPBField *copied = [field copy]; + GPBUnknownField *copied = [field copy]; [result addField:copied]; [copied release]; } @@ -136,9 +136,10 @@ static void CopyWorker(const void *key, const void *value, void *context) { return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO; } -- (GPBField *)getField:(int32_t)number { +- (GPBUnknownField *)getField:(int32_t)number { ssize_t key = number; - GPBField *result = fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; + GPBUnknownField *result = + fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil; return result; } @@ -150,12 +151,12 @@ static void CopyWorker(const void *key, const void *value, void *context) { if (!fields_) return nil; size_t count = CFDictionaryGetCount(fields_); ssize_t keys[count]; - GPBField *values[count]; + GPBUnknownField *values[count]; CFDictionaryGetKeysAndValues(fields_, (const void **)keys, (const void **)values); struct GPBFieldPair { ssize_t key; - GPBField *value; + GPBUnknownField *value; } pairs[count]; for (size_t i = 0; i < count; ++i) { pairs[i].key = keys[i]; @@ -179,13 +180,13 @@ static void CopyWorker(const void *key, const void *value, void *context) { if (!fields_) return; size_t count = CFDictionaryGetCount(fields_); ssize_t keys[count]; - GPBField *values[count]; + GPBUnknownField *values[count]; CFDictionaryGetKeysAndValues(fields_, (const void **)keys, (const void **)values); if (count > 1) { struct GPBFieldPair { ssize_t key; - GPBField *value; + GPBUnknownField *value; } pairs[count]; for (size_t i = 0; i < count; ++i) { @@ -199,7 +200,7 @@ static void CopyWorker(const void *key, const void *value, void *context) { return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1); }); for (size_t i = 0; i < count; ++i) { - GPBField *value = pairs[i].value; + GPBUnknownField *value = pairs[i].value; [value writeToOutput:output]; } } else { @@ -219,7 +220,7 @@ static void CopyWorker(const void *key, const void *value, void *context) { static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; size_t *result = context; *result += [field serializedSize]; } @@ -237,7 +238,7 @@ static void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; GPBCodedOutputStream *output = context; [field writeAsMessageSetExtensionToOutput:output]; } @@ -253,7 +254,7 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; size_t *result = context; *result += [field serializedSizeAsMessageSetExtension]; } @@ -280,7 +281,7 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup; } -- (void)addField:(GPBField *)field { +- (void)addField:(GPBUnknownField *)field { int32_t number = [field number]; checkNumber(number); if (!fields_) { @@ -297,12 +298,12 @@ static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key, CFDictionarySetValue(fields_, (const void *)key, field); } -- (GPBField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { +- (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create { ssize_t key = number; - GPBField *existing = + GPBUnknownField *existing = fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil; if (!existing && create) { - existing = [[GPBField alloc] initWithNumber:number]; + existing = [[GPBUnknownField alloc] initWithNumber:number]; // This retains existing. [self addField:existing]; [existing release]; @@ -314,19 +315,19 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, const void *value, void *context) { #pragma unused(key) - GPBField *field = value; + GPBUnknownField *field = value; GPBUnknownFieldSet *self = context; int32_t number = [field number]; checkNumber(number); - GPBField *oldField = [self mutableFieldForNumber:number create:NO]; + GPBUnknownField *oldField = [self mutableFieldForNumber:number create:NO]; if (oldField) { [oldField mergeFromField:field]; } else { // Merge only comes from GPBMessage's mergeFrom:, so it means we are on // mutable message and are an mutable instance, so make sure we need // mutable fields. - GPBField *fieldCopy = [field copy]; + GPBUnknownField *fieldCopy = [field copy]; [self addField:fieldCopy]; [fieldCopy release]; } @@ -356,18 +357,18 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, GPBCodedInputStreamState *state = &input->state_; switch (GPBWireFormatGetTagWireType(tag)) { case GPBWireFormatVarint: { - GPBField *field = [self mutableFieldForNumber:number create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addVarint:GPBCodedInputStreamReadInt64(state)]; return YES; } case GPBWireFormatFixed64: { - GPBField *field = [self mutableFieldForNumber:number create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addFixed64:GPBCodedInputStreamReadFixed64(state)]; return YES; } case GPBWireFormatLengthDelimited: { - NSData *data = GPBCodedInputStreamReadRetainedData(state); - GPBField *field = [self mutableFieldForNumber:number create:YES]; + NSData *data = GPBCodedInputStreamReadRetainedBytes(state); + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addLengthDelimited:data]; [data release]; return YES; @@ -375,7 +376,7 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, case GPBWireFormatStartGroup: { GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init]; [input readUnknownGroup:number message:unknownFieldSet]; - GPBField *field = [self mutableFieldForNumber:number create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addGroup:unknownFieldSet]; [unknownFieldSet release]; return YES; @@ -383,7 +384,7 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, case GPBWireFormatEndGroup: return NO; case GPBWireFormatFixed32: { - GPBField *field = [self mutableFieldForNumber:number create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:number create:YES]; [field addFixed32:GPBCodedInputStreamReadFixed32(state)]; return YES; } @@ -396,7 +397,7 @@ static void GPBUnknownFieldSetMergeUnknownFields(const void *key, } - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data { - GPBField *field = [self mutableFieldForNumber:fieldNum create:YES]; + GPBUnknownField *field = [self mutableFieldForNumber:fieldNum create:YES]; [field addLengthDelimited:data]; } diff --git a/objectivec/GPBUnknownField_PackagePrivate.h b/objectivec/GPBUnknownField_PackagePrivate.h new file mode 100644 index 00000000..1fbce0f9 --- /dev/null +++ b/objectivec/GPBUnknownField_PackagePrivate.h @@ -0,0 +1,49 @@ +// 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. + +#import + +#import "GPBUnknownField.h" + +@class GPBCodedOutputStream; + +@interface GPBUnknownField () + +- (instancetype)initWithNumber:(int32_t)number; + +- (void)writeToOutput:(GPBCodedOutputStream *)output; +- (size_t)serializedSize; + +- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output; +- (size_t)serializedSizeAsMessageSetExtension; + +- (void)mergeFromField:(GPBUnknownField *)other; + +@end diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h index 8813f1ad..87cd32c7 100644 --- a/objectivec/GPBUtilities.h +++ b/objectivec/GPBUtilities.h @@ -30,152 +30,153 @@ #import +#import "GPBArray.h" #import "GPBMessage.h" -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" CF_EXTERN_C_BEGIN +// Generates a string that should be a valid "Text Format" for the C++ version +// of Protocol Buffers. lineIndent can be nil if no additional line indent is +// needed. The comments provide the names according to the ObjC library, they +// most likely won't exactly match the original .proto file. +NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent); +NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, + NSString *lineIndent); + +// +// Test if the given field is set on a message. +// BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber); BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field); +// +// Clear the given field of a message. +// void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field); +//%PDDM-EXPAND GPB_ACCESSORS() +// This block of code is generated, do not edit it directly. + + +// +// Get/Set the given field of a message. +// + +// Single Fields + +NSData *GPBGetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageBytesField(GPBMessage *self, GPBFieldDescriptor *field, NSData *value); + +NSString *GPBGetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageStringField(GPBMessage *self, GPBFieldDescriptor *field, NSString *value); + +GPBMessage *GPBGetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value); + +GPBMessage *GPBGetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, GPBMessage *value); + +BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value); + +int32_t GPBGetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageInt32Field(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); + +uint32_t GPBGetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageUInt32Field(GPBMessage *self, GPBFieldDescriptor *field, uint32_t value); + +int64_t GPBGetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageInt64Field(GPBMessage *self, GPBFieldDescriptor *field, int64_t value); + +uint64_t GPBGetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageUInt64Field(GPBMessage *self, GPBFieldDescriptor *field, uint64_t value); + +float GPBGetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageFloatField(GPBMessage *self, GPBFieldDescriptor *field, float value); + +double GPBGetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageDoubleField(GPBMessage *self, GPBFieldDescriptor *field, double value); + +// Get/Set the given enum field of a message. You can only Set values that are +// members of the enum. For proto3, when doing a Get, if the value isn't a +// memeber of the enum, kGPBUnrecognizedEnumeratorValue will be returned. The +// the functions with "Raw" in the will bypass all checks. +int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); +int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); + +// Repeated Fields + +// The object will/should be GPB*Array or NSMutableArray based on the field's +// type. +id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array); + +// Map Fields + +// The object will/should be GPB*Dictionary or NSMutableDictionary based on the +// field's type. +id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field); +void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary); + +//%PDDM-EXPAND-END GPB_ACCESSORS() + // Returns an empty NSData to assign to byte fields when you wish // to assign them to empty. Prevents allocating a lot of little [NSData data] // objects. NSData *GPBEmptyNSData(void) __attribute__((pure)); -//%PDDM-EXPAND GPB_IVAR_ACCESSORS() -// This block of code is generated, do not edit it directly. +CF_EXTERN_C_END -// Getters and Setters for ivars named |name| from instance self. - -NSData* GPBGetDataIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetDataIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - NSData* value); -NSString* GPBGetStringIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetStringIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - NSString* value); -GPBMessage* GPBGetMessageIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetMessageIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBMessage* value); -GPBMessage* GPBGetGroupIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetGroupIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBMessage* value); -BOOL GPBGetBoolIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetBoolIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - BOOL value); -int32_t GPBGetInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value); -int32_t GPBGetSFixed32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetSFixed32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value); -int32_t GPBGetSInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetSInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value); -int32_t GPBGetEnumIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetEnumIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value); -uint32_t GPBGetUInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetUInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value); -uint32_t GPBGetFixed32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetFixed32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value); -int64_t GPBGetInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value); -int64_t GPBGetSInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetSInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value); -int64_t GPBGetSFixed64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetSFixed64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value); -uint64_t GPBGetUInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetUInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value); -uint64_t GPBGetFixed64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetFixed64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value); -float GPBGetFloatIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetFloatIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - float value); -double GPBGetDoubleIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field); -void GPBSetDoubleIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - double value); -//%PDDM-EXPAND-END GPB_IVAR_ACCESSORS() - -// Generates a sting that should be a valid "Text Format" for the C++ version -// of Protocol Buffers. lineIndent can be nil if no additional line indent is -// needed. The comments provide the names according to the ObjC library, they -// most likely won't exactly match the original .proto file. -NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent); -NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, - NSString *lineIndent); -CF_EXTERN_C_END +//%PDDM-DEFINE GPB_ACCESSORS() +//% +//%// +//%// Get/Set the given field of a message. +//%// +//% +//%// Single Fields +//% +//%GPB_ACCESSOR_SINGLE_FULL(Bytes, NSData, *) +//%GPB_ACCESSOR_SINGLE_FULL(String, NSString, *) +//%GPB_ACCESSOR_SINGLE_FULL(Message, GPBMessage, *) +//%GPB_ACCESSOR_SINGLE_FULL(Group, GPBMessage, *) +//%GPB_ACCESSOR_SINGLE(Bool, BOOL) +//%GPB_ACCESSOR_SINGLE(Int32, int32_t) +//%GPB_ACCESSOR_SINGLE(UInt32, uint32_t) +//%GPB_ACCESSOR_SINGLE(Int64, int64_t) +//%GPB_ACCESSOR_SINGLE(UInt64, uint64_t) +//%GPB_ACCESSOR_SINGLE(Float, float) +//%GPB_ACCESSOR_SINGLE(Double, double) +//%// Get/Set the given enum field of a message. You can only Set values that are +//%// members of the enum. For proto3, when doing a Get, if the value isn't a +//%// memeber of the enum, kGPBUnrecognizedEnumeratorValue will be returned. The +//%// the functions with "Raw" in the will bypass all checks. +//%int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); +//%int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value); +//% +//%// Repeated Fields +//% +//%// The object will/should be GPB*Array or NSMutableArray based on the field's +//%// type. +//%id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array); +//% +//%// Map Fields +//% +//%// The object will/should be GPB*Dictionary or NSMutableDictionary based on the +//%// field's type. +//%id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary); +//% -//%PDDM-DEFINE GPB_IVAR_ACCESSORS() -//%// Getters and Setters for ivars named |name| from instance self. +//%PDDM-DEFINE GPB_ACCESSOR_SINGLE(NAME, TYPE) +//%GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, ) +//%PDDM-DEFINE GPB_ACCESSOR_SINGLE_FULL(NAME, TYPE, TisP) +//%TYPE TisP##GPBGetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field); +//%void GPBSetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field, TYPE TisP##value); //% -//%GPB_IVAR_ACCESSORS_DECL(Data, NSData*) -//%GPB_IVAR_ACCESSORS_DECL(String, NSString*) -//%GPB_IVAR_ACCESSORS_DECL(Message, GPBMessage*) -//%GPB_IVAR_ACCESSORS_DECL(Group, GPBMessage*) -//%GPB_IVAR_ACCESSORS_DECL(Bool, BOOL) -//%GPB_IVAR_ACCESSORS_DECL(Int32, int32_t) -//%GPB_IVAR_ACCESSORS_DECL(SFixed32, int32_t) -//%GPB_IVAR_ACCESSORS_DECL(SInt32, int32_t) -//%GPB_IVAR_ACCESSORS_DECL(Enum, int32_t) -//%GPB_IVAR_ACCESSORS_DECL(UInt32, uint32_t) -//%GPB_IVAR_ACCESSORS_DECL(Fixed32, uint32_t) -//%GPB_IVAR_ACCESSORS_DECL(Int64, int64_t) -//%GPB_IVAR_ACCESSORS_DECL(SInt64, int64_t) -//%GPB_IVAR_ACCESSORS_DECL(SFixed64, int64_t) -//%GPB_IVAR_ACCESSORS_DECL(UInt64, uint64_t) -//%GPB_IVAR_ACCESSORS_DECL(Fixed64, uint64_t) -//%GPB_IVAR_ACCESSORS_DECL(Float, float) -//%GPB_IVAR_ACCESSORS_DECL(Double, double) -//%PDDM-DEFINE GPB_IVAR_ACCESSORS_DECL(NAME, TYPE) -//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self, -//% TYPE$S NAME$S GPBFieldDescriptor *field); -//%void GPBSet##NAME##IvarWithField(GPBMessage *self, -//% NAME$S GPBFieldDescriptor *field, -//% NAME$S TYPE value); diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m index f912b979..7a035ce6 100644 --- a/objectivec/GPBUtilities.m +++ b/objectivec/GPBUtilities.m @@ -35,9 +35,8 @@ #import "GPBArray_PackagePrivate.h" #import "GPBDescriptor_PackagePrivate.h" #import "GPBDictionary_PackagePrivate.h" -#import "GPBExtensionField.h" -#import "GPBField.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownField.h" #import "GPBUnknownFieldSet.h" static void AppendTextFormatForMessage(GPBMessage *message, @@ -53,6 +52,15 @@ NSData *GPBEmptyNSData(void) { return defaultNSData; } +void GPBCheckRuntimeVersionInternal(int32_t version) { + if (version != GOOGLE_PROTOBUF_OBJC_GEN_VERSION) { + [NSException raise:NSInternalInconsistencyException + format:@"Linked to ProtocolBuffer runtime version %d," + @" but code compiled with version %d!", + GOOGLE_PROTOBUF_OBJC_GEN_VERSION, version]; + } +} + BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) { GPBDescriptor *descriptor = [self descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber]; @@ -166,8 +174,8 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, #pragma mark - IVar accessors //%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE) -//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self, -//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//%TYPE GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { //% if (GPBGetHasIvarField(self, field)) { //% uint8_t *storage = (uint8_t *)self->messageStorage_; //% TYPE *typePtr = (TYPE *)&storage[field->description_->offset]; @@ -178,9 +186,9 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //%} //% //%// Only exists for public api, no core code should use this. -//%void GPBSet##NAME##IvarWithField(GPBMessage *self, -//% NAME$S GPBFieldDescriptor *field, -//% NAME$S TYPE value) { +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE value) { //% if (self == nil || field == nil) return; //% GPBFileSyntax syntax = [self descriptor].file.syntax; //% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax); @@ -211,18 +219,18 @@ void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, //% GPBBecomeVisibleToAutocreator(self); //%} //% -//%PDDM-DEFINE IVAR_ALIAS_DEFN(NAME, ALIAS_NAME, TYPE, ALIAS_TYPE) +//%PDDM-DEFINE IVAR_ALIAS_DEFN_OBJECT(NAME, TYPE) //%// Only exists for public api, no core code should use this. -//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self, -//% TYPE$S NAME$S GPBFieldDescriptor *field) { -//% return (TYPE)GPBGet##ALIAS_NAME##IvarWithField(self, field); +//%TYPE *GPBGetMessage##NAME##Field(GPBMessage *self, +//% TYPE$S NAME$S GPBFieldDescriptor *field) { +//% return (TYPE *)GPBGetObjectIvarWithField(self, field); //%} //% //%// Only exists for public api, no core code should use this. -//%void GPBSet##NAME##IvarWithField(GPBMessage *self, -//% NAME$S GPBFieldDescriptor *field, -//% NAME$S TYPE value) { -//% GPBSet##ALIAS_NAME##IvarWithField(self, field, (ALIAS_TYPE)value); +//%void GPBSetMessage##NAME##Field(GPBMessage *self, +//% NAME$S GPBFieldDescriptor *field, +//% NAME$S TYPE *value) { +//% GPBSetObjectIvarWithField(self, field, (id)value); //%} //% @@ -252,8 +260,8 @@ void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, } // This exists only for briging some aliased types, nothing else should use it. -GPB_INLINE void GPBSetObjectIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, id value) { +static void GPBSetObjectIvarWithField(GPBMessage *self, + GPBFieldDescriptor *field, id value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain], @@ -276,9 +284,9 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, #if defined(__clang_analyzer__) if (self->messageStorage_ == NULL) return; #endif - GPBType fieldType = GPBGetFieldType(field); + GPBDataType fieldType = GPBGetFieldDataType(field); BOOL isMapOrArray = GPBFieldIsMapOrArray(field); - BOOL fieldIsMessage = GPBTypeIsMessage(fieldType); + BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType); #ifdef DEBUG if (value == nil && !isMapOrArray && !fieldIsMessage && field.hasDefaultValue) { @@ -294,7 +302,7 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, // field, and fall back on the default value. The warning below will only // appear in debug, but the could should be changed so the intention is // clear. - NSString *hasSel = NSStringFromSelector(field->hasSel_); + NSString *hasSel = NSStringFromSelector(field->hasOrCountSel_); NSString *propName = field.name; NSString *className = self.descriptor.name; NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with " @@ -302,7 +310,7 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, @"empty, or call '%@.%@ = NO' to reset it to it's default value of " @"'%@'. Defaulting to resetting default value.", className, propName, className, propName, - (fieldType == GPBTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", + (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", className, hasSel, field.defaultValue.valueString); // Note: valueString, depending on the type, it could easily be // valueData/valueMessage. @@ -317,9 +325,9 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, } // Clear "has" if they are being set to nil. BOOL setHasValue = (value != nil); - // Under proto3, Data & String fields get cleared by resetting them to their - // default (empty) values, so if they are set to something of length zero, - // they are being cleared. + // Under proto3, Bytes & String fields get cleared by resetting them to + // their default (empty) values, so if they are set to something of length + // zero, they are being cleared. if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage && ([value length] == 0)) { setHasValue = NO; @@ -338,7 +346,7 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, if (isMapOrArray) { if (field.fieldType == GPBFieldTypeRepeated) { // If the old array was autocreated by us, then clear it. - if (GPBTypeIsObject(fieldType)) { + if (GPBDataTypeIsObject(fieldType)) { GPBAutocreatedArray *autoArray = oldValue; if (autoArray->_autocreator == self) { autoArray->_autocreator = nil; @@ -352,8 +360,8 @@ void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self, } } else { // GPBFieldTypeMap // If the old map was autocreated by us, then clear it. - if ((field.mapKeyType == GPBTypeString) && - GPBTypeIsObject(fieldType)) { + if ((field.mapKeyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(fieldType)) { GPBAutocreatedDictionary *autoDict = oldValue; if (autoDict->_autocreator == self) { autoDict->_autocreator = nil; @@ -399,7 +407,7 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { // Not set... // Non messages (string/data), get their default. - if (!GPBFieldTypeIsMessage(field)) { + if (!GPBFieldDataTypeIsMessage(field)) { return field.defaultValue.valueMessage; } @@ -417,7 +425,7 @@ id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { } // Only exists for public api, no core code should use this. -int32_t GPBGetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { +int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) { GPBFileSyntax syntax = [self descriptor].file.syntax; return GPBGetEnumIvarWithFieldInternal(self, field, syntax); } @@ -425,9 +433,9 @@ int32_t GPBGetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) { int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax) { - int32_t result = GPBGetInt32IvarWithField(self, field); - // If this is presevering unknown enums, make sure the value is - // valid before returning it. + int32_t result = GPBGetMessageInt32Field(self, field); + // If this is presevering unknown enums, make sure the value is valid before + // returning it. if (GPBHasPreservingUnknownEnumSemantics(syntax) && ![field isValidEnumValue:result]) { result = kGPBUnrecognizedEnumeratorValue; @@ -436,8 +444,8 @@ int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, - int32_t value) { +void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, + int32_t value) { GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); } @@ -454,11 +462,25 @@ void GPBSetEnumIvarWithFieldInternal(GPBMessage *self, GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); } +// Only exists for public api, no core code should use this. +int32_t GPBGetMessageRawEnumField(GPBMessage *self, + GPBFieldDescriptor *field) { + int32_t result = GPBGetMessageInt32Field(self, field); + return result; +} + +// Only exists for public api, no core code should use this. +void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, + int32_t value) { + GPBFileSyntax syntax = [self descriptor].file.syntax; + GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); +} + //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Bool, BOOL) // This block of code is generated, do not edit it directly. -BOOL GPBGetBoolIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { +BOOL GPBGetMessageBoolField(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; BOOL *typePtr = (BOOL *)&storage[field->description_->offset]; @@ -469,9 +491,9 @@ BOOL GPBGetBoolIvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetBoolIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - BOOL value) { +void GPBSetMessageBoolField(GPBMessage *self, + GPBFieldDescriptor *field, + BOOL value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetBoolIvarWithFieldInternal(self, field, value, syntax); @@ -505,8 +527,8 @@ void GPBSetBoolIvarWithFieldInternal(GPBMessage *self, //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t) // This block of code is generated, do not edit it directly. -int32_t GPBGetInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { +int32_t GPBGetMessageInt32Field(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; int32_t *typePtr = (int32_t *)&storage[field->description_->offset]; @@ -517,9 +539,9 @@ int32_t GPBGetInt32IvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value) { +void GPBSetMessageInt32Field(GPBMessage *self, + GPBFieldDescriptor *field, + int32_t value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetInt32IvarWithFieldInternal(self, field, value, syntax); @@ -553,8 +575,8 @@ void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t) // This block of code is generated, do not edit it directly. -uint32_t GPBGetUInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { +uint32_t GPBGetMessageUInt32Field(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset]; @@ -565,9 +587,9 @@ uint32_t GPBGetUInt32IvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetUInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value) { +void GPBSetMessageUInt32Field(GPBMessage *self, + GPBFieldDescriptor *field, + uint32_t value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax); @@ -601,8 +623,8 @@ void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self, //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t) // This block of code is generated, do not edit it directly. -int64_t GPBGetInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { +int64_t GPBGetMessageInt64Field(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; int64_t *typePtr = (int64_t *)&storage[field->description_->offset]; @@ -613,9 +635,9 @@ int64_t GPBGetInt64IvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value) { +void GPBSetMessageInt64Field(GPBMessage *self, + GPBFieldDescriptor *field, + int64_t value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetInt64IvarWithFieldInternal(self, field, value, syntax); @@ -649,8 +671,8 @@ void GPBSetInt64IvarWithFieldInternal(GPBMessage *self, //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t) // This block of code is generated, do not edit it directly. -uint64_t GPBGetUInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { +uint64_t GPBGetMessageUInt64Field(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset]; @@ -661,9 +683,9 @@ uint64_t GPBGetUInt64IvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetUInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value) { +void GPBSetMessageUInt64Field(GPBMessage *self, + GPBFieldDescriptor *field, + uint64_t value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax); @@ -697,8 +719,8 @@ void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self, //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float) // This block of code is generated, do not edit it directly. -float GPBGetFloatIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { +float GPBGetMessageFloatField(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; float *typePtr = (float *)&storage[field->description_->offset]; @@ -709,9 +731,9 @@ float GPBGetFloatIvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetFloatIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - float value) { +void GPBSetMessageFloatField(GPBMessage *self, + GPBFieldDescriptor *field, + float value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetFloatIvarWithFieldInternal(self, field, value, syntax); @@ -745,8 +767,8 @@ void GPBSetFloatIvarWithFieldInternal(GPBMessage *self, //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double) // This block of code is generated, do not edit it directly. -double GPBGetDoubleIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { +double GPBGetMessageDoubleField(GPBMessage *self, + GPBFieldDescriptor *field) { if (GPBGetHasIvarField(self, field)) { uint8_t *storage = (uint8_t *)self->messageStorage_; double *typePtr = (double *)&storage[field->description_->offset]; @@ -757,9 +779,9 @@ double GPBGetDoubleIvarWithField(GPBMessage *self, } // Only exists for public api, no core code should use this. -void GPBSetDoubleIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - double value) { +void GPBSetMessageDoubleField(GPBMessage *self, + GPBFieldDescriptor *field, + double value) { if (self == nil || field == nil) return; GPBFileSyntax syntax = [self descriptor].file.syntax; GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax); @@ -794,223 +816,225 @@ void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self, // Aliases are function calls that are virtually the same. -//%PDDM-EXPAND IVAR_ALIAS_DEFN(SInt32, Int32, int32_t, int32_t) -// This block of code is generated, do not edit it directly. - -// Only exists for public api, no core code should use this. -int32_t GPBGetSInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (int32_t)GPBGetInt32IvarWithField(self, field); -} - -// Only exists for public api, no core code should use this. -void GPBSetSInt32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value) { - GPBSetInt32IvarWithField(self, field, (int32_t)value); -} - -//%PDDM-EXPAND IVAR_ALIAS_DEFN(SFixed32, Int32, int32_t, int32_t) -// This block of code is generated, do not edit it directly. - -// Only exists for public api, no core code should use this. -int32_t GPBGetSFixed32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (int32_t)GPBGetInt32IvarWithField(self, field); -} - -// Only exists for public api, no core code should use this. -void GPBSetSFixed32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int32_t value) { - GPBSetInt32IvarWithField(self, field, (int32_t)value); -} - -//%PDDM-EXPAND IVAR_ALIAS_DEFN(Fixed32, UInt32, uint32_t, uint32_t) -// This block of code is generated, do not edit it directly. - -// Only exists for public api, no core code should use this. -uint32_t GPBGetFixed32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (uint32_t)GPBGetUInt32IvarWithField(self, field); -} - -// Only exists for public api, no core code should use this. -void GPBSetFixed32IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint32_t value) { - GPBSetUInt32IvarWithField(self, field, (uint32_t)value); -} - -//%PDDM-EXPAND IVAR_ALIAS_DEFN(SInt64, Int64, int64_t, int64_t) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(String, NSString) // This block of code is generated, do not edit it directly. // Only exists for public api, no core code should use this. -int64_t GPBGetSInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (int64_t)GPBGetInt64IvarWithField(self, field); -} - -// Only exists for public api, no core code should use this. -void GPBSetSInt64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value) { - GPBSetInt64IvarWithField(self, field, (int64_t)value); -} - -//%PDDM-EXPAND IVAR_ALIAS_DEFN(SFixed64, Int64, int64_t, int64_t) -// This block of code is generated, do not edit it directly. - -// Only exists for public api, no core code should use this. -int64_t GPBGetSFixed64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (int64_t)GPBGetInt64IvarWithField(self, field); +NSString *GPBGetMessageStringField(GPBMessage *self, + GPBFieldDescriptor *field) { + return (NSString *)GPBGetObjectIvarWithField(self, field); } // Only exists for public api, no core code should use this. -void GPBSetSFixed64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - int64_t value) { - GPBSetInt64IvarWithField(self, field, (int64_t)value); +void GPBSetMessageStringField(GPBMessage *self, + GPBFieldDescriptor *field, + NSString *value) { + GPBSetObjectIvarWithField(self, field, (id)value); } -//%PDDM-EXPAND IVAR_ALIAS_DEFN(Fixed64, UInt64, uint64_t, uint64_t) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Bytes, NSData) // This block of code is generated, do not edit it directly. // Only exists for public api, no core code should use this. -uint64_t GPBGetFixed64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (uint64_t)GPBGetUInt64IvarWithField(self, field); +NSData *GPBGetMessageBytesField(GPBMessage *self, + GPBFieldDescriptor *field) { + return (NSData *)GPBGetObjectIvarWithField(self, field); } // Only exists for public api, no core code should use this. -void GPBSetFixed64IvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - uint64_t value) { - GPBSetUInt64IvarWithField(self, field, (uint64_t)value); +void GPBSetMessageBytesField(GPBMessage *self, + GPBFieldDescriptor *field, + NSData *value) { + GPBSetObjectIvarWithField(self, field, (id)value); } -//%PDDM-EXPAND IVAR_ALIAS_DEFN(String, Object, NSString*, id) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage) // This block of code is generated, do not edit it directly. // Only exists for public api, no core code should use this. -NSString* GPBGetStringIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (NSString*)GPBGetObjectIvarWithField(self, field); +GPBMessage *GPBGetMessageMessageField(GPBMessage *self, + GPBFieldDescriptor *field) { + return (GPBMessage *)GPBGetObjectIvarWithField(self, field); } // Only exists for public api, no core code should use this. -void GPBSetStringIvarWithField(GPBMessage *self, +void GPBSetMessageMessageField(GPBMessage *self, GPBFieldDescriptor *field, - NSString* value) { + GPBMessage *value) { GPBSetObjectIvarWithField(self, field, (id)value); } -//%PDDM-EXPAND IVAR_ALIAS_DEFN(Data, Object, NSData*, id) +//%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage) // This block of code is generated, do not edit it directly. // Only exists for public api, no core code should use this. -NSData* GPBGetDataIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (NSData*)GPBGetObjectIvarWithField(self, field); +GPBMessage *GPBGetMessageGroupField(GPBMessage *self, + GPBFieldDescriptor *field) { + return (GPBMessage *)GPBGetObjectIvarWithField(self, field); } // Only exists for public api, no core code should use this. -void GPBSetDataIvarWithField(GPBMessage *self, +void GPBSetMessageGroupField(GPBMessage *self, GPBFieldDescriptor *field, - NSData* value) { + GPBMessage *value) { GPBSetObjectIvarWithField(self, field, (id)value); } -//%PDDM-EXPAND IVAR_ALIAS_DEFN(Message, Object, GPBMessage*, id) -// This block of code is generated, do not edit it directly. +//%PDDM-EXPAND-END (4 expansions) // Only exists for public api, no core code should use this. -GPBMessage* GPBGetMessageIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (GPBMessage*)GPBGetObjectIvarWithField(self, field); +id GPBGetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field) { +#if DEBUG + if (field.fieldType != GPBFieldTypeRepeated) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a repeated field.", + [self class], field.name]; + } +#endif + return GPBGetObjectIvarWithField(self, field); } // Only exists for public api, no core code should use this. -void GPBSetMessageIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBMessage* value) { - GPBSetObjectIvarWithField(self, field, (id)value); +void GPBSetMessageRepeatedField(GPBMessage *self, GPBFieldDescriptor *field, id array) { +#if DEBUG + if (field.fieldType != GPBFieldTypeRepeated) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a repeated field.", + [self class], field.name]; + } + Class expectedClass = Nil; + switch (GPBGetFieldDataType(field)) { + case GPBDataTypeBool: + expectedClass = [GPBBoolArray class]; + break; + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + expectedClass = [GPBInt32Array class]; + break; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + expectedClass = [GPBUInt32Array class]; + break; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + expectedClass = [GPBInt64Array class]; + break; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + expectedClass = [GPBUInt64Array class]; + break; + case GPBDataTypeFloat: + expectedClass = [GPBFloatArray class]; + break; + case GPBDataTypeDouble: + expectedClass = [GPBDoubleArray class]; + break; + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + expectedClass = [NSMutableDictionary class]; + break; + case GPBDataTypeEnum: + expectedClass = [GPBBoolArray class]; + break; + } + if (array && ![array isKindOfClass:expectedClass]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Expected %@ object, got %@.", + [self class], field.name, expectedClass, [array class]]; + } +#endif + GPBSetObjectIvarWithField(self, field, array); +} + +#if DEBUG +static NSString *TypeToStr(GPBDataType dataType) { + switch (dataType) { + case GPBDataTypeBool: + return @"Bool"; + case GPBDataTypeSFixed32: + case GPBDataTypeInt32: + case GPBDataTypeSInt32: + return @"Int32"; + case GPBDataTypeFixed32: + case GPBDataTypeUInt32: + return @"UInt32"; + case GPBDataTypeSFixed64: + case GPBDataTypeInt64: + case GPBDataTypeSInt64: + return @"Int64"; + case GPBDataTypeFixed64: + case GPBDataTypeUInt64: + return @"UInt64"; + case GPBDataTypeFloat: + return @"Float"; + case GPBDataTypeDouble: + return @"Double"; + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: + return @"Object"; + case GPBDataTypeEnum: + return @"Bool"; + } } - -//%PDDM-EXPAND IVAR_ALIAS_DEFN(Group, Object, GPBMessage*, id) -// This block of code is generated, do not edit it directly. +#endif // Only exists for public api, no core code should use this. -GPBMessage* GPBGetGroupIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field) { - return (GPBMessage*)GPBGetObjectIvarWithField(self, field); +id GPBGetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field) { +#if DEBUG + if (field.fieldType != GPBFieldTypeMap) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a map<> field.", + [self class], field.name]; + } +#endif + return GPBGetObjectIvarWithField(self, field); } // Only exists for public api, no core code should use this. -void GPBSetGroupIvarWithField(GPBMessage *self, - GPBFieldDescriptor *field, - GPBMessage* value) { - GPBSetObjectIvarWithField(self, field, (id)value); -} - -//%PDDM-EXPAND-END (10 expansions) - -#pragma mark - Misc Dynamic Runtime Utils - -void GPBApplyFunctionsToMessageFields(GPBApplyFunctions *functions, - GPBMessage *msg, void *context) { - GPBDescriptor *descriptor = [[msg class] descriptor]; - for (GPBFieldDescriptor *field in descriptor->fields_) { - BOOL wasGood; - if (GPBFieldIsMapOrArray(field)) { - wasGood = (*functions)[GPBApplyFunctionObject](field, context); +void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, + id dictionary) { +#if DEBUG + if (field.fieldType != GPBFieldTypeMap) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@ is not a map<> field.", + [self class], field.name]; + } + if (dictionary) { + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + NSString *keyStr = TypeToStr(keyDataType); + NSString *valueStr = TypeToStr(valueDataType); + if (keyDataType == GPBDataTypeString) { + keyStr = @"String"; + } + Class expectedClass = Nil; + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { + expectedClass = [NSMutableDictionary class]; } else { - wasGood = GPBApplyFunctionsBasedOnField(field, functions, context); + NSString *className = + [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr]; + expectedClass = NSClassFromString(className); + NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass); } - if (!wasGood) { - break; + if (![dictionary isKindOfClass:expectedClass]) { + [NSException raise:NSInvalidArgumentException + format:@"%@.%@: Expected %@ object, got %@.", + [self class], field.name, expectedClass, + [dictionary class]]; } } +#endif + GPBSetObjectIvarWithField(self, field, dictionary); } -BOOL GPBApplyFunctionsBasedOnField(GPBFieldDescriptor *field, - GPBApplyFunctions *functions, - void *context) { - static const GPBApplyFunctionOrder typeMap[GPBTypeCount] = { - GPBApplyFunctionBool, - GPBApplyFunctionUInt32, - GPBApplyFunctionInt32, - GPBApplyFunctionFloat, - GPBApplyFunctionUInt64, - GPBApplyFunctionInt64, - GPBApplyFunctionDouble, - GPBApplyFunctionInt32, - GPBApplyFunctionInt64, - GPBApplyFunctionInt32, - GPBApplyFunctionInt64, - GPBApplyFunctionUInt32, - GPBApplyFunctionUInt64, - GPBApplyFunctionObject, - GPBApplyFunctionObject, - GPBApplyFunctionObject, - GPBApplyFunctionObject, - GPBApplyFunctionInt32 - }; - return (*functions)[typeMap[GPBGetFieldType(field)]](field, context); -} - -void GPBApplyStrictFunctionsToMessageFields(GPBApplyStrictFunctions *functions, - GPBMessage *msg, void *context) { - GPBDescriptor *descriptor = [[msg class] descriptor]; - for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) { - GPBApplyFunction function = (*functions)[GPBGetFieldType(fieldDescriptor)]; - BOOL wasGood = function(fieldDescriptor, context); - if (!wasGood) { - break; - } - } -} +#pragma mark - Misc Dynamic Runtime Utils const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) { Protocol *protocol = @@ -1072,9 +1096,9 @@ static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) { static void AppendTextFormatForMapMessageField( id map, GPBFieldDescriptor *field, NSMutableString *toStr, NSString *lineIndent, NSString *fieldName, NSString *lineEnding) { - GPBType keyType = field.mapKeyType; - GPBType valueType = GPBGetFieldType(field); - BOOL isMessageValue = GPBTypeIsMessage(valueType); + GPBDataType keyDataType = field.mapKeyDataType; + GPBDataType valueDataType = GPBGetFieldDataType(field); + BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType); NSString *msgStartFirst = [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding]; @@ -1088,7 +1112,8 @@ static void AppendTextFormatForMapMessageField( __block BOOL isFirst = YES; - if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) { + if ((keyDataType == GPBDataTypeString) && + GPBDataTypeIsObject(valueDataType)) { // map is an NSDictionary. NSDictionary *dict = map; [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) { @@ -1101,16 +1126,16 @@ static void AppendTextFormatForMapMessageField( [toStr appendString:@"\n"]; [toStr appendString:valueLine]; - switch (valueType) { - case GPBTypeString: + switch (valueDataType) { + case GPBDataTypeString: AppendStringEscaped(value, toStr); break; - case GPBTypeData: + case GPBDataTypeBytes: AppendBufferAsString(value, toStr); break; - case GPBTypeMessage: + case GPBDataTypeMessage: [toStr appendString:@"{\n"]; NSString *subIndent = [lineIndent stringByAppendingString:@" "]; AppendTextFormatForMessage(value, toStr, subIndent); @@ -1133,7 +1158,7 @@ static void AppendTextFormatForMapMessageField( isFirst = NO; // Key always is a NSString. - if (keyType == GPBTypeString) { + if (keyDataType == GPBDataTypeString) { [toStr appendString:keyLine]; AppendStringEscaped(keyObj, toStr); [toStr appendString:@"\n"]; @@ -1142,23 +1167,23 @@ static void AppendTextFormatForMapMessageField( } [toStr appendString:valueLine]; - switch (valueType) { - case GPBTypeString: + switch (valueDataType) { + case GPBDataTypeString: AppendStringEscaped(valueObj, toStr); break; - case GPBTypeData: + case GPBDataTypeBytes: AppendBufferAsString(valueObj, toStr); break; - case GPBTypeMessage: + case GPBDataTypeMessage: [toStr appendString:@"{\n"]; NSString *subIndent = [lineIndent stringByAppendingString:@" "]; AppendTextFormatForMessage(valueObj, toStr, subIndent); [toStr appendFormat:@"%@ }", lineIndent]; break; - case GPBTypeEnum: { + case GPBDataTypeEnum: { int32_t enumValue = [valueObj intValue]; NSString *valueStr = nil; GPBEnumDescriptor *descriptor = field.enumDescriptor; @@ -1174,7 +1199,7 @@ static void AppendTextFormatForMapMessageField( } default: - NSCAssert(valueType != GPBTypeGroup, @"Can't happen"); + NSCAssert(valueDataType != GPBDataTypeGroup, @"Can't happen"); // Everything else is a NSString. [toStr appendString:valueObj]; break; @@ -1245,8 +1270,8 @@ static void AppendTextFormatForMessageField(GPBMessage *message, id array = arrayOrMap; const BOOL isRepeated = (array != nil); - GPBType fieldDataType = GPBGetFieldType(field); - BOOL isMessageField = GPBTypeIsMessage(fieldDataType); + GPBDataType fieldDataType = GPBGetFieldDataType(field); + BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType); for (NSUInteger j = 0; j < count; ++j) { // Start the line. [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, @@ -1254,12 +1279,12 @@ static void AppendTextFormatForMessageField(GPBMessage *message, // The value. switch (fieldDataType) { -#define FIELD_CASE(GPBTYPE, CTYPE, ARRAY_TYPE, ...) \ - case GPBType##GPBTYPE: { \ - CTYPE v = (isRepeated ? [(GPB##ARRAY_TYPE##Array *)array valueAtIndex:j] \ - : GPBGet##GPBTYPE##IvarWithField(message, field)); \ - [toStr appendFormat:__VA_ARGS__, v]; \ - break; \ +#define FIELD_CASE(GPBDATATYPE, CTYPE, REAL_TYPE, ...) \ + case GPBDataType##GPBDATATYPE: { \ + CTYPE v = (isRepeated ? [(GPB##REAL_TYPE##Array *)array valueAtIndex:j] \ + : GPBGetMessage##REAL_TYPE##Field(message, field)); \ + [toStr appendFormat:__VA_ARGS__, v]; \ + break; \ } FIELD_CASE(Int32, int32_t, Int32, @"%d") @@ -1277,9 +1302,9 @@ static void AppendTextFormatForMessageField(GPBMessage *message, #undef FIELD_CASE - case GPBTypeEnum: { + case GPBDataTypeEnum: { int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j] - : GPBGetInt32IvarWithField(message, field)); + : GPBGetMessageInt32Field(message, field)); NSString *valueStr = nil; GPBEnumDescriptor *descriptor = field.enumDescriptor; if (descriptor) { @@ -1293,29 +1318,29 @@ static void AppendTextFormatForMessageField(GPBMessage *message, break; } - case GPBTypeBool: { + case GPBDataTypeBool: { BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j] - : GPBGetBoolIvarWithField(message, field)); + : GPBGetMessageBoolField(message, field)); [toStr appendString:(v ? @"true" : @"false")]; break; } - case GPBTypeString: { + case GPBDataTypeString: { NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] - : GPBGetStringIvarWithField(message, field)); + : GPBGetMessageStringField(message, field)); AppendStringEscaped(v, toStr); break; } - case GPBTypeData: { + case GPBDataTypeBytes: { NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] - : GPBGetDataIvarWithField(message, field)); + : GPBGetMessageBytesField(message, field)); AppendBufferAsString(v, toStr); break; } - case GPBTypeGroup: - case GPBTypeMessage: { + case GPBDataTypeGroup: + case GPBDataTypeMessage: { GPBMessage *v = (isRepeated ? [(NSArray *)array objectAtIndex:j] : GPBGetObjectIvarWithField(message, field)); @@ -1342,7 +1367,7 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, NSString *lineIndent) { uint32_t start = range.start; uint32_t end = range.end; - for (GPBExtensionField *extension in activeExtensions) { + for (GPBExtensionDescriptor *extension in activeExtensions) { uint32_t fieldNumber = extension.fieldNumber; if (fieldNumber < start) { // Not there yet. @@ -1354,8 +1379,7 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, } id rawExtValue = [message getExtension:extension]; - GPBExtensionDescriptor *extDescriptor = [extension descriptor]; - BOOL isRepeated = extDescriptor.isRepeated; + BOOL isRepeated = extension.isRepeated; NSUInteger numValues = 1; NSString *lineEnding = @""; @@ -1363,28 +1387,28 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, numValues = [(NSArray *)rawExtValue count]; } - NSString *singletonName = extension.descriptor.singletonName; + NSString *singletonName = extension.singletonName; if (numValues == 1) { lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName]; } else { [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName]; } - GPBType extType = extDescriptor.type; + GPBDataType extDataType = extension.dataType; for (NSUInteger j = 0; j < numValues; ++j) { id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue); // Start the line. [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber, - (GPBTypeIsMessage(extType) ? "" : ":")]; + (GPBDataTypeIsMessage(extDataType) ? "" : ":")]; // The value. - switch (extType) { -#define FIELD_CASE(GPBTYPE, CTYPE, NUMSELECTOR, ...) \ - case GPBType##GPBTYPE: { \ - CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \ - [toStr appendFormat:__VA_ARGS__, v]; \ - break; \ + switch (extDataType) { +#define FIELD_CASE(GPBDATATYPE, CTYPE, NUMSELECTOR, ...) \ + case GPBDataType##GPBDATATYPE: { \ + CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \ + [toStr appendFormat:__VA_ARGS__, v]; \ + break; \ } FIELD_CASE(Int32, int32_t, intValue, @"%d") @@ -1408,21 +1432,21 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, #undef FIELD_CASE - case GPBTypeBool: + case GPBDataTypeBool: [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true" : @"false")]; break; - case GPBTypeString: + case GPBDataTypeString: AppendStringEscaped(curValue, toStr); break; - case GPBTypeData: + case GPBDataTypeBytes: AppendBufferAsString((NSData *)curValue, toStr); break; - case GPBTypeGroup: - case GPBTypeMessage: { + case GPBDataTypeGroup: + case GPBDataTypeMessage: { [toStr appendFormat:@"{%@\n", lineEnding]; NSString *subIndent = [lineIndent stringByAppendingString:@" "]; AppendTextFormatForMessage(curValue, toStr, subIndent); @@ -1431,7 +1455,7 @@ static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, break; } - } // switch(extType) + } // switch(extDataType) } // for(numValues) @@ -1487,7 +1511,7 @@ NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, if (lineIndent == nil) lineIndent = @""; NSMutableString *result = [NSMutableString string]; - for (GPBField *field in [unknownSet sortedFields]) { + for (GPBUnknownField *field in [unknownSet sortedFields]) { int32_t fieldNumber = [field number]; #define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \ @@ -1527,13 +1551,13 @@ NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, // Helpers to decode a varint. Not using GPBCodedInputStream version because // that needs a state object, and we don't want to create an input stream out // of the data. -static inline int8_t ReadRawByteFromData(const uint8_t **data) { +GPB_INLINE int8_t ReadRawByteFromData(const uint8_t **data) { int8_t result = *((int8_t *)(*data)); ++(*data); return result; } -static inline int32_t ReadRawVarint32FromData(const uint8_t **data) { +static int32_t ReadRawVarint32FromData(const uint8_t **data) { int8_t tmp = ReadRawByteFromData(data); if (tmp >= 0) { return tmp; diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h index 1481d071..cac551f6 100644 --- a/objectivec/GPBUtilities_PackagePrivate.h +++ b/objectivec/GPBUtilities_PackagePrivate.h @@ -48,6 +48,15 @@ CF_EXTERN_C_BEGIN +// These two are used to inject a runtime check for version mismatch into the +// generated sources to make sure they are linked with a supporting runtime. +void GPBCheckRuntimeVersionInternal(int32_t version); +GPB_INLINE void GPBDebugCheckRuntimeVersion() { +#if DEBUG + GPBCheckRuntimeVersionInternal(GOOGLE_PROTOBUF_OBJC_GEN_VERSION); +#endif +} + // Conversion functions for de/serializing floating point types. GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) { @@ -116,40 +125,38 @@ GPB_INLINE uint64_t GPBEncodeZigZag64(int64_t n) { return (n << 1) ^ (n >> 63); } -GPB_INLINE BOOL GPBTypeIsObject(GPBType type) { +GPB_INLINE BOOL GPBDataTypeIsObject(GPBDataType type) { switch (type) { - case GPBTypeData: - case GPBTypeString: - case GPBTypeMessage: - case GPBTypeGroup: + case GPBDataTypeBytes: + case GPBDataTypeString: + case GPBDataTypeMessage: + case GPBDataTypeGroup: return YES; default: return NO; } } -GPB_INLINE BOOL GPBTypeIsMessage(GPBType type) { +GPB_INLINE BOOL GPBDataTypeIsMessage(GPBDataType type) { switch (type) { - case GPBTypeMessage: - case GPBTypeGroup: + case GPBDataTypeMessage: + case GPBDataTypeGroup: return YES; default: return NO; } } -GPB_INLINE BOOL GPBTypeIsEnum(GPBType type) { return type == GPBTypeEnum; } - -GPB_INLINE BOOL GPBFieldTypeIsMessage(GPBFieldDescriptor *field) { - return GPBTypeIsMessage(field->description_->type); +GPB_INLINE BOOL GPBFieldDataTypeIsMessage(GPBFieldDescriptor *field) { + return GPBDataTypeIsMessage(field->description_->dataType); } -GPB_INLINE BOOL GPBFieldTypeIsObject(GPBFieldDescriptor *field) { - return GPBTypeIsObject(field->description_->type); +GPB_INLINE BOOL GPBFieldDataTypeIsObject(GPBFieldDescriptor *field) { + return GPBDataTypeIsObject(field->description_->dataType); } GPB_INLINE BOOL GPBExtensionIsMessage(GPBExtensionDescriptor *ext) { - return GPBTypeIsMessage(ext->description_->type); + return GPBDataTypeIsMessage(ext->description_->dataType); } // The field is an array/map or it has an object value. @@ -158,7 +165,7 @@ GPB_INLINE BOOL GPBFieldStoresObject(GPBFieldDescriptor *field) { if ((desc->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0) { return YES; } - return GPBTypeIsObject(desc->type); + return GPBDataTypeIsObject(desc->dataType); } BOOL GPBGetHasIvar(GPBMessage *self, int32_t index, uint32_t fieldNumber); @@ -272,109 +279,6 @@ void GPBSetAutocreatedRetainedObjectIvarWithField( void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, GPBFieldDescriptor *field); -// Utilities for applying various functions based on Objective C types. - -// A basic functor that is passed a field and a context. Returns YES -// if the calling function should continue processing, and NO if the calling -// function should stop processing. -typedef BOOL (*GPBApplyFunction)(GPBFieldDescriptor *field, void *context); - -// Functions called for various types. See ApplyFunctionsToMessageFields. -typedef enum { - GPBApplyFunctionObject, - GPBApplyFunctionBool, - GPBApplyFunctionInt32, - GPBApplyFunctionUInt32, - GPBApplyFunctionInt64, - GPBApplyFunctionUInt64, - GPBApplyFunctionFloat, - GPBApplyFunctionDouble, -} GPBApplyFunctionOrder; - -enum { - // A count of the number of types in GPBApplyFunctionOrder. Separated out - // from the GPBApplyFunctionOrder enum to avoid warnings regarding not - // handling GPBApplyFunctionCount in switch statements. - GPBApplyFunctionCount = GPBApplyFunctionDouble + 1 -}; - -typedef GPBApplyFunction GPBApplyFunctions[GPBApplyFunctionCount]; - -// Functions called for various types. -// See ApplyStrictFunctionsToMessageFields. -// They are in the same order as the GPBTypes enum. -typedef GPBApplyFunction GPBApplyStrictFunctions[GPBTypeCount]; - -// A macro for easily initializing a GPBApplyFunctions struct -// GPBApplyFunctions foo = GPBAPPLY_FUNCTIONS_INIT(Foo); -#define GPBAPPLY_FUNCTIONS_INIT(PREFIX) \ - { \ - PREFIX##Object, \ - PREFIX##Bool, \ - PREFIX##Int32, \ - PREFIX##UInt32, \ - PREFIX##Int64, \ - PREFIX##UInt64, \ - PREFIX##Float, \ - PREFIX##Double, \ - } - -// A macro for easily initializing a GPBApplyStrictFunctions struct -// GPBApplyStrictFunctions foo = GPBAPPLY_STRICT_FUNCTIONS_INIT(Foo); -// These need to stay in the same order as -// the GPBType enum. -#define GPBAPPLY_STRICT_FUNCTIONS_INIT(PREFIX) \ - { \ - PREFIX##Bool, \ - PREFIX##Fixed32, \ - PREFIX##SFixed32, \ - PREFIX##Float, \ - PREFIX##Fixed64, \ - PREFIX##SFixed64, \ - PREFIX##Double, \ - PREFIX##Int32, \ - PREFIX##Int64, \ - PREFIX##SInt32, \ - PREFIX##SInt64, \ - PREFIX##UInt32, \ - PREFIX##UInt64, \ - PREFIX##Data, \ - PREFIX##String, \ - PREFIX##Message, \ - PREFIX##Group, \ - PREFIX##Enum, \ -} - -// Iterates over the fields of a proto |msg| and applies the functions in -// |functions| to them with |context|. If one of the functions in |functions| -// returns NO, it will return immediately and not process the rest of the -// ivars. The types in the fields are mapped so: -// Int32, Enum, SInt32 and SFixed32 will be mapped to the int32Function, -// UInt32 and Fixed32 will be mapped to the uint32Function, -// Bytes, String, Message and Group will be mapped to the objectFunction, -// etc.. -// If you require more specific mappings look at -// GPBApplyStrictFunctionsToMessageFields. -void GPBApplyFunctionsToMessageFields(GPBApplyFunctions *functions, - GPBMessage *msg, void *context); - -// Iterates over the fields of a proto |msg| and applies the functions in -// |functions| to them with |context|. If one of the functions in |functions| -// returns NO, it will return immediately and not process the rest of the -// ivars. The types in the fields are mapped directly: -// Int32 -> functions[GPBTypeInt32], -// SFixed32 -> functions[GPBTypeSFixed32], -// etc... -// If you can use looser mappings look at GPBApplyFunctionsToMessageFields. -void GPBApplyStrictFunctionsToMessageFields(GPBApplyStrictFunctions *functions, - GPBMessage *msg, void *context); - -// Applies the appropriate function in |functions| based on |field|. -// Returns the value from function(name, context). -// Throws an exception if the type is unrecognized. -BOOL GPBApplyFunctionsBasedOnField(GPBFieldDescriptor *field, - GPBApplyFunctions *functions, void *context); - // Returns an Objective C encoding for |selector|. |instanceSel| should be // YES if it's an instance selector (as opposed to a class selector). // |selector| must be a selector from MessageSignatureProtocol. @@ -410,7 +314,7 @@ GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SInt32) GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SInt64) GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, UInt32) GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, UInt64) -GPB_MESSAGE_SIGNATURE_ENTRY(NSData *, Data) +GPB_MESSAGE_SIGNATURE_ENTRY(NSData *, Bytes) GPB_MESSAGE_SIGNATURE_ENTRY(NSString *, String) GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Message) GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Group) @@ -419,6 +323,7 @@ GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Enum) #undef GPB_MESSAGE_SIGNATURE_ENTRY - (id)getArray; +- (NSUInteger)getArrayCount; - (void)setArray:(NSArray *)array; + (id)getClassValue; @end diff --git a/objectivec/GPBWireFormat.h b/objectivec/GPBWireFormat.h index 55f2edfc..45089bd0 100644 --- a/objectivec/GPBWireFormat.h +++ b/objectivec/GPBWireFormat.h @@ -28,7 +28,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -#import "GPBTypes.h" +#import "GPBRuntimeTypes.h" CF_EXTERN_C_BEGIN @@ -52,7 +52,7 @@ uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType) GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) __attribute__((const)); uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) __attribute__((const)); -GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked) +GPBWireFormat GPBWireFormatForType(GPBDataType dataType, BOOL isPacked) __attribute__((const)); #define GPBWireFormatMessageSetItemTag \ diff --git a/objectivec/GPBWireFormat.m b/objectivec/GPBWireFormat.m index 7435221f..193235d6 100644 --- a/objectivec/GPBWireFormat.m +++ b/objectivec/GPBWireFormat.m @@ -49,30 +49,30 @@ uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) { return GPBLogicalRightShift32(tag, GPBWireFormatTagTypeBits); } -GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked) { +GPBWireFormat GPBWireFormatForType(GPBDataType type, BOOL isPacked) { if (isPacked) { return GPBWireFormatLengthDelimited; } - static const GPBWireFormat format[GPBTypeCount] = { - GPBWireFormatVarint, // GPBTypeBool - GPBWireFormatFixed32, // GPBTypeFixed32 - GPBWireFormatFixed32, // GPBTypeSFixed32 - GPBWireFormatFixed32, // GPBTypeFloat - GPBWireFormatFixed64, // GPBTypeFixed64 - GPBWireFormatFixed64, // GPBTypeSFixed64 - GPBWireFormatFixed64, // GPBTypeDouble - GPBWireFormatVarint, // GPBTypeInt32 - GPBWireFormatVarint, // GPBTypeInt64 - GPBWireFormatVarint, // GPBTypeSInt32 - GPBWireFormatVarint, // GPBTypeSInt64 - GPBWireFormatVarint, // GPBTypeUInt32 - GPBWireFormatVarint, // GPBTypeUInt64 - GPBWireFormatLengthDelimited, // GPBTypeBytes - GPBWireFormatLengthDelimited, // GPBTypeString - GPBWireFormatLengthDelimited, // GPBTypeMessage - GPBWireFormatStartGroup, // GPBTypeGroup - GPBWireFormatVarint // GPBTypeEnum + static const GPBWireFormat format[GPBDataType_Count] = { + GPBWireFormatVarint, // GPBDataTypeBool + GPBWireFormatFixed32, // GPBDataTypeFixed32 + GPBWireFormatFixed32, // GPBDataTypeSFixed32 + GPBWireFormatFixed32, // GPBDataTypeFloat + GPBWireFormatFixed64, // GPBDataTypeFixed64 + GPBWireFormatFixed64, // GPBDataTypeSFixed64 + GPBWireFormatFixed64, // GPBDataTypeDouble + GPBWireFormatVarint, // GPBDataTypeInt32 + GPBWireFormatVarint, // GPBDataTypeInt64 + GPBWireFormatVarint, // GPBDataTypeSInt32 + GPBWireFormatVarint, // GPBDataTypeSInt64 + GPBWireFormatVarint, // GPBDataTypeUInt32 + GPBWireFormatVarint, // GPBDataTypeUInt64 + GPBWireFormatLengthDelimited, // GPBDataTypeBytes + GPBWireFormatLengthDelimited, // GPBDataTypeString + GPBWireFormatLengthDelimited, // GPBDataTypeMessage + GPBWireFormatStartGroup, // GPBDataTypeGroup + GPBWireFormatVarint // GPBDataTypeEnum }; return format[type]; } diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj index f18ba2f8..b0a0712e 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj @@ -6,20 +6,6 @@ objectVersion = 47; objects = { -/* Begin PBXAggregateTarget section */ - 8BD3981414BE4AE70081D629 /* Compile_Protos */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */; - buildPhases = ( - 8BD3981814BE4AF30081D629 /* ShellScript */, - ); - dependencies = ( - ); - name = Compile_Protos; - productName = Compile_Protos; - }; -/* End PBXAggregateTarget section */ - /* Begin PBXBuildFile section */ 2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */; }; 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */; }; @@ -27,7 +13,7 @@ 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */; }; 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */; }; 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; }; - 7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBField.m */; }; + 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */; }; 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; }; 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; }; 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; }; @@ -51,7 +37,6 @@ 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; }; 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; }; 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; }; - 8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */; }; 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; }; 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC2B1A8D444600FCC765 /* GPBArray.m */; }; @@ -71,8 +56,24 @@ F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */; }; F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */; }; F4487C831AAF6AB300531423 /* GPBMessageTests+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */; }; - F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionField.m */; }; + F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */; }; F45E57C71AE6DC6A000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */; }; + F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; }; + F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; }; + F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; }; + F4E6759D1B21D0000054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */; }; + F4E6759F1B21D0000054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */; }; + F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; }; + F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; }; + F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; }; + F4E675AE1B21D0A70054530B /* Any.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675871B21D0000054530B /* Any.pbobjc.m */; }; + F4E675AF1B21D0A70054530B /* Api.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675891B21D0000054530B /* Api.pbobjc.m */; }; + F4E675B01B21D0A70054530B /* Empty.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758B1B21D0000054530B /* Empty.pbobjc.m */; }; + F4E675B11B21D0A70054530B /* FieldMask.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */; }; + F4E675B21B21D0A70054530B /* SourceContext.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */; }; + F4E675B31B21D0A70054530B /* Struct.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675911B21D0000054530B /* Struct.pbobjc.m */; }; + F4E675B41B21D0A70054530B /* Type.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675931B21D0000054530B /* Type.pbobjc.m */; }; + F4E675B51B21D0A70054530B /* Wrappers.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = F4E675951B21D0000054530B /* Wrappers.pbobjc.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -83,12 +84,12 @@ remoteGlobalIDString = 7461B52D0F94FAF800A0C422; remoteInfo = ProtocolBuffers; }; - 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */ = { + F45BBC181B0CE3D7002D064D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; proxyType = 1; - remoteGlobalIDString = 8BD3981414BE4AE70081D629; - remoteInfo = Compile_Protos; + remoteGlobalIDString = F45BBC141B0CE3C6002D064D; + remoteInfo = "Compile Unittest Protos"; }; /* End PBXContainerItemProxy section */ @@ -106,8 +107,8 @@ 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStream.m; sourceTree = ""; }; 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry.h; sourceTree = ""; }; 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionRegistry.m; sourceTree = ""; }; - 7461B4AE0F94F99000A0C422 /* GPBField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBField.h; sourceTree = ""; }; - 7461B4AF0F94F99000A0C422 /* GPBField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBField.m; sourceTree = ""; }; + 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField.h; sourceTree = ""; }; + 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownField.m; sourceTree = ""; }; 7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = ""; }; 7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = ""; }; 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = ""; }; @@ -126,10 +127,7 @@ 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = ""; }; 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = ""; }; 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = ""; }; - 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField.h; sourceTree = ""; }; 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = ""; }; - 8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter1.txt; sourceTree = ""; }; - 8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_filter.proto; sourceTree = ""; }; 8B210CCD159383D60032D72D /* golden_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_message; sourceTree = ""; }; 8B210CCF159386920032D72D /* golden_packed_fields_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_packed_fields_message; sourceTree = ""; }; 8B4248B81A8C254000BC1EC6 /* protobuf */ = {isa = PBXFileReference; lastKnownFileType = text; name = protobuf; path = ../../Intermediates/ProtocolBuffers_OSX.build/DerivedSources/protos/google/protobuf; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -162,12 +160,11 @@ 8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBStringTests.m; sourceTree = ""; }; 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = ""; }; 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBFilteredMessageTests.m; sourceTree = ""; }; 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = ""; }; 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = ""; }; 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = ""; }; 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Descriptor.pbobjc.m; path = google/protobuf/Descriptor.pbobjc.m; sourceTree = SOURCE_ROOT; }; - 8BEB5AE01498033E0078BF9D /* GPBTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBTypes.h; sourceTree = ""; }; + 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = ""; }; F401DC2A1A8D444600FCC765 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = ""; }; F401DC2B1A8D444600FCC765 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = ""; }; F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = ""; }; @@ -192,16 +189,39 @@ F4487C7C1AAE06AC00531423 /* GPBUtilities_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUtilities_PackagePrivate.h; sourceTree = ""; }; F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = ""; }; F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = ""; }; - F44B25D81A729803005CCF68 /* Filter2.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter2.txt; sourceTree = ""; }; F451D3F51A8AAE8700B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = ""; }; - F45C69CB16DFD08D0081955B /* GPBExtensionField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionField.m; sourceTree = ""; }; + F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = ""; }; F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_map_unittest_data.txt; sourceTree = ""; }; F4AC9E1D1A8BEB3500BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = ""; }; - F4B6B8AF1A9CC98000892426 /* GPBField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBField_PackagePrivate.h; sourceTree = ""; }; + F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownField_PackagePrivate.h; sourceTree = ""; }; F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = ""; }; - F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField_PackagePrivate.h; sourceTree = ""; }; + F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionInternals.h; sourceTree = ""; }; F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = ""; }; - F4B6B8B91A9D338B00892426 /* unittest_name_mangling.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_name_mangling.proto; sourceTree = ""; }; + F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc_startup.proto; sourceTree = ""; }; + F4E675861B21D0000054530B /* Any.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Any.pbobjc.h; path = google/protobuf/Any.pbobjc.h; sourceTree = ""; }; + F4E675871B21D0000054530B /* Any.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Any.pbobjc.m; path = google/protobuf/Any.pbobjc.m; sourceTree = ""; }; + F4E675881B21D0000054530B /* Api.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Api.pbobjc.h; path = google/protobuf/Api.pbobjc.h; sourceTree = ""; }; + F4E675891B21D0000054530B /* Api.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Api.pbobjc.m; path = google/protobuf/Api.pbobjc.m; sourceTree = ""; }; + F4E6758A1B21D0000054530B /* Empty.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Empty.pbobjc.h; path = google/protobuf/Empty.pbobjc.h; sourceTree = ""; }; + F4E6758B1B21D0000054530B /* Empty.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Empty.pbobjc.m; path = google/protobuf/Empty.pbobjc.m; sourceTree = ""; }; + F4E6758C1B21D0000054530B /* FieldMask.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FieldMask.pbobjc.h; path = google/protobuf/FieldMask.pbobjc.h; sourceTree = ""; }; + F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FieldMask.pbobjc.m; path = google/protobuf/FieldMask.pbobjc.m; sourceTree = ""; }; + F4E6758E1B21D0000054530B /* SourceContext.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceContext.pbobjc.h; path = google/protobuf/SourceContext.pbobjc.h; sourceTree = ""; }; + F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = SourceContext.pbobjc.m; path = google/protobuf/SourceContext.pbobjc.m; sourceTree = ""; }; + F4E675901B21D0000054530B /* Struct.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Struct.pbobjc.h; path = google/protobuf/Struct.pbobjc.h; sourceTree = ""; }; + F4E675911B21D0000054530B /* Struct.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Struct.pbobjc.m; path = google/protobuf/Struct.pbobjc.m; sourceTree = ""; }; + F4E675921B21D0000054530B /* Type.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Type.pbobjc.h; path = google/protobuf/Type.pbobjc.h; sourceTree = ""; }; + F4E675931B21D0000054530B /* Type.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Type.pbobjc.m; path = google/protobuf/Type.pbobjc.m; sourceTree = ""; }; + F4E675941B21D0000054530B /* Wrappers.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Wrappers.pbobjc.h; path = google/protobuf/Wrappers.pbobjc.h; sourceTree = ""; }; + F4E675951B21D0000054530B /* Wrappers.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Wrappers.pbobjc.m; path = google/protobuf/Wrappers.pbobjc.m; sourceTree = ""; }; + F4E675A61B21D05C0054530B /* any.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = any.proto; path = ../src/google/protobuf/any.proto; sourceTree = ""; }; + F4E675A71B21D05C0054530B /* api.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = api.proto; path = ../src/google/protobuf/api.proto; sourceTree = ""; }; + F4E675A81B21D05C0054530B /* empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = empty.proto; path = ../src/google/protobuf/empty.proto; sourceTree = ""; }; + F4E675A91B21D05C0054530B /* field_mask.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = field_mask.proto; path = ../src/google/protobuf/field_mask.proto; sourceTree = ""; }; + F4E675AA1B21D05C0054530B /* source_context.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = source_context.proto; path = ../src/google/protobuf/source_context.proto; sourceTree = ""; }; + F4E675AB1B21D05C0054530B /* struct.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = struct.proto; path = ../src/google/protobuf/struct.proto; sourceTree = ""; }; + F4E675AC1B21D05C0054530B /* type.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = type.proto; path = ../src/google/protobuf/type.proto; sourceTree = ""; }; + F4E675AD1B21D05C0054530B /* wrappers.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = wrappers.proto; path = ../src/google/protobuf/wrappers.proto; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -273,15 +293,39 @@ 29B97315FDCFA39411CA2CEA /* Generated */ = { isa = PBXGroup; children = ( - 8B42494B1A92A16600BC1EC6 /* descriptor.proto */, - 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */, + F4E675861B21D0000054530B /* Any.pbobjc.h */, + F4E675871B21D0000054530B /* Any.pbobjc.m */, + F4E675A61B21D05C0054530B /* any.proto */, + F4E675881B21D0000054530B /* Api.pbobjc.h */, + F4E675891B21D0000054530B /* Api.pbobjc.m */, + F4E675A71B21D05C0054530B /* api.proto */, 8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */, - 8B42494C1A92A16600BC1EC6 /* duration.proto */, + 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */, + 8B42494B1A92A16600BC1EC6 /* descriptor.proto */, 8B4248D31A92826400BC1EC6 /* Duration.pbobjc.h */, 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */, - 8B42494D1A92A16600BC1EC6 /* timestamp.proto */, + 8B42494C1A92A16600BC1EC6 /* duration.proto */, + F4E6758A1B21D0000054530B /* Empty.pbobjc.h */, + F4E6758B1B21D0000054530B /* Empty.pbobjc.m */, + F4E675A81B21D05C0054530B /* empty.proto */, + F4E675A91B21D05C0054530B /* field_mask.proto */, + F4E6758C1B21D0000054530B /* FieldMask.pbobjc.h */, + F4E6758D1B21D0000054530B /* FieldMask.pbobjc.m */, + F4E675AA1B21D05C0054530B /* source_context.proto */, + F4E6758E1B21D0000054530B /* SourceContext.pbobjc.h */, + F4E6758F1B21D0000054530B /* SourceContext.pbobjc.m */, + F4E675901B21D0000054530B /* Struct.pbobjc.h */, + F4E675911B21D0000054530B /* Struct.pbobjc.m */, + F4E675AB1B21D05C0054530B /* struct.proto */, 8B4248D51A92826400BC1EC6 /* Timestamp.pbobjc.h */, 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */, + 8B42494D1A92A16600BC1EC6 /* timestamp.proto */, + F4E675921B21D0000054530B /* Type.pbobjc.h */, + F4E675931B21D0000054530B /* Type.pbobjc.m */, + F4E675AC1B21D05C0054530B /* type.proto */, + F4E675941B21D0000054530B /* Wrappers.pbobjc.h */, + F4E675951B21D0000054530B /* Wrappers.pbobjc.m */, + F4E675AD1B21D05C0054530B /* wrappers.proto */, ); name = Generated; sourceTree = ""; @@ -297,9 +341,8 @@ 7461B3C50F94F84100A0C422 /* Extensions */ = { isa = PBXGroup; children = ( - F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */, - 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */, - F45C69CB16DFD08D0081955B /* GPBExtensionField.m */, + F4B6B8B61A9CD1DE00892426 /* GPBExtensionInternals.h */, + F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */, 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */, 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */, F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */, @@ -312,9 +355,9 @@ 7461B4850F94F96600A0C422 /* Fields */ = { isa = PBXGroup; children = ( - F4B6B8AF1A9CC98000892426 /* GPBField_PackagePrivate.h */, - 7461B4AE0F94F99000A0C422 /* GPBField.h */, - 7461B4AF0F94F99000A0C422 /* GPBField.m */, + F4B6B8AF1A9CC98000892426 /* GPBUnknownField_PackagePrivate.h */, + 7461B4AE0F94F99000A0C422 /* GPBUnknownField.h */, + 7461B4AF0F94F99000A0C422 /* GPBUnknownField.m */, F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */, 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */, 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */, @@ -353,8 +396,6 @@ isa = PBXGroup; children = ( 8B4248B81A8C254000BC1EC6 /* protobuf */, - 8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */, - F44B25D81A729803005CCF68 /* Filter2.txt */, 8B210CCD159383D60032D72D /* golden_message */, 8B210CCF159386920032D72D /* golden_packed_fields_message */, 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */, @@ -370,7 +411,6 @@ F4353D301AC06F10005A6198 /* GPBDictionaryTests+String.m */, F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */, F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */, - 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */, 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */, F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */, F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */, @@ -392,13 +432,12 @@ 8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */, 8B7E6A7614893DBA00F8884A /* unittest_empty.proto */, 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */, - 8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */, 8B7E6A7814893DBB00F8884A /* unittest_import.proto */, 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */, 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */, - F4B6B8B91A9D338B00892426 /* unittest_name_mangling.proto */, 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */, 8B09AAF614B663A7007B4184 /* unittest_objc.proto */, + F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */, 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */, F4487C781AADFB3100531423 /* unittest_runtime_proto2.proto */, F4487C791AADFB3200531423 /* unittest_runtime_proto3.proto */, @@ -419,7 +458,7 @@ F43725911AC9832D004DCAFB /* GPBDictionary_PackagePrivate.h */, F4353D201ABB1537005A6198 /* GPBDictionary.h */, F4353D211ABB1537005A6198 /* GPBDictionary.m */, - 8BEB5AE01498033E0078BF9D /* GPBTypes.h */, + 8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */, F4487C7C1AAE06AC00531423 /* GPBUtilities_PackagePrivate.h */, 7461B4E50F94F99000A0C422 /* GPBUtilities.h */, 7461B4E60F94F99000A0C422 /* GPBUtilities.m */, @@ -448,6 +487,22 @@ }; /* End PBXHeadersBuildPhase section */ +/* Begin PBXLegacyTarget section */ + F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "$(ACTION)"; + buildConfigurationList = F45BBC171B0CE3C6002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */; + buildPhases = ( + ); + buildToolPath = DevTools/compile_testing_protos.sh; + dependencies = ( + ); + name = "Compile Unittest Protos"; + passBuildSettingsInEnvironment = 1; + productName = "Compile Unittest Protos"; + }; +/* End PBXLegacyTarget section */ + /* Begin PBXNativeTarget section */ 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */ = { isa = PBXNativeTarget; @@ -479,7 +534,7 @@ ); dependencies = ( 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */, - 8BD3982114BE59EB0081D629 /* PBXTargetDependency */, + F45BBC191B0CE3D7002D064D /* PBXTargetDependency */, ); name = UnitTests; productName = UnitTests; @@ -510,11 +565,14 @@ isa = PBXProject; attributes = { LastTestingUpgradeCheck = 0600; - LastUpgradeCheck = 0620; + LastUpgradeCheck = 0630; TargetAttributes = { 8BBEA4A5147C727100C4ADB7 = { TestTargetID = 8B9A5EA41831993600A9D33B; }; + F45BBC141B0CE3C6002D064D = { + CreatedOnToolsVersion = 6.3.2; + }; }; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_OSX" */; @@ -530,8 +588,8 @@ targets = ( 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */, 8BBEA4A5147C727100C4ADB7 /* UnitTests */, - 8BD3981414BE4AE70081D629 /* Compile_Protos */, F4487C381A9F8E0200531423 /* TestSingleSourceBuild */, + F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */, ); }; /* End PBXProject section */ @@ -551,51 +609,6 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 8BD3981814BE4AF30081D629 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "$(SRCROOT)/../src/google/protobuf/unittest_custom_options.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_embed_optimize_for.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_empty.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_enormous_descriptor.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_import_lite.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_import.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_lite_imports_nonlite.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_lite.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_mset.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_no_generic_services.proto", - "$(SRCROOT)/../src/google/protobuf/unittest.proto", - "$(SRCROOT)/Tests/unittest_objc.proto", - "$(SRCROOT)/../src/.libs/libprotoc.10.dylib", - "$(SRCROOT)/../src/google/protobuf/unittest_import_public_lite.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_import_public.proto", - "$(SRCROOT)/Tests/unittest_filter.proto", - "$(SRCROOT)/../src/.libs/libprotobuf.10.dylib", - "$(SRCROOT)/../src/.libs/protoc", - "$(SRCROOT)/Tests/Filter1.txt", - "$(SRCROOT)/Tests/Filter2.txt", - "$(SRCROOT)/Tests/unittest_cycle.proto", - "$(SRCROOT)/Tests/unittest_name_mangling.proto", - "$(SRCROOT)/Tests/unittest_runtime_proto2.proto", - "$(SRCROOT)/Tests/unittest_runtime_proto3.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_drop_unknown_fields.proto", - "$(SRCROOT)/../src/google/protobuf/unittest_preserve_unknown_enum.proto", - "$(SRCROOT)/../src/google/protobuf/map_lite_unittest.proto", - "$(SRCROOT)/../src/google/protobuf/map_proto2_unittest.proto", - "$(SRCROOT)/../src/google/protobuf/map_unittest.proto", - ); - outputPaths = ( - "$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.h", - "$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.m", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/bash; - shellScript = "set -eu\nmkdir -p \"${PROJECT_DERIVED_FILE_DIR}/protos\"\nexport PATH=\"${PATH}:.\"\ncd \"${SRCROOT}\"/../src\n\nPROTOC=./protoc\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_custom_options.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_enormous_descriptor.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_embed_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_empty.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_mset.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_no_generic_services.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_drop_unknown_fields.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_preserve_unknown_enum.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_lite_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_proto2_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_unittest.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_objc.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_cycle.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_name_mangling.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto2.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto3.proto\n\n# Use the filter\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_filter.proto\n\n"; - showEnvVarsInLog = 0; - }; F4B62A781AF91F6000AFCEDC /* Script: Check Runtime Stamps */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -620,19 +633,27 @@ files = ( 2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */, 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */, + F4E6759B1B21D0000054530B /* Empty.pbobjc.m in Sources */, 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */, F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */, 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */, - 7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */, + F4E6759D1B21D0000054530B /* FieldMask.pbobjc.m in Sources */, + 7461B54C0F94FB4E00A0C422 /* GPBUnknownField.m in Sources */, 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */, 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */, 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */, 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */, + F4E675991B21D0000054530B /* Api.pbobjc.m in Sources */, + F4E6759F1B21D0000054530B /* SourceContext.pbobjc.m in Sources */, F4353D231ABB1537005A6198 /* GPBDictionary.m in Sources */, 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */, 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */, - F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */, + F4E675971B21D0000054530B /* Any.pbobjc.m in Sources */, + F45C69CC16DFD08D0081955B /* GPBExtensionInternals.m in Sources */, 8B4248D21A927E1500BC1EC6 /* GPBWellKnownTypes.m in Sources */, + F4E675A31B21D0000054530B /* Type.pbobjc.m in Sources */, + F4E675A11B21D0000054530B /* Struct.pbobjc.m in Sources */, + F4E675A51B21D0000054530B /* Wrappers.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -645,12 +666,18 @@ F4353D361AC06F10005A6198 /* GPBDictionaryTests+Int64.m in Sources */, F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */, 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */, + F4E675B21B21D0A70054530B /* SourceContext.pbobjc.m in Sources */, 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */, F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */, 8B4248DC1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m in Sources */, + F4E675B01B21D0A70054530B /* Empty.pbobjc.m in Sources */, + F4E675B41B21D0A70054530B /* Type.pbobjc.m in Sources */, F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */, + F4E675B51B21D0A70054530B /* Wrappers.pbobjc.m in Sources */, + F4E675AE1B21D0A70054530B /* Any.pbobjc.m in Sources */, 8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */, 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */, + F4E675B31B21D0A70054530B /* Struct.pbobjc.m in Sources */, F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */, F4353D351AC06F10005A6198 /* GPBDictionaryTests+Int32.m in Sources */, 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */, @@ -665,9 +692,10 @@ 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */, 8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */, 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */, + F4E675B11B21D0A70054530B /* FieldMask.pbobjc.m in Sources */, 8B96157514CA019D00A2AC0B /* Descriptor.pbobjc.m in Sources */, - 8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */, 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */, + F4E675AF1B21D0A70054530B /* Api.pbobjc.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -687,10 +715,10 @@ target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */; targetProxy = 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */; }; - 8BD3982114BE59EB0081D629 /* PBXTargetDependency */ = { + F45BBC191B0CE3D7002D064D /* PBXTargetDependency */ = { isa = PBXTargetDependency; - target = 8BD3981414BE4AE70081D629 /* Compile_Protos */; - targetProxy = 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */; + target = F45BBC141B0CE3C6002D064D /* Compile Unittest Protos */; + targetProxy = F45BBC181B0CE3D7002D064D /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ @@ -746,20 +774,6 @@ }; name = Release; }; - 8BD3981514BE4AE70081D629 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 8BD3981614BE4AE70081D629 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; C01FCF4F08A954540054247B /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -864,6 +878,18 @@ }; name = Release; }; + F45BBC151B0CE3C6002D064D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Debug; + }; + F45BBC161B0CE3C6002D064D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -885,15 +911,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 8BD3981514BE4AE70081D629 /* Debug */, - 8BD3981614BE4AE70081D629 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_OSX" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -912,6 +929,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F45BBC171B0CE3C6002D064D /* Build configuration list for PBXLegacyTarget "Compile Unittest Protos" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F45BBC151B0CE3C6002D064D /* Debug */, + F45BBC161B0CE3C6002D064D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme index 7083f5e3..3b3eeb12 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme @@ -1,6 +1,6 @@ - - @@ -51,16 +48,223 @@ Identifier = "ConcurrencyTests"> + Identifier = "DescriptorTests"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Identifier = "GPBUInt32ArrayTests"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -71,6 +275,9 @@ + + diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme index 617fb47f..583a464a 100644 --- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme +++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme @@ -1,6 +1,6 @@ - - @@ -51,16 +48,223 @@ Identifier = "ConcurrencyTests"> + Identifier = "DescriptorTests"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Identifier = "GPBUInt32ArrayTests"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -71,6 +275,9 @@ + + @@ -96,7 +303,8 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" allowLocationSimulation = "YES"> - + ** (no default) Since Objective C uses a global namespace for all of its classes, there can -be collisions. This option provides a prefix that will be added to the Enums -and Objects (for messages) generated from the proto. Convention is to base +be collisions. This option provides a prefix that will be added to the Enums +and Objects (for messages) generated from the proto. Convention is to base the prefix on the package the proto is in. Contributing ------------ Please make updates to the tests along with changes. If just changing the -runtime, the Xcode projects can be used to build and run tests. If change also -require changes to the generated code, `objectivec/DevTools/full_mac_build.sh` -can be used to easily rebuild and test changes. Passing `-h` to the script will -show the addition options that could be useful. +runtime, the Xcode projects can be used to build and run tests. If your change +also requires changes to the generated code, +`objectivec/DevTools/full_mac_build.sh` can be used to easily rebuild and test +changes. Passing `-h` to the script will show the addition options that could +be useful. Documentation ------------- diff --git a/objectivec/Tests/Filter1.txt b/objectivec/Tests/Filter1.txt deleted file mode 100644 index 88a5cac8..00000000 --- a/objectivec/Tests/Filter1.txt +++ /dev/null @@ -1,40 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 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. - - -// Test the filter system for the ObjC Protocol Buffer Compiler. - -// Class names are matched using file name globbing rules. -// Whitespace is not allowed at the beginning of a line (except for a line -// that is a single newline). - -Keep -RemoveEnumMessage_KeepNestedInside -RemoveJustKidding diff --git a/objectivec/Tests/Filter2.txt b/objectivec/Tests/Filter2.txt deleted file mode 100644 index 5a2bb0f8..00000000 --- a/objectivec/Tests/Filter2.txt +++ /dev/null @@ -1,35 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2014 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. - - -// Test the filter system for the ObjC Protocol Buffer Compiler to test -// multiple filter support. - -Other diff --git a/objectivec/Tests/GPBARCUnittestProtos.m b/objectivec/Tests/GPBARCUnittestProtos.m index daf4effc..d0408869 100644 --- a/objectivec/Tests/GPBARCUnittestProtos.m +++ b/objectivec/Tests/GPBARCUnittestProtos.m @@ -41,16 +41,15 @@ #import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.h" #import "google/protobuf/UnittestEmpty.pbobjc.h" #import "google/protobuf/UnittestEnormousDescriptor.pbobjc.h" -#import "google/protobuf/UnittestFilter.pbobjc.h" #import "google/protobuf/UnittestImport.pbobjc.h" #import "google/protobuf/UnittestImportLite.pbobjc.h" #import "google/protobuf/UnittestImportPublic.pbobjc.h" #import "google/protobuf/UnittestImportPublicLite.pbobjc.h" #import "google/protobuf/UnittestLite.pbobjc.h" #import "google/protobuf/UnittestMset.pbobjc.h" -#import "google/protobuf/UnittestNameMangling.pbobjc.h" #import "google/protobuf/UnittestNoGenericServices.pbobjc.h" #import "google/protobuf/UnittestObjc.pbobjc.h" +#import "google/protobuf/UnittestObjcStartup.pbobjc.h" #import "google/protobuf/UnittestOptimizeFor.pbobjc.h" #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m index 5f29d7c8..579fe65c 100644 --- a/objectivec/Tests/GPBCodedInputStreamTests.m +++ b/objectivec/Tests/GPBCodedInputStreamTests.m @@ -260,7 +260,7 @@ [GPBCodedInputStream streamWithData:[NSMutableData dataWithData:data]]; XCTAssertEqual(tag, [input readTag]); - XCTAssertThrows([input readData]); + XCTAssertThrows([input readBytes]); } // Verifies fix for b/10315336. diff --git a/objectivec/Tests/GPBConcurrencyTests.m b/objectivec/Tests/GPBConcurrencyTests.m index e500ad77..daf75e7e 100644 --- a/objectivec/Tests/GPBConcurrencyTests.m +++ b/objectivec/Tests/GPBConcurrencyTests.m @@ -196,7 +196,8 @@ static const int kNumMessages = 100; NSArray *threads = [self createThreadsWithSelector:sel object:messages]; [self startThreads:threads]; [self joinThreads:threads]; - GPBExtensionField *extension = [UnittestRoot optionalForeignMessageExtension]; + GPBExtensionDescriptor *extension = + [UnittestRoot optionalForeignMessageExtension]; for (TestAllExtensions *message in messages) { XCTAssertFalse([message hasExtension:extension]); } diff --git a/objectivec/Tests/GPBFilteredMessageTests.m b/objectivec/Tests/GPBFilteredMessageTests.m deleted file mode 100644 index b0588837..00000000 --- a/objectivec/Tests/GPBFilteredMessageTests.m +++ /dev/null @@ -1,98 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 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. - -// Tests our filter system for ObjC. -// The proto being filtered is unittest_filter.proto. -// The filter file is Filter.txt. - -#import "GPBTestUtilities.h" - -#import "google/protobuf/UnittestFilter.pbobjc.h" - -// If we get an error about this already being defined, it is most likely -// because of an error in protoc which is supposed to be filtering -// the Remove message. -enum { Other_FieldNumber_B = 0 }; - -@interface FilteredMessageTests : GPBTestCase -@end - -@implementation FilteredMessageTests - -- (void)testEnumFiltering { - // If compile fails here it is because protoc did not generate KeepEnum. - XCTAssertTrue(KeepEnum_IsValidValue(KeepEnum_KeepValue)); - XCTAssertNotNil(KeepEnum_EnumDescriptor()); - - // If compile fails here it is because protoc did not generate - // KeepEnumInsideEnum and is probably due to nested enum handling being - // broken. - XCTAssertTrue(RemoveEnumMessage_KeepEnumInside_IsValidValue( - RemoveEnumMessage_KeepEnumInside_KeepValue)); - XCTAssertNotNil(RemoveEnumMessage_KeepEnumInside_EnumDescriptor()); -} - -- (void)testMessageFiltering { - // Messages that should be generated. - XCTAssertNil([UnittestFilterRoot extensionRegistry]); - XCTAssertNotNil([[[Keep alloc] init] autorelease]); - XCTAssertNotNil([[[Other alloc] init] autorelease]); - XCTAssertNotNil([[[RemoveJustKidding alloc] init] autorelease]); - XCTAssertNotNil( - [[[RemoveEnumMessage_KeepNestedInside alloc] init] autorelease]); - - // Messages that should not be generated - XCTAssertNil(NSClassFromString(@"Remove")); - XCTAssertNil(NSClassFromString(@"RemoveEnumMessage")); - XCTAssertNil(NSClassFromString(@"RemoveEnumMessage_RemoveNestedInside")); - - // These should all fail compile if protoc is bad. - XCTAssertTrue([Other instancesRespondToSelector:@selector(hasA)]); - XCTAssertTrue([Other instancesRespondToSelector:@selector(setHasA:)]); - XCTAssertTrue([Other instancesRespondToSelector:@selector(a)]); - XCTAssertTrue([Other instancesRespondToSelector:@selector(setA:)]); - - // These the compiler should not generate. - XCTAssertFalse( - [Other instancesRespondToSelector:NSSelectorFromString(@"hasB")]); - XCTAssertFalse( - [Other instancesRespondToSelector:NSSelectorFromString(@"setHasB:")]); - XCTAssertFalse([Other instancesRespondToSelector:NSSelectorFromString(@"b")]); - XCTAssertFalse( - [Other instancesRespondToSelector:NSSelectorFromString(@"setB:")]); - - // This should fail if protoc filters it. - XCTAssertEqual(Other_FieldNumber_A, 1); - - // Make sure the definition at the top of the file is providing the value. - XCTAssertEqual(Other_FieldNumber_B, 0); -} - -@end diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m index 4621f90f..8942a843 100644 --- a/objectivec/Tests/GPBMessageTests+Runtime.m +++ b/objectivec/Tests/GPBMessageTests+Runtime.m @@ -36,6 +36,7 @@ #import "google/protobuf/MapUnittest.pbobjc.h" #import "google/protobuf/Unittest.pbobjc.h" +#import "google/protobuf/UnittestObjcStartup.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto3.pbobjc.h" @@ -47,6 +48,14 @@ // TODO(thomasvl): Pull tests over from GPBMessageTests that are runtime // specific. +- (void)testStartupOrdering { + // Just have to create a message. Nothing else uses the classes from + // this file, so the first selector invoked on the class will initialize + // it, which also initializes the root. + TestObjCStartupMessage *message = [TestObjCStartupMessage message]; + XCTAssertNotNil(message); +} + - (void)testProto2HasMethodSupport { NSArray *names = @[ @"Int32", @@ -70,8 +79,8 @@ ]; // Proto2 gets: - // - has* on all non repeated fields. - // - setHas* on all non repeated fields. + + // Single fields - has*/setHas* is valid. for (NSString *name in names) { // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32: @@ -85,21 +94,28 @@ name); } - // Repeated - no has/setHas + // Repeated fields + // - no has*/setHas* + // - *Count for (NSString *name in names) { - // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32: + // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array: SEL hasSel = NSSelectorFromString( - [NSString stringWithFormat:@"hasRepeated%@", name]); + [NSString stringWithFormat:@"hasRepeated%@Array", name]); SEL setHasSel = NSSelectorFromString( - [NSString stringWithFormat:@"setHasRepeated%@:", name]); + [NSString stringWithFormat:@"setHasRepeated%@Array:", name]); XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", name); XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name); + // build the selector, i.e. - repeatedInt32Array_Count + SEL countSel = NSSelectorFromString( + [NSString stringWithFormat:@"repeated%@Array_Count", name]); + XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + name); } - // Oneofs - no has/setHas + // OneOf fields - no has*/setHas* for (NSString *name in names) { // build the selector, i.e. - hasOneofInt32/setHasOneofInt32: @@ -112,6 +128,50 @@ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name); } + + // map<> fields + // - no has*/setHas* + // - *Count + + NSArray *mapNames = @[ + @"Int32Int32", + @"Int64Int64", + @"Uint32Uint32", + @"Uint64Uint64", + @"Sint32Sint32", + @"Sint64Sint64", + @"Fixed32Fixed32", + @"Fixed64Fixed64", + @"Sfixed32Sfixed32", + @"Sfixed64Sfixed64", + @"Int32Float", + @"Int32Double", + @"BoolBool", + @"StringString", + @"StringBytes", + @"StringMessage", + @"Int32Bytes", + @"Int32Enum", + @"Int32Message", + ]; + + for (NSString *name in mapNames) { + // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32: + SEL hasSel = NSSelectorFromString( + [NSString stringWithFormat:@"hasMap%@", name]); + SEL setHasSel = NSSelectorFromString( + [NSString stringWithFormat:@"setHasMap%@:", name]); + XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", + name); + XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], + @"field: %@", name); + // build the selector, i.e. - mapInt32Int32Count + SEL countSel = NSSelectorFromString( + [NSString stringWithFormat:@"map%@_Count", name]); + XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + name); + } + } - (void)testProto3HasMethodSupport { @@ -136,10 +196,10 @@ ]; // Proto3 gets: - // - has* on non repeated message fields. - // - setHas* on all non repeated message fields. - // Singlular + // Single fields + // - has*/setHas* invalid for primative types. + // - has*/setHas* valid for Message. for (NSString *name in names) { // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32: @@ -147,7 +207,7 @@ [NSString stringWithFormat:@"hasOptional%@", name]); SEL setHasSel = NSSelectorFromString( [NSString stringWithFormat:@"setHasOptional%@:", name]); - if ([name isEqual:@"Group"] || [name isEqual:@"Message"]) { + if ([name isEqual:@"Message"]) { // Sub messages/groups are the exception. XCTAssertTrue([Message3 instancesRespondToSelector:hasSel], @"field: %@", name); @@ -161,21 +221,28 @@ } } - // Repeated - no has/setHas + // Repeated fields + // - no has*/setHas* + // - *Count for (NSString *name in names) { - // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32: + // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array: SEL hasSel = NSSelectorFromString( - [NSString stringWithFormat:@"hasRepeated%@", name]); + [NSString stringWithFormat:@"hasRepeated%@Array", name]); SEL setHasSel = NSSelectorFromString( - [NSString stringWithFormat:@"setHasRepeated%@:", name]); + [NSString stringWithFormat:@"setHasRepeated%@Array:", name]); XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name); XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name); + // build the selector, i.e. - repeatedInt32Array_Count + SEL countSel = NSSelectorFromString( + [NSString stringWithFormat:@"repeated%@Array_Count", name]); + XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + name); } - // Oneofs - no has/setHas + // OneOf fields - no has*/setHas* for (NSString *name in names) { // build the selector, i.e. - hasOneofInt32/setHasOneofInt32: @@ -188,6 +255,49 @@ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name); } + + // map<> fields + // - no has*/setHas* + // - *Count + + NSArray *mapNames = @[ + @"Int32Int32", + @"Int64Int64", + @"Uint32Uint32", + @"Uint64Uint64", + @"Sint32Sint32", + @"Sint64Sint64", + @"Fixed32Fixed32", + @"Fixed64Fixed64", + @"Sfixed32Sfixed32", + @"Sfixed64Sfixed64", + @"Int32Float", + @"Int32Double", + @"BoolBool", + @"StringString", + @"StringBytes", + @"StringMessage", + @"Int32Bytes", + @"Int32Enum", + @"Int32Message", + ]; + + for (NSString *name in mapNames) { + // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32: + SEL hasSel = NSSelectorFromString( + [NSString stringWithFormat:@"hasMap%@", name]); + SEL setHasSel = NSSelectorFromString( + [NSString stringWithFormat:@"setHasMap%@:", name]); + XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", + name); + XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], + @"field: %@", name); + // build the selector, i.e. - mapInt32Int32Count + SEL countSel = NSSelectorFromString( + [NSString stringWithFormat:@"map%@_Count", name]); + XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", + name); + } } - (void)testProto2SingleFieldHasBehavior { diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m index 6d5527b5..ae4be9e5 100644 --- a/objectivec/Tests/GPBMessageTests+Serialization.m +++ b/objectivec/Tests/GPBMessageTests+Serialization.m @@ -36,6 +36,7 @@ #import "google/protobuf/MapProto2Unittest.pbobjc.h" #import "google/protobuf/MapUnittest.pbobjc.h" +#import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestDropUnknownFields.pbobjc.h" #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.h" @@ -166,17 +167,15 @@ static NSData *DataFromCStr(const char *str) { [unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]); XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OneofEnum]); - GPBField *field = [unknownFields getField:Message2_FieldNumber_OptionalEnum]; + GPBUnknownField *field = + [unknownFields getField:Message2_FieldNumber_OptionalEnum]; XCTAssertEqual(field.varintList.count, 1U); XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3); - // Repeated in proto3 default to packed, so this will be length delimited - // unknown field, and the value (Message3_Enum_Extra3) encodes into one byte. field = [unknownFields getField:Message2_FieldNumber_RepeatedEnumArray]; - XCTAssertEqual(field.lengthDelimitedList.count, 1U); - NSData *expected = DataFromCStr("\x1E"); - XCTAssertEqualObjects([field.lengthDelimitedList objectAtIndex:0], expected); + XCTAssertEqual(field.varintList.count, 1U); + XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3); field = [unknownFields getField:Message2_FieldNumber_OneofEnum]; XCTAssertEqual(field.varintList.count, 1U); @@ -678,6 +677,131 @@ static NSData *DataFromCStr(const char *str) { //%PDDM-EXPAND-END (2 expansions) +- (void)testPackedUnpackedMessageParsing { + // packed is optional, a repeated field should parse when packed or unpacked. + + TestPackedTypes *packedOrig = [TestPackedTypes message]; + TestUnpackedTypes *unpackedOrig = [TestUnpackedTypes message]; + [self setPackedFields:packedOrig repeatedCount:4]; + [self setUnpackedFields:unpackedOrig repeatedCount:4]; + + NSData *packedData = [packedOrig data]; + NSData *unpackedData = [unpackedOrig data]; + XCTAssertNotNil(packedData); + XCTAssertNotNil(unpackedData); + XCTAssertNotEqualObjects(packedData, unpackedData, + @"Data should differ (packed vs unpacked) use"); + + NSError *error = nil; + TestPackedTypes *packedParse = + [TestPackedTypes parseFromData:unpackedData error:&error]; + XCTAssertNotNil(packedParse); + XCTAssertNil(error); + XCTAssertEqualObjects(packedParse, packedOrig); + + error = nil; + TestUnpackedTypes *unpackedParsed = + [TestUnpackedTypes parseFromData:packedData error:&error]; + XCTAssertNotNil(unpackedParsed); + XCTAssertNil(error); + XCTAssertEqualObjects(unpackedParsed, unpackedOrig); +} + +- (void)testPackedUnpackedExtensionParsing { + // packed is optional, a repeated extension should parse when packed or + // unpacked. + + TestPackedExtensions *packedOrig = [TestPackedExtensions message]; + TestUnpackedExtensions *unpackedOrig = [TestUnpackedExtensions message]; + [self setPackedExtensions:packedOrig repeatedCount:kGPBDefaultRepeatCount]; + [self setUnpackedExtensions:unpackedOrig repeatedCount:kGPBDefaultRepeatCount]; + + NSData *packedData = [packedOrig data]; + NSData *unpackedData = [unpackedOrig data]; + XCTAssertNotNil(packedData); + XCTAssertNotNil(unpackedData); + XCTAssertNotEqualObjects(packedData, unpackedData, + @"Data should differ (packed vs unpacked) use"); + + NSError *error = nil; + TestPackedExtensions *packedParse = + [TestPackedExtensions parseFromData:unpackedData + extensionRegistry:[UnittestRoot extensionRegistry] + error:&error]; + XCTAssertNotNil(packedParse); + XCTAssertNil(error); + XCTAssertEqualObjects(packedParse, packedOrig); + + error = nil; + TestUnpackedExtensions *unpackedParsed = + [TestUnpackedExtensions parseFromData:packedData + extensionRegistry:[UnittestRoot extensionRegistry] + error:&error]; + XCTAssertNotNil(unpackedParsed); + XCTAssertNil(error); + XCTAssertEqualObjects(unpackedParsed, unpackedOrig); +} + +- (void)testPackedExtensionVsFieldParsing { + // Extensions and fields end up on the wire the same way, so they can parse + // each other. + + TestPackedTypes *fieldsOrig = [TestPackedTypes message]; + TestPackedExtensions *extsOrig = [TestPackedExtensions message]; + [self setPackedFields:fieldsOrig repeatedCount:kGPBDefaultRepeatCount]; + [self setPackedExtensions:extsOrig repeatedCount:kGPBDefaultRepeatCount]; + + NSData *fieldsData = [fieldsOrig data]; + NSData *extsData = [extsOrig data]; + XCTAssertNotNil(fieldsData); + XCTAssertNotNil(extsData); + XCTAssertEqualObjects(fieldsData, extsData); + + NSError *error = nil; + TestPackedTypes *fieldsParse = + [TestPackedTypes parseFromData:extsData error:&error]; + XCTAssertNotNil(fieldsParse); + XCTAssertNil(error); + XCTAssertEqualObjects(fieldsParse, fieldsOrig); + + error = nil; + TestPackedExtensions *extsParse = + [TestPackedExtensions parseFromData:fieldsData + extensionRegistry:[UnittestRoot extensionRegistry] + error:&error]; + XCTAssertNotNil(extsParse); + XCTAssertNil(error); + XCTAssertEqualObjects(extsParse, extsOrig); +} + +- (void)testUnpackedExtensionVsFieldParsing { + // Extensions and fields end up on the wire the same way, so they can parse + // each other. + + TestUnpackedTypes *fieldsOrig = [TestUnpackedTypes message]; + TestUnpackedExtensions *extsOrig = [TestUnpackedExtensions message]; + [self setUnpackedFields:fieldsOrig repeatedCount:3]; + [self setUnpackedExtensions:extsOrig repeatedCount:3]; + + NSData *fieldsData = [fieldsOrig data]; + NSData *extsData = [extsOrig data]; + XCTAssertNotNil(fieldsData); + XCTAssertNotNil(extsData); + XCTAssertEqualObjects(fieldsData, extsData); + + TestUnpackedTypes *fieldsParse = + [TestUnpackedTypes parseFromData:extsData error:NULL]; + XCTAssertNotNil(fieldsParse); + XCTAssertEqualObjects(fieldsParse, fieldsOrig); + + TestUnpackedExtensions *extsParse = + [TestUnpackedExtensions parseFromData:fieldsData + extensionRegistry:[UnittestRoot extensionRegistry] + error:NULL]; + XCTAssertNotNil(extsParse); + XCTAssertEqualObjects(extsParse, extsOrig); +} + #pragma mark - Subset from from map_tests.cc // TEST(GeneratedMapFieldTest, StandardWireFormat) diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m index e0154c1a..cd0de8fc 100644 --- a/objectivec/Tests/GPBMessageTests.m +++ b/objectivec/Tests/GPBMessageTests.m @@ -35,12 +35,11 @@ #import "GPBArray_PackagePrivate.h" #import "GPBDescriptor.h" #import "GPBDictionary_PackagePrivate.h" -#import "GPBField_PackagePrivate.h" #import "GPBMessage_PackagePrivate.h" +#import "GPBUnknownField_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h" #import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestObjc.pbobjc.h" -#import "google/protobuf/UnittestNameMangling.pbobjc.h" @interface MessageTests : GPBTestCase @end @@ -420,10 +419,11 @@ GPBUnknownFieldSet *unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBField *field = [[[GPBField alloc] initWithNumber:2] autorelease]; + GPBUnknownField *field = + [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field addVarint:2]; [unknownFields addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:4]; [unknownFields addField:field]; @@ -451,7 +451,7 @@ GPBFieldDescriptor *fieldDescriptor = [descriptor fieldWithName:@"defaultInt32"]; XCTAssertNotNil(fieldDescriptor); - GPBValue defaultValue = [fieldDescriptor defaultValue]; + GPBGenericValue defaultValue = [fieldDescriptor defaultValue]; [message setDefaultInt32:defaultValue.valueInt32]; XCTAssertTrue(message.hasDefaultInt32); XCTAssertEqual(message.defaultInt32, defaultValue.valueInt32); @@ -1554,7 +1554,7 @@ // The other should not. TestAllExtensions *message = [TestAllExtensions message]; TestAllExtensions *message2 = [TestAllExtensions message]; - GPBExtensionField *extension = [UnittestRoot optionalGroupExtension]; + GPBExtensionDescriptor *extension = [UnittestRoot optionalGroupExtension]; [message setExtension:extension value:[message2 getExtension:extension]]; XCTAssertEqual([message getExtension:extension], [message2 getExtension:extension]); @@ -1571,9 +1571,9 @@ - (void)testCopyWithAutocreatedExtension { // Mutable copy shouldn't copy autocreated extensions. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; - GPBExtensionField *optionalNestedMessageExtesion = + GPBExtensionDescriptor *optionalNestedMessageExtesion = [UnittestRoot optionalNestedMessageExtension]; TestAllTypes_OptionalGroup *optionalGroup = [message getExtension:optionalGroupExtension]; @@ -1603,7 +1603,7 @@ - (void)testClearMessageAutocreatedExtension { // Call clear should cause it to recreate its autocreated extensions. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; TestAllTypes_OptionalGroup *optionalGroup = [[message getExtension:optionalGroupExtension] retain]; @@ -1620,7 +1620,7 @@ // Should be able to retain autocreated extension while the creator is // dealloced. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; @autoreleasepool { @@ -1638,7 +1638,7 @@ - (void)testClearAutocreatedExtension { // Clearing autocreated extension should NOT cause it to lose its creator. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; TestAllTypes_OptionalGroup *optionalGroup = [[message getExtension:optionalGroupExtension] retain]; @@ -1651,7 +1651,8 @@ // Clearing autocreated extension should not cause its creator to become // visible - GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension]; + GPBExtensionDescriptor *recursiveExtension = + [UnittestObjcRoot recursiveExtension]; TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension]; TestAllExtensions *message_lvl3 = [message_lvl2 getExtension:recursiveExtension]; @@ -1663,7 +1664,8 @@ // Setting an extension should cause the extension to appear to its creator. // Test this several levels deep. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension]; + GPBExtensionDescriptor *recursiveExtension = + [UnittestObjcRoot recursiveExtension]; TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension]; TestAllExtensions *message_lvl3 = [message_lvl2 getExtension:recursiveExtension]; @@ -1686,7 +1688,7 @@ - (void)testSetAutocreatedExtensionToSelf { // Setting extension to itself should cause it to become visible. TestAllExtensions *message = [TestAllExtensions message]; - GPBExtensionField *optionalGroupExtension = + GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension]; XCTAssertNotNil([message getExtension:optionalGroupExtension]); XCTAssertFalse([message hasExtension:optionalGroupExtension]); @@ -1696,7 +1698,8 @@ } - (void)testAutocreatedExtensionMemoryLeaks { - GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension]; + GPBExtensionDescriptor *recursiveExtension = + [UnittestObjcRoot recursiveExtension]; // Test for memory leaks with autocreated extensions. TestAllExtensions *message; @@ -1729,7 +1732,8 @@ } - (void)testSetExtensionWithAutocreatedValue { - GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension]; + GPBExtensionDescriptor *recursiveExtension = + [UnittestObjcRoot recursiveExtension]; TestAllExtensions *message; @autoreleasepool { @@ -1814,9 +1818,9 @@ } - (void)testEnumDescriptorFromExtensionDescriptor { - GPBExtensionField *extField = [UnittestRoot optionalForeignEnumExtension]; - GPBExtensionDescriptor *extDescriptor = extField.descriptor; - XCTAssertEqual(extDescriptor.type, GPBTypeEnum); + GPBExtensionDescriptor *extDescriptor = + [UnittestRoot optionalForeignEnumExtension]; + XCTAssertEqual(extDescriptor.dataType, GPBDataTypeEnum); GPBEnumDescriptor *enumDescriptor = extDescriptor.enumDescriptor; GPBEnumDescriptor *expectedDescriptor = ForeignEnum_EnumDescriptor(); XCTAssertEqualObjects(enumDescriptor, expectedDescriptor); @@ -1925,11 +1929,4 @@ EnumTestMsg_MyEnum_NegTwo); } -- (void)testMutableNameManagling { - // These basically confirm that all the expected name mangling happened by not - // having compile errors. - - // TODO(thomasvl): Write these, see unittest_name_mangling.proto. -} - @end diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h index 6ae68c3a..44c80844 100644 --- a/objectivec/Tests/GPBTestUtilities.h +++ b/objectivec/Tests/GPBTestUtilities.h @@ -35,6 +35,8 @@ @class TestMap; @class TestPackedTypes; @class TestPackedExtensions; +@class TestUnpackedTypes; +@class TestUnpackedExtensions; @class GPBExtensionRegistry; @@ -55,8 +57,12 @@ extern const uint32_t kGPBDefaultRepeatCount; repeatedCount:(uint32_t)count; - (void)setPackedFields:(TestPackedTypes *)message repeatedCount:(uint32_t)count; +- (void)setUnpackedFields:(TestUnpackedTypes *)message + repeatedCount:(uint32_t)count; - (void)setPackedExtensions:(TestPackedExtensions *)message repeatedCount:(uint32_t)count; +- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message + repeatedCount:(uint32_t)count; - (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count; - (TestAllTypes *)allSetRepeatedCount:(uint32_t)count; diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m index 6058dfc1..3d85c744 100644 --- a/objectivec/Tests/GPBTestUtilities.m +++ b/objectivec/Tests/GPBTestUtilities.m @@ -599,6 +599,33 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqual(count, message.repeatedStringPieceArray.count); XCTAssertEqual(count, message.repeatedCordArray.count); + XCTAssertEqual(count, message.repeatedInt32Array_Count); + XCTAssertEqual(count, message.repeatedInt64Array_Count); + XCTAssertEqual(count, message.repeatedUint32Array_Count); + XCTAssertEqual(count, message.repeatedUint64Array_Count); + XCTAssertEqual(count, message.repeatedSint32Array_Count); + XCTAssertEqual(count, message.repeatedSint64Array_Count); + XCTAssertEqual(count, message.repeatedFixed32Array_Count); + XCTAssertEqual(count, message.repeatedFixed64Array_Count); + XCTAssertEqual(count, message.repeatedSfixed32Array_Count); + XCTAssertEqual(count, message.repeatedSfixed64Array_Count); + XCTAssertEqual(count, message.repeatedFloatArray_Count); + XCTAssertEqual(count, message.repeatedDoubleArray_Count); + XCTAssertEqual(count, message.repeatedBoolArray_Count); + XCTAssertEqual(count, message.repeatedStringArray_Count); + XCTAssertEqual(count, message.repeatedBytesArray_Count); + + XCTAssertEqual(count, message.repeatedGroupArray_Count); + XCTAssertEqual(count, message.repeatedNestedMessageArray_Count); + XCTAssertEqual(count, message.repeatedForeignMessageArray_Count); + XCTAssertEqual(count, message.repeatedImportMessageArray_Count); + XCTAssertEqual(count, message.repeatedNestedEnumArray_Count); + XCTAssertEqual(count, message.repeatedForeignEnumArray_Count); + XCTAssertEqual(count, message.repeatedImportEnumArray_Count); + + XCTAssertEqual(count, message.repeatedStringPieceArray_Count); + XCTAssertEqual(count, message.repeatedCordArray_Count); + for (uint32_t i = 0; i < count; ++i) { XCTAssertEqual((int)(201 + i * 100), [message.repeatedInt32Array valueAtIndex:i]); @@ -1097,6 +1124,72 @@ const uint32_t kGPBDefaultRepeatCount = 2; } } +- (void)setAllTestPackedFields:(TestPackedTypes *)message { + // Must match -setAllTestUnpackedFields: + [message.packedInt32Array addValue:101]; + [message.packedInt64Array addValue:102]; + [message.packedUint32Array addValue:103]; + [message.packedUint64Array addValue:104]; + [message.packedSint32Array addValue:105]; + [message.packedSint64Array addValue:106]; + [message.packedFixed32Array addValue:107]; + [message.packedFixed64Array addValue:108]; + [message.packedSfixed32Array addValue:109]; + [message.packedSfixed64Array addValue:110]; + [message.packedFloatArray addValue:111.f]; + [message.packedDoubleArray addValue:112.]; + [message.packedBoolArray addValue:YES]; + [message.packedEnumArray addValue:ForeignEnum_ForeignBar]; + + [message.packedInt32Array addValue:201]; + [message.packedInt64Array addValue:302]; + [message.packedUint32Array addValue:203]; + [message.packedUint64Array addValue:204]; + [message.packedSint32Array addValue:205]; + [message.packedSint64Array addValue:206]; + [message.packedFixed32Array addValue:207]; + [message.packedFixed64Array addValue:208]; + [message.packedSfixed32Array addValue:209]; + [message.packedSfixed64Array addValue:210]; + [message.packedFloatArray addValue:211.f]; + [message.packedDoubleArray addValue:212.]; + [message.packedBoolArray addValue:NO]; + [message.packedEnumArray addValue:ForeignEnum_ForeignBaz]; +} + +- (void)setAllTestUnpackedFields:(TestUnpackedTypes *)message { + // Must match -setAllTestPackedFields: + [message.unpackedInt32Array addValue:101]; + [message.unpackedInt64Array addValue:102]; + [message.unpackedUint32Array addValue:103]; + [message.unpackedUint64Array addValue:104]; + [message.unpackedSint32Array addValue:105]; + [message.unpackedSint64Array addValue:106]; + [message.unpackedFixed32Array addValue:107]; + [message.unpackedFixed64Array addValue:108]; + [message.unpackedSfixed32Array addValue:109]; + [message.unpackedSfixed64Array addValue:110]; + [message.unpackedFloatArray addValue:111.f]; + [message.unpackedDoubleArray addValue:112.]; + [message.unpackedBoolArray addValue:YES]; + [message.unpackedEnumArray addValue:ForeignEnum_ForeignBar]; + + [message.unpackedInt32Array addValue:201]; + [message.unpackedInt64Array addValue:302]; + [message.unpackedUint32Array addValue:203]; + [message.unpackedUint64Array addValue:204]; + [message.unpackedSint32Array addValue:205]; + [message.unpackedSint64Array addValue:206]; + [message.unpackedFixed32Array addValue:207]; + [message.unpackedFixed64Array addValue:208]; + [message.unpackedSfixed32Array addValue:209]; + [message.unpackedSfixed64Array addValue:210]; + [message.unpackedFloatArray addValue:211.f]; + [message.unpackedDoubleArray addValue:212.]; + [message.unpackedBoolArray addValue:NO]; + [message.unpackedEnumArray addValue:ForeignEnum_ForeignBaz]; +} + - (GPBExtensionRegistry *)extensionRegistry { return [UnittestRoot extensionRegistry]; } @@ -1189,6 +1282,7 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqualObjects(message.optionalCord, @""); // Repeated fields are empty. + XCTAssertEqual(0U, message.repeatedInt32Array.count); XCTAssertEqual(0U, message.repeatedInt64Array.count); XCTAssertEqual(0U, message.repeatedUint32Array.count); @@ -1216,6 +1310,33 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqual(0U, message.repeatedStringPieceArray.count); XCTAssertEqual(0U, message.repeatedCordArray.count); + XCTAssertEqual(0U, message.repeatedInt32Array_Count); + XCTAssertEqual(0U, message.repeatedInt64Array_Count); + XCTAssertEqual(0U, message.repeatedUint32Array_Count); + XCTAssertEqual(0U, message.repeatedUint64Array_Count); + XCTAssertEqual(0U, message.repeatedSint32Array_Count); + XCTAssertEqual(0U, message.repeatedSint64Array_Count); + XCTAssertEqual(0U, message.repeatedFixed32Array_Count); + XCTAssertEqual(0U, message.repeatedFixed64Array_Count); + XCTAssertEqual(0U, message.repeatedSfixed32Array_Count); + XCTAssertEqual(0U, message.repeatedSfixed64Array_Count); + XCTAssertEqual(0U, message.repeatedFloatArray_Count); + XCTAssertEqual(0U, message.repeatedDoubleArray_Count); + XCTAssertEqual(0U, message.repeatedBoolArray_Count); + XCTAssertEqual(0U, message.repeatedStringArray_Count); + XCTAssertEqual(0U, message.repeatedBytesArray_Count); + + XCTAssertEqual(0U, message.repeatedGroupArray_Count); + XCTAssertEqual(0U, message.repeatedNestedMessageArray_Count); + XCTAssertEqual(0U, message.repeatedForeignMessageArray_Count); + XCTAssertEqual(0U, message.repeatedImportMessageArray_Count); + XCTAssertEqual(0U, message.repeatedNestedEnumArray_Count); + XCTAssertEqual(0U, message.repeatedForeignEnumArray_Count); + XCTAssertEqual(0U, message.repeatedImportEnumArray_Count); + + XCTAssertEqual(0U, message.repeatedStringPieceArray_Count); + XCTAssertEqual(0U, message.repeatedCordArray_Count); + // hasBlah() should also be NO for all default fields. XCTAssertFalse(message.hasDefaultInt32); XCTAssertFalse(message.hasDefaultInt64); @@ -1474,6 +1595,7 @@ const uint32_t kGPBDefaultRepeatCount = 2; // ModifyRepeatedFields only sets the second repeated element of each // field. In addition to verifying this, we also verify that the first // element and size were *not* modified. + XCTAssertEqual(count, message.repeatedInt32Array.count); XCTAssertEqual(count, message.repeatedInt64Array.count); XCTAssertEqual(count, message.repeatedUint32Array.count); @@ -1501,6 +1623,33 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqual(count, message.repeatedStringPieceArray.count); XCTAssertEqual(count, message.repeatedCordArray.count); + XCTAssertEqual(count, message.repeatedInt32Array_Count); + XCTAssertEqual(count, message.repeatedInt64Array_Count); + XCTAssertEqual(count, message.repeatedUint32Array_Count); + XCTAssertEqual(count, message.repeatedUint64Array_Count); + XCTAssertEqual(count, message.repeatedSint32Array_Count); + XCTAssertEqual(count, message.repeatedSint64Array_Count); + XCTAssertEqual(count, message.repeatedFixed32Array_Count); + XCTAssertEqual(count, message.repeatedFixed64Array_Count); + XCTAssertEqual(count, message.repeatedSfixed32Array_Count); + XCTAssertEqual(count, message.repeatedSfixed64Array_Count); + XCTAssertEqual(count, message.repeatedFloatArray_Count); + XCTAssertEqual(count, message.repeatedDoubleArray_Count); + XCTAssertEqual(count, message.repeatedBoolArray_Count); + XCTAssertEqual(count, message.repeatedStringArray_Count); + XCTAssertEqual(count, message.repeatedBytesArray_Count); + + XCTAssertEqual(count, message.repeatedGroupArray_Count); + XCTAssertEqual(count, message.repeatedNestedMessageArray_Count); + XCTAssertEqual(count, message.repeatedForeignMessageArray_Count); + XCTAssertEqual(count, message.repeatedImportMessageArray_Count); + XCTAssertEqual(count, message.repeatedNestedEnumArray_Count); + XCTAssertEqual(count, message.repeatedForeignEnumArray_Count); + XCTAssertEqual(count, message.repeatedImportEnumArray_Count); + + XCTAssertEqual(count, message.repeatedStringPieceArray_Count); + XCTAssertEqual(count, message.repeatedCordArray_Count); + XCTAssertEqual(201, [message.repeatedInt32Array valueAtIndex:0]); XCTAssertEqual(202LL, [message.repeatedInt64Array valueAtIndex:0]); XCTAssertEqual(203U, [message.repeatedUint32Array valueAtIndex:0]); @@ -1563,105 +1712,101 @@ const uint32_t kGPBDefaultRepeatCount = 2; - (void)setPackedFields:(TestPackedTypes *)message repeatedCount:(uint32_t)count { - { - GPBInt32Array *scratch = [GPBInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:601 + i * 100]; - } - [message setPackedInt32Array:scratch]; + // Must match -setUnpackedFields:repeatedCount: + // Must match -setPackedExtensions:repeatedCount: + // Must match -setUnpackedExtensions:repeatedCount: + for (uint32_t i = 0; i < count; ++i) { + [message.packedInt32Array addValue:601 + i * 100]; } - { - GPBInt64Array *scratch = [GPBInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:602 + i * 100]; - } - [message setPackedInt64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedInt64Array addValue:602 + i * 100]; } - { - GPBUInt32Array *scratch = [GPBUInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:603 + i * 100]; - } - [message setPackedUint32Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedUint32Array addValue:603 + i * 100]; } - { - GPBUInt64Array *scratch = [GPBUInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:604 + i * 100]; - } - [message setPackedUint64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedUint64Array addValue:604 + i * 100]; } - { - GPBInt32Array *scratch = [GPBInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:605 + i * 100]; - } - [message setPackedSint32Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedSint32Array addValue:605 + i * 100]; } - { - GPBInt64Array *scratch = [GPBInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:606 + i * 100]; - } - [message setPackedSint64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedSint64Array addValue:606 + i * 100]; } - { - GPBUInt32Array *scratch = [GPBUInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:607 + i * 100]; - } - [message setPackedFixed32Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedFixed32Array addValue:607 + i * 100]; } - { - GPBUInt64Array *scratch = [GPBUInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:608 + i * 100]; - } - [message setPackedFixed64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedFixed64Array addValue:608 + i * 100]; } - { - GPBInt32Array *scratch = [GPBInt32Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:609 + i * 100]; - } - [message setPackedSfixed32Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedSfixed32Array addValue:609 + i * 100]; } - { - GPBInt64Array *scratch = [GPBInt64Array array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:610 + i * 100]; - } - [message setPackedSfixed64Array:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedSfixed64Array addValue:610 + i * 100]; } - { - GPBFloatArray *scratch = [GPBFloatArray array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:611 + i * 100]; - } - [message setPackedFloatArray:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedFloatArray addValue:611 + i * 100]; } - { - GPBDoubleArray *scratch = [GPBDoubleArray array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:612 + i * 100]; - } - [message setPackedDoubleArray:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedDoubleArray addValue:612 + i * 100]; } - { - GPBBoolArray *scratch = [GPBBoolArray array]; - for (uint32_t i = 0; i < count; ++i) { - [scratch addValue:(i % 2) ? YES : NO]; - } - [message setPackedBoolArray:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedBoolArray addValue:(i % 2) ? YES : NO]; } - { - GPBEnumArray *scratch = - [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue]; - for (uint32_t i = 0; i < count; ++i) { - [scratch - addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz]; - } - [message setPackedEnumArray:scratch]; + for (uint32_t i = 0; i < count; ++i) { + [message.packedEnumArray + addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz]; + } +} + +- (void)setUnpackedFields:(TestUnpackedTypes *)message + repeatedCount:(uint32_t)count { + // Must match -setPackedFields:repeatedCount: + // Must match -setPackedExtensions:repeatedCount: + // Must match -setUnpackedExtensions:repeatedCount: + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedInt32Array addValue:601 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedInt64Array addValue:602 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedUint32Array addValue:603 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedUint64Array addValue:604 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedSint32Array addValue:605 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedSint64Array addValue:606 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedFixed32Array addValue:607 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedFixed64Array addValue:608 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedSfixed32Array addValue:609 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedSfixed64Array addValue:610 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedFloatArray addValue:611 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedDoubleArray addValue:612 + i * 100]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedBoolArray addValue:(i % 2) ? YES : NO]; + } + for (uint32_t i = 0; i < count; ++i) { + [message.unpackedEnumArray + addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz]; } } @@ -1708,6 +1853,9 @@ const uint32_t kGPBDefaultRepeatCount = 2; - (void)setPackedExtensions:(TestPackedExtensions *)message repeatedCount:(uint32_t)count { + // Must match -setPackedFields:repeatedCount: + // Must match -setUnpackedFields:repeatedCount: + // Must match -setUnpackedExtensions:repeatedCount: for (uint32_t i = 0; i < count; i++) { [message addExtension:[UnittestRoot packedInt32Extension] value:@(601 + i * 100)]; @@ -1741,6 +1889,44 @@ const uint32_t kGPBDefaultRepeatCount = 2; } } +- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message + repeatedCount:(uint32_t)count { + // Must match -setPackedFields:repeatedCount: + // Must match -setUnpackedFields:repeatedCount: + // Must match -setPackedExtensions:repeatedCount: + for (uint32_t i = 0; i < count; i++) { + [message addExtension:[UnittestRoot unpackedInt32Extension] + value:@(601 + i * 100)]; + [message addExtension:[UnittestRoot unpackedInt64Extension] + value:@(602 + i * 100)]; + [message addExtension:[UnittestRoot unpackedUint32Extension] + value:@(603 + i * 100)]; + [message addExtension:[UnittestRoot unpackedUint64Extension] + value:@(604 + i * 100)]; + [message addExtension:[UnittestRoot unpackedSint32Extension] + value:@(605 + i * 100)]; + [message addExtension:[UnittestRoot unpackedSint64Extension] + value:@(606 + i * 100)]; + [message addExtension:[UnittestRoot unpackedFixed32Extension] + value:@(607 + i * 100)]; + [message addExtension:[UnittestRoot unpackedFixed64Extension] + value:@(608 + i * 100)]; + [message addExtension:[UnittestRoot unpackedSfixed32Extension] + value:@(609 + i * 100)]; + [message addExtension:[UnittestRoot unpackedSfixed64Extension] + value:@(610 + i * 100)]; + [message addExtension:[UnittestRoot unpackedFloatExtension] + value:@(611 + i * 100)]; + [message addExtension:[UnittestRoot unpackedDoubleExtension] + value:@(612 + i * 100)]; + [message addExtension:[UnittestRoot unpackedBoolExtension] + value:@((i % 2) ? YES : NO)]; + [message addExtension:[UnittestRoot unpackedEnumExtension] + value:@((i % 2) ? ForeignEnum_ForeignBar + : ForeignEnum_ForeignBaz)]; + } +} + - (void)assertPackedExtensionsSet:(TestPackedExtensions *)message repeatedCount:(uint32_t)count{ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt32Extension]] count]); @@ -1884,6 +2070,34 @@ const uint32_t kGPBDefaultRepeatCount = 2; XCTAssertEqualObjects(message.repeatedStringPieceArray, [message valueForKey:@"repeatedStringPieceArray"]); XCTAssertEqualObjects(message.repeatedCordArray, [message valueForKey:@"repeatedCordArray"]); + XCTAssertEqualObjects(@(message.repeatedInt32Array_Count), [message valueForKey:@"repeatedInt32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedInt64Array_Count), [message valueForKey:@"repeatedInt64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedUint32Array_Count), [message valueForKey:@"repeatedUint32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedUint64Array_Count), [message valueForKey:@"repeatedUint64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedSint32Array_Count), [message valueForKey:@"repeatedSint32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedSint64Array_Count), [message valueForKey:@"repeatedSint64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedFixed32Array_Count), [message valueForKey:@"repeatedFixed32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedFixed64Array_Count), [message valueForKey:@"repeatedFixed64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedSfixed32Array_Count), [message valueForKey:@"repeatedSfixed32Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedSfixed64Array_Count), [message valueForKey:@"repeatedSfixed64Array_Count"]); + XCTAssertEqualObjects(@(message.repeatedFloatArray_Count), [message valueForKey:@"repeatedFloatArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedDoubleArray_Count), [message valueForKey:@"repeatedDoubleArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedBoolArray_Count), [message valueForKey:@"repeatedBoolArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedStringArray_Count), [message valueForKey:@"repeatedStringArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedBytesArray_Count), [message valueForKey:@"repeatedBytesArray_Count"]); + + XCTAssertEqualObjects(@(message.repeatedGroupArray_Count), [message valueForKey:@"repeatedGroupArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedNestedMessageArray_Count), [message valueForKey:@"repeatedNestedMessageArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedForeignMessageArray_Count), [message valueForKey:@"repeatedForeignMessageArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedImportMessageArray_Count), [message valueForKey:@"repeatedImportMessageArray_Count"]); + + XCTAssertEqualObjects(@(message.repeatedNestedEnumArray_Count), [message valueForKey:@"repeatedNestedEnumArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedForeignEnumArray_Count), [message valueForKey:@"repeatedForeignEnumArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedImportEnumArray_Count), [message valueForKey:@"repeatedImportEnumArray_Count"]); + + XCTAssertEqualObjects(@(message.repeatedStringPieceArray_Count), [message valueForKey:@"repeatedStringPieceArray_Count"]); + XCTAssertEqualObjects(@(message.repeatedCordArray_Count), [message valueForKey:@"repeatedCordArray_Count"]); + // ----------------------------------------------------------------- XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @YES); diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m index 2c271bf7..0a3fc583 100644 --- a/objectivec/Tests/GPBUnittestProtos.m +++ b/objectivec/Tests/GPBUnittestProtos.m @@ -40,16 +40,15 @@ #import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.m" #import "google/protobuf/UnittestEmpty.pbobjc.m" #import "google/protobuf/UnittestEnormousDescriptor.pbobjc.m" -#import "google/protobuf/UnittestFilter.pbobjc.m" #import "google/protobuf/UnittestImport.pbobjc.m" #import "google/protobuf/UnittestImportLite.pbobjc.m" #import "google/protobuf/UnittestImportPublic.pbobjc.m" #import "google/protobuf/UnittestImportPublicLite.pbobjc.m" #import "google/protobuf/UnittestLite.pbobjc.m" #import "google/protobuf/UnittestMset.pbobjc.m" -#import "google/protobuf/UnittestNameMangling.pbobjc.m" #import "google/protobuf/UnittestNoGenericServices.pbobjc.m" #import "google/protobuf/UnittestObjc.pbobjc.m" +#import "google/protobuf/UnittestObjcStartup.pbobjc.m" #import "google/protobuf/UnittestOptimizeFor.pbobjc.m" #import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m" #import "google/protobuf/UnittestRuntimeProto2.pbobjc.m" diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m index 491bba9e..01217ca6 100644 --- a/objectivec/Tests/GPBUnknownFieldSetTest.m +++ b/objectivec/Tests/GPBUnknownFieldSetTest.m @@ -30,7 +30,7 @@ #import "GPBTestUtilities.h" -#import "GPBField_PackagePrivate.h" +#import "GPBUnknownField_PackagePrivate.h" #import "GPBUnknownFieldSet_PackagePrivate.h" #import "google/protobuf/Unittest.pbobjc.h" @@ -60,7 +60,7 @@ unknownFields_ = emptyMessage_.unknownFields; } -- (GPBField*)getField:(int32_t)number { +- (GPBUnknownField *)getField:(int32_t)number { return [unknownFields_ getField:number]; } @@ -75,17 +75,17 @@ [unknownFields_ getTags:tags]; for (NSUInteger i = 0; i < count; ++i) { int32_t tag = tags[i]; - GPBField* field = [unknownFields_ getField:tag]; + GPBUnknownField* field = [unknownFields_ getField:tag]; if (field.varintList.count == 0) { // Original field is not a varint, so use a varint. - GPBField* varintField = - [[[GPBField alloc] initWithNumber:tag] autorelease]; + GPBUnknownField* varintField = + [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; [varintField addVarint:1]; [bizarroFields addField:varintField]; } else { // Original field *is* a varint, so use something else. - GPBField* fixed32Field = - [[[GPBField alloc] initWithNumber:tag] autorelease]; + GPBUnknownField* fixed32Field = + [[[GPBUnknownField alloc] initWithNumber:tag] autorelease]; [fixed32Field addFixed32:1]; [bizarroFields addField:fixed32Field]; } @@ -110,34 +110,34 @@ - (void)testMergeFrom { GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - GPBField* field = [[[GPBField alloc] initWithNumber:2] autorelease]; + GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field addVarint:2]; [set1 addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:4]; [set1 addField:field]; GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - field = [[[GPBField alloc] initWithNumber:1] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field addVarint:1]; [set2 addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:3]; [set2 addField:field]; GPBUnknownFieldSet* set3 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - field = [[[GPBField alloc] initWithNumber:1] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field addVarint:1]; [set3 addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:4]; [set3 addField:field]; GPBUnknownFieldSet* set4 = [[[GPBUnknownFieldSet alloc] init] autorelease]; - field = [[[GPBField alloc] initWithNumber:2] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field addVarint:2]; [set4 addField:field]; - field = [[[GPBField alloc] initWithNumber:3] autorelease]; + field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease]; [field addVarint:3]; [set4 addField:field]; @@ -162,7 +162,7 @@ } - (void)testClearMessage { - TestEmptyMessage* message = [TestEmptyMessage message]; + TestEmptyMessage *message = [TestEmptyMessage message]; [message mergeFrom:emptyMessage_]; [message clear]; XCTAssertEqual(message.serializedSize, (size_t)0); @@ -170,8 +170,9 @@ - (void)testParseKnownAndUnknown { // Test mixing known and unknown fields when parsing. - GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease]; - GPBField* field = [[[GPBField alloc] initWithNumber:123456] autorelease]; + GPBUnknownFieldSet *fields = [[unknownFields_ copy] autorelease]; + GPBUnknownField *field = + [[[GPBUnknownField alloc] initWithNumber:123456] autorelease]; [field addVarint:654321]; [fields addField:field]; @@ -181,7 +182,7 @@ [self assertAllFieldsSet:destination repeatedCount:kGPBDefaultRepeatCount]; XCTAssertEqual(destination.unknownFields.countOfFields, (NSUInteger)1); - GPBField* field2 = [destination.unknownFields getField:123456]; + GPBUnknownField* field2 = [destination.unknownFields getField:123456]; XCTAssertEqual(field2.varintList.count, (NSUInteger)1); XCTAssertEqual(654321ULL, [field2.varintList valueAtIndex:0]); } @@ -230,7 +231,7 @@ - (void)testLargeVarint { GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease]; - GPBField* field = [[[GPBField alloc] initWithNumber:1] autorelease]; + GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field addVarint:0x7FFFFFFFFFFFFFFFL]; [fields addField:field]; @@ -238,19 +239,19 @@ GPBUnknownFieldSet* parsed = [[[GPBUnknownFieldSet alloc] init] autorelease]; [parsed mergeFromData:data]; - GPBField* field2 = [parsed getField:1]; + GPBUnknownField* field2 = [parsed getField:1]; XCTAssertEqual(field2.varintList.count, (NSUInteger)1); XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]); } - (void)testMergingFields { - GPBField* field1 = [[[GPBField alloc] initWithNumber:1] autorelease]; + GPBUnknownField* field1 = [[[GPBUnknownField alloc] initWithNumber:1] autorelease]; [field1 addVarint:1]; [field1 addFixed32:2]; [field1 addFixed64:3]; [field1 addLengthDelimited:[NSData dataWithBytes:"hello" length:5]]; [field1 addGroup:[[unknownFields_ copy] autorelease]]; - GPBField* field2 = [[[GPBField alloc] initWithNumber:2] autorelease]; + GPBUnknownField* field2 = [[[GPBUnknownField alloc] initWithNumber:2] autorelease]; [field2 mergeFromField:field1]; XCTAssertEqualObjects(field1, field2); } diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m index 02de0197..ba1fc270 100644 --- a/objectivec/Tests/GPBUtilitiesTests.m +++ b/objectivec/Tests/GPBUtilitiesTests.m @@ -47,141 +47,6 @@ @interface UtilitiesTests : GPBTestCase @end -// Support code for testing -typedef struct { - uint32_t _has_storage_[1]; - BOOL aBool; - int32_t aInt32; - uint32_t aUInt32; - int64_t aInt64; - uint64_t aUInt64; - float aFloat; - double aDouble; - id aObject; - BOOL _hasTest; - BOOL stopper; - BOOL shouldNotBeCounted; - GPBInt32Array *anArray; -} ApplyFunctionsTest_Storage; - -@interface ApplyFunctionsTest : GPBMessage -@property(nonatomic, readwrite) BOOL aBool; -@property(nonatomic, readwrite) int32_t aInt32; -@property(nonatomic, readwrite) uint32_t aUInt32; -@property(nonatomic, readwrite) int64_t aInt64; -@property(nonatomic, readwrite) uint64_t aUInt64; -@property(nonatomic, readwrite) float aFloat; -@property(nonatomic, readwrite) double aDouble; -@property(nonatomic, readwrite, retain) id aObject; -@property(nonatomic, readwrite) BOOL _hasTest; -@property(nonatomic, readwrite) BOOL stopper; -@property(nonatomic, readwrite) BOOL shouldNotBeCounted; -@property(nonatomic, readwrite, retain) GPBInt32Array *anArray; -@end - -@implementation ApplyFunctionsTest - -@dynamic aBool, aInt32, aUInt32, aInt64, aUInt64, aFloat, aDouble, aObject; -@dynamic _hasTest, stopper, shouldNotBeCounted, anArray; - -+ (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; - if (!descriptor) { - static GPBMessageFieldDescription fields[] = { -#define FIELD_ENTRY(NAME, INDEX) \ - { \ - .name = "a" #NAME, .hasIndex = INDEX, .type = GPBType##NAME, \ - .offset = offsetof(ApplyFunctionsTest_Storage, a##NAME), \ - } - FIELD_ENTRY(Bool, 1), - FIELD_ENTRY(Int32, 2), - FIELD_ENTRY(UInt32, 3), - FIELD_ENTRY(Int64, 4), - FIELD_ENTRY(UInt64, 5), - FIELD_ENTRY(Float, 6), - FIELD_ENTRY(Double, 7), -#undef FIELD_ENTRY - { - .name = "aObject", - .type = GPBTypeString, - .hasIndex = 8, - .offset = offsetof(ApplyFunctionsTest_Storage, aObject), - }, - { - .name = "stopper", - .type = GPBTypeBool, - .hasIndex = 9, - .offset = offsetof(ApplyFunctionsTest_Storage, stopper), - }, - { - .name = "shouldNotBeCounted", - .type = GPBTypeBool, - .hasIndex = 10, - .offset = offsetof(ApplyFunctionsTest_Storage, shouldNotBeCounted), - }, - { - .name = "anArray", - .type = GPBTypeInt32, - .hasIndex = 11, - .flags = GPBFieldRepeated, - .offset = offsetof(ApplyFunctionsTest_Storage, anArray), - }, - }; - descriptor = [GPBDescriptor - allocDescriptorForClass:[self class] - rootClass:Nil - file:nil - fields:fields - fieldCount:sizeof(fields) / - sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(ApplyFunctionsTest_Storage) - wireFormat:NO]; - } - return descriptor; -} - -@end - -typedef struct { - int calledBool; - int calledInt32; - int calledUInt32; - int calledInt64; - int calledUInt64; - int calledFloat; - int calledDouble; - int calledObject; - int hitCount; -} TestApplyFunctionsContext; - -// Really, who needs templates? -// Macro for testing apply functions. Declares a variety of different functions -// base on |NAME|. -#define TEST_APPLY_FUNCTIONS_FUNC(NAME) \ - static BOOL TestApplyFunction##NAME(GPBFieldDescriptor *field, \ - void *voidContext) { \ - TestApplyFunctionsContext *context = voidContext; \ - if (field->getSel_ == sel_getUid("stopper")) return NO; \ - context->called##NAME += 1; \ - context->hitCount += 1; \ - return YES; \ - } - -TEST_APPLY_FUNCTIONS_FUNC(Bool) -TEST_APPLY_FUNCTIONS_FUNC(Int32) -TEST_APPLY_FUNCTIONS_FUNC(UInt32) -TEST_APPLY_FUNCTIONS_FUNC(Int64) -TEST_APPLY_FUNCTIONS_FUNC(UInt64) -TEST_APPLY_FUNCTIONS_FUNC(Float) -TEST_APPLY_FUNCTIONS_FUNC(Double) -TEST_APPLY_FUNCTIONS_FUNC(Object) - @implementation UtilitiesTests - (void)testRightShiftFunctions { @@ -194,61 +59,6 @@ TEST_APPLY_FUNCTIONS_FUNC(Object) XCTAssertEqual(GPBLogicalRightShift64((1LL << 63), 63), 1LL); } -- (void)testMutability { - ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message]; - XCTAssertEqual(0, [foo_message aInt32]); - [foo_message setAInt32:100]; - XCTAssertEqual(100, [foo_message aInt32]); -} - -- (void)testSerializedSize { - ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message]; - [foo_message setAInt32:100]; - size_t size1 = [foo_message serializedSize]; - [foo_message setAInt64:100]; - size_t size2 = [foo_message serializedSize]; - - // Intentionally doing a pointer comparison. - XCTAssertNotEqual(size1, size2); -} - -- (void)testCopying { - ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message]; - [foo_message setAInt32:100]; - [foo_message setAObject:@"Happy"]; - ApplyFunctionsTest *foo = [[foo_message copy] autorelease]; - XCTAssertNotEqual(foo, foo_message); // Pointer comparision - XCTAssertEqualObjects(foo, foo_message); -} - -- (void)testApplyFunctions { - // Covers ApplyFunctionsToProtoVariables and - // ApplyFunctionsBasedOnEncodingType. - // This test depends on the layout of the ivars to be in the order - // declared in the interface. If this is not true, it will fail and will - // need to be rewritten to accomodate. - TestApplyFunctionsContext context; - memset(&context, 0, sizeof(context)); - GPBApplyFunctions foo = GPBAPPLY_FUNCTIONS_INIT(TestApplyFunction); - ApplyFunctionsTest *msg = [ApplyFunctionsTest message]; - GPBApplyFunctionsToMessageFields(&foo, msg, &context); - - // Only eight vars should be set. - // "stopper" should cause the loop to quit so it and shouldNotBeCounted should - // not be counted. - // "_hasTest" should be skipped over. - // Each of the vars should only be set once. - XCTAssertEqual(context.hitCount, 8); - XCTAssertEqual(context.calledBool, 1); - XCTAssertEqual(context.calledInt32, 1); - XCTAssertEqual(context.calledUInt32, 1); - XCTAssertEqual(context.calledInt64, 1); - XCTAssertEqual(context.calledUInt64, 1); - XCTAssertEqual(context.calledFloat, 1); - XCTAssertEqual(context.calledDouble, 1); - XCTAssertEqual(context.calledObject, 1); -} - - (void)testGPBDecodeTextFormatName { uint8_t decodeData[] = { 0x6, diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m index fc5c4bda..d722d7b2 100644 --- a/objectivec/Tests/GPBWireFormatTests.m +++ b/objectivec/Tests/GPBWireFormatTests.m @@ -32,7 +32,7 @@ #import "GPBCodedInputStream.h" #import "GPBMessage_PackagePrivate.h" -#import "GPBField_PackagePrivate.h" +#import "GPBUnknownField_PackagePrivate.h" #import "google/protobuf/Unittest.pbobjc.h" #import "google/protobuf/UnittestMset.pbobjc.h" @@ -143,8 +143,8 @@ const int kUnknownTypeId = 1550055; setI:123]; [[message_set getExtension:[TestMessageSetExtension2 messageSetExtension]] setStr:@"foo"]; - GPBField* unknownField = - [[[GPBField alloc] initWithNumber:kUnknownTypeId] autorelease]; + GPBUnknownField* unknownField = + [[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease]; [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]]; GPBUnknownFieldSet* unknownFieldSet = [[[GPBUnknownFieldSet alloc] init] autorelease]; @@ -159,9 +159,9 @@ const int kUnknownTypeId = 1550055; XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0); XCTAssertEqual(raw.itemArray.count, (NSUInteger)3); - XCTAssertEqual([raw.itemArray[0] typeId], + XCTAssertEqual((uint32_t)[raw.itemArray[0] typeId], [TestMessageSetExtension1 messageSetExtension].fieldNumber); - XCTAssertEqual([raw.itemArray[1] typeId], + XCTAssertEqual((uint32_t)[raw.itemArray[1] typeId], [TestMessageSetExtension2 messageSetExtension].fieldNumber); XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId); @@ -227,7 +227,7 @@ const int kUnknownTypeId = 1550055; @"foo"); XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1); - GPBField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId]; + GPBUnknownField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId]; XCTAssertNotNil(unknownField); XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1); XCTAssertEqualObjects(unknownField.lengthDelimitedList[0], diff --git a/objectivec/Tests/unittest_filter.proto b/objectivec/Tests/unittest_filter.proto deleted file mode 100644 index 1398dfc8..00000000 --- a/objectivec/Tests/unittest_filter.proto +++ /dev/null @@ -1,71 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2013 Google Inc. All rights reserved. -// -// 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. - -syntax = "proto2"; - -package protobuf_unittest; - - -message Keep { -} - -message Remove { -} - -message RemoveJustKidding { -} - -message Other { - optional Keep a = 1; - optional Remove b = 2; -} - -enum RemoveEnum { - RemoveValue = 1; -} - -enum KeepEnum { - KeepValue = 1; -} - -message RemoveEnumMessage { - enum KeepEnumInside { - KeepValue = 1; - } - - enum RemoveEnumInside { - RemoveValue = 1; - } - - message KeepNestedInside { - } - - message RemoveNestedInside { - } -} diff --git a/objectivec/Tests/unittest_name_mangling.proto b/objectivec/Tests/unittest_name_mangling.proto deleted file mode 100644 index aadad6d6..00000000 --- a/objectivec/Tests/unittest_name_mangling.proto +++ /dev/null @@ -1,37 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2015 Google Inc. All rights reserved. -// -// 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. - -syntax = "proto2"; - -option objc_class_prefix = "ABC"; - -package protobuf_unittest; - -// TODO(thomasvl): Add tests for the special cases in name mangling. - diff --git a/objectivec/Tests/unittest_objc_startup.proto b/objectivec/Tests/unittest_objc_startup.proto new file mode 100644 index 00000000..aee7bd55 --- /dev/null +++ b/objectivec/Tests/unittest_objc_startup.proto @@ -0,0 +1,49 @@ +// 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. + +syntax = "proto2"; + +package protobuf_objc_unittest; + +message TestObjCStartupMessage { + extensions 1 to max; +} + +extend TestObjCStartupMessage { + // Singular + optional int32 optional_int32_extension = 1; + repeated int32 repeated_int32_extension = 2; +} + +message TestObjCStartupNested { + extend TestObjCStartupMessage { + optional string nested_string_extension = 3; + } +} diff --git a/objectivec/google/protobuf/Any.pbobjc.m b/objectivec/google/protobuf/Any.pbobjc.m index 4db73cb9..b41102a4 100644 --- a/objectivec/google/protobuf/Any.pbobjc.m +++ b/objectivec/google/protobuf/Any.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBAnyRoot_FileDescriptor + static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -29,16 +32,16 @@ static GPBFileDescriptor *GPBAnyRoot_FileDescriptor(void) { @dynamic typeURL; @dynamic value; -typedef struct GPBAny_Storage { +typedef struct GPBAny__storage_ { uint32_t _has_storage_[1]; NSString *typeURL; NSData *value; -} GPBAny_Storage; +} GPBAny__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -46,10 +49,10 @@ typedef struct GPBAny_Storage { .number = GPBAny_FieldNumber_TypeURL, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, - .type = GPBTypeString, - .offset = offsetof(GPBAny_Storage, typeURL), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBAny__storage_, typeURL), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -57,10 +60,10 @@ typedef struct GPBAny_Storage { .number = GPBAny_FieldNumber_Value, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeData, - .offset = offsetof(GPBAny_Storage, value), + .dataType = GPBDataTypeBytes, + .offset = offsetof(GPBAny__storage_, value), .defaultValue.valueData = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; @@ -69,20 +72,23 @@ typedef struct GPBAny_Storage { #else static const char *extraTextFormatInfo = "\001\001\004\241!!\000"; #endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBAny class] - rootClass:[GPBAnyRoot class] - file:GPBAnyRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBAny_Storage) - wireFormat:NO - extraTextFormatInfo:extraTextFormatInfo]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBAny class] + rootClass:[GPBAnyRoot class] + file:GPBAnyRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBAny__storage_) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Api.pbobjc.h b/objectivec/google/protobuf/Api.pbobjc.h index 9e6fc850..061347be 100644 --- a/objectivec/google/protobuf/Api.pbobjc.h +++ b/objectivec/google/protobuf/Api.pbobjc.h @@ -45,10 +45,12 @@ typedef GPB_ENUM(GPBApi_FieldNumber) { // The methods of this api, in unspecified order. // |methodsArray| contains |GPBMethod| @property(nonatomic, readwrite, strong) NSMutableArray *methodsArray; +@property(nonatomic, readonly) NSUInteger methodsArray_Count; // Any metadata attached to the API. // |optionsArray| contains |GPBOption| @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; // A version string for this api. If specified, must have the form // `major-version.minor-version`, as in `1.10`. If the minor version @@ -113,6 +115,7 @@ typedef GPB_ENUM(GPBMethod_FieldNumber) { // Any metadata attached to the method. // |optionsArray| contains |GPBOption| @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; @end diff --git a/objectivec/google/protobuf/Api.pbobjc.m b/objectivec/google/protobuf/Api.pbobjc.m index 9416860a..c2be94ab 100644 --- a/objectivec/google/protobuf/Api.pbobjc.m +++ b/objectivec/google/protobuf/Api.pbobjc.m @@ -16,10 +16,8 @@ // about thread safety and initialization of registry. static GPBExtensionRegistry* registry = nil; if (!registry) { + GPBDebugCheckRuntimeVersion(); registry = [[GPBExtensionRegistry alloc] init]; - static GPBExtensionDescription descriptions[] = { - }; - #pragma unused (descriptions) [registry addExtensions:[GPBSourceContextRoot extensionRegistry]]; [registry addExtensions:[GPBTypeRoot extensionRegistry]]; } @@ -28,11 +26,14 @@ @end +#pragma mark - GPBApiRoot_FileDescriptor + static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -44,24 +45,24 @@ static GPBFileDescriptor *GPBApiRoot_FileDescriptor(void) { @implementation GPBApi @dynamic name; -@dynamic methodsArray; -@dynamic optionsArray; +@dynamic methodsArray, methodsArray_Count; +@dynamic optionsArray, optionsArray_Count; @dynamic version; @dynamic hasSourceContext, sourceContext; -typedef struct GPBApi_Storage { +typedef struct GPBApi__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *methodsArray; NSMutableArray *optionsArray; NSString *version; GPBSourceContext *sourceContext; -} GPBApi_Storage; +} GPBApi__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -69,10 +70,10 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBApi_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBApi__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -80,10 +81,10 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_MethodsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBApi_Storage, methodsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBApi__storage_, methodsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBMethod), + .dataTypeSpecific.className = GPBStringifySymbol(GPBMethod), .fieldOptions = NULL, }, { @@ -91,10 +92,10 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBApi_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBApi__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, { @@ -102,10 +103,10 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_Version, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBApi_Storage, version), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBApi__storage_, version), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -113,26 +114,29 @@ typedef struct GPBApi_Storage { .number = GPBApi_FieldNumber_SourceContext, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBApi_Storage, sourceContext), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBApi__storage_, sourceContext), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBApi class] - rootClass:[GPBApiRoot class] - file:GPBApiRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBApi_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBApi class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBApi__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -148,9 +152,9 @@ typedef struct GPBApi_Storage { @dynamic requestStreaming; @dynamic responseTypeURL; @dynamic responseStreaming; -@dynamic optionsArray; +@dynamic optionsArray, optionsArray_Count; -typedef struct GPBMethod_Storage { +typedef struct GPBMethod__storage_ { uint32_t _has_storage_[1]; BOOL requestStreaming; BOOL responseStreaming; @@ -158,12 +162,12 @@ typedef struct GPBMethod_Storage { NSString *requestTypeURL; NSString *responseTypeURL; NSMutableArray *optionsArray; -} GPBMethod_Storage; +} GPBMethod__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -171,10 +175,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBMethod_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethod__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -182,10 +186,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_RequestTypeURL, .hasIndex = 1, .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, - .type = GPBTypeString, - .offset = offsetof(GPBMethod_Storage, requestTypeURL), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethod__storage_, requestTypeURL), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -193,10 +197,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_RequestStreaming, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBMethod_Storage, requestStreaming), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethod__storage_, requestStreaming), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -204,10 +208,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_ResponseTypeURL, .hasIndex = 3, .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, - .type = GPBTypeString, - .offset = offsetof(GPBMethod_Storage, responseTypeURL), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethod__storage_, responseTypeURL), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -215,10 +219,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_ResponseStreaming, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBMethod_Storage, responseStreaming), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethod__storage_, responseStreaming), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -226,10 +230,10 @@ typedef struct GPBMethod_Storage { .number = GPBMethod_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBMethod_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBMethod__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, }; @@ -238,20 +242,23 @@ typedef struct GPBMethod_Storage { #else static const char *extraTextFormatInfo = "\002\002\007\244\241!!\000\004\010\244\241!!\000"; #endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethod class] - rootClass:[GPBApiRoot class] - file:GPBApiRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBMethod_Storage) - wireFormat:NO - extraTextFormatInfo:extraTextFormatInfo]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMethod class] + rootClass:[GPBApiRoot class] + file:GPBApiRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBMethod__storage_) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.h b/objectivec/google/protobuf/Descriptor.pbobjc.h index 5a53abbc..e0106534 100644 --- a/objectivec/google/protobuf/Descriptor.pbobjc.h +++ b/objectivec/google/protobuf/Descriptor.pbobjc.h @@ -152,6 +152,7 @@ typedef GPB_ENUM(GPBFileDescriptorSet_FieldNumber) { // |fileArray| contains |GPBFileDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *fileArray; +@property(nonatomic, readonly) NSUInteger fileArray_Count; @end @@ -186,26 +187,33 @@ typedef GPB_ENUM(GPBFileDescriptorProto_FieldNumber) { // Names of files imported by this file. // |dependencyArray| contains |NSString| @property(nonatomic, readwrite, strong) NSMutableArray *dependencyArray; +@property(nonatomic, readonly) NSUInteger dependencyArray_Count; // Indexes of the public imported files in the dependency list above. @property(nonatomic, readwrite, strong) GPBInt32Array *publicDependencyArray; +@property(nonatomic, readonly) NSUInteger publicDependencyArray_Count; // Indexes of the weak imported files in the dependency list. // For Google-internal migration only. Do not use. @property(nonatomic, readwrite, strong) GPBInt32Array *weakDependencyArray; +@property(nonatomic, readonly) NSUInteger weakDependencyArray_Count; // All top-level definitions in this file. // |messageTypeArray| contains |GPBDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *messageTypeArray; +@property(nonatomic, readonly) NSUInteger messageTypeArray_Count; // |enumTypeArray| contains |GPBEnumDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *enumTypeArray; +@property(nonatomic, readonly) NSUInteger enumTypeArray_Count; // |serviceArray| contains |GPBServiceDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *serviceArray; +@property(nonatomic, readonly) NSUInteger serviceArray_Count; // |extensionArray| contains |GPBFieldDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *extensionArray; +@property(nonatomic, readonly) NSUInteger extensionArray_Count; @property(nonatomic, readwrite) BOOL hasOptions; @property(nonatomic, readwrite, strong) GPBFileOptions *options; @@ -247,32 +255,40 @@ typedef GPB_ENUM(GPBDescriptorProto_FieldNumber) { // |fieldArray| contains |GPBFieldDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *fieldArray; +@property(nonatomic, readonly) NSUInteger fieldArray_Count; // |extensionArray| contains |GPBFieldDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *extensionArray; +@property(nonatomic, readonly) NSUInteger extensionArray_Count; // |nestedTypeArray| contains |GPBDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *nestedTypeArray; +@property(nonatomic, readonly) NSUInteger nestedTypeArray_Count; // |enumTypeArray| contains |GPBEnumDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *enumTypeArray; +@property(nonatomic, readonly) NSUInteger enumTypeArray_Count; // |extensionRangeArray| contains |GPBDescriptorProto_ExtensionRange| @property(nonatomic, readwrite, strong) NSMutableArray *extensionRangeArray; +@property(nonatomic, readonly) NSUInteger extensionRangeArray_Count; // |oneofDeclArray| contains |GPBOneofDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *oneofDeclArray; +@property(nonatomic, readonly) NSUInteger oneofDeclArray_Count; @property(nonatomic, readwrite) BOOL hasOptions; @property(nonatomic, readwrite, strong) GPBMessageOptions *options; // |reservedRangeArray| contains |GPBDescriptorProto_ReservedRange| @property(nonatomic, readwrite, strong) NSMutableArray *reservedRangeArray; +@property(nonatomic, readonly) NSUInteger reservedRangeArray_Count; // Reserved field names, which may not be used by fields in the same message. // A given name may only be reserved once. // |reservedNameArray| contains |NSString| @property(nonatomic, readwrite, strong) NSMutableArray *reservedNameArray; +@property(nonatomic, readonly) NSUInteger reservedNameArray_Count; @end @@ -407,6 +423,7 @@ typedef GPB_ENUM(GPBEnumDescriptorProto_FieldNumber) { // |valueArray| contains |GPBEnumValueDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *valueArray; +@property(nonatomic, readonly) NSUInteger valueArray_Count; @property(nonatomic, readwrite) BOOL hasOptions; @property(nonatomic, readwrite, strong) GPBEnumOptions *options; @@ -451,6 +468,7 @@ typedef GPB_ENUM(GPBServiceDescriptorProto_FieldNumber) { // |methodArray| contains |GPBMethodDescriptorProto| @property(nonatomic, readwrite, strong) NSMutableArray *methodArray; +@property(nonatomic, readonly) NSUInteger methodArray_Count; @property(nonatomic, readwrite) BOOL hasOptions; @property(nonatomic, readwrite, strong) GPBServiceOptions *options; @@ -617,6 +635,7 @@ typedef GPB_ENUM(GPBFileOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -693,6 +712,7 @@ typedef GPB_ENUM(GPBMessageOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -782,6 +802,7 @@ typedef GPB_ENUM(GPBFieldOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -810,6 +831,7 @@ typedef GPB_ENUM(GPBEnumOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -832,6 +854,7 @@ typedef GPB_ENUM(GPBEnumValueOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -854,6 +877,7 @@ typedef GPB_ENUM(GPBServiceOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -876,6 +900,7 @@ typedef GPB_ENUM(GPBMethodOptions_FieldNumber) { // The parser stores options it doesn't recognize here. See above. // |uninterpretedOptionArray| contains |GPBUninterpretedOption| @property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray; +@property(nonatomic, readonly) NSUInteger uninterpretedOptionArray_Count; @end @@ -901,6 +926,7 @@ typedef GPB_ENUM(GPBUninterpretedOption_FieldNumber) { // |nameArray| contains |GPBUninterpretedOption_NamePart| @property(nonatomic, readwrite, strong) NSMutableArray *nameArray; +@property(nonatomic, readonly) NSUInteger nameArray_Count; // The value of the uninterpreted option, in whatever type the tokenizer // identified it as during parsing. Exactly one of these should be set. @@ -1001,6 +1027,7 @@ typedef GPB_ENUM(GPBSourceCodeInfo_FieldNumber) { // be recorded in the future. // |locationArray| contains |GPBSourceCodeInfo_Location| @property(nonatomic, readwrite, strong) NSMutableArray *locationArray; +@property(nonatomic, readonly) NSUInteger locationArray_Count; @end @@ -1040,6 +1067,7 @@ typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) { // this path refers to the whole field declaration (from the beginning // of the label to the terminating semicolon). @property(nonatomic, readwrite, strong) GPBInt32Array *pathArray; +@property(nonatomic, readonly) NSUInteger pathArray_Count; // Always has exactly three or four elements: start line, start column, // end line (optional, otherwise assumed same as start line), end column. @@ -1047,6 +1075,7 @@ typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) { // and column numbers are zero-based -- typically you will want to add // 1 to each before displaying to a user. @property(nonatomic, readwrite, strong) GPBInt32Array *spanArray; +@property(nonatomic, readonly) NSUInteger spanArray_Count; // If this SourceCodeInfo represents a complete declaration, these are any // comments appearing before and after the declaration which appear to be @@ -1103,6 +1132,7 @@ typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) { // |leadingDetachedCommentsArray| contains |NSString| @property(nonatomic, readwrite, strong) NSMutableArray *leadingDetachedCommentsArray; +@property(nonatomic, readonly) NSUInteger leadingDetachedCommentsArray_Count; @end diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.m b/objectivec/google/protobuf/Descriptor.pbobjc.m index 7f1bdd49..8c535b9a 100644 --- a/objectivec/google/protobuf/Descriptor.pbobjc.m +++ b/objectivec/google/protobuf/Descriptor.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBDescriptorRoot_FileDescriptor + static GPBFileDescriptor *GPBDescriptorRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto2]; } @@ -26,17 +29,17 @@ static GPBFileDescriptor *GPBDescriptorRoot_FileDescriptor(void) { @implementation GPBFileDescriptorSet -@dynamic fileArray; +@dynamic fileArray, fileArray_Count; -typedef struct GPBFileDescriptorSet_Storage { +typedef struct GPBFileDescriptorSet__storage_ { uint32_t _has_storage_[1]; NSMutableArray *fileArray; -} GPBFileDescriptorSet_Storage; +} GPBFileDescriptorSet__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -44,26 +47,29 @@ typedef struct GPBFileDescriptorSet_Storage { .number = GPBFileDescriptorSet_FieldNumber_FileArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorSet_Storage, fileArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorSet__storage_, fileArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFileDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFileDescriptorProto), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorSet class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBFileDescriptorSet_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorSet class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFileDescriptorSet__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -76,18 +82,18 @@ typedef struct GPBFileDescriptorSet_Storage { @dynamic hasName, name; @dynamic hasPackage, package; -@dynamic dependencyArray; -@dynamic publicDependencyArray; -@dynamic weakDependencyArray; -@dynamic messageTypeArray; -@dynamic enumTypeArray; -@dynamic serviceArray; -@dynamic extensionArray; +@dynamic dependencyArray, dependencyArray_Count; +@dynamic publicDependencyArray, publicDependencyArray_Count; +@dynamic weakDependencyArray, weakDependencyArray_Count; +@dynamic messageTypeArray, messageTypeArray_Count; +@dynamic enumTypeArray, enumTypeArray_Count; +@dynamic serviceArray, serviceArray_Count; +@dynamic extensionArray, extensionArray_Count; @dynamic hasOptions, options; @dynamic hasSourceCodeInfo, sourceCodeInfo; @dynamic hasSyntax, syntax; -typedef struct GPBFileDescriptorProto_Storage { +typedef struct GPBFileDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; NSString *package; @@ -101,12 +107,12 @@ typedef struct GPBFileDescriptorProto_Storage { GPBInt32Array *publicDependencyArray; GPBInt32Array *weakDependencyArray; NSString *syntax; -} GPBFileDescriptorProto_Storage; +} GPBFileDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -114,10 +120,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -125,10 +131,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_Package, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileDescriptorProto_Storage, package), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileDescriptorProto__storage_, package), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -136,10 +142,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_DependencyArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBFileDescriptorProto_Storage, dependencyArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileDescriptorProto__storage_, dependencyArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -147,10 +153,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_MessageTypeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, messageTypeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, messageTypeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto), .fieldOptions = NULL, }, { @@ -158,10 +164,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_EnumTypeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, enumTypeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, enumTypeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto), .fieldOptions = NULL, }, { @@ -169,10 +175,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_ServiceArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, serviceArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, serviceArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBServiceDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBServiceDescriptorProto), .fieldOptions = NULL, }, { @@ -180,10 +186,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_ExtensionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, extensionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, extensionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), .fieldOptions = NULL, }, { @@ -191,10 +197,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_Options, .hasIndex = 9, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFileOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFileOptions), .fieldOptions = NULL, }, { @@ -202,10 +208,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_SourceCodeInfo, .hasIndex = 10, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileDescriptorProto_Storage, sourceCodeInfo), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileDescriptorProto__storage_, sourceCodeInfo), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo), .fieldOptions = NULL, }, { @@ -213,10 +219,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_PublicDependencyArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeInt32, - .offset = offsetof(GPBFileDescriptorProto_Storage, publicDependencyArray), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBFileDescriptorProto__storage_, publicDependencyArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -224,10 +230,10 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_WeakDependencyArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeInt32, - .offset = offsetof(GPBFileDescriptorProto_Storage, weakDependencyArray), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBFileDescriptorProto__storage_, weakDependencyArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -235,26 +241,29 @@ typedef struct GPBFileDescriptorProto_Storage { .number = GPBFileDescriptorProto_FieldNumber_Syntax, .hasIndex = 11, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileDescriptorProto_Storage, syntax), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileDescriptorProto__storage_, syntax), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorProto class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBFileDescriptorProto_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorProto class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFileDescriptorProto__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -266,17 +275,17 @@ typedef struct GPBFileDescriptorProto_Storage { @implementation GPBDescriptorProto @dynamic hasName, name; -@dynamic fieldArray; -@dynamic extensionArray; -@dynamic nestedTypeArray; -@dynamic enumTypeArray; -@dynamic extensionRangeArray; -@dynamic oneofDeclArray; +@dynamic fieldArray, fieldArray_Count; +@dynamic extensionArray, extensionArray_Count; +@dynamic nestedTypeArray, nestedTypeArray_Count; +@dynamic enumTypeArray, enumTypeArray_Count; +@dynamic extensionRangeArray, extensionRangeArray_Count; +@dynamic oneofDeclArray, oneofDeclArray_Count; @dynamic hasOptions, options; -@dynamic reservedRangeArray; -@dynamic reservedNameArray; +@dynamic reservedRangeArray, reservedRangeArray_Count; +@dynamic reservedNameArray, reservedNameArray_Count; -typedef struct GPBDescriptorProto_Storage { +typedef struct GPBDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *fieldArray; @@ -288,12 +297,12 @@ typedef struct GPBDescriptorProto_Storage { NSMutableArray *oneofDeclArray; NSMutableArray *reservedRangeArray; NSMutableArray *reservedNameArray; -} GPBDescriptorProto_Storage; +} GPBDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -301,10 +310,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -312,10 +321,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_FieldArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, fieldArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, fieldArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), .fieldOptions = NULL, }, { @@ -323,10 +332,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_NestedTypeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, nestedTypeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, nestedTypeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto), .fieldOptions = NULL, }, { @@ -334,10 +343,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_EnumTypeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, enumTypeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, enumTypeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto), .fieldOptions = NULL, }, { @@ -345,10 +354,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_ExtensionRangeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, extensionRangeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, extensionRangeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ExtensionRange), + .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ExtensionRange), .fieldOptions = NULL, }, { @@ -356,10 +365,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_ExtensionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, extensionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, extensionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto), .fieldOptions = NULL, }, { @@ -367,10 +376,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_Options, .hasIndex = 7, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBMessageOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBMessageOptions), .fieldOptions = NULL, }, { @@ -378,10 +387,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_OneofDeclArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, oneofDeclArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, oneofDeclArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOneofDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOneofDescriptorProto), .fieldOptions = NULL, }, { @@ -389,10 +398,10 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_ReservedRangeArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBDescriptorProto_Storage, reservedRangeArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBDescriptorProto__storage_, reservedRangeArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ReservedRange), + .dataTypeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ReservedRange), .fieldOptions = NULL, }, { @@ -400,26 +409,29 @@ typedef struct GPBDescriptorProto_Storage { .number = GPBDescriptorProto_FieldNumber_ReservedNameArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBDescriptorProto_Storage, reservedNameArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBDescriptorProto__storage_, reservedNameArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBDescriptorProto_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBDescriptorProto__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -433,16 +445,16 @@ typedef struct GPBDescriptorProto_Storage { @dynamic hasStart, start; @dynamic hasEnd, end; -typedef struct GPBDescriptorProto_ExtensionRange_Storage { +typedef struct GPBDescriptorProto_ExtensionRange__storage_ { uint32_t _has_storage_[1]; int32_t start; int32_t end; -} GPBDescriptorProto_ExtensionRange_Storage; +} GPBDescriptorProto_ExtensionRange__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -450,10 +462,10 @@ typedef struct GPBDescriptorProto_ExtensionRange_Storage { .number = GPBDescriptorProto_ExtensionRange_FieldNumber_Start, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDescriptorProto_ExtensionRange_Storage, start), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDescriptorProto_ExtensionRange__storage_, start), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -461,26 +473,29 @@ typedef struct GPBDescriptorProto_ExtensionRange_Storage { .number = GPBDescriptorProto_ExtensionRange_FieldNumber_End, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDescriptorProto_ExtensionRange_Storage, end), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDescriptorProto_ExtensionRange__storage_, end), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ExtensionRange class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBDescriptorProto_ExtensionRange_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ExtensionRange class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBDescriptorProto_ExtensionRange__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -494,16 +509,16 @@ typedef struct GPBDescriptorProto_ExtensionRange_Storage { @dynamic hasStart, start; @dynamic hasEnd, end; -typedef struct GPBDescriptorProto_ReservedRange_Storage { +typedef struct GPBDescriptorProto_ReservedRange__storage_ { uint32_t _has_storage_[1]; int32_t start; int32_t end; -} GPBDescriptorProto_ReservedRange_Storage; +} GPBDescriptorProto_ReservedRange__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -511,10 +526,10 @@ typedef struct GPBDescriptorProto_ReservedRange_Storage { .number = GPBDescriptorProto_ReservedRange_FieldNumber_Start, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDescriptorProto_ReservedRange_Storage, start), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDescriptorProto_ReservedRange__storage_, start), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -522,26 +537,29 @@ typedef struct GPBDescriptorProto_ReservedRange_Storage { .number = GPBDescriptorProto_ReservedRange_FieldNumber_End, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDescriptorProto_ReservedRange_Storage, end), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDescriptorProto_ReservedRange__storage_, end), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ReservedRange class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBDescriptorProto_ReservedRange_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ReservedRange class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBDescriptorProto_ReservedRange__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -562,7 +580,7 @@ typedef struct GPBDescriptorProto_ReservedRange_Storage { @dynamic hasOneofIndex, oneofIndex; @dynamic hasOptions, options; -typedef struct GPBFieldDescriptorProto_Storage { +typedef struct GPBFieldDescriptorProto__storage_ { uint32_t _has_storage_[1]; int32_t number; GPBFieldDescriptorProto_Label label; @@ -573,12 +591,12 @@ typedef struct GPBFieldDescriptorProto_Storage { NSString *typeName; NSString *defaultValue; GPBFieldOptions *options; -} GPBFieldDescriptorProto_Storage; +} GPBFieldDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -586,10 +604,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFieldDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -597,10 +615,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Extendee, .hasIndex = 5, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFieldDescriptorProto_Storage, extendee), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldDescriptorProto__storage_, extendee), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -608,10 +626,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Number, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBFieldDescriptorProto_Storage, number), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBFieldDescriptorProto__storage_, number), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -619,10 +637,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Label, .hasIndex = 2, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFieldDescriptorProto_Storage, label), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFieldDescriptorProto__storage_, label), .defaultValue.valueEnum = GPBFieldDescriptorProto_Label_LabelOptional, - .typeSpecific.enumDescFunc = GPBFieldDescriptorProto_Label_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFieldDescriptorProto_Label_EnumDescriptor, .fieldOptions = NULL, }, { @@ -630,10 +648,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Type, .hasIndex = 3, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFieldDescriptorProto_Storage, type), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFieldDescriptorProto__storage_, type), .defaultValue.valueEnum = GPBFieldDescriptorProto_Type_TypeDouble, - .typeSpecific.enumDescFunc = GPBFieldDescriptorProto_Type_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFieldDescriptorProto_Type_EnumDescriptor, .fieldOptions = NULL, }, { @@ -641,10 +659,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_TypeName, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFieldDescriptorProto_Storage, typeName), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldDescriptorProto__storage_, typeName), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -652,10 +670,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_DefaultValue, .hasIndex = 6, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFieldDescriptorProto_Storage, defaultValue), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldDescriptorProto__storage_, defaultValue), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -663,10 +681,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_Options, .hasIndex = 8, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBFieldDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFieldDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBFieldOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBFieldOptions), .fieldOptions = NULL, }, { @@ -674,10 +692,10 @@ typedef struct GPBFieldDescriptorProto_Storage { .number = GPBFieldDescriptorProto_FieldNumber_OneofIndex, .hasIndex = 7, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBFieldDescriptorProto_Storage, oneofIndex), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBFieldDescriptorProto__storage_, oneofIndex), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; @@ -685,19 +703,22 @@ typedef struct GPBFieldDescriptorProto_Storage { { .enumDescriptorFunc = GPBFieldDescriptorProto_Type_EnumDescriptor }, { .enumDescriptorFunc = GPBFieldDescriptorProto_Label_EnumDescriptor }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldDescriptorProto class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:enums - enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBFieldDescriptorProto_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFieldDescriptorProto class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:enums + enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFieldDescriptorProto__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -798,15 +819,15 @@ BOOL GPBFieldDescriptorProto_Label_IsValidValue(int32_t value__) { @dynamic hasName, name; -typedef struct GPBOneofDescriptorProto_Storage { +typedef struct GPBOneofDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; -} GPBOneofDescriptorProto_Storage; +} GPBOneofDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -814,26 +835,29 @@ typedef struct GPBOneofDescriptorProto_Storage { .number = GPBOneofDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBOneofDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBOneofDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBOneofDescriptorProto class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBOneofDescriptorProto_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBOneofDescriptorProto class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBOneofDescriptorProto__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -845,20 +869,20 @@ typedef struct GPBOneofDescriptorProto_Storage { @implementation GPBEnumDescriptorProto @dynamic hasName, name; -@dynamic valueArray; +@dynamic valueArray, valueArray_Count; @dynamic hasOptions, options; -typedef struct GPBEnumDescriptorProto_Storage { +typedef struct GPBEnumDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *valueArray; GPBEnumOptions *options; -} GPBEnumDescriptorProto_Storage; +} GPBEnumDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -866,10 +890,10 @@ typedef struct GPBEnumDescriptorProto_Storage { .number = GPBEnumDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBEnumDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBEnumDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -877,10 +901,10 @@ typedef struct GPBEnumDescriptorProto_Storage { .number = GPBEnumDescriptorProto_FieldNumber_ValueArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumDescriptorProto_Storage, valueArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumDescriptorProto__storage_, valueArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumValueDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValueDescriptorProto), .fieldOptions = NULL, }, { @@ -888,26 +912,29 @@ typedef struct GPBEnumDescriptorProto_Storage { .number = GPBEnumDescriptorProto_FieldNumber_Options, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumOptions), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumDescriptorProto class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBEnumDescriptorProto_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumDescriptorProto class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEnumDescriptorProto__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -922,17 +949,17 @@ typedef struct GPBEnumDescriptorProto_Storage { @dynamic hasNumber, number; @dynamic hasOptions, options; -typedef struct GPBEnumValueDescriptorProto_Storage { +typedef struct GPBEnumValueDescriptorProto__storage_ { uint32_t _has_storage_[1]; int32_t number; NSString *name; GPBEnumValueOptions *options; -} GPBEnumValueDescriptorProto_Storage; +} GPBEnumValueDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -940,10 +967,10 @@ typedef struct GPBEnumValueDescriptorProto_Storage { .number = GPBEnumValueDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBEnumValueDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBEnumValueDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -951,10 +978,10 @@ typedef struct GPBEnumValueDescriptorProto_Storage { .number = GPBEnumValueDescriptorProto_FieldNumber_Number, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBEnumValueDescriptorProto_Storage, number), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBEnumValueDescriptorProto__storage_, number), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -962,26 +989,29 @@ typedef struct GPBEnumValueDescriptorProto_Storage { .number = GPBEnumValueDescriptorProto_FieldNumber_Options, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumValueDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumValueDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumValueOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValueOptions), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValueDescriptorProto class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBEnumValueDescriptorProto_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumValueDescriptorProto class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEnumValueDescriptorProto__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -993,20 +1023,20 @@ typedef struct GPBEnumValueDescriptorProto_Storage { @implementation GPBServiceDescriptorProto @dynamic hasName, name; -@dynamic methodArray; +@dynamic methodArray, methodArray_Count; @dynamic hasOptions, options; -typedef struct GPBServiceDescriptorProto_Storage { +typedef struct GPBServiceDescriptorProto__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *methodArray; GPBServiceOptions *options; -} GPBServiceDescriptorProto_Storage; +} GPBServiceDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1014,10 +1044,10 @@ typedef struct GPBServiceDescriptorProto_Storage { .number = GPBServiceDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBServiceDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBServiceDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1025,10 +1055,10 @@ typedef struct GPBServiceDescriptorProto_Storage { .number = GPBServiceDescriptorProto_FieldNumber_MethodArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBServiceDescriptorProto_Storage, methodArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBServiceDescriptorProto__storage_, methodArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBMethodDescriptorProto), + .dataTypeSpecific.className = GPBStringifySymbol(GPBMethodDescriptorProto), .fieldOptions = NULL, }, { @@ -1036,26 +1066,29 @@ typedef struct GPBServiceDescriptorProto_Storage { .number = GPBServiceDescriptorProto_FieldNumber_Options, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBServiceDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBServiceDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBServiceOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBServiceOptions), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBServiceDescriptorProto class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBServiceDescriptorProto_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBServiceDescriptorProto class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBServiceDescriptorProto__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1073,7 +1106,7 @@ typedef struct GPBServiceDescriptorProto_Storage { @dynamic hasClientStreaming, clientStreaming; @dynamic hasServerStreaming, serverStreaming; -typedef struct GPBMethodDescriptorProto_Storage { +typedef struct GPBMethodDescriptorProto__storage_ { uint32_t _has_storage_[1]; BOOL clientStreaming; BOOL serverStreaming; @@ -1081,12 +1114,12 @@ typedef struct GPBMethodDescriptorProto_Storage { NSString *inputType; NSString *outputType; GPBMethodOptions *options; -} GPBMethodDescriptorProto_Storage; +} GPBMethodDescriptorProto__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1094,10 +1127,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBMethodDescriptorProto_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethodDescriptorProto__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1105,10 +1138,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_InputType, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBMethodDescriptorProto_Storage, inputType), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethodDescriptorProto__storage_, inputType), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1116,10 +1149,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_OutputType, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBMethodDescriptorProto_Storage, outputType), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBMethodDescriptorProto__storage_, outputType), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1127,10 +1160,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_Options, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBMethodDescriptorProto_Storage, options), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBMethodDescriptorProto__storage_, options), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBMethodOptions), + .dataTypeSpecific.className = GPBStringifySymbol(GPBMethodOptions), .fieldOptions = NULL, }, { @@ -1138,10 +1171,10 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_ClientStreaming, .hasIndex = 4, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMethodDescriptorProto_Storage, clientStreaming), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethodDescriptorProto__storage_, clientStreaming), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1149,26 +1182,29 @@ typedef struct GPBMethodDescriptorProto_Storage { .number = GPBMethodDescriptorProto_FieldNumber_ServerStreaming, .hasIndex = 5, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMethodDescriptorProto_Storage, serverStreaming), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethodDescriptorProto__storage_, serverStreaming), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethodDescriptorProto class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBMethodDescriptorProto_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMethodDescriptorProto class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBMethodDescriptorProto__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1193,9 +1229,9 @@ typedef struct GPBMethodDescriptorProto_Storage { @dynamic hasCcEnableArenas, ccEnableArenas; @dynamic hasObjcClassPrefix, objcClassPrefix; @dynamic hasCsharpNamespace, csharpNamespace; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBFileOptions_Storage { +typedef struct GPBFileOptions__storage_ { uint32_t _has_storage_[1]; BOOL javaMultipleFiles; BOOL ccGenericServices; @@ -1212,12 +1248,12 @@ typedef struct GPBFileOptions_Storage { NSString *objcClassPrefix; NSString *csharpNamespace; NSMutableArray *uninterpretedOptionArray; -} GPBFileOptions_Storage; +} GPBFileOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1225,10 +1261,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaPackage, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, javaPackage), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, javaPackage), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1236,10 +1272,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaOuterClassname, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, javaOuterClassname), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, javaOuterClassname), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1247,10 +1283,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_OptimizeFor, .hasIndex = 5, .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFileOptions_Storage, optimizeFor), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFileOptions__storage_, optimizeFor), .defaultValue.valueEnum = GPBFileOptions_OptimizeMode_Speed, - .typeSpecific.enumDescFunc = GPBFileOptions_OptimizeMode_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFileOptions_OptimizeMode_EnumDescriptor, .fieldOptions = NULL, }, { @@ -1258,10 +1294,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaMultipleFiles, .hasIndex = 2, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, javaMultipleFiles), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, javaMultipleFiles), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1269,10 +1305,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_GoPackage, .hasIndex = 6, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, goPackage), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, goPackage), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1280,10 +1316,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_CcGenericServices, .hasIndex = 7, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, ccGenericServices), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, ccGenericServices), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1291,10 +1327,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaGenericServices, .hasIndex = 8, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, javaGenericServices), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, javaGenericServices), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1302,10 +1338,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_PyGenericServices, .hasIndex = 9, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, pyGenericServices), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, pyGenericServices), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1313,10 +1349,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaGenerateEqualsAndHash, .hasIndex = 3, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, javaGenerateEqualsAndHash), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, javaGenerateEqualsAndHash), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1324,10 +1360,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_Deprecated, .hasIndex = 10, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1335,10 +1371,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_JavaStringCheckUtf8, .hasIndex = 4, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, javaStringCheckUtf8), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, javaStringCheckUtf8), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1346,10 +1382,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_CcEnableArenas, .hasIndex = 11, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFileOptions_Storage, ccEnableArenas), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFileOptions__storage_, ccEnableArenas), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1357,10 +1393,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_ObjcClassPrefix, .hasIndex = 12, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, objcClassPrefix), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, objcClassPrefix), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1368,10 +1404,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_CsharpNamespace, .hasIndex = 13, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBFileOptions_Storage, csharpNamespace), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFileOptions__storage_, csharpNamespace), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1379,10 +1415,10 @@ typedef struct GPBFileOptions_Storage { .number = GPBFileOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFileOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFileOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; @@ -1392,19 +1428,22 @@ typedef struct GPBFileOptions_Storage { static GPBExtensionRange ranges[] = { { .start = 1000, .end = 536870912 }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileOptions class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:enums - enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) - ranges:ranges - rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) - storageSize:sizeof(GPBFileOptions_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFileOptions class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:enums + enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) + ranges:ranges + rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) + storageSize:sizeof(GPBFileOptions__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1448,21 +1487,21 @@ BOOL GPBFileOptions_OptimizeMode_IsValidValue(int32_t value__) { @dynamic hasNoStandardDescriptorAccessor, noStandardDescriptorAccessor; @dynamic hasDeprecated, deprecated; @dynamic hasMapEntry, mapEntry; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBMessageOptions_Storage { +typedef struct GPBMessageOptions__storage_ { uint32_t _has_storage_[1]; BOOL messageSetWireFormat; BOOL noStandardDescriptorAccessor; BOOL deprecated; BOOL mapEntry; NSMutableArray *uninterpretedOptionArray; -} GPBMessageOptions_Storage; +} GPBMessageOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1470,10 +1509,10 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_MessageSetWireFormat, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMessageOptions_Storage, messageSetWireFormat), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMessageOptions__storage_, messageSetWireFormat), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1481,10 +1520,10 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_NoStandardDescriptorAccessor, .hasIndex = 1, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMessageOptions_Storage, noStandardDescriptorAccessor), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMessageOptions__storage_, noStandardDescriptorAccessor), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1492,10 +1531,10 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_Deprecated, .hasIndex = 2, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMessageOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMessageOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1503,10 +1542,10 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_MapEntry, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBMessageOptions_Storage, mapEntry), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMessageOptions__storage_, mapEntry), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1514,29 +1553,32 @@ typedef struct GPBMessageOptions_Storage { .number = GPBMessageOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBMessageOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBMessageOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; static GPBExtensionRange ranges[] = { { .start = 1000, .end = 536870912 }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessageOptions class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:ranges - rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) - storageSize:sizeof(GPBMessageOptions_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMessageOptions class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:ranges + rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) + storageSize:sizeof(GPBMessageOptions__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1553,9 +1595,9 @@ typedef struct GPBMessageOptions_Storage { @dynamic hasLazy, lazy; @dynamic hasDeprecated, deprecated; @dynamic hasWeak, weak; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBFieldOptions_Storage { +typedef struct GPBFieldOptions__storage_ { uint32_t _has_storage_[1]; BOOL packed; BOOL deprecated; @@ -1564,12 +1606,12 @@ typedef struct GPBFieldOptions_Storage { GPBFieldOptions_CType ctype; GPBFieldOptions_JSType jstype; NSMutableArray *uninterpretedOptionArray; -} GPBFieldOptions_Storage; +} GPBFieldOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1577,10 +1619,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Ctype, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFieldOptions_Storage, ctype), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFieldOptions__storage_, ctype), .defaultValue.valueEnum = GPBFieldOptions_CType_String, - .typeSpecific.enumDescFunc = GPBFieldOptions_CType_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFieldOptions_CType_EnumDescriptor, .fieldOptions = NULL, }, { @@ -1588,10 +1630,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Packed, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBFieldOptions_Storage, packed), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFieldOptions__storage_, packed), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1599,10 +1641,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Deprecated, .hasIndex = 4, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFieldOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFieldOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1610,10 +1652,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Lazy, .hasIndex = 3, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFieldOptions_Storage, lazy), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFieldOptions__storage_, lazy), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1621,10 +1663,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Jstype, .hasIndex = 2, .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBFieldOptions_Storage, jstype), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBFieldOptions__storage_, jstype), .defaultValue.valueEnum = GPBFieldOptions_JSType_JsNormal, - .typeSpecific.enumDescFunc = GPBFieldOptions_JSType_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBFieldOptions_JSType_EnumDescriptor, .fieldOptions = NULL, }, { @@ -1632,10 +1674,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_Weak, .hasIndex = 5, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBFieldOptions_Storage, weak), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBFieldOptions__storage_, weak), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1643,10 +1685,10 @@ typedef struct GPBFieldOptions_Storage { .number = GPBFieldOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBFieldOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBFieldOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; @@ -1657,19 +1699,22 @@ typedef struct GPBFieldOptions_Storage { static GPBExtensionRange ranges[] = { { .start = 1000, .end = 536870912 }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldOptions class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:enums - enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) - ranges:ranges - rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) - storageSize:sizeof(GPBFieldOptions_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFieldOptions class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:enums + enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) + ranges:ranges + rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) + storageSize:sizeof(GPBFieldOptions__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1740,19 +1785,19 @@ BOOL GPBFieldOptions_JSType_IsValidValue(int32_t value__) { @dynamic hasAllowAlias, allowAlias; @dynamic hasDeprecated, deprecated; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBEnumOptions_Storage { +typedef struct GPBEnumOptions__storage_ { uint32_t _has_storage_[1]; BOOL allowAlias; BOOL deprecated; NSMutableArray *uninterpretedOptionArray; -} GPBEnumOptions_Storage; +} GPBEnumOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1760,10 +1805,10 @@ typedef struct GPBEnumOptions_Storage { .number = GPBEnumOptions_FieldNumber_AllowAlias, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBEnumOptions_Storage, allowAlias), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBEnumOptions__storage_, allowAlias), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1771,10 +1816,10 @@ typedef struct GPBEnumOptions_Storage { .number = GPBEnumOptions_FieldNumber_Deprecated, .hasIndex = 1, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBEnumOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBEnumOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1782,29 +1827,32 @@ typedef struct GPBEnumOptions_Storage { .number = GPBEnumOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; static GPBExtensionRange ranges[] = { { .start = 1000, .end = 536870912 }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumOptions class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:ranges - rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) - storageSize:sizeof(GPBEnumOptions_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumOptions class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:ranges + rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) + storageSize:sizeof(GPBEnumOptions__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1816,18 +1864,18 @@ typedef struct GPBEnumOptions_Storage { @implementation GPBEnumValueOptions @dynamic hasDeprecated, deprecated; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBEnumValueOptions_Storage { +typedef struct GPBEnumValueOptions__storage_ { uint32_t _has_storage_[1]; BOOL deprecated; NSMutableArray *uninterpretedOptionArray; -} GPBEnumValueOptions_Storage; +} GPBEnumValueOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1835,10 +1883,10 @@ typedef struct GPBEnumValueOptions_Storage { .number = GPBEnumValueOptions_FieldNumber_Deprecated, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBEnumValueOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBEnumValueOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1846,29 +1894,32 @@ typedef struct GPBEnumValueOptions_Storage { .number = GPBEnumValueOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumValueOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumValueOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; static GPBExtensionRange ranges[] = { { .start = 1000, .end = 536870912 }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValueOptions class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:ranges - rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) - storageSize:sizeof(GPBEnumValueOptions_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumValueOptions class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:ranges + rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) + storageSize:sizeof(GPBEnumValueOptions__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1880,18 +1931,18 @@ typedef struct GPBEnumValueOptions_Storage { @implementation GPBServiceOptions @dynamic hasDeprecated, deprecated; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBServiceOptions_Storage { +typedef struct GPBServiceOptions__storage_ { uint32_t _has_storage_[1]; BOOL deprecated; NSMutableArray *uninterpretedOptionArray; -} GPBServiceOptions_Storage; +} GPBServiceOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1899,10 +1950,10 @@ typedef struct GPBServiceOptions_Storage { .number = GPBServiceOptions_FieldNumber_Deprecated, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBServiceOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBServiceOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1910,29 +1961,32 @@ typedef struct GPBServiceOptions_Storage { .number = GPBServiceOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBServiceOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBServiceOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; static GPBExtensionRange ranges[] = { { .start = 1000, .end = 536870912 }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBServiceOptions class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:ranges - rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) - storageSize:sizeof(GPBServiceOptions_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBServiceOptions class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:ranges + rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) + storageSize:sizeof(GPBServiceOptions__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -1944,18 +1998,18 @@ typedef struct GPBServiceOptions_Storage { @implementation GPBMethodOptions @dynamic hasDeprecated, deprecated; -@dynamic uninterpretedOptionArray; +@dynamic uninterpretedOptionArray, uninterpretedOptionArray_Count; -typedef struct GPBMethodOptions_Storage { +typedef struct GPBMethodOptions__storage_ { uint32_t _has_storage_[1]; BOOL deprecated; NSMutableArray *uninterpretedOptionArray; -} GPBMethodOptions_Storage; +} GPBMethodOptions__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -1963,10 +2017,10 @@ typedef struct GPBMethodOptions_Storage { .number = GPBMethodOptions_FieldNumber_Deprecated, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasDefaultValue, - .type = GPBTypeBool, - .offset = offsetof(GPBMethodOptions_Storage, deprecated), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBMethodOptions__storage_, deprecated), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -1974,29 +2028,32 @@ typedef struct GPBMethodOptions_Storage { .number = GPBMethodOptions_FieldNumber_UninterpretedOptionArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBMethodOptions_Storage, uninterpretedOptionArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBMethodOptions__storage_, uninterpretedOptionArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption), .fieldOptions = NULL, }, }; static GPBExtensionRange ranges[] = { { .start = 1000, .end = 536870912 }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethodOptions class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:ranges - rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) - storageSize:sizeof(GPBMethodOptions_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBMethodOptions class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:ranges + rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange) + storageSize:sizeof(GPBMethodOptions__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -2007,7 +2064,7 @@ typedef struct GPBMethodOptions_Storage { @implementation GPBUninterpretedOption -@dynamic nameArray; +@dynamic nameArray, nameArray_Count; @dynamic hasIdentifierValue, identifierValue; @dynamic hasPositiveIntValue, positiveIntValue; @dynamic hasNegativeIntValue, negativeIntValue; @@ -2015,7 +2072,7 @@ typedef struct GPBMethodOptions_Storage { @dynamic hasStringValue, stringValue; @dynamic hasAggregateValue, aggregateValue; -typedef struct GPBUninterpretedOption_Storage { +typedef struct GPBUninterpretedOption__storage_ { uint32_t _has_storage_[1]; NSMutableArray *nameArray; NSString *identifierValue; @@ -2024,12 +2081,12 @@ typedef struct GPBUninterpretedOption_Storage { uint64_t positiveIntValue; int64_t negativeIntValue; double doubleValue; -} GPBUninterpretedOption_Storage; +} GPBUninterpretedOption__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -2037,10 +2094,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_NameArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBUninterpretedOption_Storage, nameArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBUninterpretedOption__storage_, nameArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption_NamePart), + .dataTypeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption_NamePart), .fieldOptions = NULL, }, { @@ -2048,10 +2105,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_IdentifierValue, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBUninterpretedOption_Storage, identifierValue), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBUninterpretedOption__storage_, identifierValue), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2059,10 +2116,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_PositiveIntValue, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeUInt64, - .offset = offsetof(GPBUninterpretedOption_Storage, positiveIntValue), + .dataType = GPBDataTypeUInt64, + .offset = offsetof(GPBUninterpretedOption__storage_, positiveIntValue), .defaultValue.valueUInt64 = 0ULL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2070,10 +2127,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_NegativeIntValue, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeInt64, - .offset = offsetof(GPBUninterpretedOption_Storage, negativeIntValue), + .dataType = GPBDataTypeInt64, + .offset = offsetof(GPBUninterpretedOption__storage_, negativeIntValue), .defaultValue.valueInt64 = 0LL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2081,10 +2138,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_DoubleValue, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeDouble, - .offset = offsetof(GPBUninterpretedOption_Storage, doubleValue), + .dataType = GPBDataTypeDouble, + .offset = offsetof(GPBUninterpretedOption__storage_, doubleValue), .defaultValue.valueDouble = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2092,10 +2149,10 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_StringValue, .hasIndex = 5, .flags = GPBFieldOptional, - .type = GPBTypeData, - .offset = offsetof(GPBUninterpretedOption_Storage, stringValue), + .dataType = GPBDataTypeBytes, + .offset = offsetof(GPBUninterpretedOption__storage_, stringValue), .defaultValue.valueData = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2103,26 +2160,29 @@ typedef struct GPBUninterpretedOption_Storage { .number = GPBUninterpretedOption_FieldNumber_AggregateValue, .hasIndex = 6, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBUninterpretedOption_Storage, aggregateValue), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBUninterpretedOption__storage_, aggregateValue), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBUninterpretedOption_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBUninterpretedOption__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -2136,16 +2196,16 @@ typedef struct GPBUninterpretedOption_Storage { @dynamic hasNamePart, namePart; @dynamic hasIsExtension, isExtension; -typedef struct GPBUninterpretedOption_NamePart_Storage { +typedef struct GPBUninterpretedOption_NamePart__storage_ { uint32_t _has_storage_[1]; BOOL isExtension; NSString *namePart; -} GPBUninterpretedOption_NamePart_Storage; +} GPBUninterpretedOption_NamePart__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -2153,10 +2213,10 @@ typedef struct GPBUninterpretedOption_NamePart_Storage { .number = GPBUninterpretedOption_NamePart_FieldNumber_NamePart, .hasIndex = 0, .flags = GPBFieldRequired, - .type = GPBTypeString, - .offset = offsetof(GPBUninterpretedOption_NamePart_Storage, namePart), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBUninterpretedOption_NamePart__storage_, namePart), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2164,26 +2224,29 @@ typedef struct GPBUninterpretedOption_NamePart_Storage { .number = GPBUninterpretedOption_NamePart_FieldNumber_IsExtension, .hasIndex = 1, .flags = GPBFieldRequired, - .type = GPBTypeBool, - .offset = offsetof(GPBUninterpretedOption_NamePart_Storage, isExtension), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBUninterpretedOption_NamePart__storage_, isExtension), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption_NamePart class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBUninterpretedOption_NamePart_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption_NamePart class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBUninterpretedOption_NamePart__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -2194,17 +2257,17 @@ typedef struct GPBUninterpretedOption_NamePart_Storage { @implementation GPBSourceCodeInfo -@dynamic locationArray; +@dynamic locationArray, locationArray_Count; -typedef struct GPBSourceCodeInfo_Storage { +typedef struct GPBSourceCodeInfo__storage_ { uint32_t _has_storage_[1]; NSMutableArray *locationArray; -} GPBSourceCodeInfo_Storage; +} GPBSourceCodeInfo__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -2212,26 +2275,29 @@ typedef struct GPBSourceCodeInfo_Storage { .number = GPBSourceCodeInfo_FieldNumber_LocationArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBSourceCodeInfo_Storage, locationArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBSourceCodeInfo__storage_, locationArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo_Location), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo_Location), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBSourceCodeInfo_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBSourceCodeInfo__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -2242,25 +2308,25 @@ typedef struct GPBSourceCodeInfo_Storage { @implementation GPBSourceCodeInfo_Location -@dynamic pathArray; -@dynamic spanArray; +@dynamic pathArray, pathArray_Count; +@dynamic spanArray, spanArray_Count; @dynamic hasLeadingComments, leadingComments; @dynamic hasTrailingComments, trailingComments; -@dynamic leadingDetachedCommentsArray; +@dynamic leadingDetachedCommentsArray, leadingDetachedCommentsArray_Count; -typedef struct GPBSourceCodeInfo_Location_Storage { +typedef struct GPBSourceCodeInfo_Location__storage_ { uint32_t _has_storage_[1]; GPBInt32Array *pathArray; GPBInt32Array *spanArray; NSString *leadingComments; NSString *trailingComments; NSMutableArray *leadingDetachedCommentsArray; -} GPBSourceCodeInfo_Location_Storage; +} GPBSourceCodeInfo_Location__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -2268,10 +2334,10 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_PathArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated | GPBFieldPacked, - .type = GPBTypeInt32, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, pathArray), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, pathArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, #if GPBOBJC_INCLUDE_FIELD_OPTIONS .fieldOptions = "\000\000\000\002\020\001", #else @@ -2283,10 +2349,10 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_SpanArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated | GPBFieldPacked, - .type = GPBTypeInt32, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, spanArray), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, spanArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, #if GPBOBJC_INCLUDE_FIELD_OPTIONS .fieldOptions = "\000\000\000\002\020\001", #else @@ -2298,10 +2364,10 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_LeadingComments, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, leadingComments), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, leadingComments), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2309,10 +2375,10 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_TrailingComments, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, trailingComments), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, trailingComments), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -2320,26 +2386,29 @@ typedef struct GPBSourceCodeInfo_Location_Storage { .number = GPBSourceCodeInfo_Location_FieldNumber_LeadingDetachedCommentsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBSourceCodeInfo_Location_Storage, leadingDetachedCommentsArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBSourceCodeInfo_Location__storage_, leadingDetachedCommentsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo_Location class] - rootClass:[GPBDescriptorRoot class] - file:GPBDescriptorRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBSourceCodeInfo_Location_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo_Location class] + rootClass:[GPBDescriptorRoot class] + file:GPBDescriptorRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBSourceCodeInfo_Location__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m index 4db030f4..e4fd4951 100644 --- a/objectivec/google/protobuf/Duration.pbobjc.m +++ b/objectivec/google/protobuf/Duration.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBDurationRoot_FileDescriptor + static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -29,16 +32,16 @@ static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) { @dynamic seconds; @dynamic nanos; -typedef struct GPBDuration_Storage { +typedef struct GPBDuration__storage_ { uint32_t _has_storage_[1]; int32_t nanos; int64_t seconds; -} GPBDuration_Storage; +} GPBDuration__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -46,10 +49,10 @@ typedef struct GPBDuration_Storage { .number = GPBDuration_FieldNumber_Seconds, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt64, - .offset = offsetof(GPBDuration_Storage, seconds), + .dataType = GPBDataTypeInt64, + .offset = offsetof(GPBDuration__storage_, seconds), .defaultValue.valueInt64 = 0LL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -57,26 +60,29 @@ typedef struct GPBDuration_Storage { .number = GPBDuration_FieldNumber_Nanos, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBDuration_Storage, nanos), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBDuration__storage_, nanos), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDuration class] - rootClass:[GPBDurationRoot class] - file:GPBDurationRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBDuration_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDuration class] + rootClass:[GPBDurationRoot class] + file:GPBDurationRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBDuration__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Empty.pbobjc.m b/objectivec/google/protobuf/Empty.pbobjc.m index 619fe905..17f0c1ac 100644 --- a/objectivec/google/protobuf/Empty.pbobjc.m +++ b/objectivec/google/protobuf/Empty.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBEmptyRoot_FileDescriptor + static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -27,30 +30,31 @@ static GPBFileDescriptor *GPBEmptyRoot_FileDescriptor(void) { @implementation GPBEmpty -typedef struct GPBEmpty_Storage { +typedef struct GPBEmpty__storage_ { uint32_t _has_storage_[0]; -} GPBEmpty_Storage; +} GPBEmpty__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { - static GPBMessageFieldDescription fields[] = { - }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] - rootClass:[GPBEmptyRoot class] - file:GPBEmptyRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBEmpty_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEmpty class] + rootClass:[GPBEmptyRoot class] + file:GPBEmptyRoot_FileDescriptor() + fields:NULL + fieldCount:0 + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEmpty__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.h b/objectivec/google/protobuf/FieldMask.pbobjc.h index ac6f03d2..f9b26fa2 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.h +++ b/objectivec/google/protobuf/FieldMask.pbobjc.h @@ -152,6 +152,7 @@ typedef GPB_ENUM(GPBFieldMask_FieldNumber) { // The set of field mask paths. // |pathsArray| contains |NSString| @property(nonatomic, readwrite, strong) NSMutableArray *pathsArray; +@property(nonatomic, readonly) NSUInteger pathsArray_Count; @end diff --git a/objectivec/google/protobuf/FieldMask.pbobjc.m b/objectivec/google/protobuf/FieldMask.pbobjc.m index e37ac6c2..f9684f51 100644 --- a/objectivec/google/protobuf/FieldMask.pbobjc.m +++ b/objectivec/google/protobuf/FieldMask.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBFieldMaskRoot_FileDescriptor + static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -26,17 +29,17 @@ static GPBFileDescriptor *GPBFieldMaskRoot_FileDescriptor(void) { @implementation GPBFieldMask -@dynamic pathsArray; +@dynamic pathsArray, pathsArray_Count; -typedef struct GPBFieldMask_Storage { +typedef struct GPBFieldMask__storage_ { uint32_t _has_storage_[1]; NSMutableArray *pathsArray; -} GPBFieldMask_Storage; +} GPBFieldMask__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -44,26 +47,29 @@ typedef struct GPBFieldMask_Storage { .number = GPBFieldMask_FieldNumber_PathsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBFieldMask_Storage, pathsArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBFieldMask__storage_, pathsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] - rootClass:[GPBFieldMaskRoot class] - file:GPBFieldMaskRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBFieldMask_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFieldMask class] + rootClass:[GPBFieldMaskRoot class] + file:GPBFieldMaskRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFieldMask__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/SourceContext.pbobjc.m b/objectivec/google/protobuf/SourceContext.pbobjc.m index 271f9243..ac1827fc 100644 --- a/objectivec/google/protobuf/SourceContext.pbobjc.m +++ b/objectivec/google/protobuf/SourceContext.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBSourceContextRoot_FileDescriptor + static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -28,15 +31,15 @@ static GPBFileDescriptor *GPBSourceContextRoot_FileDescriptor(void) { @dynamic fileName; -typedef struct GPBSourceContext_Storage { +typedef struct GPBSourceContext__storage_ { uint32_t _has_storage_[1]; NSString *fileName; -} GPBSourceContext_Storage; +} GPBSourceContext__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -44,26 +47,29 @@ typedef struct GPBSourceContext_Storage { .number = GPBSourceContext_FieldNumber_FileName, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBSourceContext_Storage, fileName), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBSourceContext__storage_, fileName), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] - rootClass:[GPBSourceContextRoot class] - file:GPBSourceContextRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBSourceContext_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBSourceContext class] + rootClass:[GPBSourceContextRoot class] + file:GPBSourceContextRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBSourceContext__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Struct.pbobjc.h b/objectivec/google/protobuf/Struct.pbobjc.h index f55af82b..45456955 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.h +++ b/objectivec/google/protobuf/Struct.pbobjc.h @@ -57,6 +57,7 @@ typedef GPB_ENUM(GPBStruct_FieldNumber) { // Map of dynamically typed values. // |fields| values are |GPBValue| @property(nonatomic, readwrite, strong) NSMutableDictionary *fields; +@property(nonatomic, readonly) NSUInteger fields_Count; @end @@ -126,6 +127,7 @@ typedef GPB_ENUM(GPBListValue_FieldNumber) { // Repeated field of dynamically typed values. // |valuesArray| contains |GPBValue| @property(nonatomic, readwrite, strong) NSMutableArray *valuesArray; +@property(nonatomic, readonly) NSUInteger valuesArray_Count; @end diff --git a/objectivec/google/protobuf/Struct.pbobjc.m b/objectivec/google/protobuf/Struct.pbobjc.m index e5a8b547..14b8f271 100644 --- a/objectivec/google/protobuf/Struct.pbobjc.m +++ b/objectivec/google/protobuf/Struct.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBStructRoot_FileDescriptor + static GPBFileDescriptor *GPBStructRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -51,17 +54,17 @@ BOOL GPBNullValue_IsValidValue(int32_t value__) { @implementation GPBStruct -@dynamic fields; +@dynamic fields, fields_Count; -typedef struct GPBStruct_Storage { +typedef struct GPBStruct__storage_ { uint32_t _has_storage_[1]; NSMutableDictionary *fields; -} GPBStruct_Storage; +} GPBStruct__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -69,26 +72,29 @@ typedef struct GPBStruct_Storage { .number = GPBStruct_FieldNumber_Fields, .hasIndex = GPBNoHasBit, .flags = GPBFieldMapKeyString, - .type = GPBTypeMessage, - .offset = offsetof(GPBStruct_Storage, fields), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBStruct__storage_, fields), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBValue), + .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBStruct class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBStruct_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStruct class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBStruct__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -107,7 +113,7 @@ typedef struct GPBStruct_Storage { @dynamic structValue; @dynamic listValue; -typedef struct GPBValue_Storage { +typedef struct GPBValue__storage_ { uint32_t _has_storage_[2]; BOOL boolValue; GPBNullValue nullValue; @@ -115,12 +121,12 @@ typedef struct GPBValue_Storage { GPBStruct *structValue; GPBListValue *listValue; double numberValue; -} GPBValue_Storage; +} GPBValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageOneofDescription oneofs[] = { { @@ -134,10 +140,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_NullValue, .hasIndex = -1, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBValue_Storage, nullValue), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBValue__storage_, nullValue), .defaultValue.valueEnum = GPBNullValue_NullValue, - .typeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBNullValue_EnumDescriptor, .fieldOptions = NULL, }, { @@ -145,10 +151,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_NumberValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeDouble, - .offset = offsetof(GPBValue_Storage, numberValue), + .dataType = GPBDataTypeDouble, + .offset = offsetof(GPBValue__storage_, numberValue), .defaultValue.valueDouble = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -156,10 +162,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_StringValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBValue_Storage, stringValue), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBValue__storage_, stringValue), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -167,10 +173,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_BoolValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBValue_Storage, boolValue), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBValue__storage_, boolValue), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -178,10 +184,10 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_StructValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBValue_Storage, structValue), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBValue__storage_, structValue), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBStruct), + .dataTypeSpecific.className = GPBStringifySymbol(GPBStruct), .fieldOptions = NULL, }, { @@ -189,26 +195,29 @@ typedef struct GPBValue_Storage { .number = GPBValue_FieldNumber_ListValue, .hasIndex = -1, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBValue_Storage, listValue), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBValue__storage_, listValue), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBListValue), + .dataTypeSpecific.className = GPBStringifySymbol(GPBListValue), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBValue class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:oneofs - oneofCount:sizeof(oneofs) / sizeof(GPBMessageOneofDescription) - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:oneofs + oneofCount:sizeof(oneofs) / sizeof(GPBMessageOneofDescription) + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -218,7 +227,7 @@ typedef struct GPBValue_Storage { int32_t GPBValue_NullValue_RawValue(GPBValue *message) { GPBDescriptor *descriptor = [GPBValue descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBValue_FieldNumber_NullValue]; - return GPBGetInt32IvarWithField(message, field); + return GPBGetMessageInt32Field(message, field); } void SetGPBValue_NullValue_RawValue(GPBValue *message, int32_t value) { @@ -236,17 +245,17 @@ void GPBValue_ClearKindOneOfCase(GPBValue *message) { @implementation GPBListValue -@dynamic valuesArray; +@dynamic valuesArray, valuesArray_Count; -typedef struct GPBListValue_Storage { +typedef struct GPBListValue__storage_ { uint32_t _has_storage_[1]; NSMutableArray *valuesArray; -} GPBListValue_Storage; +} GPBListValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -254,26 +263,29 @@ typedef struct GPBListValue_Storage { .number = GPBListValue_FieldNumber_ValuesArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBListValue_Storage, valuesArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBListValue__storage_, valuesArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBValue), + .dataTypeSpecific.className = GPBStringifySymbol(GPBValue), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBListValue class] - rootClass:[GPBStructRoot class] - file:GPBStructRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBListValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBListValue class] + rootClass:[GPBStructRoot class] + file:GPBStructRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBListValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m index 197dff48..a206f159 100644 --- a/objectivec/google/protobuf/Timestamp.pbobjc.m +++ b/objectivec/google/protobuf/Timestamp.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBTimestampRoot_FileDescriptor + static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -29,16 +32,16 @@ static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) { @dynamic seconds; @dynamic nanos; -typedef struct GPBTimestamp_Storage { +typedef struct GPBTimestamp__storage_ { uint32_t _has_storage_[1]; int32_t nanos; int64_t seconds; -} GPBTimestamp_Storage; +} GPBTimestamp__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -46,10 +49,10 @@ typedef struct GPBTimestamp_Storage { .number = GPBTimestamp_FieldNumber_Seconds, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt64, - .offset = offsetof(GPBTimestamp_Storage, seconds), + .dataType = GPBDataTypeInt64, + .offset = offsetof(GPBTimestamp__storage_, seconds), .defaultValue.valueInt64 = 0LL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -57,26 +60,29 @@ typedef struct GPBTimestamp_Storage { .number = GPBTimestamp_FieldNumber_Nanos, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBTimestamp_Storage, nanos), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBTimestamp__storage_, nanos), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class] - rootClass:[GPBTimestampRoot class] - file:GPBTimestampRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBTimestamp_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class] + rootClass:[GPBTimestampRoot class] + file:GPBTimestampRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBTimestamp__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Type.pbobjc.h b/objectivec/google/protobuf/Type.pbobjc.h index 652a33a7..e3b6229f 100644 --- a/objectivec/google/protobuf/Type.pbobjc.h +++ b/objectivec/google/protobuf/Type.pbobjc.h @@ -132,15 +132,18 @@ typedef GPB_ENUM(GPBType_FieldNumber) { // The list of fields. // |fieldsArray| contains |GPBField| @property(nonatomic, readwrite, strong) NSMutableArray *fieldsArray; +@property(nonatomic, readonly) NSUInteger fieldsArray_Count; // The list of oneof definitions. // The list of oneofs declared in this Type // |oneofsArray| contains |NSString| @property(nonatomic, readwrite, strong) NSMutableArray *oneofsArray; +@property(nonatomic, readonly) NSUInteger oneofsArray_Count; // The proto options. // |optionsArray| contains |GPBOption| @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; // The source context. @property(nonatomic, readwrite) BOOL hasSourceContext; @@ -189,6 +192,7 @@ typedef GPB_ENUM(GPBField_FieldNumber) { // The proto options. // |optionsArray| contains |GPBOption| @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; @end @@ -216,10 +220,12 @@ typedef GPB_ENUM(GPBEnum_FieldNumber) { // Enum value definitions. // |enumvalueArray| contains |GPBEnumValue| @property(nonatomic, readwrite, strong) NSMutableArray *enumvalueArray; +@property(nonatomic, readonly) NSUInteger enumvalueArray_Count; // Proto options for the enum type. // |optionsArray| contains |GPBOption| @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; // The source context. @property(nonatomic, readwrite) BOOL hasSourceContext; @@ -247,6 +253,7 @@ typedef GPB_ENUM(GPBEnumValue_FieldNumber) { // Proto options for the enum value. // |optionsArray| contains |GPBOption| @property(nonatomic, readwrite, strong) NSMutableArray *optionsArray; +@property(nonatomic, readonly) NSUInteger optionsArray_Count; @end diff --git a/objectivec/google/protobuf/Type.pbobjc.m b/objectivec/google/protobuf/Type.pbobjc.m index 182370c8..5a2ce282 100644 --- a/objectivec/google/protobuf/Type.pbobjc.m +++ b/objectivec/google/protobuf/Type.pbobjc.m @@ -16,10 +16,8 @@ // about thread safety and initialization of registry. static GPBExtensionRegistry* registry = nil; if (!registry) { + GPBDebugCheckRuntimeVersion(); registry = [[GPBExtensionRegistry alloc] init]; - static GPBExtensionDescription descriptions[] = { - }; - #pragma unused (descriptions) [registry addExtensions:[GPBAnyRoot extensionRegistry]]; [registry addExtensions:[GPBSourceContextRoot extensionRegistry]]; } @@ -28,11 +26,14 @@ @end +#pragma mark - GPBTypeRoot_FileDescriptor + static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -44,24 +45,24 @@ static GPBFileDescriptor *GPBTypeRoot_FileDescriptor(void) { @implementation GPBType @dynamic name; -@dynamic fieldsArray; -@dynamic oneofsArray; -@dynamic optionsArray; +@dynamic fieldsArray, fieldsArray_Count; +@dynamic oneofsArray, oneofsArray_Count; +@dynamic optionsArray, optionsArray_Count; @dynamic hasSourceContext, sourceContext; -typedef struct GPBType_Storage { +typedef struct GPBType__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *fieldsArray; NSMutableArray *oneofsArray; NSMutableArray *optionsArray; GPBSourceContext *sourceContext; -} GPBType_Storage; +} GPBType__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -69,10 +70,10 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBType_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBType__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -80,10 +81,10 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_FieldsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBType_Storage, fieldsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBType__storage_, fieldsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBField), + .dataTypeSpecific.className = GPBStringifySymbol(GPBField), .fieldOptions = NULL, }, { @@ -91,10 +92,10 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_OneofsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeString, - .offset = offsetof(GPBType_Storage, oneofsArray), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBType__storage_, oneofsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -102,10 +103,10 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBType_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBType__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, { @@ -113,26 +114,29 @@ typedef struct GPBType_Storage { .number = GPBType_FieldNumber_SourceContext, .hasIndex = 4, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBType_Storage, sourceContext), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBType__storage_, sourceContext), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBType class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBType_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBType class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBType__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -150,9 +154,9 @@ typedef struct GPBType_Storage { @dynamic typeURL; @dynamic oneofIndex; @dynamic packed; -@dynamic optionsArray; +@dynamic optionsArray, optionsArray_Count; -typedef struct GPBField_Storage { +typedef struct GPBField__storage_ { uint32_t _has_storage_[1]; BOOL packed; GPBField_Kind kind; @@ -162,12 +166,12 @@ typedef struct GPBField_Storage { NSString *name; NSString *typeURL; NSMutableArray *optionsArray; -} GPBField_Storage; +} GPBField__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -175,10 +179,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Kind, .hasIndex = 0, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBField_Storage, kind), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBField__storage_, kind), .defaultValue.valueEnum = GPBField_Kind_TypeUnknown, - .typeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBField_Kind_EnumDescriptor, .fieldOptions = NULL, }, { @@ -186,10 +190,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Cardinality, .hasIndex = 1, .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor, - .type = GPBTypeEnum, - .offset = offsetof(GPBField_Storage, cardinality), + .dataType = GPBDataTypeEnum, + .offset = offsetof(GPBField__storage_, cardinality), .defaultValue.valueEnum = GPBField_Cardinality_CardinalityUnknown, - .typeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, + .dataTypeSpecific.enumDescFunc = GPBField_Cardinality_EnumDescriptor, .fieldOptions = NULL, }, { @@ -197,10 +201,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Number, .hasIndex = 2, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBField_Storage, number), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBField__storage_, number), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -208,10 +212,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Name, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBField_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBField__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -219,10 +223,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_TypeURL, .hasIndex = 4, .flags = GPBFieldOptional | GPBFieldTextFormatNameCustom, - .type = GPBTypeString, - .offset = offsetof(GPBField_Storage, typeURL), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBField__storage_, typeURL), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -230,10 +234,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_OneofIndex, .hasIndex = 5, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBField_Storage, oneofIndex), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBField__storage_, oneofIndex), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -241,10 +245,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_Packed, .hasIndex = 6, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBField_Storage, packed), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBField__storage_, packed), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -252,10 +256,10 @@ typedef struct GPBField_Storage { .number = GPBField_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBField_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBField__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, }; @@ -268,20 +272,23 @@ typedef struct GPBField_Storage { #else static const char *extraTextFormatInfo = "\001\006\004\241!!\000"; #endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBField class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:enums - enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBField_Storage) - wireFormat:NO - extraTextFormatInfo:extraTextFormatInfo]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBField class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:enums + enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription) + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBField__storage_) + wireFormat:NO + extraTextFormatInfo:extraTextFormatInfo]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -291,7 +298,7 @@ typedef struct GPBField_Storage { int32_t GPBField_Kind_RawValue(GPBField *message) { GPBDescriptor *descriptor = [GPBField descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Kind]; - return GPBGetInt32IvarWithField(message, field); + return GPBGetMessageInt32Field(message, field); } void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { @@ -303,7 +310,7 @@ void SetGPBField_Kind_RawValue(GPBField *message, int32_t value) { int32_t GPBField_Cardinality_RawValue(GPBField *message) { GPBDescriptor *descriptor = [GPBField descriptor]; GPBFieldDescriptor *field = [descriptor fieldWithNumber:GPBField_FieldNumber_Cardinality]; - return GPBGetInt32IvarWithField(message, field); + return GPBGetMessageInt32Field(message, field); } void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { @@ -407,22 +414,22 @@ BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { @implementation GPBEnum @dynamic name; -@dynamic enumvalueArray; -@dynamic optionsArray; +@dynamic enumvalueArray, enumvalueArray_Count; +@dynamic optionsArray, optionsArray_Count; @dynamic hasSourceContext, sourceContext; -typedef struct GPBEnum_Storage { +typedef struct GPBEnum__storage_ { uint32_t _has_storage_[1]; NSString *name; NSMutableArray *enumvalueArray; NSMutableArray *optionsArray; GPBSourceContext *sourceContext; -} GPBEnum_Storage; +} GPBEnum__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -430,10 +437,10 @@ typedef struct GPBEnum_Storage { .number = GPBEnum_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBEnum_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBEnum__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -441,10 +448,10 @@ typedef struct GPBEnum_Storage { .number = GPBEnum_FieldNumber_EnumvalueArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnum_Storage, enumvalueArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnum__storage_, enumvalueArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBEnumValue), + .dataTypeSpecific.className = GPBStringifySymbol(GPBEnumValue), .fieldOptions = NULL, }, { @@ -452,10 +459,10 @@ typedef struct GPBEnum_Storage { .number = GPBEnum_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnum_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnum__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, { @@ -463,26 +470,29 @@ typedef struct GPBEnum_Storage { .number = GPBEnum_FieldNumber_SourceContext, .hasIndex = 3, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnum_Storage, sourceContext), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnum__storage_, sourceContext), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBSourceContext), + .dataTypeSpecific.className = GPBStringifySymbol(GPBSourceContext), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnum class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBEnum_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnum class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEnum__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -495,19 +505,19 @@ typedef struct GPBEnum_Storage { @dynamic name; @dynamic number; -@dynamic optionsArray; +@dynamic optionsArray, optionsArray_Count; -typedef struct GPBEnumValue_Storage { +typedef struct GPBEnumValue__storage_ { uint32_t _has_storage_[1]; int32_t number; NSString *name; NSMutableArray *optionsArray; -} GPBEnumValue_Storage; +} GPBEnumValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -515,10 +525,10 @@ typedef struct GPBEnumValue_Storage { .number = GPBEnumValue_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBEnumValue_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBEnumValue__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -526,10 +536,10 @@ typedef struct GPBEnumValue_Storage { .number = GPBEnumValue_FieldNumber_Number, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBEnumValue_Storage, number), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBEnumValue__storage_, number), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -537,26 +547,29 @@ typedef struct GPBEnumValue_Storage { .number = GPBEnumValue_FieldNumber_OptionsArray, .hasIndex = GPBNoHasBit, .flags = GPBFieldRepeated, - .type = GPBTypeMessage, - .offset = offsetof(GPBEnumValue_Storage, optionsArray), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBEnumValue__storage_, optionsArray), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBOption), + .dataTypeSpecific.className = GPBStringifySymbol(GPBOption), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBEnumValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBEnumValue class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBEnumValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -570,16 +583,16 @@ typedef struct GPBEnumValue_Storage { @dynamic name; @dynamic hasValue, value; -typedef struct GPBOption_Storage { +typedef struct GPBOption__storage_ { uint32_t _has_storage_[1]; NSString *name; GPBAny *value; -} GPBOption_Storage; +} GPBOption__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -587,10 +600,10 @@ typedef struct GPBOption_Storage { .number = GPBOption_FieldNumber_Name, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBOption_Storage, name), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBOption__storage_, name), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, { @@ -598,26 +611,29 @@ typedef struct GPBOption_Storage { .number = GPBOption_FieldNumber_Value, .hasIndex = 1, .flags = GPBFieldOptional, - .type = GPBTypeMessage, - .offset = offsetof(GPBOption_Storage, value), + .dataType = GPBDataTypeMessage, + .offset = offsetof(GPBOption__storage_, value), .defaultValue.valueMessage = nil, - .typeSpecific.className = GPBStringifySymbol(GPBAny), + .dataTypeSpecific.className = GPBStringifySymbol(GPBAny), .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBOption class] - rootClass:[GPBTypeRoot class] - file:GPBTypeRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBOption_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBOption class] + rootClass:[GPBTypeRoot class] + file:GPBTypeRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBOption__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/objectivec/google/protobuf/Wrappers.pbobjc.m b/objectivec/google/protobuf/Wrappers.pbobjc.m index 6c342850..0403b464 100644 --- a/objectivec/google/protobuf/Wrappers.pbobjc.m +++ b/objectivec/google/protobuf/Wrappers.pbobjc.m @@ -11,11 +11,14 @@ @end +#pragma mark - GPBWrappersRoot_FileDescriptor + static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { // This is called by +initialize so there is no need to worry // about thread safety of the singleton. static GPBFileDescriptor *descriptor = NULL; if (!descriptor) { + GPBDebugCheckRuntimeVersion(); descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf" syntax:GPBFileSyntaxProto3]; } @@ -28,15 +31,15 @@ static GPBFileDescriptor *GPBWrappersRoot_FileDescriptor(void) { @dynamic value; -typedef struct GPBDoubleValue_Storage { +typedef struct GPBDoubleValue__storage_ { uint32_t _has_storage_[1]; double value; -} GPBDoubleValue_Storage; +} GPBDoubleValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -44,26 +47,29 @@ typedef struct GPBDoubleValue_Storage { .number = GPBDoubleValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeDouble, - .offset = offsetof(GPBDoubleValue_Storage, value), + .dataType = GPBDataTypeDouble, + .offset = offsetof(GPBDoubleValue__storage_, value), .defaultValue.valueDouble = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBDoubleValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBDoubleValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBDoubleValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -76,15 +82,15 @@ typedef struct GPBDoubleValue_Storage { @dynamic value; -typedef struct GPBFloatValue_Storage { +typedef struct GPBFloatValue__storage_ { uint32_t _has_storage_[1]; float value; -} GPBFloatValue_Storage; +} GPBFloatValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -92,26 +98,29 @@ typedef struct GPBFloatValue_Storage { .number = GPBFloatValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeFloat, - .offset = offsetof(GPBFloatValue_Storage, value), + .dataType = GPBDataTypeFloat, + .offset = offsetof(GPBFloatValue__storage_, value), .defaultValue.valueFloat = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBFloatValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBFloatValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBFloatValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -124,15 +133,15 @@ typedef struct GPBFloatValue_Storage { @dynamic value; -typedef struct GPBInt64Value_Storage { +typedef struct GPBInt64Value__storage_ { uint32_t _has_storage_[1]; int64_t value; -} GPBInt64Value_Storage; +} GPBInt64Value__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -140,26 +149,29 @@ typedef struct GPBInt64Value_Storage { .number = GPBInt64Value_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt64, - .offset = offsetof(GPBInt64Value_Storage, value), + .dataType = GPBDataTypeInt64, + .offset = offsetof(GPBInt64Value__storage_, value), .defaultValue.valueInt64 = 0LL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBInt64Value_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBInt64Value__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -172,15 +184,15 @@ typedef struct GPBInt64Value_Storage { @dynamic value; -typedef struct GPBUInt64Value_Storage { +typedef struct GPBUInt64Value__storage_ { uint32_t _has_storage_[1]; uint64_t value; -} GPBUInt64Value_Storage; +} GPBUInt64Value__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -188,26 +200,29 @@ typedef struct GPBUInt64Value_Storage { .number = GPBUInt64Value_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeUInt64, - .offset = offsetof(GPBUInt64Value_Storage, value), + .dataType = GPBDataTypeUInt64, + .offset = offsetof(GPBUInt64Value__storage_, value), .defaultValue.valueUInt64 = 0ULL, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBUInt64Value_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt64Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBUInt64Value__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -220,15 +235,15 @@ typedef struct GPBUInt64Value_Storage { @dynamic value; -typedef struct GPBInt32Value_Storage { +typedef struct GPBInt32Value__storage_ { uint32_t _has_storage_[1]; int32_t value; -} GPBInt32Value_Storage; +} GPBInt32Value__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -236,26 +251,29 @@ typedef struct GPBInt32Value_Storage { .number = GPBInt32Value_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeInt32, - .offset = offsetof(GPBInt32Value_Storage, value), + .dataType = GPBDataTypeInt32, + .offset = offsetof(GPBInt32Value__storage_, value), .defaultValue.valueInt32 = 0, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBInt32Value_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBInt32Value__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -268,15 +286,15 @@ typedef struct GPBInt32Value_Storage { @dynamic value; -typedef struct GPBUInt32Value_Storage { +typedef struct GPBUInt32Value__storage_ { uint32_t _has_storage_[1]; uint32_t value; -} GPBUInt32Value_Storage; +} GPBUInt32Value__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -284,26 +302,29 @@ typedef struct GPBUInt32Value_Storage { .number = GPBUInt32Value_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeUInt32, - .offset = offsetof(GPBUInt32Value_Storage, value), + .dataType = GPBDataTypeUInt32, + .offset = offsetof(GPBUInt32Value__storage_, value), .defaultValue.valueUInt32 = 0U, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBUInt32Value_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBUInt32Value class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBUInt32Value__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -316,15 +337,15 @@ typedef struct GPBUInt32Value_Storage { @dynamic value; -typedef struct GPBBoolValue_Storage { +typedef struct GPBBoolValue__storage_ { uint32_t _has_storage_[1]; BOOL value; -} GPBBoolValue_Storage; +} GPBBoolValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -332,26 +353,29 @@ typedef struct GPBBoolValue_Storage { .number = GPBBoolValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeBool, - .offset = offsetof(GPBBoolValue_Storage, value), + .dataType = GPBDataTypeBool, + .offset = offsetof(GPBBoolValue__storage_, value), .defaultValue.valueBool = NO, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBBoolValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBoolValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBBoolValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -364,15 +388,15 @@ typedef struct GPBBoolValue_Storage { @dynamic value; -typedef struct GPBStringValue_Storage { +typedef struct GPBStringValue__storage_ { uint32_t _has_storage_[1]; NSString *value; -} GPBStringValue_Storage; +} GPBStringValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -380,26 +404,29 @@ typedef struct GPBStringValue_Storage { .number = GPBStringValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeString, - .offset = offsetof(GPBStringValue_Storage, value), + .dataType = GPBDataTypeString, + .offset = offsetof(GPBStringValue__storage_, value), .defaultValue.valueString = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBStringValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBStringValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBStringValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } @@ -412,15 +439,15 @@ typedef struct GPBStringValue_Storage { @dynamic value; -typedef struct GPBBytesValue_Storage { +typedef struct GPBBytesValue__storage_ { uint32_t _has_storage_[1]; NSData *value; -} GPBBytesValue_Storage; +} GPBBytesValue__storage_; // This method is threadsafe because it is initially called // in +initialize for each subclass. + (GPBDescriptor *)descriptor { - static GPBDescriptor *descriptor = NULL; + static GPBDescriptor *descriptor = nil; if (!descriptor) { static GPBMessageFieldDescription fields[] = { { @@ -428,26 +455,29 @@ typedef struct GPBBytesValue_Storage { .number = GPBBytesValue_FieldNumber_Value, .hasIndex = 0, .flags = GPBFieldOptional, - .type = GPBTypeData, - .offset = offsetof(GPBBytesValue_Storage, value), + .dataType = GPBDataTypeBytes, + .offset = offsetof(GPBBytesValue__storage_, value), .defaultValue.valueData = nil, - .typeSpecific.className = NULL, + .dataTypeSpecific.className = NULL, .fieldOptions = NULL, }, }; - descriptor = [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] - rootClass:[GPBWrappersRoot class] - file:GPBWrappersRoot_FileDescriptor() - fields:fields - fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) - oneofs:NULL - oneofCount:0 - enums:NULL - enumCount:0 - ranges:NULL - rangeCount:0 - storageSize:sizeof(GPBBytesValue_Storage) - wireFormat:NO]; + GPBDescriptor *localDescriptor = + [GPBDescriptor allocDescriptorForClass:[GPBBytesValue class] + rootClass:[GPBWrappersRoot class] + file:GPBWrappersRoot_FileDescriptor() + fields:fields + fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription) + oneofs:NULL + oneofCount:0 + enums:NULL + enumCount:0 + ranges:NULL + rangeCount:0 + storageSize:sizeof(GPBBytesValue__storage_) + wireFormat:NO]; + NSAssert(descriptor == nil, @"Startup recursed!"); + descriptor = localDescriptor; } return descriptor; } diff --git a/src/Makefile.am b/src/Makefile.am index 33894dc1..6affcbf4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -147,7 +147,7 @@ nobase_include_HEADERS = \ google/protobuf/compiler/java/java_names.h \ google/protobuf/compiler/javanano/javanano_generator.h \ google/protobuf/compiler/objectivec/objectivec_generator.h \ - google/protobuf/compiler/objectivec/objectivec_helpers.h \ + google/protobuf/compiler/objectivec/objectivec_helpers.h \ google/protobuf/compiler/python/python_generator.h \ google/protobuf/compiler/ruby/ruby_generator.h \ google/protobuf/compiler/csharp/csharp_generator.h diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index d6609692..30a13ddb 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -55,8 +55,6 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (descriptor->file() != descriptor->enum_type()->file())) { (*variables)["property_type"] = "enum " + type; } - // TODO(thomasvl): Make inclusion of descriptor compile time and output - // both of these. Note: Extensions currently have to have the EnumDescription. (*variables)["enum_verifier"] = type + "_IsValidValue"; (*variables)["enum_desc_func"] = type + "_EnumDescriptor"; @@ -74,11 +72,9 @@ EnumFieldGenerator::~EnumFieldGenerator() {} void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific( io::Printer* printer) const { - // TODO(thomasvl): Output the CPP check to use descFunc or validator based - // on final compile. printer->Print( variables_, - " .typeSpecific.enumDescFunc = $enum_desc_func$,\n"); + " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n"); } void EnumFieldGenerator::GenerateCFunctionDeclarations( @@ -103,7 +99,7 @@ void EnumFieldGenerator::GenerateCFunctionImplementations( "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n" " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n" " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n" - " return GPBGetInt32IvarWithField(message, field);\n" + " return GPBGetMessageInt32Field(message, field);\n" "}\n" "\n" "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n" @@ -137,11 +133,9 @@ RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific( io::Printer* printer) const { - // TODO(thomasvl): Output the CPP check to use descFunc or validator based - // on final compile. printer->Print( variables_, - " .typeSpecific.enumDescFunc = $enum_desc_func$,\n"); + " .dataTypeSpecific.enumDescFunc = $enum_desc_func$,\n"); } } // namespace objectivec diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index 76137c80..4e348393 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -46,24 +46,6 @@ ExtensionGenerator::ExtensionGenerator(const string& root_class_name, : method_name_(ExtensionMethodName(descriptor)), root_class_and_method_name_(root_class_name + "_" + method_name_), descriptor_(descriptor) { - // Extensions can be filtered via the method they are accessed off the - // file's Root with. - if (FilterClass(root_class_and_method_name_)) { - filter_reason_ = - string("Extension |") + root_class_and_method_name_ + "| was not whitelisted."; - } else { - // Extensions that add a Message field also require that field be allowed - // by the filter, or they aren't usable. - ObjectiveCType objc_type = GetObjectiveCType(descriptor_); - if (objc_type == OBJECTIVECTYPE_MESSAGE) { - const string message_class_name(ClassName(descriptor_->message_type())); - if (FilterClass(message_class_name)) { - filter_reason_ = string("Extension |") + root_class_and_method_name_ + - "| needs message |" + message_class_name + - "|, which was not whitelisted."; - } - } - } if (descriptor->is_map()) { // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some // error cases, so it seems to be ok to use as a back door for errors. @@ -77,10 +59,6 @@ ExtensionGenerator::ExtensionGenerator(const string& root_class_name, ExtensionGenerator::~ExtensionGenerator() {} void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { - if (IsFiltered()) { - printer->Print("// $filter_reason$\n\n", "filter_reason", filter_reason_); - return; - } map vars; vars["method_name"] = method_name_; SourceLocation location; @@ -91,15 +69,11 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { } printer->Print(vars, "$comments$" - "+ (GPBExtensionField*)$method_name$;\n"); + "+ (GPBExtensionDescriptor *)$method_name$;\n"); } void ExtensionGenerator::GenerateStaticVariablesInitialization( - io::Printer* printer, bool* out_generated, bool root) { - if (IsFiltered()) { - return; - } - *out_generated = true; + io::Printer* printer) { map vars; vars["root_class_and_method_name"] = root_class_and_method_name_; vars["extended_type"] = ClassName(descriptor_->containing_type()); @@ -122,14 +96,14 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( vars["type"] = "NULL"; } - vars["default_name"] = GPBValueFieldName(descriptor_); + vars["default_name"] = GPBGenericValueFieldName(descriptor_); if (descriptor_->is_repeated()) { vars["default"] = "nil"; } else { vars["default"] = DefaultValue(descriptor_); } string type = GetCapitalizedType(descriptor_); - vars["extension_type"] = string("GPBType") + type; + vars["extension_type"] = string("GPBDataType") + type; if (objc_type == OBJECTIVECTYPE_ENUM) { vars["enum_desc_func_name"] = @@ -141,7 +115,7 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( printer->Print(vars, "{\n" " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n" - " .type = $extension_type$,\n" + " .dataType = $extension_type$,\n" " .extendedClass = GPBStringifySymbol($extended_type$),\n" " .fieldNumber = $number$,\n" " .defaultValue.$default_name$ = $default$,\n" @@ -152,9 +126,6 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( } void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) { - if (IsFiltered()) { - return; - } printer->Print( "[registry addExtension:$root_class_and_method_name$];\n", "root_class_and_method_name", root_class_and_method_name_); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h index 553f0887..e361e639 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h @@ -52,16 +52,12 @@ class ExtensionGenerator { ~ExtensionGenerator(); void GenerateMembersHeader(io::Printer* printer); - void GenerateStaticVariablesInitialization(io::Printer* printer, - bool* out_generated, bool root); + void GenerateStaticVariablesInitialization(io::Printer* printer); void GenerateRegistrationSource(io::Printer* printer); - bool IsFiltered() const { return filter_reason_.length() > 0; } - private: string method_name_; string root_class_and_method_name_; - string filter_reason_; const FieldDescriptor* descriptor_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index c5f05653..0f96a4e6 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -87,18 +87,16 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, field_flags.push_back("GPBFieldHasDefaultValue"); if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom"); if (descriptor->type() == FieldDescriptor::TYPE_ENUM) { - // TODO(thomasvl): Output the CPP check to use descFunc or validator based - // on final compile. field_flags.push_back("GPBFieldHasEnumDescriptor"); } (*variables)["fieldflags"] = BuildFlagsString(field_flags); (*variables)["default"] = DefaultValue(descriptor); - (*variables)["default_name"] = GPBValueFieldName(descriptor); + (*variables)["default_name"] = GPBGenericValueFieldName(descriptor); - (*variables)["typeSpecific_name"] = "className"; - (*variables)["typeSpecific_value"] = "NULL"; + (*variables)["dataTypeSpecific_name"] = "className"; + (*variables)["dataTypeSpecific_value"] = "NULL"; string field_options = descriptor->options().SerializeAsString(); // Must convert to a standard byte order for packing length into @@ -117,45 +115,6 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["storage_attribute"] = ""; } -// A field generator that writes nothing. -class EmptyFieldGenerator : public FieldGenerator { - public: - EmptyFieldGenerator(const FieldDescriptor* descriptor, const string& reason) - : FieldGenerator(descriptor), reason_(reason) {} - virtual ~EmptyFieldGenerator() {} - - virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const {} - virtual void GeneratePropertyDeclaration(io::Printer* printer) const { - string name = FieldName(descriptor_); - string type; - switch (GetObjectiveCType(descriptor_)) { - case OBJECTIVECTYPE_MESSAGE: - type = ClassName(descriptor_->message_type()) + " *"; - break; - - case OBJECTIVECTYPE_ENUM: - type = EnumName(descriptor_->enum_type()) + " "; - break; - - default: - type = string(descriptor_->type_name()) + " "; - break; - } - printer->Print("// Field |$type$$name$| $reason$\n\n", "type", type, "name", - name, "reason", reason_); - } - - virtual void GenerateFieldNumberConstant(io::Printer* printer) const {} - virtual void GeneratePropertyImplementation(io::Printer* printer) const {} - virtual void GenerateFieldDescription(io::Printer* printer) const {} - - virtual bool WantsHasProperty(void) const { return false; } - - private: - string reason_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EmptyFieldGenerator); -}; - } // namespace FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { @@ -163,12 +122,7 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { if (field->is_repeated()) { switch (GetObjectiveCType(field)) { case OBJECTIVECTYPE_MESSAGE: { - string type = ClassName(field->message_type()); - if (FilterClass(type)) { - string reason = - "Filtered by |" + type + "| not being whitelisted."; - result = new EmptyFieldGenerator(field, reason); - } else if (field->is_map()) { + if (field->is_map()) { result = new MapFieldGenerator(field); } else { result = new RepeatedMessageFieldGenerator(field); @@ -185,14 +139,7 @@ FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) { } else { switch (GetObjectiveCType(field)) { case OBJECTIVECTYPE_MESSAGE: { - string type = ClassName(field->message_type()); - if (FilterClass(type)) { - string reason = - "Filtered by |" + type + "| not being whitelisted."; - result = new EmptyFieldGenerator(field, reason); - } else { - result = new MessageFieldGenerator(field); - } + result = new MessageFieldGenerator(field); break; } case OBJECTIVECTYPE_ENUM: @@ -249,11 +196,17 @@ void FieldGenerator::GenerateFieldDescription( " .number = $field_number_name$,\n" " .hasIndex = $has_index$,\n" " .flags = $fieldflags$,\n" - " .type = GPBType$field_type$,\n" - " .offset = offsetof($classname$_Storage, $name$),\n" + " .dataType = GPBDataType$field_type$,\n" + " .offset = offsetof($classname$__storage_, $name$),\n" " .defaultValue.$default_name$ = $default$,\n"); - // " .typeSpecific.value* = [something]," + // TODO(thomasvl): It might be useful to add a CPP wrapper to support + // compiling away the EnumDescriptors. To do that, we'd need a #if here + // to control setting the descriptor vs. the validator, and above in + // SetCommonFieldVariables() we'd want to wrap how we add + // GPBFieldHasDefaultValue to the flags. + + // " .dataTypeSpecific.value* = [something]," GenerateFieldDescriptionTypeSpecific(printer); const string& field_options(variables_.find("fieldoptions")->second); @@ -280,7 +233,7 @@ void FieldGenerator::GenerateFieldDescriptionTypeSpecific( io::Printer* printer) const { printer->Print( variables_, - " .typeSpecific.$typeSpecific_name$ = $typeSpecific_value$,\n"); + " .dataTypeSpecific.$dataTypeSpecific_name$ = $dataTypeSpecific_value$,\n"); } void FieldGenerator::SetOneofIndexBase(int index_base) { @@ -410,22 +363,24 @@ void RepeatedFieldGenerator::GenerateFieldStorageDeclaration( void RepeatedFieldGenerator::GeneratePropertyImplementation( io::Printer* printer) const { - printer->Print(variables_, "@dynamic $name$;\n"); + printer->Print(variables_, "@dynamic $name$, $name$_Count;\n"); } void RepeatedFieldGenerator::GeneratePropertyDeclaration( io::Printer* printer) const { - // Repeated fields don't need the has* properties, but this has the same - // logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for dealing - // with needing Objective C's rules around storage name conventions (init*, - // new*, etc.) + // Repeated fields don't need the has* properties, but they do expose a + // *Count (to check without autocreation). So for the field property we need + // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for + // dealing with needing Objective C's rules around storage name conventions + // (init*, new*, etc.) printer->Print( variables_, "$comments$" "$array_comment$" - "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n"); + "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n" + "@property(nonatomic, readonly) NSUInteger $name$_Count;\n"); if (IsInitName(variables_.find("name")->second)) { // If property name starts with init we need to annotate it to get past ARC. // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227 diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index d04eee85..1955c053 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -54,35 +54,24 @@ namespace objectivec { FileGenerator::FileGenerator(const FileDescriptor *file) : file_(file), root_class_name_(FileClassName(file)), - is_filtered_(true), - all_extensions_filtered_(true), is_public_dep_(false) { - // Validate the objc prefix, do this even if the file's contents are filtered - // to catch a bad prefix as soon as it is found. + // Validate the objc prefix. ValidateObjCClassPrefix(file_); for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); - // The enums are exposed via C functions, so they will dead strip if - // not used. - is_filtered_ &= false; enum_generators_.push_back(generator); } for (int i = 0; i < file_->message_type_count(); i++) { MessageGenerator *generator = new MessageGenerator(root_class_name_, file_->message_type(i)); - is_filtered_ &= generator->IsFiltered(); - is_filtered_ &= generator->IsSubContentFiltered(); message_generators_.push_back(generator); } for (int i = 0; i < file_->extension_count(); i++) { ExtensionGenerator *generator = new ExtensionGenerator(root_class_name_, file_->extension(i)); - is_filtered_ &= generator->IsFiltered(); - all_extensions_filtered_ &= generator->IsFiltered(); extension_generators_.push_back(generator); } - // If there is nothing in the file we filter it. } FileGenerator::~FileGenerator() { @@ -116,8 +105,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { "protoc_gen_objc_version", SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION)); - const vector &dependency_generators = - DependencyGenerators(); + const vector &dependency_generators = DependencyGenerators(); for (vector::const_iterator iter = dependency_generators.begin(); iter != dependency_generators.end(); ++iter) { @@ -133,19 +121,17 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { printer->Print("CF_EXTERN_C_BEGIN\n\n"); - if (!IsFiltered()) { - set fwd_decls; - for (vector::iterator iter = message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->DetermineForwardDeclarations(&fwd_decls); - } - for (set::const_iterator i(fwd_decls.begin()); - i != fwd_decls.end(); ++i) { - printer->Print("$value$;\n", "value", *i); - } - if (fwd_decls.begin() != fwd_decls.end()) { - printer->Print("\n"); - } + set fwd_decls; + for (vector::iterator iter = message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->DetermineForwardDeclarations(&fwd_decls); + } + for (set::const_iterator i(fwd_decls.begin()); + i != fwd_decls.end(); ++i) { + printer->Print("$value$;\n", "value", *i); + } + if (fwd_decls.begin() != fwd_decls.end()) { + printer->Print("\n"); } // need to write out all enums first @@ -160,36 +146,27 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { } // For extensions to chain together, the Root gets created even if there - // are no extensions. So if the entire file isn't filtered away, output it. - if (!IsFiltered()) { - printer->Print( - "\n" - "#pragma mark - $root_class_name$\n" - "\n" - "@interface $root_class_name$ : GPBRootObject\n" - "\n" - "// The base class provides:\n" - "// + (GPBExtensionRegistry *)extensionRegistry;\n" - "// which is an GPBExtensionRegistry that includes all the extensions defined by\n" - "// this file and all files that it depends on.\n" - "\n" - "@end\n" - "\n", - "root_class_name", root_class_name_); - } + // are no extensions. + printer->Print( + "\n" + "#pragma mark - $root_class_name$\n" + "\n" + "@interface $root_class_name$ : GPBRootObject\n" + "\n" + "// The base class provides:\n" + "// + (GPBExtensionRegistry *)extensionRegistry;\n" + "// which is an GPBExtensionRegistry that includes all the extensions defined by\n" + "// this file and all files that it depends on.\n" + "\n" + "@end\n" + "\n", + "root_class_name", root_class_name_); if (extension_generators_.size() > 0) { - // The dynamic methods block is only needed if there are extensions. If - // they are all filtered, output the @interface as a comment so there is - // something left in the header for anyone that looks. - const char *root_line_prefix = ""; - if (AreAllExtensionsFiltered()) { - root_line_prefix = "// "; - } + // The dynamic methods block is only needed if there are extensions. printer->Print( - "$root_line_prefix$@interface $root_class_name$ (DynamicMethods)\n", - "root_class_name", root_class_name_, - "root_line_prefix", root_line_prefix); + "@interface $root_class_name$ (DynamicMethods)\n", + "root_class_name", root_class_name_); for (vector::iterator iter = extension_generators_.begin(); @@ -197,8 +174,7 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { (*iter)->GenerateMembersHeader(printer); } - printer->Print("$root_line_prefix$@end\n\n", - "root_line_prefix", root_line_prefix); + printer->Print("@end\n\n"); } // extension_generators_.size() > 0 for (vector::iterator iter = message_generators_.begin(); @@ -239,136 +215,119 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "// @@protoc_insertion_point(imports)\n" "\n"); - if (IsFiltered()) { - printer->Print( - "// File empty because all messages, extensions and enum have been filtered.\n" - "\n" - "\n" - "// Dummy symbol that will be stripped but will avoid linker warnings about\n" - "// no symbols in the .o form compiling this file.\n" - "static int $root_class_name$_dummy __attribute__((unused,used)) = 0;\n" - "\n" - "// @@protoc_insertion_point(global_scope)\n", - "root_class_name", root_class_name_); - return; - } - printer->Print( "#pragma mark - $root_class_name$\n" "\n" "@implementation $root_class_name$\n\n", "root_class_name", root_class_name_); - bool generated_extensions = false; - if (file_->extension_count() + file_->message_type_count() + - file_->dependency_count() > - 0) { - ostringstream extensions_stringstream; - - if (file_->extension_count() + file_->message_type_count() > 0) { - io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); - io::Printer extensions_printer(&extensions_outputstream, '$'); - extensions_printer.Print( - "static GPBExtensionDescription descriptions[] = {\n"); - extensions_printer.Indent(); - for (vector::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization( - &extensions_printer, &generated_extensions, true); - } - for (vector::iterator iter = - message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(&extensions_printer, - &generated_extensions); - } - extensions_printer.Outdent(); - extensions_printer.Print("};\n"); - if (generated_extensions) { - extensions_printer.Print( - "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" - " GPBExtensionField *extension = [[GPBExtensionField alloc] initWithDescription:&descriptions[i]];\n" - " [registry addExtension:extension];\n" - " [self globallyRegisterExtension:extension];\n" - " [extension release];\n" - "}\n"); - } else { - extensions_printer.Print("#pragma unused (descriptions)\n"); - } - const vector &dependency_generators = - DependencyGenerators(); - if (dependency_generators.size()) { - for (vector::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { - if (!(*iter)->IsFiltered()) { - extensions_printer.Print( - "[registry addExtensions:[$dependency$ extensionRegistry]];\n", - "dependency", (*iter)->RootClassName()); - generated_extensions = true; - } - } - } else if (!generated_extensions) { - extensions_printer.Print("#pragma unused (registry)\n"); - } + // Generate the extension initialization structures for the top level and + // any nested messages. + ostringstream extensions_stringstream; + if (file_->extension_count() + file_->message_type_count() > 0) { + io::OstreamOutputStream extensions_outputstream(&extensions_stringstream); + io::Printer extensions_printer(&extensions_outputstream, '$'); + for (vector::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); + } + for (vector::iterator iter = + message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); } + extensions_stringstream.flush(); + } - if (generated_extensions) { + // If there were any extensions or this file has any dependencies, output + // a registry to override to create the file specific registry. + const string& extensions_str = extensions_stringstream.str(); + if (extensions_str.length() > 0 || file_->dependency_count() > 0) { + printer->Print( + "+ (GPBExtensionRegistry*)extensionRegistry {\n" + " // This is called by +initialize so there is no need to worry\n" + " // about thread safety and initialization of registry.\n" + " static GPBExtensionRegistry* registry = nil;\n" + " if (!registry) {\n" + " GPBDebugCheckRuntimeVersion();\n" + " registry = [[GPBExtensionRegistry alloc] init];\n"); + + printer->Indent(); + printer->Indent(); + + if (extensions_str.length() > 0) { printer->Print( - "+ (GPBExtensionRegistry*)extensionRegistry {\n" - " // This is called by +initialize so there is no need to worry\n" - " // about thread safety and initialization of registry.\n" - " static GPBExtensionRegistry* registry = nil;\n" - " if (!registry) {\n" - " registry = [[GPBExtensionRegistry alloc] init];\n"); - - printer->Indent(); + "static GPBExtensionDescription descriptions[] = {\n"); printer->Indent(); - - extensions_stringstream.flush(); - printer->Print(extensions_stringstream.str().c_str()); - printer->Outdent(); + printer->Print(extensions_str.c_str()); printer->Outdent(); + printer->Print( + "};\n" + "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n" + " GPBExtensionDescriptor *extension =\n" + " [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]];\n" + " [registry addExtension:extension];\n" + " [self globallyRegisterExtension:extension];\n" + " [extension release];\n" + "}\n"); + } + const vector &dependency_generators = + DependencyGenerators(); + for (vector::const_iterator iter = + dependency_generators.begin(); + iter != dependency_generators.end(); ++iter) { printer->Print( - " }\n" - " return registry;\n" - "}\n" - "\n"); + "[registry addExtensions:[$dependency$ extensionRegistry]];\n", + "dependency", (*iter)->RootClassName()); } + + printer->Outdent(); + printer->Outdent(); + + printer->Print( + " }\n" + " return registry;\n" + "}\n" + "\n"); } printer->Print("@end\n\n"); - - string syntax; - switch (file_->syntax()) { - case FileDescriptor::SYNTAX_UNKNOWN: - syntax = "GPBFileSyntaxUnknown"; - break; - case FileDescriptor::SYNTAX_PROTO2: - syntax = "GPBFileSyntaxProto2"; - break; - case FileDescriptor::SYNTAX_PROTO3: - syntax = "GPBFileSyntaxProto3"; - break; + // File descriptor only needed if there are messages to use it. + if (message_generators_.size() > 0) { + string syntax; + switch (file_->syntax()) { + case FileDescriptor::SYNTAX_UNKNOWN: + syntax = "GPBFileSyntaxUnknown"; + break; + case FileDescriptor::SYNTAX_PROTO2: + syntax = "GPBFileSyntaxProto2"; + break; + case FileDescriptor::SYNTAX_PROTO3: + syntax = "GPBFileSyntaxProto3"; + break; + } + printer->Print( + "#pragma mark - $root_class_name$_FileDescriptor\n" + "\n" + "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" + " // This is called by +initialize so there is no need to worry\n" + " // about thread safety of the singleton.\n" + " static GPBFileDescriptor *descriptor = NULL;\n" + " if (!descriptor) {\n" + " GPBDebugCheckRuntimeVersion();\n" + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " syntax:$syntax$];\n" + " }\n" + " return descriptor;\n" + "}\n" + "\n", + "root_class_name", root_class_name_, + "package", file_->package(), + "syntax", syntax); } - printer->Print( - "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" - " // This is called by +initialize so there is no need to worry\n" - " // about thread safety of the singleton.\n" - " static GPBFileDescriptor *descriptor = NULL;\n" - " if (!descriptor) {\n" - " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" - " syntax:$syntax$];\n" - " }\n" - " return descriptor;\n" - "}\n" - "\n", - "root_class_name", root_class_name_, - "package", file_->package(), - "syntax", syntax); for (vector::iterator iter = enum_generators_.begin(); iter != enum_generators_.end(); ++iter) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index 95d17bfd..1bb4f0ea 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -64,8 +64,6 @@ class FileGenerator { const string& RootClassName() const { return root_class_name_; } const string Path() const; - bool IsFiltered() const { return is_filtered_; } - bool AreAllExtensionsFiltered() const { return all_extensions_filtered_; } bool IsPublicDependency() const { return is_public_dep_; } protected: @@ -84,8 +82,6 @@ class FileGenerator { vector enum_generators_; vector message_generators_; vector extension_generators_; - bool is_filtered_; - bool all_extensions_filtered_; bool is_public_dep_; const vector& DependencyGenerators(); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index 17776715..85e438f4 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -58,10 +58,6 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, return false; } - if (!InitializeClassWhitelist(error)) { - return false; - } - FileGenerator file_generator(file); string filepath = FilePath(file); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 6d6e5959..9b645f09 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -50,8 +50,6 @@ namespace objectivec { namespace { -hash_set gClassWhitelist; - // islower()/isupper()/tolower()/toupper() change based on locale. // // src/google/protobuf/stubs/strutil.h:150 has the same pattern. For the @@ -580,7 +578,7 @@ string GetCapitalizedType(const FieldDescriptor* field) { case FieldDescriptor::TYPE_STRING: return "String"; case FieldDescriptor::TYPE_BYTES: - return "Data"; + return "Bytes"; case FieldDescriptor::TYPE_ENUM: return "Enum"; case FieldDescriptor::TYPE_GROUP: @@ -684,8 +682,9 @@ static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) { } } -string GPBValueFieldName(const FieldDescriptor* field) { - // Returns the field within the GPBValue union to use for the given field. +string GPBGenericValueFieldName(const FieldDescriptor* field) { + // Returns the field within the GPBGenericValue union to use for the given + // field. if (field->is_repeated()) { return "valueMessage"; } @@ -831,60 +830,6 @@ string BuildCommentsString(const SourceLocation& location) { return final_comments; } -bool InitializeClassWhitelist(string* error) { - const char* env_var_value = getenv("GPB_OBJC_CLASS_WHITELIST_PATHS"); - if (env_var_value == NULL) { - return true; - } - - // The values are joined with ';' in case we ever want to make this a - // generator parameter also (instead of env var), and generator parameter - // parsing already has meaning for ',' and ':'. - vector file_paths = Split(env_var_value, ";", true); - - for (vector::const_iterator i = file_paths.begin(); - i != file_paths.end(); ++i) { - const string& file_path = *i; - - ifstream stream(file_path.c_str(), ifstream::in); - if (!stream.good()) { - if (error != NULL) { - stringstream err_stream; - err_stream << endl << file_path << ":0:0: error: Unable to open"; - *error = err_stream.str(); - return false; - } - } - - string input_line; - while (stream.good()) { - getline(stream, input_line); - string trimmed_line(TrimString(input_line)); - if (trimmed_line.length() == 0) { - // Skip empty lines - continue; - } - if (trimmed_line[0] == '/' || trimmed_line[0] == '#') { - // Skip comments and potential preprocessor symbols - continue; - } - gClassWhitelist.insert(trimmed_line); - } - } - return true; -} - -bool FilterClass(const string& name) { - if (gClassWhitelist.count(name) > 0) { - // Whitelisted, don't filter. - return false; - } - - // If there was no list, default to everything in. - // If there was a list, default to everything out. - return gClassWhitelist.size() > 0; -} - void TextFormatDecodeData::AddString(int32 key, const string& input_for_decode, const string& desired_output) { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index 19317698..10d51a34 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -138,16 +138,13 @@ inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) { bool IsPrimitiveType(const FieldDescriptor* field); bool IsReferenceType(const FieldDescriptor* field); -string GPBValueFieldName(const FieldDescriptor* field); +string GPBGenericValueFieldName(const FieldDescriptor* field); string DefaultValue(const FieldDescriptor* field); string BuildFlagsString(const vector& strings); string BuildCommentsString(const SourceLocation& location); -bool InitializeClassWhitelist(string* error); -bool FilterClass(const string& name); - // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the the expected output. class LIBPROTOC_EXPORT TextFormatDecodeData { diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc index b091b77a..dc1cef55 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc @@ -242,6 +242,14 @@ TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) { } #endif // PROTOBUF_HAS_DEATH_TEST +// TODO(thomasvl): Should probably add some unittests for all the special cases +// of name mangling (class name, field name, enum names). Rather than doing +// this with an ObjC test in the objectivec directory, we should be able to +// use src/google/protobuf/compiler/importer* (like other tests) to support a +// virtual file system to feed in protos, once we have the Descriptor tree, the +// tests could use the helper methods for generating names and validate the +// right things are happening. + } // namespace } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index 52e583bf..32671d42 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -178,49 +178,25 @@ MessageGenerator::MessageGenerator(const string& root_classname, : root_classname_(root_classname), descriptor_(descriptor), field_generators_(descriptor), - class_name_(ClassName(descriptor_)), - sub_content_filtered_(true) { - if (FilterClass(class_name_)) { - filter_reason_ = - string("Message |") + class_name_ + "| was not whitelisted."; + class_name_(ClassName(descriptor_)) { + for (int i = 0; i < descriptor_->extension_count(); i++) { + extension_generators_.push_back( + new ExtensionGenerator(class_name_, descriptor_->extension(i))); } - if (!IsFiltered()) { - // No need to generate extensions if this message is filtered - for (int i = 0; i < descriptor_->extension_count(); i++) { - extension_generators_.push_back( - new ExtensionGenerator(class_name_, descriptor_->extension(i))); - } - // No need to generate oneofs if this message is filtered. - 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_->oneof_decl_count(); i++) { + OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i)); + oneof_generators_.push_back(generator); } - // We may have enums of this message that are used even if the message - // itself is filtered. for (int i = 0; i < descriptor_->enum_type_count(); i++) { EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i)); - // The enums are exposed via C functions, so they will dead strip if - // not used. - sub_content_filtered_ &= false; enum_generators_.push_back(generator); } - // We may have nested messages that are used even if the message itself - // is filtered. for (int i = 0; i < descriptor_->nested_type_count(); i++) { - const Descriptor* nested_descriptor = descriptor_->nested_type(i); MessageGenerator* generator = - new MessageGenerator(root_classname_, nested_descriptor); - // Don't check map entries for being filtered, as they don't directly - // generate anything in Objective C. In theory, they only should include - // references to other toplevel types, but we still make the generators - // to be safe. - if (!IsMapEntryMessage(nested_descriptor)) { - sub_content_filtered_ &= generator->IsFiltered(); - } - sub_content_filtered_ &= generator->IsSubContentFiltered(); + new MessageGenerator(root_classname_, descriptor_->nested_type(i)); nested_message_generators_.push_back(generator); } } @@ -236,31 +212,26 @@ MessageGenerator::~MessageGenerator() { } void MessageGenerator::GenerateStaticVariablesInitialization( - io::Printer* printer, bool* out_generated) { - if (!IsFiltered()) { - // Skip extensions if we are filtered. - for (vector::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(printer, out_generated, - false); - } + io::Printer* printer) { + for (vector::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer); } - // Generating sub messages is perfectly fine though. for (vector::iterator iter = nested_message_generators_.begin(); iter != nested_message_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(printer, out_generated); + (*iter)->GenerateStaticVariablesInitialization(printer); } } void MessageGenerator::DetermineForwardDeclarations(set* fwd_decls) { - if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { + 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 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; } @@ -291,12 +262,10 @@ void MessageGenerator::GenerateEnumHeader(io::Printer* printer) { void MessageGenerator::GenerateExtensionRegistrationSource( io::Printer* printer) { - if (!IsFiltered()) { - for (vector::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateRegistrationSource(printer); - } + for (vector::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateRegistrationSource(printer); } for (vector::iterator iter = @@ -317,101 +286,84 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { return; } - if (IsFiltered()) { - printer->Print("// $filter_reason$\n\n", - "filter_reason", filter_reason_); - } else { - printer->Print( - "#pragma mark - $classname$\n" - "\n", - "classname", class_name_); + printer->Print( + "#pragma mark - $classname$\n" + "\n", + "classname", class_name_); - if (descriptor_->field_count()) { - // Even if there are fields, they could be filtered away, so always use - // a buffer to confirm we have something. - ostringstream fieldnumber_stringstream; - { - scoped_array sorted_fields( - SortFieldsByNumber(descriptor_)); - - io::OstreamOutputStream fieldnumber_outputstream( - &fieldnumber_stringstream); - io::Printer fieldnumber_printer(&fieldnumber_outputstream, '$'); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(sorted_fields[i]) - .GenerateFieldNumberConstant(&fieldnumber_printer); - } - fieldnumber_stringstream.flush(); - } - const string& fieldnumber_str = fieldnumber_stringstream.str(); - if (fieldnumber_str.length()) { - printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", - "classname", class_name_); - printer->Indent(); - printer->Print(fieldnumber_str.c_str()); - printer->Outdent(); - printer->Print("};\n\n"); - } - } + if (descriptor_->field_count()) { + scoped_array sorted_fields( + SortFieldsByNumber(descriptor_)); - for (vector::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GenerateCaseEnum(printer); - } + printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", + "classname", class_name_); + printer->Indent(); - string message_comments; - SourceLocation location; - if (descriptor_->GetSourceLocation(&location)) { - message_comments = BuildCommentsString(location); - } else { - message_comments = ""; + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(sorted_fields[i]) + .GenerateFieldNumberConstant(printer); } - printer->Print( - "$comments$@interface $classname$ : GPBMessage\n\n", - "classname", class_name_, - "comments", message_comments); + printer->Outdent(); + printer->Print("};\n\n"); + } - vector 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); - } + for (vector::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 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); } + field_generators_.get(field).GeneratePropertyDeclaration(printer); + } - printer->Print("@end\n\n"); + printer->Print("@end\n\n"); - for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateCFunctionDeclarations(printer); - } + for (int i = 0; i < descriptor_->field_count(); i++) { + field_generators_.get(descriptor_->field(i)) + .GenerateCFunctionDeclarations(printer); + } - if (!oneof_generators_.empty()) { - for (vector::iterator iter = oneof_generators_.begin(); - iter != oneof_generators_.end(); ++iter) { - (*iter)->GenerateClearFunctionDeclaration(printer); - } - printer->Print("\n"); + if (!oneof_generators_.empty()) { + for (vector::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::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateMembersHeader(printer); - } - printer->Print("@end\n\n"); + if (descriptor_->extension_count() > 0) { + printer->Print("@interface $classname$ (DynamicMethods)\n\n", + "classname", class_name_); + for (vector::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateMembersHeader(printer); } + printer->Print("@end\n\n"); } for (vector::iterator iter = @@ -422,7 +374,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { } void MessageGenerator::GenerateSource(io::Printer* printer) { - if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) { + if (!IsMapEntryMessage(descriptor_)) { printer->Print( "#pragma mark - $classname$\n" "\n", @@ -454,6 +406,23 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { 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. @@ -467,7 +436,7 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Print( "\n" - "typedef struct $classname$_Storage {\n" + "typedef struct $classname$__storage_ {\n" " uint32_t _has_storage_[$sizeof_has_storage$];\n", "classname", class_name_, "sizeof_has_storage", SimpleItoa(sizeof_has_storage)); @@ -479,14 +448,14 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { } printer->Outdent(); - printer->Print("} $classname$_Storage;\n\n", "classname", class_name_); + 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 = NULL;\n" + " static GPBDescriptor *descriptor = nil;\n" " if (!descriptor) {\n"); bool has_oneofs = oneof_generators_.size(); @@ -507,30 +476,45 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " };\n"); } - printer->Print( - " static GPBMessageFieldDescription fields[] = {\n"); - printer->Indent(); - printer->Indent(); - printer->Indent(); TextFormatDecodeData text_format_decode_data; - 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()); + 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"); } - printer->Outdent(); - printer->Outdent(); - printer->Outdent(); bool has_enums = enum_generators_.size(); if (has_enums) { printer->Print( - " };\n" " static GPBMessageEnumDescription enums[] = {\n"); printer->Indent(); printer->Indent(); @@ -543,12 +527,13 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Outdent(); + printer->Print( + " };\n"); } bool has_extensions = sorted_extensions.size(); if (has_extensions) { printer->Print( - " };\n" " static GPBExtensionRange ranges[] = {\n"); printer->Indent(); printer->Indent(); @@ -561,11 +546,16 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Outdent(); + printer->Print( + " };\n"); } map 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"; @@ -578,23 +568,23 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { vars["wireformat"] = descriptor_->options().message_set_wire_format() ? "YES" : "NO"; - printer->Print(" };\n"); if (text_format_decode_data.num_entries() == 0) { printer->Print( vars, - " descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" - " rootClass:[$rootclassname$ class]\n" - " file:$rootclassname$_FileDescriptor()\n" - " fields:fields\n" - " fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\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"); + " 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( @@ -604,26 +594,29 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { "#else\n" " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n" "#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n" - " descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n" - " rootClass:[$rootclassname$ class]\n" - " file:$rootclassname$_FileDescriptor()\n" - " fields:fields\n" - " fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\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"); + " 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( - " }\n" - " return descriptor;\n" - "}\n\n" - "@end\n\n"); + " 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)) diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h index 8d03c0b8..06b536ff 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h @@ -57,20 +57,13 @@ class MessageGenerator { MessageGenerator(const string& root_classname, const Descriptor* descriptor); ~MessageGenerator(); - void GenerateStaticVariablesInitialization(io::Printer* printer, - bool* out_generated); + void GenerateStaticVariablesInitialization(io::Printer* printer); void GenerateEnumHeader(io::Printer* printer); void GenerateMessageHeader(io::Printer* printer); void GenerateSource(io::Printer* printer); void GenerateExtensionRegistrationSource(io::Printer* printer); void DetermineForwardDeclarations(set* fwd_decls); - // This only speaks for this message, not sub message/enums. - bool IsFiltered() const { return filter_reason_.length() > 0; } - // This message being filtered doesn't effect this, instead it covers if - // there are any nested messages or enums. - bool IsSubContentFiltered() const { return sub_content_filtered_; } - private: void GenerateParseFromMethodsHeader(io::Printer* printer); @@ -87,8 +80,6 @@ class MessageGenerator { const Descriptor* descriptor_; FieldGeneratorMap field_generators_; const string class_name_; - string filter_reason_; - bool sub_content_filtered_; vector extension_generators_; vector enum_generators_; vector nested_message_generators_; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc index 2e3bdfdb..f2ce4e5b 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc @@ -53,7 +53,7 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["group_or_message"] = (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; - (*variables)["typeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; + (*variables)["dataTypeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")"; } } // namespace -- cgit v1.2.3 From e38294a62d7f37c0661273a9a26fda16d557423f Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Tue, 9 Jun 2015 19:30:44 +0100 Subject: First pass at the mutable API. Quite a bit more to do - in particular, it's pretty slow right now. --- csharp/protos/extest/unittest_issues.proto | 86 +- .../ProtocolBuffers.Test/AbstractMessageTest.cs | 548 - csharp/src/ProtocolBuffers.Test/ByteStringTest.cs | 2 +- .../ProtocolBuffers.Test/CodedInputStreamTest.cs | 64 +- .../ProtocolBuffers.Test/CodedOutputStreamTest.cs | 23 +- .../Collections/PopsicleListTest.cs | 125 - .../Compatibility/BinaryCompatibilityTests.cs | 18 - .../Compatibility/CompatibilityTests.cs | 227 - .../Compatibility/DictionaryCompatibilityTests.cs | 35 - .../Compatibility/JsonCompatibilityTests.cs | 43 - .../Compatibility/TestResources.cs | 38 - .../Compatibility/TextCompatibilityTests.cs | 35 - .../Compatibility/XmlCompatibilityTests.cs | 45 - .../Compatibility/google_message1.dat | Bin 228 -> 0 bytes .../Compatibility/google_message2.dat | Bin 84570 -> 0 bytes .../ProtocolBuffers.Test/DeprecatedMemberTest.cs | 82 +- csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs | 152 +- .../src/ProtocolBuffers.Test/DynamicMessageTest.cs | 276 - .../ProtocolBuffers.Test/ExtendableMessageTest.cs | 200 - .../src/ProtocolBuffers.Test/FieldPresenceTest.cs | 198 - .../ProtocolBuffers.Test/GeneratedBuilderTest.cs | 102 - .../ProtocolBuffers.Test/GeneratedMessageTest.cs | 911 +- csharp/src/ProtocolBuffers.Test/IssuesTest.cs | 10 +- .../MessageStreamIteratorTest.cs | 90 - .../MessageStreamWriterTest.cs | 78 - csharp/src/ProtocolBuffers.Test/MessageTest.cs | 344 - csharp/src/ProtocolBuffers.Test/MessageUtilTest.cs | 82 - csharp/src/ProtocolBuffers.Test/NameHelpersTest.cs | 81 - .../ProtocolBuffers.Test.csproj | 62 +- .../src/ProtocolBuffers.Test/ReflectionTester.cs | 1033 - .../src/ProtocolBuffers.Test/RepeatedFieldTest.cs | 50 + .../ProtocolBuffers.Test/ReusableBuilderTest.cs | 166 - csharp/src/ProtocolBuffers.Test/TestCornerCases.cs | 22 +- .../ProtocolBuffers.Test/TestMimeMessageFormats.cs | 277 - .../ProtocolBuffers.Test/TestProtos/GoogleSize.cs | 4547 --- .../ProtocolBuffers.Test/TestProtos/GoogleSpeed.cs | 6612 ---- .../ProtocolBuffers.Test/TestProtos/Unittest.cs | 33878 ----------------- .../TestProtos/UnittestCustomOptions.cs | 7543 ---- .../TestProtos/UnittestDropUnknownFields.cs | 732 - .../TestProtos/UnittestEnormousDescriptor.cs | 36189 ------------------- .../TestProtos/UnittestExtrasXmltest.cs | 2277 -- .../TestProtos/UnittestImport.cs | 347 - .../TestProtos/UnittestImportProto3.cs | 165 + .../TestProtos/UnittestImportPublic.cs | 333 - .../TestProtos/UnittestImportPublicProto3.cs | 150 + .../TestProtos/UnittestIssues.cs | 2571 +- .../TestProtos/UnittestMset.cs | 1824 - .../TestProtos/UnittestNoFieldPresence.cs | 3876 -- .../TestProtos/UnittestOptimizeFor.cs | 738 - .../TestProtos/UnittestProto3.cs | 6060 ++++ .../TestProtos/UnknownEnumTest.cs | 809 - .../TestReaderForUrlEncoded.cs | 83 - csharp/src/ProtocolBuffers.Test/TestResources.cs | 301 - csharp/src/ProtocolBuffers.Test/TestUtil.cs | 1862 - .../ProtocolBuffers.Test/TestWriterFormatJson.cs | 498 - .../ProtocolBuffers.Test/TestWriterFormatXml.cs | 468 - csharp/src/ProtocolBuffers.Test/TextFormatTest.cs | 560 - .../ProtocolBuffers.Test/UnknownFieldSetTest.cs | 431 - csharp/src/ProtocolBuffers.Test/WireFormatTest.cs | 255 +- csharp/src/ProtocolBuffers/AbstractBuilder.cs | 274 - csharp/src/ProtocolBuffers/AbstractBuilderLite.cs | 264 - csharp/src/ProtocolBuffers/AbstractMessage.cs | 293 - csharp/src/ProtocolBuffers/AbstractMessageLite.cs | 140 - csharp/src/ProtocolBuffers/ByteArray.cs | 2 +- csharp/src/ProtocolBuffers/ByteString.cs | 20 +- csharp/src/ProtocolBuffers/CodedInputStream.cs | 163 +- .../CodedOutputStream.ComputeSize.cs | 71 +- csharp/src/ProtocolBuffers/CodedOutputStream.cs | 338 +- .../ProtocolBuffers/Collections/Dictionaries.cs | 2 +- .../src/ProtocolBuffers/Collections/Enumerables.cs | 2 +- .../ProtocolBuffers/Collections/IPopsicleList.cs | 58 - csharp/src/ProtocolBuffers/Collections/Lists.cs | 2 +- .../ProtocolBuffers/Collections/PopsicleList.cs | 208 - .../Collections/ReadOnlyDictionary.cs | 2 +- .../ProtocolBuffers/Collections/RepeatedField.cs | 168 + .../Collections/RepeatedFieldExtensions.cs | 47 + csharp/src/ProtocolBuffers/Delegates.cs | 54 - .../DescriptorProtos/DescriptorProtoFile.cs | 12724 ++----- .../DescriptorProtos/IDescriptorProto.cs | 2 +- .../DescriptorProtos/PartialClasses.cs | 2 +- .../ProtocolBuffers/Descriptors/DescriptorBase.cs | 5 +- .../ProtocolBuffers/Descriptors/DescriptorPool.cs | 4 +- .../ProtocolBuffers/Descriptors/DescriptorUtil.cs | 4 +- .../Descriptors/DescriptorValidationException.cs | 13 +- .../ProtocolBuffers/Descriptors/EnumDescriptor.cs | 31 +- .../Descriptors/EnumValueDescriptor.cs | 7 +- .../ProtocolBuffers/Descriptors/FieldDescriptor.cs | 223 +- .../Descriptors/FieldMappingAttribute.cs | 4 +- .../src/ProtocolBuffers/Descriptors/FieldType.cs | 2 +- .../ProtocolBuffers/Descriptors/FileDescriptor.cs | 55 +- .../src/ProtocolBuffers/Descriptors/IDescriptor.cs | 4 +- .../Descriptors/IndexedDescriptorBase.cs | 4 +- .../src/ProtocolBuffers/Descriptors/MappedType.cs | 2 +- .../Descriptors/MessageDescriptor.cs | 30 +- .../Descriptors/MethodDescriptor.cs | 4 +- .../ProtocolBuffers/Descriptors/OneofDescriptor.cs | 4 +- .../Descriptors/PackageDescriptor.cs | 2 +- .../Descriptors/ServiceDescriptor.cs | 8 +- csharp/src/ProtocolBuffers/DynamicMessage.cs | 624 - csharp/src/ProtocolBuffers/EnumHelper.cs | 85 + csharp/src/ProtocolBuffers/EnumLite.cs | 234 - csharp/src/ProtocolBuffers/ExtendableBuilder.cs | 212 - .../src/ProtocolBuffers/ExtendableBuilderLite.cs | 345 - csharp/src/ProtocolBuffers/ExtendableMessage.cs | 274 - .../src/ProtocolBuffers/ExtendableMessageLite.cs | 221 - csharp/src/ProtocolBuffers/ExtensionInfo.cs | 88 - csharp/src/ProtocolBuffers/ExtensionRegistry.cs | 215 - .../src/ProtocolBuffers/ExtensionRegistryLite.cs | 232 - csharp/src/ProtocolBuffers/Extensions.cs | 70 + .../FieldAccess/FieldAccessorBase.cs | 38 + .../FieldAccess/FieldAccessorTable.cs | 104 +- .../ProtocolBuffers/FieldAccess/IFieldAccessor.cs | 59 +- .../ProtocolBuffers/FieldAccess/OneofAccessor.cs | 13 +- .../ProtocolBuffers/FieldAccess/ReflectionUtil.cs | 57 +- .../FieldAccess/RepeatedEnumAccessor.cs | 83 - .../FieldAccess/RepeatedFieldAccessor.cs | 37 + .../FieldAccess/RepeatedMessageAccessor.cs | 97 - .../FieldAccess/RepeatedPrimitiveAccessor.cs | 158 - .../FieldAccess/SingleEnumAccessor.cs | 75 - .../FieldAccess/SingleFieldAccessor.cs | 89 + .../FieldAccess/SingleMessageAccessor.cs | 91 - .../FieldAccess/SinglePrimitiveAccessor.cs | 162 - csharp/src/ProtocolBuffers/FieldSet.cs | 632 - csharp/src/ProtocolBuffers/FrameworkPortability.cs | 2 +- csharp/src/ProtocolBuffers/GeneratedBuilder.cs | 230 - csharp/src/ProtocolBuffers/GeneratedBuilderLite.cs | 100 - .../src/ProtocolBuffers/GeneratedExtensionBase.cs | 185 - .../src/ProtocolBuffers/GeneratedExtensionLite.cs | 354 - csharp/src/ProtocolBuffers/GeneratedMessage.cs | 191 - csharp/src/ProtocolBuffers/GeneratedMessageLite.cs | 182 - .../ProtocolBuffers/GeneratedRepeatExtension.cs | 88 - .../ProtocolBuffers/GeneratedSingleExtension.cs | 65 - csharp/src/ProtocolBuffers/IBuilder.cs | 323 - csharp/src/ProtocolBuffers/IBuilderLite.cs | 213 - csharp/src/ProtocolBuffers/ICodedInputStream.cs | 50 +- csharp/src/ProtocolBuffers/ICodedOutputStream.cs | 103 +- csharp/src/ProtocolBuffers/IMessage.cs | 216 +- csharp/src/ProtocolBuffers/IMessageLite.cs | 188 - .../InvalidProtocolBufferException.cs | 2 +- csharp/src/ProtocolBuffers/LimitedInputStream.cs | 78 + csharp/src/ProtocolBuffers/MessageParser.cs | 57 + .../src/ProtocolBuffers/MessageStreamIterator.cs | 170 - csharp/src/ProtocolBuffers/MessageStreamWriter.cs | 70 - csharp/src/ProtocolBuffers/MessageUtil.cs | 109 - csharp/src/ProtocolBuffers/NameHelpers.cs | 140 - csharp/src/ProtocolBuffers/ProtocolBuffers.csproj | 61 +- csharp/src/ProtocolBuffers/SortedList.cs | 167 - csharp/src/ProtocolBuffers/TextFormat.cs | 893 - csharp/src/ProtocolBuffers/TextGenerator.cs | 2 +- csharp/src/ProtocolBuffers/TextTokenizer.cs | 501 - csharp/src/ProtocolBuffers/ThrowHelper.cs | 2 +- .../UninitializedMessageException.cs | 208 - csharp/src/ProtocolBuffers/UnknownField.cs | 415 - csharp/src/ProtocolBuffers/UnknownFieldSet.cs | 1061 - csharp/src/ProtocolBuffers/WireFormat.cs | 4 +- .../protobuf/compiler/csharp/csharp_enum_field.cc | 8 +- .../protobuf/compiler/csharp/csharp_field_base.cc | 19 +- .../protobuf/compiler/csharp/csharp_message.cc | 99 +- .../protobuf/compiler/csharp/csharp_message.h | 1 + .../compiler/csharp/csharp_message_field.cc | 30 +- .../compiler/csharp/csharp_primitive_field.cc | 16 +- .../compiler/csharp/csharp_repeated_enum_field.cc | 25 +- .../csharp/csharp_repeated_message_field.cc | 27 +- .../csharp/csharp_repeated_primitive_field.cc | 10 +- src/google/protobuf/descriptor.proto | 2 +- src/google/protobuf/unittest_import_proto3.proto | 68 + .../protobuf/unittest_import_public_proto3.proto | 42 + src/google/protobuf/unittest_proto3.proto | 388 + 168 files changed, 11868 insertions(+), 133448 deletions(-) delete mode 100644 csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Collections/PopsicleListTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/BinaryCompatibilityTests.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/CompatibilityTests.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/DictionaryCompatibilityTests.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/TestResources.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/TextCompatibilityTests.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/google_message1.dat delete mode 100644 csharp/src/ProtocolBuffers.Test/Compatibility/google_message2.dat delete mode 100644 csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/ExtendableMessageTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/GeneratedBuilderTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/MessageStreamIteratorTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/MessageStreamWriterTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/MessageTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/MessageUtilTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/NameHelpersTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/ReflectionTester.cs create mode 100644 csharp/src/ProtocolBuffers.Test/RepeatedFieldTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/ReusableBuilderTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestMimeMessageFormats.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/GoogleSize.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/GoogleSpeed.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/Unittest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestCustomOptions.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestDropUnknownFields.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestEnormousDescriptor.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestExtrasXmltest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImport.cs create mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublic.cs create mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestMset.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestNoFieldPresence.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestOptimizeFor.cs create mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestProtos/UnknownEnumTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestReaderForUrlEncoded.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestResources.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestUtil.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestWriterFormatJson.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TestWriterFormatXml.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/TextFormatTest.cs delete mode 100644 csharp/src/ProtocolBuffers.Test/UnknownFieldSetTest.cs delete mode 100644 csharp/src/ProtocolBuffers/AbstractBuilder.cs delete mode 100644 csharp/src/ProtocolBuffers/AbstractBuilderLite.cs delete mode 100644 csharp/src/ProtocolBuffers/AbstractMessage.cs delete mode 100644 csharp/src/ProtocolBuffers/AbstractMessageLite.cs delete mode 100644 csharp/src/ProtocolBuffers/Collections/IPopsicleList.cs delete mode 100644 csharp/src/ProtocolBuffers/Collections/PopsicleList.cs create mode 100644 csharp/src/ProtocolBuffers/Collections/RepeatedField.cs create mode 100644 csharp/src/ProtocolBuffers/Collections/RepeatedFieldExtensions.cs delete mode 100644 csharp/src/ProtocolBuffers/Delegates.cs delete mode 100644 csharp/src/ProtocolBuffers/DynamicMessage.cs create mode 100644 csharp/src/ProtocolBuffers/EnumHelper.cs delete mode 100644 csharp/src/ProtocolBuffers/EnumLite.cs delete mode 100644 csharp/src/ProtocolBuffers/ExtendableBuilder.cs delete mode 100644 csharp/src/ProtocolBuffers/ExtendableBuilderLite.cs delete mode 100644 csharp/src/ProtocolBuffers/ExtendableMessage.cs delete mode 100644 csharp/src/ProtocolBuffers/ExtendableMessageLite.cs delete mode 100644 csharp/src/ProtocolBuffers/ExtensionInfo.cs delete mode 100644 csharp/src/ProtocolBuffers/ExtensionRegistry.cs delete mode 100644 csharp/src/ProtocolBuffers/ExtensionRegistryLite.cs create mode 100644 csharp/src/ProtocolBuffers/Extensions.cs create mode 100644 csharp/src/ProtocolBuffers/FieldAccess/FieldAccessorBase.cs delete mode 100644 csharp/src/ProtocolBuffers/FieldAccess/RepeatedEnumAccessor.cs create mode 100644 csharp/src/ProtocolBuffers/FieldAccess/RepeatedFieldAccessor.cs delete mode 100644 csharp/src/ProtocolBuffers/FieldAccess/RepeatedMessageAccessor.cs delete mode 100644 csharp/src/ProtocolBuffers/FieldAccess/RepeatedPrimitiveAccessor.cs delete mode 100644 csharp/src/ProtocolBuffers/FieldAccess/SingleEnumAccessor.cs create mode 100644 csharp/src/ProtocolBuffers/FieldAccess/SingleFieldAccessor.cs delete mode 100644 csharp/src/ProtocolBuffers/FieldAccess/SingleMessageAccessor.cs delete mode 100644 csharp/src/ProtocolBuffers/FieldAccess/SinglePrimitiveAccessor.cs delete mode 100644 csharp/src/ProtocolBuffers/FieldSet.cs delete mode 100644 csharp/src/ProtocolBuffers/GeneratedBuilder.cs delete mode 100644 csharp/src/ProtocolBuffers/GeneratedBuilderLite.cs delete mode 100644 csharp/src/ProtocolBuffers/GeneratedExtensionBase.cs delete mode 100644 csharp/src/ProtocolBuffers/GeneratedExtensionLite.cs delete mode 100644 csharp/src/ProtocolBuffers/GeneratedMessage.cs delete mode 100644 csharp/src/ProtocolBuffers/GeneratedMessageLite.cs delete mode 100644 csharp/src/ProtocolBuffers/GeneratedRepeatExtension.cs delete mode 100644 csharp/src/ProtocolBuffers/GeneratedSingleExtension.cs delete mode 100644 csharp/src/ProtocolBuffers/IBuilder.cs delete mode 100644 csharp/src/ProtocolBuffers/IBuilderLite.cs delete mode 100644 csharp/src/ProtocolBuffers/IMessageLite.cs create mode 100644 csharp/src/ProtocolBuffers/LimitedInputStream.cs create mode 100644 csharp/src/ProtocolBuffers/MessageParser.cs delete mode 100644 csharp/src/ProtocolBuffers/MessageStreamIterator.cs delete mode 100644 csharp/src/ProtocolBuffers/MessageStreamWriter.cs delete mode 100644 csharp/src/ProtocolBuffers/MessageUtil.cs delete mode 100644 csharp/src/ProtocolBuffers/NameHelpers.cs delete mode 100644 csharp/src/ProtocolBuffers/SortedList.cs delete mode 100644 csharp/src/ProtocolBuffers/TextFormat.cs delete mode 100644 csharp/src/ProtocolBuffers/TextTokenizer.cs delete mode 100644 csharp/src/ProtocolBuffers/UninitializedMessageException.cs delete mode 100644 csharp/src/ProtocolBuffers/UnknownField.cs delete mode 100644 csharp/src/ProtocolBuffers/UnknownFieldSet.cs create mode 100644 src/google/protobuf/unittest_import_proto3.proto create mode 100644 src/google/protobuf/unittest_import_public_proto3.proto create mode 100644 src/google/protobuf/unittest_proto3.proto (limited to 'src/google/protobuf/compiler') diff --git a/csharp/protos/extest/unittest_issues.proto b/csharp/protos/extest/unittest_issues.proto index 97249dff..c123acf1 100644 --- a/csharp/protos/extest/unittest_issues.proto +++ b/csharp/protos/extest/unittest_issues.proto @@ -1,4 +1,4 @@ -syntax = "proto2"; +syntax = "proto3"; // These proto descriptors have at one time been reported as an issue or defect. // They are kept here to replicate the issue, and continue to verify the fix. @@ -9,65 +9,6 @@ option csharp_namespace = "UnitTest.Issues.TestProtos"; package unittest_issues; option optimize_for = SPEED; -// The following is a representative set of features -/* -enum EnumOptions { - ONE = 0; - TWO = 1; - THREE = 2; -} - -message TestBasicChild -{ - repeated EnumOptions options = 3; - optional bytes binary = 4; -} - -message TestBasicNoFields { -} - -message TestBasicRescursive { - optional TestBasicRescursive child = 1; -} - -message TestBasicMessage { - - optional int64 number = 6; - repeated int32 numbers = 2; - optional string text = 3; - repeated string textlines = 700; - optional bool valid = 5; - - optional TestBasicChild child = 1; - repeated group Children = 401 - { - repeated EnumOptions options = 3; - optional bytes binary = 4; - } - - extensions 100 to 199; -} - -message TestBasicExtension { - required int32 number = 1; -} - -extend TestBasicMessage { - optional EnumOptions extension_enum = 101; - optional string extension_text = 102; - repeated int32 extension_number = 103 [packed = true]; - optional TestBasicExtension extension_message = 199; -} - -// Issue for non-qualified type reference in new services generation -option (google.protobuf.csharp_file_options).service_generator_type = IRPCDISPATCH; - -service TestGenericService { - rpc Foo(TestBasicNoFields) returns (TestBasicMessage); - rpc Bar(TestBasicNoFields) returns (TestBasicMessage); -} -*/ - // Old issue 13: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=13 // New issue 309: https://github.com/google/protobuf/issues/309 @@ -90,27 +31,17 @@ service TestGenericService { // optional int32 _01 = 1; // } -// Issue 28: Circular message dependencies result in null defaults for DefaultInstance - -message MyMessageAReferenceB { - required MyMessageBReferenceA value = 1; -} - -message MyMessageBReferenceA { - required MyMessageAReferenceB value = 1; -} - // issue 19 - negative enum values enum NegativeEnum { + NEGATIVE_ENUM_ZERO = 0; FiveBelow = -5; MinusOne = -1; - Zero = 0; } message NegativeEnumMessage { - optional NegativeEnum value = 1; - repeated NegativeEnum values = 2; + NegativeEnum value = 1; + repeated NegativeEnum values = 2 [packed = false]; repeated NegativeEnum packed_values = 3 [packed=true]; } @@ -121,21 +52,22 @@ message DeprecatedChild { } enum DeprecatedEnum { + DEPRECATED_ZERO = 0; one = 1; } message DeprecatedFieldsMessage { - optional int32 PrimitiveValue = 1 [deprecated = true]; + int32 PrimitiveValue = 1 [deprecated = true]; repeated int32 PrimitiveArray = 2 [deprecated = true]; - optional DeprecatedChild MessageValue = 3 [deprecated = true]; + DeprecatedChild MessageValue = 3 [deprecated = true]; repeated DeprecatedChild MessageArray = 4 [deprecated = true]; - optional DeprecatedEnum EnumValue = 5 [deprecated = true]; + DeprecatedEnum EnumValue = 5 [deprecated = true]; repeated DeprecatedEnum EnumArray = 6 [deprecated = true]; } // Issue 45: http://code.google.com/p/protobuf-csharp-port/issues/detail?id=45 message ItemField { - optional int32 item = 1; + int32 item = 1; } diff --git a/csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs b/csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs deleted file mode 100644 index 8118808b..00000000 --- a/csharp/src/ProtocolBuffers.Test/AbstractMessageTest.cs +++ /dev/null @@ -1,548 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using Google.ProtocolBuffers.Descriptors; -using Google.ProtocolBuffers.TestProtos; -using NUnit.Framework; - -namespace Google.ProtocolBuffers -{ - public class AbstractMessageTest - { - [Test] - public void Clear() - { - AbstractMessageWrapper message = - new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(TestUtil.GetAllSet())).Clear().Build(); - TestUtil.AssertClear((TestAllTypes) message.WrappedMessage); - } - - [Test] - public void Copy() - { - AbstractMessageWrapper message = - new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()).MergeFrom(TestUtil.GetAllSet()).Build(); - TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage); - } - - [Test] - public void CreateAndBuild() - { - TestAllTypes.CreateBuilder() - .Build(); - } - - [Test] - public void SerializedSize() - { - TestAllTypes message = TestUtil.GetAllSet(); - IMessage abstractMessage = new AbstractMessageWrapper(TestUtil.GetAllSet()); - - Assert.AreEqual(message.SerializedSize, abstractMessage.SerializedSize); - } - - [Test] - public void Serialization() - { - IMessage abstractMessage = new AbstractMessageWrapper(TestUtil.GetAllSet()); - TestUtil.AssertAllFieldsSet(TestAllTypes.ParseFrom(abstractMessage.ToByteString())); - Assert.AreEqual(TestUtil.GetAllSet().ToByteString(), abstractMessage.ToByteString()); - } - - [Test] - public void Parsing() - { - IBuilder builder = new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder()); - AbstractMessageWrapper message = - (AbstractMessageWrapper) builder.WeakMergeFrom(TestUtil.GetAllSet().ToByteString()).WeakBuild(); - TestUtil.AssertAllFieldsSet((TestAllTypes) message.WrappedMessage); - } - - [Test] - public void PackedSerialization() - { - IMessage abstractMessage = new AbstractMessageWrapper(TestUtil.GetPackedSet()); - TestUtil.AssertPackedFieldsSet(TestPackedTypes.ParseFrom(abstractMessage.ToByteString())); - Assert.AreEqual(TestUtil.GetPackedSet().ToByteString(), abstractMessage.ToByteString()); - } - - [Test] - public void PackedParsing() - { - AbstractMessageWrapper.Builder builder = new AbstractMessageWrapper.Builder(TestPackedTypes.CreateBuilder()); - AbstractMessageWrapper message = builder.MergeFrom(TestUtil.GetPackedSet().ToByteString()).Build(); - TestUtil.AssertPackedFieldsSet((TestPackedTypes)message.WrappedMessage); - } - - [Test] - public void UnpackedParsingOfPackedInput() - { - byte[] bytes = TestUtil.GetPackedSet().ToByteArray(); - TestUnpackedTypes message = TestUnpackedTypes.ParseFrom(bytes); - TestUtil.AssertUnpackedFieldsSet(message); - } - - [Test] - public void PackedParsingOfUnpackedInput() - { - byte[] bytes = TestUnpackedTypes.ParseFrom(TestUtil.GetPackedSet().ToByteArray()).ToByteArray(); - TestPackedTypes message = TestPackedTypes.ParseFrom(bytes); - TestUtil.AssertPackedFieldsSet(message); - } - - [Test] - public void UnpackedParsingOfPackedInputExtensions() - { - byte[] bytes = TestUtil.GetPackedSet().ToByteArray(); - ExtensionRegistry registry = ExtensionRegistry.CreateInstance(); - Unittest.RegisterAllExtensions(registry); - UnittestImport.RegisterAllExtensions(registry); - TestUnpackedExtensions message = TestUnpackedExtensions.ParseFrom(bytes, registry); - TestUtil.AssertUnpackedExtensionsSet(message); - } - - [Test] - public void PackedParsingOfUnpackedInputExtensions() - { - byte[] bytes = TestUnpackedTypes.ParseFrom(TestUtil.GetPackedSet().ToByteArray()).ToByteArray(); - ExtensionRegistry registry = ExtensionRegistry.CreateInstance(); - Unittest.RegisterAllExtensions(registry); - TestPackedExtensions message = TestPackedExtensions.ParseFrom(bytes, registry); - TestUtil.AssertPackedExtensionsSet(message); - } - - [Test] - public void OptimizedForSize() - { - // We're mostly only Checking that this class was compiled successfully. - TestOptimizedForSize message = TestOptimizedForSize.CreateBuilder().SetI(1).Build(); - message = TestOptimizedForSize.ParseFrom(message.ToByteString()); - Assert.AreEqual(2, message.SerializedSize); - } - - // ----------------------------------------------------------------- - // Tests for isInitialized(). - - private static readonly TestRequired TestRequiredUninitialized = TestRequired.DefaultInstance; - - private static readonly TestRequired TestRequiredInitialized = - TestRequired.CreateBuilder().SetA(1).SetB(2).SetC(3).Build(); - - [Test] - public void IsInitialized() - { - TestRequired.Builder builder = TestRequired.CreateBuilder(); - AbstractMessageWrapper.Builder abstractBuilder = new AbstractMessageWrapper.Builder(builder); - - Assert.IsFalse(abstractBuilder.IsInitialized); - builder.A = 1; - Assert.IsFalse(abstractBuilder.IsInitialized); - builder.B = 1; - Assert.IsFalse(abstractBuilder.IsInitialized); - builder.C = 1; - Assert.IsTrue(abstractBuilder.IsInitialized); - } - - [Test] - public void ForeignIsInitialized() - { - TestRequiredForeign.Builder builder = TestRequiredForeign.CreateBuilder(); - AbstractMessageWrapper.Builder abstractBuilder = new AbstractMessageWrapper.Builder(builder); - - Assert.IsTrue(abstractBuilder.IsInitialized); - - builder.SetOptionalMessage(TestRequiredUninitialized); - Assert.IsFalse(abstractBuilder.IsInitialized); - - builder.SetOptionalMessage(TestRequiredInitialized); - Assert.IsTrue(abstractBuilder.IsInitialized); - - builder.AddRepeatedMessage(TestRequiredUninitialized); - Assert.IsFalse(abstractBuilder.IsInitialized); - - builder.SetRepeatedMessage(0, TestRequiredInitialized); - Assert.IsTrue(abstractBuilder.IsInitialized); - } - - // ----------------------------------------------------------------- - // Tests for mergeFrom - - private static readonly TestAllTypes MergeSource = TestAllTypes.CreateBuilder() - .SetOptionalInt32(1) - .SetOptionalString("foo") - .SetOptionalForeignMessage(ForeignMessage.DefaultInstance) - .AddRepeatedString("bar") - .Build(); - - private static readonly TestAllTypes MergeDest = TestAllTypes.CreateBuilder() - .SetOptionalInt64(2) - .SetOptionalString("baz") - .SetOptionalForeignMessage(ForeignMessage.CreateBuilder().SetC(3).Build()) - .AddRepeatedString("qux") - .Build(); - - private const string MergeResultText = "optional_int32: 1\n" + - "optional_int64: 2\n" + - "optional_string: \"foo\"\n" + - "optional_foreign_message {\n" + - " c: 3\n" + - "}\n" + - "repeated_string: \"qux\"\n" + - "repeated_string: \"bar\"\n"; - - [Test] - public void MergeFrom() - { - AbstractMessageWrapper result = (AbstractMessageWrapper) - new AbstractMessageWrapper.Builder(TestAllTypes.CreateBuilder(MergeDest)) - .MergeFrom(MergeSource) - .Build(); - - Assert.AreEqual(MergeResultText, result.ToString()); - } - - // ----------------------------------------------------------------- - // Tests for equals and hashCode - - [Test] - public void EqualsAndHashCode() - { - TestAllTypes a = TestUtil.GetAllSet(); - TestAllTypes b = TestAllTypes.CreateBuilder().Build(); - TestAllTypes c = TestAllTypes.CreateBuilder(b).AddRepeatedString("x").Build(); - TestAllTypes d = TestAllTypes.CreateBuilder(c).AddRepeatedString("y").Build(); - TestAllExtensions e = TestUtil.GetAllExtensionsSet(); - TestAllExtensions f = TestAllExtensions.CreateBuilder(e) - .AddExtension(Unittest.RepeatedInt32Extension, 999).Build(); - - CheckEqualsIsConsistent(a); - CheckEqualsIsConsistent(b); - CheckEqualsIsConsistent(c); - CheckEqualsIsConsistent(d); - CheckEqualsIsConsistent(e); - CheckEqualsIsConsistent(f); - - CheckNotEqual(a, b); - CheckNotEqual(a, c); - CheckNotEqual(a, d); - CheckNotEqual(a, e); - CheckNotEqual(a, f); - - CheckNotEqual(b, c); - CheckNotEqual(b, d); - CheckNotEqual(b, e); - CheckNotEqual(b, f); - - CheckNotEqual(c, d); - CheckNotEqual(c, e); - CheckNotEqual(c, f); - - CheckNotEqual(d, e); - CheckNotEqual(d, f); - - CheckNotEqual(e, f); - - // Deserializing into the TestEmptyMessage such that every field is an UnknownFieldSet.Field - TestEmptyMessage eUnknownFields = TestEmptyMessage.ParseFrom(e.ToByteArray()); - TestEmptyMessage fUnknownFields = TestEmptyMessage.ParseFrom(f.ToByteArray()); - CheckNotEqual(eUnknownFields, fUnknownFields); - CheckEqualsIsConsistent(eUnknownFields); - CheckEqualsIsConsistent(fUnknownFields); - - // Subseqent reconstitutions should be identical - TestEmptyMessage eUnknownFields2 = TestEmptyMessage.ParseFrom(e.ToByteArray()); - CheckEqualsIsConsistent(eUnknownFields, eUnknownFields2); - } - - /// - /// Asserts that the given protos are equal and have the same hash code. - /// - private static void CheckEqualsIsConsistent(IMessage message) - { - // Object should be equal to itself. - Assert.AreEqual(message, message); - - // Object should be equal to a dynamic copy of itself. - DynamicMessage dynamic = DynamicMessage.CreateBuilder(message).Build(); - CheckEqualsIsConsistent(message, dynamic); - } - - /// - /// Asserts that the given protos are equal and have the same hash code. - /// - private static void CheckEqualsIsConsistent(IMessage message1, IMessage message2) - { - // Not using Assert.AreEqual as that checks for type equality, which isn't - // what we want bearing in mind the dynamic message checks. - Assert.IsTrue(message1.Equals(message2)); - Assert.IsTrue(message2.Equals(message1)); - Assert.AreEqual(message2.GetHashCode(), message1.GetHashCode()); - } - - /// - /// Asserts that the given protos are not equal and have different hash codes. - /// - /// - /// It's valid for non-equal objects to have the same hash code, so - /// this test is stricter than it needs to be. However, this should happen - /// relatively rarely. (If this test fails, it's probably still due to a bug.) - /// - private static void CheckNotEqual(IMessage m1, IMessage m2) - { - String equalsError = string.Format("{0} should not be equal to {1}", m1, m2); - Assert.IsFalse(m1.Equals(m2), equalsError); - Assert.IsFalse(m2.Equals(m1), equalsError); - - Assert.IsFalse(m1.GetHashCode() == m2.GetHashCode(), - string.Format("{0} should have a different hash code from {1}", m1, m2)); - } - - /// - /// Extends AbstractMessage and wraps some other message object. The methods - /// of the Message interface which aren't explicitly implemented by - /// AbstractMessage are forwarded to the wrapped object. This allows us to - /// test that AbstractMessage's implementations work even if the wrapped - /// object does not use them. - /// - private class AbstractMessageWrapper : AbstractMessage - { - private readonly IMessage wrappedMessage; - - public IMessage WrappedMessage - { - get { return wrappedMessage; } - } - - public AbstractMessageWrapper(IMessage wrappedMessage) - { - this.wrappedMessage = wrappedMessage; - } - - public override MessageDescriptor DescriptorForType - { - get { return wrappedMessage.DescriptorForType; } - } - - public override AbstractMessageWrapper DefaultInstanceForType - { - get { return new AbstractMessageWrapper(wrappedMessage.WeakDefaultInstanceForType); } - } - - public override IDictionary AllFields - { - get { return wrappedMessage.AllFields; } - } - - public override bool HasField(FieldDescriptor field) - { - return wrappedMessage.HasField(field); - } - - public override bool HasOneof(OneofDescriptor oneof) - { - return wrappedMessage.HasOneof(oneof); - } - - public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof) - { - return wrappedMessage.OneofFieldDescriptor(oneof); - } - - public override object this[FieldDescriptor field] - { - get { return wrappedMessage[field]; } - } - - public override object this[FieldDescriptor field, int index] - { - get { return wrappedMessage[field, index]; } - } - - public override int GetRepeatedFieldCount(FieldDescriptor field) - { - return wrappedMessage.GetRepeatedFieldCount(field); - } - - public override UnknownFieldSet UnknownFields - { - get { return wrappedMessage.UnknownFields; } - } - - public override Builder CreateBuilderForType() - { - return new Builder(wrappedMessage.WeakCreateBuilderForType()); - } - - public override Builder ToBuilder() - { - return new Builder(wrappedMessage.WeakToBuilder()); - } - - internal class Builder : AbstractBuilder - { - private readonly IBuilder wrappedBuilder; - - protected override Builder ThisBuilder - { - get { return this; } - } - - internal Builder(IBuilder wrappedBuilder) - { - this.wrappedBuilder = wrappedBuilder; - } - - public override Builder MergeFrom(AbstractMessageWrapper other) - { - wrappedBuilder.WeakMergeFrom(other.wrappedMessage); - return this; - } - - public override bool IsInitialized - { - get { return wrappedBuilder.IsInitialized; } - } - - public override IDictionary AllFields - { - get { return wrappedBuilder.AllFields; } - } - - public override object this[FieldDescriptor field] - { - get { return wrappedBuilder[field]; } - set { wrappedBuilder[field] = value; } - } - - public override MessageDescriptor DescriptorForType - { - get { return wrappedBuilder.DescriptorForType; } - } - - public override int GetRepeatedFieldCount(FieldDescriptor field) - { - return wrappedBuilder.GetRepeatedFieldCount(field); - } - - public override object this[FieldDescriptor field, int index] - { - get { return wrappedBuilder[field, index]; } - set { wrappedBuilder[field, index] = value; } - } - - public override bool HasField(FieldDescriptor field) - { - return wrappedBuilder.HasField(field); - } - - public override bool HasOneof(OneofDescriptor oneof) - { - return wrappedBuilder.HasOneof(oneof); - } - - public override FieldDescriptor OneofFieldDescriptor(OneofDescriptor oneof) - { - return wrappedBuilder.OneofFieldDescriptor(oneof); - } - - public override UnknownFieldSet UnknownFields - { - get { return wrappedBuilder.UnknownFields; } - set { wrappedBuilder.UnknownFields = value; } - } - - public override AbstractMessageWrapper Build() - { - return new AbstractMessageWrapper(wrappedBuilder.WeakBuild()); - } - - public override AbstractMessageWrapper BuildPartial() - { - return new AbstractMessageWrapper(wrappedBuilder.WeakBuildPartial()); - } - - public override Builder Clone() - { - return new Builder(wrappedBuilder.WeakClone()); - } - - public override AbstractMessageWrapper DefaultInstanceForType - { - get { return new AbstractMessageWrapper(wrappedBuilder.WeakDefaultInstanceForType); } - } - - public override Builder ClearField(FieldDescriptor field) - { - wrappedBuilder.WeakClearField(field); - return this; - } - - public override Builder ClearOneof(OneofDescriptor oneof) - { - wrappedBuilder.WeakClearOneof(oneof); - return this; - } - - public override Builder AddRepeatedField(FieldDescriptor field, object value) - { - wrappedBuilder.WeakAddRepeatedField(field, value); - return this; - } - - public override IBuilder CreateBuilderForField(FieldDescriptor field) - { - wrappedBuilder.CreateBuilderForField(field); - return this; - } - - public override Builder MergeFrom(IMessage other) - { - wrappedBuilder.WeakMergeFrom(other); - return this; - } - - public override Builder MergeFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry) - { - wrappedBuilder.WeakMergeFrom(input, extensionRegistry); - return this; - } - } - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/ByteStringTest.cs b/csharp/src/ProtocolBuffers.Test/ByteStringTest.cs index e4f7bd9e..0edd149b 100644 --- a/csharp/src/ProtocolBuffers.Test/ByteStringTest.cs +++ b/csharp/src/ProtocolBuffers.Test/ByteStringTest.cs @@ -38,7 +38,7 @@ using System; using System.Text; using NUnit.Framework; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { public class ByteStringTest { diff --git a/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs b/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs index 9bb8ba27..57650049 100644 --- a/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs +++ b/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs @@ -37,11 +37,12 @@ using System; using System.Collections.Generic; using System.IO; -using Google.ProtocolBuffers.Descriptors; -using Google.ProtocolBuffers.TestProtos; +using Google.Protobuf.Collections; +using Google.Protobuf.Descriptors; +using Google.Protobuf.TestProtos; using NUnit.Framework; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { public class CodedInputStreamTest { @@ -231,7 +232,7 @@ namespace Google.ProtocolBuffers Assert.AreEqual(0x7FFFFFFFFFFFFFFFL, CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFEL)); Assert.AreEqual(unchecked((long) 0x8000000000000000L), CodedInputStream.DecodeZigZag64(0xFFFFFFFFFFFFFFFFL)); } - + /* [Test] public void ReadWholeMessage() { @@ -273,7 +274,7 @@ namespace Google.ProtocolBuffers unknownFields.MergeFieldFrom(tag, input1); input2.SkipField(); } - } + }*/ /// /// Test that a bug in SkipRawBytes has been fixed: if the skip @@ -290,7 +291,7 @@ namespace Google.ProtocolBuffers input.PopLimit(limit); Assert.AreEqual(2, input.ReadRawByte()); } - + /* public void ReadHugeBlob() { // Allocate and initialize a 1MB blob. @@ -318,7 +319,7 @@ namespace Google.ProtocolBuffers .SetOptionalBytes(TestUtil.GetAllSet().OptionalBytes) .Build(); TestUtil.AssertAllFieldsSet(message3); - } + }*/ [Test] public void ReadMaliciouslyLargeBlob() @@ -348,12 +349,11 @@ namespace Google.ProtocolBuffers { if (depth == 0) { - return TestRecursiveMessage.CreateBuilder().SetI(5).Build(); + return new TestRecursiveMessage { I = 5 }; } else { - return TestRecursiveMessage.CreateBuilder() - .SetA(MakeRecursiveMessage(depth - 1)).Build(); + return new TestRecursiveMessage { A = MakeRecursiveMessage(depth - 1) }; } } @@ -361,12 +361,12 @@ namespace Google.ProtocolBuffers { if (depth == 0) { - Assert.IsFalse(message.HasA); + Assert.IsNull(message.A); Assert.AreEqual(5, message.I); } else { - Assert.IsTrue(message.HasA); + Assert.IsNotNull(message.A); AssertMessageDepth(message.A, depth - 1); } } @@ -377,15 +377,16 @@ namespace Google.ProtocolBuffers ByteString data64 = MakeRecursiveMessage(64).ToByteString(); ByteString data65 = MakeRecursiveMessage(65).ToByteString(); - AssertMessageDepth(TestRecursiveMessage.ParseFrom(data64), 64); + AssertMessageDepth(TestRecursiveMessage.Parser.ParseFrom(data64), 64); - Assert.Throws(() => TestRecursiveMessage.ParseFrom(data65)); + Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(data65)); CodedInputStream input = data64.CreateCodedInput(); input.SetRecursionLimit(8); - Assert.Throws(() => TestRecursiveMessage.ParseFrom(input)); + Assert.Throws(() => TestRecursiveMessage.Parser.ParseFrom(input)); } + /* [Test] public void SizeLimit() { @@ -396,7 +397,7 @@ namespace Google.ProtocolBuffers input.SetSizeLimit(16); Assert.Throws(() => TestAllTypes.ParseFrom(input)); - } + }*/ [Test] public void ResetSizeCounter() @@ -465,17 +466,16 @@ namespace Google.ProtocolBuffers } } - enum TestNegEnum { None = 0, Value = -2 } + enum TestNegEnum : long { None = 0, Value = -2 } [Test] public void TestNegativeEnum() { byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 }; CodedInputStream input = CodedInputStream.CreateInstance(bytes); - object unk; TestNegEnum val = TestNegEnum.None; - Assert.IsTrue(input.ReadEnum(ref val, out unk)); + Assert.IsTrue(input.ReadEnum(ref val)); Assert.IsTrue(input.IsAtEnd); Assert.AreEqual(TestNegEnum.Value, val); } @@ -487,7 +487,7 @@ namespace Google.ProtocolBuffers int msgSize = 1 + 1 + arraySize; byte[] bytes = new byte[msgSize]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WritePackedInt32Array(8, "", arraySize, new int[] { 0, -1, -2, -3, -4, -5 }); + output.WritePackedInt32Array(8, "", new RepeatedField { 0, -1, -2, -3, -4, -5 }); Assert.AreEqual(0, output.SpaceLeft); @@ -497,15 +497,12 @@ namespace Google.ProtocolBuffers Assert.IsTrue(input.ReadTag(out tag, out name)); List values = new List(); - ICollection unk; - input.ReadEnumArray(tag, name, values, out unk); + input.ReadEnumArray(tag, name, values); - Assert.AreEqual(2, values.Count); + Assert.AreEqual(6, values.Count); Assert.AreEqual(TestNegEnum.None, values[0]); - Assert.AreEqual(TestNegEnum.Value, values[1]); - - Assert.NotNull(unk); - Assert.AreEqual(4, unk.Count); + Assert.AreEqual(TestNegEnum.Value, values[2]); + // TODO(jonskeet): Test unknown value preservation } [Test] @@ -515,7 +512,7 @@ namespace Google.ProtocolBuffers int msgSize = arraySize; byte[] bytes = new byte[msgSize]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteInt32Array(8, "", new int[] { 0, -1, -2, -3, -4, -5 }); + output.WriteInt32Array(8, "", new RepeatedField { 0, -1, -2, -3, -4, -5 }); Assert.AreEqual(0, output.SpaceLeft); @@ -525,15 +522,12 @@ namespace Google.ProtocolBuffers Assert.IsTrue(input.ReadTag(out tag, out name)); List values = new List(); - ICollection unk; - input.ReadEnumArray(tag, name, values, out unk); + input.ReadEnumArray(tag, name, values); - Assert.AreEqual(2, values.Count); + Assert.AreEqual(6, values.Count); Assert.AreEqual(TestNegEnum.None, values[0]); - Assert.AreEqual(TestNegEnum.Value, values[1]); - - Assert.NotNull(unk); - Assert.AreEqual(4, unk.Count); + Assert.AreEqual(TestNegEnum.Value, values[2]); + // TODO(jonskeet): Test unknown value preservation } //Issue 71: CodedInputStream.ReadBytes go to slow path unnecessarily diff --git a/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs b/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs index 4d5b8302..df80b3af 100644 --- a/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs +++ b/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs @@ -37,10 +37,10 @@ using System; using System.Collections.Generic; using System.IO; -using Google.ProtocolBuffers.TestProtos; +using Google.Protobuf.Collections; using NUnit.Framework; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { public class CodedOutputStreamTest { @@ -195,6 +195,7 @@ namespace Google.ProtocolBuffers 0x9abcdef012345678UL); } + /* [Test] public void WriteWholeMessage() { @@ -228,6 +229,7 @@ namespace Google.ProtocolBuffers TestUtil.AssertEqualBytes(TestUtil.GetGoldenPackedFieldsMessage().ToByteArray(), rawBytes); } + */ [Test] public void EncodeZigZag32() @@ -294,25 +296,27 @@ namespace Google.ProtocolBuffers public void TestNegativeEnumNoTag() { Assert.AreEqual(10, CodedOutputStream.ComputeInt32SizeNoTag(-2)); - Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag(-2)); + Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag(TestNegEnum.Value)); byte[] bytes = new byte[10]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnumNoTag(-2); + output.WriteEnumNoTag(TestNegEnum.Value); Assert.AreEqual(0, output.SpaceLeft); Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes)); } + enum TestNegEnum : long { None = 0, Value = -2 } + [Test] public void TestNegativeEnumWithTag() { Assert.AreEqual(11, CodedOutputStream.ComputeInt32Size(8, -2)); - Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, -2)); + Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, TestNegEnum.Value)); byte[] bytes = new byte[11]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnum(8, "", -2, -2); + output.WriteEnum(8, "", TestNegEnum.Value); Assert.AreEqual(0, output.SpaceLeft); //fyi, 0x40 == 0x08 << 3 + 0, field num + wire format shift @@ -326,7 +330,8 @@ namespace Google.ProtocolBuffers int msgSize = 1 + 1 + arraySize; byte[] bytes = new byte[msgSize]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WritePackedEnumArray(8, "", arraySize, new int[] { 0, -1, -2, -3, -4, -5 }); + output.WritePackedEnumArray(8, "", new RepeatedField { + 0, (TestNegEnum) (-1), TestNegEnum.Value, (TestNegEnum) (-3), (TestNegEnum) (-4), (TestNegEnum) (-5) }); Assert.AreEqual(0, output.SpaceLeft); @@ -350,8 +355,8 @@ namespace Google.ProtocolBuffers int msgSize = arraySize; byte[] bytes = new byte[msgSize]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnumArray(8, "", new int[] { 0, -1, -2, -3, -4, -5 }); - + output.WriteEnumArray(8, "", new RepeatedField { + 0, (TestNegEnum) (-1), TestNegEnum.Value, (TestNegEnum) (-3), (TestNegEnum) (-4), (TestNegEnum) (-5) }); Assert.AreEqual(0, output.SpaceLeft); CodedInputStream input = CodedInputStream.CreateInstance(bytes); diff --git a/csharp/src/ProtocolBuffers.Test/Collections/PopsicleListTest.cs b/csharp/src/ProtocolBuffers.Test/Collections/PopsicleListTest.cs deleted file mode 100644 index f336a84b..00000000 --- a/csharp/src/ProtocolBuffers.Test/Collections/PopsicleListTest.cs +++ /dev/null @@ -1,125 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections.Generic; -using NUnit.Framework; - -namespace Google.ProtocolBuffers.Collections -{ - public class PopsicleListTest - { - [Test] - public void MutatingOperationsOnFrozenList() - { - PopsicleList list = new PopsicleList(); - list.MakeReadOnly(); - Assert.Throws(() => list.Add("")); - Assert.Throws(() => list.Clear()); - Assert.Throws(() => list.Insert(0, "")); - Assert.Throws(() => list.Remove("")); - Assert.Throws(() => list.RemoveAt(0)); - Assert.Throws(() => list.Add(new[] { "", "" })); - } - - [Test] - public void NonMutatingOperationsOnFrozenList() - { - PopsicleList list = new PopsicleList(); - list.MakeReadOnly(); - Assert.IsFalse(list.Contains("")); - Assert.AreEqual(0, list.Count); - list.CopyTo(new string[5], 0); - list.GetEnumerator(); - Assert.AreEqual(-1, list.IndexOf("")); - Assert.IsTrue(list.IsReadOnly); - } - - [Test] - public void MutatingOperationsOnFluidList() - { - PopsicleList list = new PopsicleList(); - list.Add(""); - list.Clear(); - list.Insert(0, ""); - list.Remove(""); - list.Add("x"); // Just to make the next call valid - list.RemoveAt(0); - } - - [Test] - public void NonMutatingOperationsOnFluidList() - { - PopsicleList list = new PopsicleList(); - Assert.IsFalse(list.Contains("")); - Assert.AreEqual(0, list.Count); - list.CopyTo(new string[5], 0); - list.GetEnumerator(); - Assert.AreEqual(-1, list.IndexOf("")); - Assert.IsFalse(list.IsReadOnly); - } - - [Test] - public void DoesNotAddNullEnumerable() - { - PopsicleList list = new PopsicleList(); - Assert.Throws(() => list.Add((IEnumerable) null)); - } - - [Test] - public void DoesNotAddRangeWithNull() - { - PopsicleList list = new PopsicleList(); - // TODO(jonskeet): Change to ArgumentException? The argument isn't null... - Assert.Throws(() => list.Add(new[] {"a", "b", null})); - } - - [Test] - public void DoesNotAddNull() - { - PopsicleList list = new PopsicleList(); - Assert.Throws(() => list.Add((string) null)); - } - - [Test] - public void DoesNotSetNull() - { - PopsicleList list = new PopsicleList(); - list.Add("a"); - Assert.Throws(() => list[0] = null); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/BinaryCompatibilityTests.cs b/csharp/src/ProtocolBuffers.Test/Compatibility/BinaryCompatibilityTests.cs deleted file mode 100644 index 30d257ad..00000000 --- a/csharp/src/ProtocolBuffers.Test/Compatibility/BinaryCompatibilityTests.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System; - -namespace Google.ProtocolBuffers.Compatibility -{ - public class BinaryCompatibilityTests : CompatibilityTests - { - protected override object SerializeMessage(TMessage message) - { - byte[] bresult = message.ToByteArray(); - return Convert.ToBase64String(bresult); - } - - protected override TBuilder DeserializeMessage(object message, TBuilder builder, ExtensionRegistry registry) - { - return builder.MergeFrom((byte[])Convert.FromBase64String((string)message), registry); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/CompatibilityTests.cs b/csharp/src/ProtocolBuffers.Test/Compatibility/CompatibilityTests.cs deleted file mode 100644 index a050827e..00000000 --- a/csharp/src/ProtocolBuffers.Test/Compatibility/CompatibilityTests.cs +++ /dev/null @@ -1,227 +0,0 @@ -using System; -using Google.ProtocolBuffers.TestProtos; -using NUnit.Framework; - - -namespace Google.ProtocolBuffers.Compatibility -{ - /// - /// This abstract base implements several tests to ensure that well-known messages can be written - /// and read to/from various formats without losing data. Implementations override the two serialization - /// methods to provide the tests with the means to read and write for a given format. - /// - public abstract class CompatibilityTests - { - protected abstract object SerializeMessage(TMessage message) - where TMessage : IMessageLite - where TBuilder : IBuilderLite; - - protected abstract TBuilder DeserializeMessage(object message, TBuilder builder, ExtensionRegistry registry) - where TMessage : IMessageLite - where TBuilder : IBuilderLite; - - protected virtual void AssertOutputEquals(object lhs, object rhs) - { - Assert.AreEqual(lhs, rhs); - } - - [Test] - public virtual void RoundTripWithEmptyChildMessageSize() - { - SizeMessage1 msg = SizeMessage1.CreateBuilder() - .SetField100(100) - .SetField15(SizeMessage1SubMessage.DefaultInstance) - .BuildPartial(); - byte[] contents = msg.ToByteArray(); - object content = SerializeMessage(msg); - - SizeMessage1 copy = DeserializeMessage(content, SizeMessage1.CreateBuilder(), ExtensionRegistry.Empty).BuildPartial(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(contents), Convert.ToBase64String(copy.ToByteArray())); - } - - [Test] - public virtual void RoundTripWithEmptyChildMessageSpeed() - { - SpeedMessage1 msg = SpeedMessage1.CreateBuilder() - .SetField100(100) - .SetField15(SpeedMessage1SubMessage.DefaultInstance) - .BuildPartial(); - byte[] contents = msg.ToByteArray(); - object content = SerializeMessage(msg); - - SpeedMessage1 copy = DeserializeMessage(content, SpeedMessage1.CreateBuilder(), ExtensionRegistry.Empty).BuildPartial(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(contents), Convert.ToBase64String(copy.ToByteArray())); - } - - [Test] - public virtual void RoundTripMessage1OptimizeSize() - { - SizeMessage1 msg = SizeMessage1.CreateBuilder().MergeFrom(TestResources.google_message1).Build(); - object content = SerializeMessage(msg); - - SizeMessage1 copy = DeserializeMessage(content, SizeMessage1.CreateBuilder(), ExtensionRegistry.Empty).Build(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(TestResources.google_message1), Convert.ToBase64String(copy.ToByteArray())); - } - - [Test] - public virtual void RoundTripMessage2OptimizeSize() - { - SizeMessage2 msg = SizeMessage2.CreateBuilder().MergeFrom(TestResources.google_message2).Build(); - object content = SerializeMessage(msg); - - SizeMessage2 copy = DeserializeMessage(content, SizeMessage2.CreateBuilder(), ExtensionRegistry.Empty).Build(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(TestResources.google_message2), Convert.ToBase64String(copy.ToByteArray())); - } - - [Test] - public virtual void RoundTripMessage1OptimizeSpeed() - { - SpeedMessage1 msg = SpeedMessage1.CreateBuilder().MergeFrom(TestResources.google_message1).Build(); - object content = SerializeMessage(msg); - - SpeedMessage1 copy = DeserializeMessage(content, SpeedMessage1.CreateBuilder(), ExtensionRegistry.Empty).Build(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(TestResources.google_message1), Convert.ToBase64String(copy.ToByteArray())); - } - - [Test] - public virtual void RoundTripMessage2OptimizeSpeed() - { - SpeedMessage2 msg = SpeedMessage2.CreateBuilder().MergeFrom(TestResources.google_message2).Build(); - object content = SerializeMessage(msg); - - SpeedMessage2 copy = DeserializeMessage(content, SpeedMessage2.CreateBuilder(), ExtensionRegistry.Empty).Build(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(TestResources.google_message2), Convert.ToBase64String(copy.ToByteArray())); - } - - #region Test message builders - - protected static TestAllTypes.Builder AddAllTypes(TestAllTypes.Builder builder) - { - return builder.SetOptionalInt32(1001) - .SetOptionalInt64(1001) - .SetOptionalUint32(1001) - .SetOptionalUint64(1001) - .SetOptionalSint32(-1001) - .SetOptionalSint64(-1001) - .SetOptionalFixed32(1001) - .SetOptionalFixed64(1001) - .SetOptionalSfixed32(-1001) - .SetOptionalSfixed64(-1001) - .SetOptionalFloat(1001.1001f) - .SetOptionalDouble(1001.1001) - .SetOptionalBool(true) - .SetOptionalString("this is a string value") - .SetOptionalBytes(ByteString.CopyFromUtf8("this is an array of bytes")) - .SetOptionalGroup(new TestAllTypes.Types.OptionalGroup.Builder().SetA(1001)) - .SetOptionalNestedMessage(new TestAllTypes.Types.NestedMessage.Builder().SetBb(1001)) - .SetOptionalNestedEnum(TestAllTypes.Types.NestedEnum.FOO) - ; - } - - protected static TestAllTypes.Builder AddRepeatedTypes(TestAllTypes.Builder builder, int size) - { - //repeated values - for (int i = 0; i < size; i++) - builder.AddRepeatedInt32(1001 + i) - .AddRepeatedInt64(1001) - .AddRepeatedUint32(1001) - .AddRepeatedUint64(1001) - .AddRepeatedSint32(-1001) - .AddRepeatedSint64(-1001) - .AddRepeatedFixed32(1001) - .AddRepeatedFixed64(1001) - .AddRepeatedSfixed32(-1001) - .AddRepeatedSfixed64(-1001) - .AddRepeatedFloat(1001.1001f) - .AddRepeatedDouble(1001.1001) - .AddRepeatedBool(true) - .AddRepeatedString("this is a string value") - .AddRepeatedBytes(ByteString.CopyFromUtf8("this is an array of bytes")) - .AddRepeatedGroup(new TestAllTypes.Types.RepeatedGroup.Builder().SetA(1001)) - .AddRepeatedNestedMessage(new TestAllTypes.Types.NestedMessage.Builder().SetBb(1001)) - .AddRepeatedNestedEnum(TestAllTypes.Types.NestedEnum.FOO) - ; - return builder; - } - - protected static TestPackedTypes.Builder AddPackedTypes(TestPackedTypes.Builder builder, int size) - { - for(int i=0; i < size; i++ ) - builder.AddPackedInt32(1001) - .AddPackedInt64(1001) - .AddPackedUint32(1001) - .AddPackedUint64(1001) - .AddPackedSint32(-1001) - .AddPackedSint64(-1001) - .AddPackedFixed32(1001) - .AddPackedFixed64(1001) - .AddPackedSfixed32(-1001) - .AddPackedSfixed64(-1001) - .AddPackedFloat(1001.1001f) - .AddPackedDouble(1001.1001) - .AddPackedBool(true) - .AddPackedEnum(ForeignEnum.FOREIGN_FOO) - ; - return builder; - } - - #endregion - - [Test] - public void TestRoundTripAllTypes() - { - TestAllTypes msg = AddAllTypes(new TestAllTypes.Builder()).Build(); - object content = SerializeMessage(msg); - - TestAllTypes copy = DeserializeMessage(content, TestAllTypes.CreateBuilder(), ExtensionRegistry.Empty).Build(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(msg.ToByteArray()), Convert.ToBase64String(copy.ToByteArray())); - } - - [Test] - public void TestRoundTripRepeatedTypes() - { - TestAllTypes msg = AddRepeatedTypes(new TestAllTypes.Builder(), 5).Build(); - object content = SerializeMessage(msg); - - TestAllTypes copy = DeserializeMessage(content, TestAllTypes.CreateBuilder(), ExtensionRegistry.Empty).Build(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(msg.ToByteArray()), Convert.ToBase64String(copy.ToByteArray())); - } - - [Test] - public void TestRoundTripPackedTypes() - { - TestPackedTypes msg = AddPackedTypes(new TestPackedTypes.Builder(), 5).Build(); - object content = SerializeMessage(msg); - - TestPackedTypes copy = DeserializeMessage(content, TestPackedTypes.CreateBuilder(), ExtensionRegistry.Empty).Build(); - - Assert.AreEqual(msg, copy); - AssertOutputEquals(content, SerializeMessage(copy)); - Assert.AreEqual(Convert.ToBase64String(msg.ToByteArray()), Convert.ToBase64String(copy.ToByteArray())); - } - } -} diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/DictionaryCompatibilityTests.cs b/csharp/src/ProtocolBuffers.Test/Compatibility/DictionaryCompatibilityTests.cs deleted file mode 100644 index 299bb1a6..00000000 --- a/csharp/src/ProtocolBuffers.Test/Compatibility/DictionaryCompatibilityTests.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; -using System.Collections.Generic; -using Google.ProtocolBuffers.Serialization; -using NUnit.Framework; - -namespace Google.ProtocolBuffers.Compatibility -{ - [TestFixture] - public class DictionaryCompatibilityTests : CompatibilityTests - { - protected override object SerializeMessage(TMessage message) - { - DictionaryWriter writer = new DictionaryWriter(); - writer.WriteMessage(message); - return writer.ToDictionary(); - } - - protected override TBuilder DeserializeMessage(object message, TBuilder builder, ExtensionRegistry registry) - { - new DictionaryReader((IDictionary)message).Merge(builder); - return builder; - } - - protected override void AssertOutputEquals(object lhs, object rhs) - { - IDictionary left = (IDictionary)lhs; - IDictionary right = (IDictionary)rhs; - - Assert.AreEqual( - String.Join(",", new List(left.Keys).ToArray()), - String.Join(",", new List(right.Keys).ToArray()) - ); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs b/csharp/src/ProtocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs deleted file mode 100644 index a1e0ed33..00000000 --- a/csharp/src/ProtocolBuffers.Test/Compatibility/JsonCompatibilityTests.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System.IO; -using Google.ProtocolBuffers.Serialization; -using NUnit.Framework; - -namespace Google.ProtocolBuffers.Compatibility -{ - [TestFixture] - public class JsonCompatibilityTests : CompatibilityTests - { - protected override object SerializeMessage(TMessage message) - { - StringWriter sw = new StringWriter(); - JsonFormatWriter.CreateInstance(sw) - .WriteMessage(message); - return sw.ToString(); - } - - protected override TBuilder DeserializeMessage(object message, TBuilder builder, ExtensionRegistry registry) - { - JsonFormatReader.CreateInstance((string)message).Merge(builder); - return builder; - } - } - - [TestFixture] - public class JsonCompatibilityFormattedTests : CompatibilityTests - { - protected override object SerializeMessage(TMessage message) - { - StringWriter sw = new StringWriter(); - JsonFormatWriter.CreateInstance(sw) - .Formatted() - .WriteMessage(message); - return sw.ToString(); - } - - protected override TBuilder DeserializeMessage(object message, TBuilder builder, ExtensionRegistry registry) - { - JsonFormatReader.CreateInstance((string)message).Merge(builder); - return builder; - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/TestResources.cs b/csharp/src/ProtocolBuffers.Test/Compatibility/TestResources.cs deleted file mode 100644 index 2282d61f..00000000 --- a/csharp/src/ProtocolBuffers.Test/Compatibility/TestResources.cs +++ /dev/null @@ -1,38 +0,0 @@ -using System.IO; -using NUnit.Framework; - -namespace Google.ProtocolBuffers.Compatibility -{ - static class TestResources - { - public static byte[] google_message1 - { - get - { - Stream resource = typeof(TestResources).Assembly.GetManifestResourceStream( - typeof(TestResources).Namespace + ".google_message1.dat"); - - Assert.NotNull(resource); - - byte[] bytes = new byte[resource.Length]; - int amtRead = resource.Read(bytes, 0, bytes.Length); - Assert.AreEqual(bytes.Length, amtRead); - return bytes; - } - } - public static byte[] google_message2 - { - get - { - Stream resource = typeof(TestResources).Assembly.GetManifestResourceStream( - typeof(TestResources).Namespace + ".google_message2.dat"); - - Assert.NotNull(resource); - byte[] bytes = new byte[resource.Length]; - int amtRead = resource.Read(bytes, 0, bytes.Length); - Assert.AreEqual(bytes.Length, amtRead); - return bytes; - } - } - } -} diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/TextCompatibilityTests.cs b/csharp/src/ProtocolBuffers.Test/Compatibility/TextCompatibilityTests.cs deleted file mode 100644 index 89d6e260..00000000 --- a/csharp/src/ProtocolBuffers.Test/Compatibility/TextCompatibilityTests.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.IO; -using NUnit.Framework; - -namespace Google.ProtocolBuffers.Compatibility -{ - [TestFixture] - public class TextCompatibilityTests : CompatibilityTests - { - protected override object SerializeMessage(TMessage message) - { - StringWriter text = new StringWriter(); - message.PrintTo(text); - return text.ToString(); - } - - protected override TBuilder DeserializeMessage(object message, TBuilder builder, ExtensionRegistry registry) - { - TextFormat.Merge(new StringReader((string)message), registry, (IBuilder)builder); - return builder; - } - //This test can take a very long time to run. - [Test] - public override void RoundTripMessage2OptimizeSize() - { - //base.RoundTripMessage2OptimizeSize(); - } - - //This test can take a very long time to run. - [Test] - public override void RoundTripMessage2OptimizeSpeed() - { - //base.RoundTripMessage2OptimizeSpeed(); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs b/csharp/src/ProtocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs deleted file mode 100644 index 91d40d83..00000000 --- a/csharp/src/ProtocolBuffers.Test/Compatibility/XmlCompatibilityTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -using System.IO; -using System.Xml; -using Google.ProtocolBuffers.Serialization; -using NUnit.Framework; - -namespace Google.ProtocolBuffers.Compatibility -{ - [TestFixture] - public class XmlCompatibilityTests : CompatibilityTests - { - protected override object SerializeMessage(TMessage message) - { - StringWriter text = new StringWriter(); - XmlFormatWriter writer = XmlFormatWriter.CreateInstance(text); - writer.WriteMessage("root", message); - return text.ToString(); - } - - protected override TBuilder DeserializeMessage(object message, TBuilder builder, ExtensionRegistry registry) - { - XmlFormatReader reader = XmlFormatReader.CreateInstance((string)message); - return reader.Merge("root", builder, registry); - } - } - - [TestFixture] - public class XmlCompatibilityFormattedTests : CompatibilityTests - { - protected override object SerializeMessage(TMessage message) - { - StringWriter text = new StringWriter(); - XmlWriter xwtr = XmlWriter.Create(text, new XmlWriterSettings { Indent = true, IndentChars = " " }); - - XmlFormatWriter writer = XmlFormatWriter.CreateInstance(xwtr).SetOptions(XmlWriterOptions.OutputNestedArrays); - writer.WriteMessage("root", message); - return text.ToString(); - } - - protected override TBuilder DeserializeMessage(object message, TBuilder builder, ExtensionRegistry registry) - { - XmlFormatReader reader = XmlFormatReader.CreateInstance((string)message).SetOptions(XmlReaderOptions.ReadNestedArrays); - return reader.Merge("root", builder, registry); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/google_message1.dat b/csharp/src/ProtocolBuffers.Test/Compatibility/google_message1.dat deleted file mode 100644 index bc0f064c..00000000 Binary files a/csharp/src/ProtocolBuffers.Test/Compatibility/google_message1.dat and /dev/null differ diff --git a/csharp/src/ProtocolBuffers.Test/Compatibility/google_message2.dat b/csharp/src/ProtocolBuffers.Test/Compatibility/google_message2.dat deleted file mode 100644 index 06c09441..00000000 Binary files a/csharp/src/ProtocolBuffers.Test/Compatibility/google_message2.dat and /dev/null differ diff --git a/csharp/src/ProtocolBuffers.Test/DeprecatedMemberTest.cs b/csharp/src/ProtocolBuffers.Test/DeprecatedMemberTest.cs index db64d37a..c962df54 100644 --- a/csharp/src/ProtocolBuffers.Test/DeprecatedMemberTest.cs +++ b/csharp/src/ProtocolBuffers.Test/DeprecatedMemberTest.cs @@ -1,9 +1,9 @@ using System; using System.Reflection; -using UnitTest.Issues.TestProtos; +using Google.Protobuf.TestProtos; using NUnit.Framework; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { public class DeprecatedMemberTest { @@ -16,84 +16,8 @@ namespace Google.ProtocolBuffers [Test] public void TestDepreatedPrimitiveValue() { - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("HasPrimitiveValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("PrimitiveValue")); - - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("HasPrimitiveValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("PrimitiveValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearPrimitiveValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetPrimitiveValue")); - } - [Test] - public void TestDepreatedPrimitiveArray() - { - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("PrimitiveArrayList")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("PrimitiveArrayCount")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetMethod("GetPrimitiveArray")); - - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("PrimitiveArrayList")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("PrimitiveArrayCount")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("GetPrimitiveArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetPrimitiveArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddPrimitiveArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddRangePrimitiveArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearPrimitiveArray")); - } - [Test] - public void TestDepreatedMessageValue() - { - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("HasMessageValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("MessageValue")); - - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("HasMessageValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("MessageValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("MergeMessageValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearMessageValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetMessageValue", new[] { typeof(DeprecatedChild) })); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetMessageValue", new[] { typeof(DeprecatedChild.Builder) })); - } - [Test] - public void TestDepreatedMessageArray() - { - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("MessageArrayList")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("MessageArrayCount")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetMethod("GetMessageArray")); - - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("MessageArrayList")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("MessageArrayCount")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("GetMessageArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetMessageArray", new[] { typeof(int), typeof(DeprecatedChild) })); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetMessageArray", new[] { typeof(int), typeof(DeprecatedChild.Builder) })); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddMessageArray", new[] { typeof(DeprecatedChild) })); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddMessageArray", new[] { typeof(DeprecatedChild.Builder) })); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddRangeMessageArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearMessageArray")); - } - [Test] - public void TestDepreatedEnumValue() - { - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("HasEnumValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("EnumValue")); - - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("HasEnumValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("EnumValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearEnumValue")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetEnumValue")); + AssertIsDeprecated(typeof(TestDeprecatedFields).GetProperty("DeprecatedInt32")); } - [Test] - public void TestDepreatedEnumArray() - { - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("EnumArrayList")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetProperty("EnumArrayCount")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage).GetMethod("GetEnumArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("EnumArrayList")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetProperty("EnumArrayCount")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("GetEnumArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("SetEnumArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddEnumArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("AddRangeEnumArray")); - AssertIsDeprecated(typeof(DeprecatedFieldsMessage.Builder).GetMethod("ClearEnumArray")); - } } } diff --git a/csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs b/csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs index 3c26f441..8c01e16a 100644 --- a/csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs +++ b/csharp/src/ProtocolBuffers.Test/DescriptorsTest.cs @@ -34,11 +34,11 @@ #endregion -using Google.ProtocolBuffers.Descriptors; -using Google.ProtocolBuffers.TestProtos; +using Google.Protobuf.Descriptors; +using Google.Protobuf.TestProtos; using NUnit.Framework; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { /// /// Tests for descriptors. (Not in its own namespace or broken up into individual classes as the @@ -49,21 +49,21 @@ namespace Google.ProtocolBuffers [Test] public void FileDescriptor() { - FileDescriptor file = Unittest.Descriptor; + FileDescriptor file = UnittestProto3.Descriptor; - Assert.AreEqual("google/protobuf/unittest.proto", file.Name); + Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Name); Assert.AreEqual("protobuf_unittest", file.Package); Assert.AreEqual("UnittestProto", file.Options.JavaOuterClassname); - Assert.AreEqual("google/protobuf/unittest.proto", file.Proto.Name); + Assert.AreEqual("google/protobuf/unittest_proto3.proto", file.Proto.Name); // unittest.proto doesn't have any public imports, but unittest_import.proto does. Assert.AreEqual(0, file.PublicDependencies.Count); - Assert.AreEqual(1, UnittestImport.Descriptor.PublicDependencies.Count); - Assert.AreEqual(UnittestImportPublic.Descriptor, UnittestImport.Descriptor.PublicDependencies[0]); + Assert.AreEqual(1, UnittestImportProto3.Descriptor.PublicDependencies.Count); + Assert.AreEqual(UnittestImportPublicProto3.Descriptor, UnittestImportProto3.Descriptor.PublicDependencies[0]); Assert.AreEqual(1, file.Dependencies.Count); - Assert.AreEqual(UnittestImport.Descriptor, file.Dependencies[0]); + Assert.AreEqual(UnittestImportProto3.Descriptor, file.Dependencies[0]); MessageDescriptor messageType = TestAllTypes.Descriptor; Assert.AreEqual(messageType, file.MessageTypes[0]); @@ -78,23 +78,12 @@ namespace Google.ProtocolBuffers Assert.AreEqual(file.EnumTypes[0], file.FindTypeByName("ForeignEnum")); Assert.Null(file.FindTypeByName("NoSuchType")); Assert.Null(file.FindTypeByName("protobuf_unittest.ForeignEnum")); - Assert.AreEqual(1, UnittestImport.Descriptor.EnumTypes.Count); - Assert.AreEqual("ImportEnum", UnittestImport.Descriptor.EnumTypes[0].Name); + Assert.AreEqual(1, UnittestImportProto3.Descriptor.EnumTypes.Count); + Assert.AreEqual("ImportEnum", UnittestImportProto3.Descriptor.EnumTypes[0].Name); for (int i = 0; i < file.EnumTypes.Count; i++) { Assert.AreEqual(i, file.EnumTypes[i].Index); } - - FieldDescriptor extension = Unittest.OptionalInt32Extension.Descriptor; - Assert.AreEqual(extension, file.Extensions[0]); - Assert.AreEqual(extension, file.FindTypeByName("optional_int32_extension")); - Assert.Null(file.FindTypeByName("no_such_ext")); - Assert.Null(file.FindTypeByName("protobuf_unittest.optional_int32_extension")); - Assert.AreEqual(0, UnittestImport.Descriptor.Extensions.Count); - for (int i = 0; i < file.Extensions.Count; i++) - { - Assert.AreEqual(i, file.Extensions[i].Index); - } } [Test] @@ -105,19 +94,20 @@ namespace Google.ProtocolBuffers Assert.AreEqual("TestAllTypes", messageType.Name); Assert.AreEqual("protobuf_unittest.TestAllTypes", messageType.FullName); - Assert.AreEqual(Unittest.Descriptor, messageType.File); - Assert.Null(messageType.ContainingType); - Assert.AreEqual(DescriptorProtos.MessageOptions.DefaultInstance, messageType.Options); - Assert.AreEqual("TestAllTypes", messageType.Proto.Name); + Assert.AreEqual(UnittestProto3.Descriptor, messageType.File); + Assert.IsNull(messageType.ContainingType); + Assert.IsNull(messageType.Options); + + Assert.AreEqual("TestAllTypes", messageType.Name); Assert.AreEqual("NestedMessage", nestedType.Name); Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedMessage", nestedType.FullName); - Assert.AreEqual(Unittest.Descriptor, nestedType.File); + Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File); Assert.AreEqual(messageType, nestedType.ContainingType); FieldDescriptor field = messageType.Fields[0]; - Assert.AreEqual("optional_int32", field.Name); - Assert.AreEqual(field, messageType.FindDescriptor("optional_int32")); + Assert.AreEqual("single_int32", field.Name); + Assert.AreEqual(field, messageType.FindDescriptor("single_int32")); Assert.Null(messageType.FindDescriptor("no_such_field")); Assert.AreEqual(field, messageType.FindFieldByNumber(1)); Assert.Null(messageType.FindFieldByNumber(571283)); @@ -146,115 +136,66 @@ namespace Google.ProtocolBuffers public void FieldDescriptor() { MessageDescriptor messageType = TestAllTypes.Descriptor; - FieldDescriptor primitiveField = messageType.FindDescriptor("optional_int32"); - FieldDescriptor enumField = messageType.FindDescriptor("optional_nested_enum"); - FieldDescriptor messageField = messageType.FindDescriptor("optional_foreign_message"); - FieldDescriptor cordField = messageType.FindDescriptor("optional_cord"); - FieldDescriptor extension = Unittest.OptionalInt32Extension.Descriptor; - FieldDescriptor nestedExtension = TestRequired.Single.Descriptor; + FieldDescriptor primitiveField = messageType.FindDescriptor("single_int32"); + FieldDescriptor enumField = messageType.FindDescriptor("single_nested_enum"); + FieldDescriptor messageField = messageType.FindDescriptor("single_foreign_message"); - Assert.AreEqual("optional_int32", primitiveField.Name); - Assert.AreEqual("protobuf_unittest.TestAllTypes.optional_int32", + Assert.AreEqual("single_int32", primitiveField.Name); + Assert.AreEqual("protobuf_unittest.TestAllTypes.single_int32", primitiveField.FullName); Assert.AreEqual(1, primitiveField.FieldNumber); Assert.AreEqual(messageType, primitiveField.ContainingType); - Assert.AreEqual(Unittest.Descriptor, primitiveField.File); + Assert.AreEqual(UnittestProto3.Descriptor, primitiveField.File); Assert.AreEqual(FieldType.Int32, primitiveField.FieldType); Assert.AreEqual(MappedType.Int32, primitiveField.MappedType); - Assert.AreEqual(DescriptorProtos.FieldOptions.DefaultInstance, primitiveField.Options); - Assert.IsFalse(primitiveField.IsExtension); - Assert.AreEqual("optional_int32", primitiveField.Proto.Name); - - Assert.AreEqual("optional_nested_enum", enumField.Name); + Assert.IsNull(primitiveField.Options); + + Assert.AreEqual("single_nested_enum", enumField.Name); Assert.AreEqual(FieldType.Enum, enumField.FieldType); Assert.AreEqual(MappedType.Enum, enumField.MappedType); // Assert.AreEqual(TestAllTypes.Types.NestedEnum.DescriptorProtoFile, enumField.EnumType); - Assert.AreEqual("optional_foreign_message", messageField.Name); + Assert.AreEqual("single_foreign_message", messageField.Name); Assert.AreEqual(FieldType.Message, messageField.FieldType); Assert.AreEqual(MappedType.Message, messageField.MappedType); Assert.AreEqual(ForeignMessage.Descriptor, messageField.MessageType); - - Assert.AreEqual("optional_cord", cordField.Name); - Assert.AreEqual(FieldType.String, cordField.FieldType); - Assert.AreEqual(MappedType.String, cordField.MappedType); - Assert.AreEqual(DescriptorProtos.FieldOptions.Types.CType.CORD, cordField.Options.Ctype); - - Assert.AreEqual("optional_int32_extension", extension.Name); - Assert.AreEqual("protobuf_unittest.optional_int32_extension", extension.FullName); - Assert.AreEqual(1, extension.FieldNumber); - Assert.AreEqual(TestAllExtensions.Descriptor, extension.ContainingType); - Assert.AreEqual(Unittest.Descriptor, extension.File); - Assert.AreEqual(FieldType.Int32, extension.FieldType); - Assert.AreEqual(MappedType.Int32, extension.MappedType); - Assert.AreEqual(DescriptorProtos.FieldOptions.DefaultInstance, - extension.Options); - Assert.IsTrue(extension.IsExtension); - Assert.AreEqual(null, extension.ExtensionScope); - Assert.AreEqual("optional_int32_extension", extension.Proto.Name); - - Assert.AreEqual("single", nestedExtension.Name); - Assert.AreEqual("protobuf_unittest.TestRequired.single", - nestedExtension.FullName); - Assert.AreEqual(TestRequired.Descriptor, - nestedExtension.ExtensionScope); } [Test] public void FieldDescriptorLabel() { - FieldDescriptor requiredField = - TestRequired.Descriptor.FindDescriptor("a"); - FieldDescriptor optionalField = - TestAllTypes.Descriptor.FindDescriptor("optional_int32"); + FieldDescriptor singleField = + TestAllTypes.Descriptor.FindDescriptor("single_int32"); FieldDescriptor repeatedField = TestAllTypes.Descriptor.FindDescriptor("repeated_int32"); - Assert.IsTrue(requiredField.IsRequired); - Assert.IsFalse(requiredField.IsRepeated); - Assert.IsFalse(optionalField.IsRequired); - Assert.IsFalse(optionalField.IsRepeated); + Assert.IsFalse(singleField.IsRequired); + Assert.IsFalse(singleField.IsRepeated); Assert.IsFalse(repeatedField.IsRequired); Assert.IsTrue(repeatedField.IsRepeated); } - [Test] - public void FieldDescriptorDefault() - { - MessageDescriptor d = TestAllTypes.Descriptor; - Assert.IsFalse(d.FindDescriptor("optional_int32").HasDefaultValue); - Assert.AreEqual(0, d.FindDescriptor("optional_int32").DefaultValue); - Assert.IsTrue(d.FindDescriptor("default_int32").HasDefaultValue); - Assert.AreEqual(41, d.FindDescriptor("default_int32").DefaultValue); - - d = TestExtremeDefaultValues.Descriptor; - Assert.AreEqual(TestExtremeDefaultValues.DefaultInstance.EscapedBytes, - d.FindDescriptor("escaped_bytes").DefaultValue); - Assert.AreEqual(uint.MaxValue, d.FindDescriptor("large_uint32").DefaultValue); - Assert.AreEqual(ulong.MaxValue, d.FindDescriptor("large_uint64").DefaultValue); - } [Test] public void EnumDescriptor() { // Note: this test is a bit different to the Java version because there's no static way of getting to the descriptor - EnumDescriptor enumType = Unittest.Descriptor.FindTypeByName("ForeignEnum"); + EnumDescriptor enumType = UnittestProto3.Descriptor.FindTypeByName("ForeignEnum"); EnumDescriptor nestedType = TestAllTypes.Descriptor.FindDescriptor("NestedEnum"); Assert.AreEqual("ForeignEnum", enumType.Name); Assert.AreEqual("protobuf_unittest.ForeignEnum", enumType.FullName); - Assert.AreEqual(Unittest.Descriptor, enumType.File); + Assert.AreEqual(UnittestProto3.Descriptor, enumType.File); Assert.Null(enumType.ContainingType); - Assert.AreEqual(DescriptorProtos.EnumOptions.DefaultInstance, - enumType.Options); + Assert.Null(enumType.Options); Assert.AreEqual("NestedEnum", nestedType.Name); Assert.AreEqual("protobuf_unittest.TestAllTypes.NestedEnum", nestedType.FullName); - Assert.AreEqual(Unittest.Descriptor, nestedType.File); + Assert.AreEqual(UnittestProto3.Descriptor, nestedType.File); Assert.AreEqual(TestAllTypes.Descriptor, nestedType.ContainingType); EnumValueDescriptor value = enumType.FindValueByName("FOREIGN_FOO"); - Assert.AreEqual(value, enumType.Values[0]); + Assert.AreEqual(value, enumType.Values[1]); Assert.AreEqual("FOREIGN_FOO", value.Name); Assert.AreEqual(4, value.Number); Assert.AreEqual((int) ForeignEnum.FOREIGN_FOO, value.Number); @@ -265,22 +206,5 @@ namespace Google.ProtocolBuffers Assert.AreEqual(i, enumType.Values[i].Index); } } - - - [Test] - public void CustomOptions() - { - MessageDescriptor descriptor = TestMessageWithCustomOptions.Descriptor; - Assert.IsTrue(descriptor.Options.HasExtension(UnittestCustomOptions.MessageOpt1)); - Assert.AreEqual(-56, descriptor.Options.GetExtension(UnittestCustomOptions.MessageOpt1)); - - - FieldDescriptor field = descriptor.FindFieldByName("field1"); - Assert.NotNull(field); - - Assert.IsTrue(field.Options.HasExtension(UnittestCustomOptions.FieldOpt1)); - Assert.AreEqual(8765432109uL, field.Options.GetExtension(UnittestCustomOptions.FieldOpt1)); - - } } } \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs b/csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs deleted file mode 100644 index f60db213..00000000 --- a/csharp/src/ProtocolBuffers.Test/DynamicMessageTest.cs +++ /dev/null @@ -1,276 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections.Generic; -using Google.ProtocolBuffers.Descriptors; -using Google.ProtocolBuffers.TestProtos; -using NUnit.Framework; - -namespace Google.ProtocolBuffers -{ - public class DynamicMessageTest - { - private ReflectionTester reflectionTester; - private ReflectionTester extensionsReflectionTester; - private ReflectionTester packedReflectionTester; - - public DynamicMessageTest() - { - reflectionTester = ReflectionTester.CreateTestAllTypesInstance(); - extensionsReflectionTester = ReflectionTester.CreateTestAllExtensionsInstance(); - packedReflectionTester = ReflectionTester.CreateTestPackedTypesInstance(); - } - - [Test] - public void DynamicMessageAccessors() - { - IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - reflectionTester.SetAllFieldsViaReflection(builder); - IMessage message = builder.WeakBuild(); - reflectionTester.AssertAllFieldsSetViaReflection(message); - } - - [Test] - public void DoubleBuildError() - { - DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - builder.Build(); - Assert.Throws(() => builder.Build()); - } - - [Test] - public void DynamicMessageSettersRejectNull() - { - IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - reflectionTester.AssertReflectionSettersRejectNull(builder); - } - - [Test] - public void DynamicMessageExtensionAccessors() - { - // We don't need to extensively test DynamicMessage's handling of - // extensions because, frankly, it doesn't do anything special with them. - // It treats them just like any other fields. - IBuilder builder = DynamicMessage.CreateBuilder(TestAllExtensions.Descriptor); - extensionsReflectionTester.SetAllFieldsViaReflection(builder); - IMessage message = builder.WeakBuild(); - extensionsReflectionTester.AssertAllFieldsSetViaReflection(message); - } - - [Test] - public void DynamicMessageExtensionSettersRejectNull() - { - IBuilder builder = DynamicMessage.CreateBuilder(TestAllExtensions.Descriptor); - extensionsReflectionTester.AssertReflectionSettersRejectNull(builder); - } - - [Test] - public void DynamicMessageRepeatedSetters() - { - IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - reflectionTester.SetAllFieldsViaReflection(builder); - reflectionTester.ModifyRepeatedFieldsViaReflection(builder); - IMessage message = builder.WeakBuild(); - reflectionTester.AssertRepeatedFieldsModifiedViaReflection(message); - } - - [Test] - public void DynamicMessageRepeatedSettersRejectNull() - { - IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - reflectionTester.AssertReflectionRepeatedSettersRejectNull(builder); - } - - [Test] - public void DynamicMessageDefaults() - { - reflectionTester.AssertClearViaReflection(DynamicMessage.GetDefaultInstance(TestAllTypes.Descriptor)); - reflectionTester.AssertClearViaReflection(DynamicMessage.CreateBuilder(TestAllTypes.Descriptor).Build()); - } - - [Test] - public void DynamicMessageSerializedSize() - { - TestAllTypes message = TestUtil.GetAllSet(); - - IBuilder dynamicBuilder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - reflectionTester.SetAllFieldsViaReflection(dynamicBuilder); - IMessage dynamicMessage = dynamicBuilder.WeakBuild(); - - Assert.AreEqual(message.SerializedSize, dynamicMessage.SerializedSize); - } - - [Test] - public void DynamicMessageSerialization() - { - IBuilder builder = DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - reflectionTester.SetAllFieldsViaReflection(builder); - IMessage message = builder.WeakBuild(); - - ByteString rawBytes = message.ToByteString(); - TestAllTypes message2 = TestAllTypes.ParseFrom(rawBytes); - - TestUtil.AssertAllFieldsSet(message2); - - // In fact, the serialized forms should be exactly the same, byte-for-byte. - Assert.AreEqual(TestUtil.GetAllSet().ToByteString(), rawBytes); - } - - [Test] - public void DynamicMessageParsing() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - TestUtil.SetAllFields(builder); - TestAllTypes message = builder.Build(); - - ByteString rawBytes = message.ToByteString(); - - IMessage message2 = DynamicMessage.ParseFrom(TestAllTypes.Descriptor, rawBytes); - reflectionTester.AssertAllFieldsSetViaReflection(message2); - } - - [Test] - public void DynamicMessagePackedSerialization() - { - IBuilder builder = DynamicMessage.CreateBuilder(TestPackedTypes.Descriptor); - packedReflectionTester.SetPackedFieldsViaReflection(builder); - IMessage message = builder.WeakBuild(); - - ByteString rawBytes = message.ToByteString(); - TestPackedTypes message2 = TestPackedTypes.ParseFrom(rawBytes); - - TestUtil.AssertPackedFieldsSet(message2); - - // In fact, the serialized forms should be exactly the same, byte-for-byte. - Assert.AreEqual(TestUtil.GetPackedSet().ToByteString(), rawBytes); - } - - [Test] - public void DynamicMessagePackedParsing() - { - TestPackedTypes.Builder builder = TestPackedTypes.CreateBuilder(); - TestUtil.SetPackedFields(builder); - TestPackedTypes message = builder.Build(); - - ByteString rawBytes = message.ToByteString(); - - IMessage message2 = DynamicMessage.ParseFrom(TestPackedTypes.Descriptor, rawBytes); - packedReflectionTester.AssertPackedFieldsSetViaReflection(message2); - } - - [Test] - public void DynamicMessageCopy() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - TestUtil.SetAllFields(builder); - TestAllTypes message = builder.Build(); - - DynamicMessage copy = DynamicMessage.CreateBuilder(message).Build(); - reflectionTester.AssertAllFieldsSetViaReflection(copy); - - // Oneof - FieldDescriptor bytesField = - TestAllTypes.Descriptor.FindFieldByName("oneof_bytes"); - FieldDescriptor uint32Field = - TestAllTypes.Descriptor.FindFieldByName("oneof_uint32"); - Assert.True(copy.HasField(bytesField)); - Assert.False(copy.HasField(uint32Field)); - - DynamicMessage.Builder dynamicBuilder = DynamicMessage.CreateBuilder(message); - dynamicBuilder[uint32Field] = 123U; - DynamicMessage copy2 = dynamicBuilder.Build(); - Assert.IsFalse(copy2.HasField(bytesField)); - Assert.IsTrue(copy2.HasField(uint32Field)); - Assert.AreEqual(123U, copy2[uint32Field]); - } - - [Test] - public void ToBuilder() - { - DynamicMessage.Builder builder = - DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - reflectionTester.SetAllFieldsViaReflection(builder); - int unknownFieldNum = 9; - ulong unknownFieldVal = 90; - builder.SetUnknownFields(UnknownFieldSet.CreateBuilder() - .AddField(unknownFieldNum, - UnknownField.CreateBuilder().AddVarint(unknownFieldVal).Build()) - .Build()); - DynamicMessage message = builder.Build(); - - DynamicMessage derived = message.ToBuilder().Build(); - reflectionTester.AssertAllFieldsSetViaReflection(derived); - - IList values = derived.UnknownFields.FieldDictionary[unknownFieldNum].VarintList; - Assert.AreEqual(1, values.Count); - Assert.AreEqual(unknownFieldVal, values[0]); - } - - [Test] - public void DynamicOneofMessage() - { - DynamicMessage.Builder builder = - DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - OneofDescriptor oneof = TestAllTypes.Descriptor.Oneofs[0]; - Assert.False(builder.HasOneof(oneof)); - Assert.AreSame(null, builder.OneofFieldDescriptor(oneof)); - - reflectionTester.SetAllFieldsViaReflection(builder); - Assert.True(builder.HasOneof(oneof)); - FieldDescriptor field = oneof.Field(3); - Assert.AreSame(field, builder.OneofFieldDescriptor(oneof)); - Assert.AreEqual(TestUtil.ToBytes("604"), builder[field]); - - DynamicMessage message = builder.BuildPartial(); - Assert.IsTrue(message.HasOneof(oneof)); - - DynamicMessage.Builder mergedBuilder = - DynamicMessage.CreateBuilder(TestAllTypes.Descriptor); - FieldDescriptor mergedField = oneof.Field(0); - mergedBuilder[mergedField] = 123U; - Assert.IsTrue(mergedBuilder.HasField(mergedField)); - mergedBuilder.MergeFrom(message); - Assert.IsTrue(mergedBuilder.HasField(field)); - Assert.IsFalse(mergedBuilder.HasField(mergedField)); - - mergedBuilder.ClearOneof(oneof); - Assert.AreSame(null, mergedBuilder.OneofFieldDescriptor(oneof)); - message = mergedBuilder.Build(); - Assert.AreSame(null, message.OneofFieldDescriptor(oneof)); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/ExtendableMessageTest.cs b/csharp/src/ProtocolBuffers.Test/ExtendableMessageTest.cs deleted file mode 100644 index 2aaf39c8..00000000 --- a/csharp/src/ProtocolBuffers.Test/ExtendableMessageTest.cs +++ /dev/null @@ -1,200 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using Google.ProtocolBuffers.TestProtos; -using NUnit.Framework; - -namespace Google.ProtocolBuffers -{ - public class ExtendableMessageTest - { - [Test] - public void ExtensionWriterInvalidExtension() - { - Assert.Throws(() => - TestPackedExtensions.CreateBuilder()[Unittest.OptionalForeignMessageExtension.Descriptor] = - ForeignMessage.DefaultInstance); - } - - [Test] - public void ExtensionWriterTest() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder() - .SetExtension(Unittest.DefaultBoolExtension, true) - .SetExtension(Unittest.DefaultBytesExtension, ByteString.CopyFromUtf8("123")) - .SetExtension(Unittest.DefaultCordExtension, "123") - .SetExtension(Unittest.DefaultDoubleExtension, 123) - .SetExtension(Unittest.DefaultFixed32Extension, 123u) - .SetExtension(Unittest.DefaultFixed64Extension, 123u) - .SetExtension(Unittest.DefaultFloatExtension, 123) - .SetExtension(Unittest.DefaultForeignEnumExtension, ForeignEnum.FOREIGN_BAZ) - .SetExtension(Unittest.DefaultImportEnumExtension, ImportEnum.IMPORT_BAZ) - .SetExtension(Unittest.DefaultInt32Extension, 123) - .SetExtension(Unittest.DefaultInt64Extension, 123) - .SetExtension(Unittest.DefaultNestedEnumExtension, TestAllTypes.Types.NestedEnum.FOO) - .SetExtension(Unittest.DefaultSfixed32Extension, 123) - .SetExtension(Unittest.DefaultSfixed64Extension, 123) - .SetExtension(Unittest.DefaultSint32Extension, 123) - .SetExtension(Unittest.DefaultSint64Extension, 123) - .SetExtension(Unittest.DefaultStringExtension, "123") - .SetExtension(Unittest.DefaultStringPieceExtension, "123") - .SetExtension(Unittest.DefaultUint32Extension, 123u) - .SetExtension(Unittest.DefaultUint64Extension, 123u) - //Optional - .SetExtension(Unittest.OptionalBoolExtension, true) - .SetExtension(Unittest.OptionalBytesExtension, ByteString.CopyFromUtf8("123")) - .SetExtension(Unittest.OptionalCordExtension, "123") - .SetExtension(Unittest.OptionalDoubleExtension, 123) - .SetExtension(Unittest.OptionalFixed32Extension, 123u) - .SetExtension(Unittest.OptionalFixed64Extension, 123u) - .SetExtension(Unittest.OptionalFloatExtension, 123) - .SetExtension(Unittest.OptionalForeignEnumExtension, ForeignEnum.FOREIGN_BAZ) - .SetExtension(Unittest.OptionalImportEnumExtension, ImportEnum.IMPORT_BAZ) - .SetExtension(Unittest.OptionalInt32Extension, 123) - .SetExtension(Unittest.OptionalInt64Extension, 123) - .SetExtension(Unittest.OptionalNestedEnumExtension, TestAllTypes.Types.NestedEnum.FOO) - .SetExtension(Unittest.OptionalSfixed32Extension, 123) - .SetExtension(Unittest.OptionalSfixed64Extension, 123) - .SetExtension(Unittest.OptionalSint32Extension, 123) - .SetExtension(Unittest.OptionalSint64Extension, 123) - .SetExtension(Unittest.OptionalStringExtension, "123") - .SetExtension(Unittest.OptionalStringPieceExtension, "123") - .SetExtension(Unittest.OptionalUint32Extension, 123u) - .SetExtension(Unittest.OptionalUint64Extension, 123u) - //Repeated - .AddExtension(Unittest.RepeatedBoolExtension, true) - .AddExtension(Unittest.RepeatedBytesExtension, ByteString.CopyFromUtf8("123")) - .AddExtension(Unittest.RepeatedCordExtension, "123") - .AddExtension(Unittest.RepeatedDoubleExtension, 123) - .AddExtension(Unittest.RepeatedFixed32Extension, 123u) - .AddExtension(Unittest.RepeatedFixed64Extension, 123u) - .AddExtension(Unittest.RepeatedFloatExtension, 123) - .AddExtension(Unittest.RepeatedForeignEnumExtension, ForeignEnum.FOREIGN_BAZ) - .AddExtension(Unittest.RepeatedImportEnumExtension, ImportEnum.IMPORT_BAZ) - .AddExtension(Unittest.RepeatedInt32Extension, 123) - .AddExtension(Unittest.RepeatedInt64Extension, 123) - .AddExtension(Unittest.RepeatedNestedEnumExtension, TestAllTypes.Types.NestedEnum.FOO) - .AddExtension(Unittest.RepeatedSfixed32Extension, 123) - .AddExtension(Unittest.RepeatedSfixed64Extension, 123) - .AddExtension(Unittest.RepeatedSint32Extension, 123) - .AddExtension(Unittest.RepeatedSint64Extension, 123) - .AddExtension(Unittest.RepeatedStringExtension, "123") - .AddExtension(Unittest.RepeatedStringPieceExtension, "123") - .AddExtension(Unittest.RepeatedUint32Extension, 123u) - .AddExtension(Unittest.RepeatedUint64Extension, 123u) - ; - TestAllExtensions msg = builder.Build(); - - ExtensionRegistry registry = ExtensionRegistry.CreateInstance(); - Unittest.RegisterAllExtensions(registry); - - TestAllExtensions.Builder copyBuilder = TestAllExtensions.CreateBuilder().MergeFrom(msg.ToByteArray(), - registry); - TestAllExtensions copy = copyBuilder.Build(); - - Assert.AreEqual(msg.ToByteArray(), copy.ToByteArray()); - - Assert.AreEqual(true, copy.GetExtension(Unittest.DefaultBoolExtension)); - Assert.AreEqual(ByteString.CopyFromUtf8("123"), copy.GetExtension(Unittest.DefaultBytesExtension)); - Assert.AreEqual("123", copy.GetExtension(Unittest.DefaultCordExtension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.DefaultDoubleExtension)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.DefaultFixed32Extension)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.DefaultFixed64Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.DefaultFloatExtension)); - Assert.AreEqual(ForeignEnum.FOREIGN_BAZ, copy.GetExtension(Unittest.DefaultForeignEnumExtension)); - Assert.AreEqual(ImportEnum.IMPORT_BAZ, copy.GetExtension(Unittest.DefaultImportEnumExtension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.DefaultInt32Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.DefaultInt64Extension)); - Assert.AreEqual(TestAllTypes.Types.NestedEnum.FOO, - copy.GetExtension(Unittest.DefaultNestedEnumExtension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.DefaultSfixed32Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.DefaultSfixed64Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.DefaultSint32Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.DefaultSint64Extension)); - Assert.AreEqual("123", copy.GetExtension(Unittest.DefaultStringExtension)); - Assert.AreEqual("123", copy.GetExtension(Unittest.DefaultStringPieceExtension)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.DefaultUint32Extension)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.DefaultUint64Extension)); - - Assert.AreEqual(true, copy.GetExtension(Unittest.OptionalBoolExtension)); - Assert.AreEqual(ByteString.CopyFromUtf8("123"), copy.GetExtension(Unittest.OptionalBytesExtension)); - Assert.AreEqual("123", copy.GetExtension(Unittest.OptionalCordExtension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.OptionalDoubleExtension)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.OptionalFixed32Extension)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.OptionalFixed64Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.OptionalFloatExtension)); - Assert.AreEqual(ForeignEnum.FOREIGN_BAZ, copy.GetExtension(Unittest.OptionalForeignEnumExtension)); - Assert.AreEqual(ImportEnum.IMPORT_BAZ, copy.GetExtension(Unittest.OptionalImportEnumExtension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.OptionalInt32Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.OptionalInt64Extension)); - Assert.AreEqual(TestAllTypes.Types.NestedEnum.FOO, - copy.GetExtension(Unittest.OptionalNestedEnumExtension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.OptionalSfixed32Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.OptionalSfixed64Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.OptionalSint32Extension)); - Assert.AreEqual(123, copy.GetExtension(Unittest.OptionalSint64Extension)); - Assert.AreEqual("123", copy.GetExtension(Unittest.OptionalStringExtension)); - Assert.AreEqual("123", copy.GetExtension(Unittest.OptionalStringPieceExtension)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.OptionalUint32Extension)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.OptionalUint64Extension)); - - Assert.AreEqual(true, copy.GetExtension(Unittest.RepeatedBoolExtension, 0)); - Assert.AreEqual(ByteString.CopyFromUtf8("123"), - copy.GetExtension(Unittest.RepeatedBytesExtension, 0)); - Assert.AreEqual("123", copy.GetExtension(Unittest.RepeatedCordExtension, 0)); - Assert.AreEqual(123, copy.GetExtension(Unittest.RepeatedDoubleExtension, 0)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.RepeatedFixed32Extension, 0)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.RepeatedFixed64Extension, 0)); - Assert.AreEqual(123, copy.GetExtension(Unittest.RepeatedFloatExtension, 0)); - Assert.AreEqual(ForeignEnum.FOREIGN_BAZ, - copy.GetExtension(Unittest.RepeatedForeignEnumExtension, 0)); - Assert.AreEqual(ImportEnum.IMPORT_BAZ, copy.GetExtension(Unittest.RepeatedImportEnumExtension, 0)); - Assert.AreEqual(123, copy.GetExtension(Unittest.RepeatedInt32Extension, 0)); - Assert.AreEqual(123, copy.GetExtension(Unittest.RepeatedInt64Extension, 0)); - Assert.AreEqual(TestAllTypes.Types.NestedEnum.FOO, - copy.GetExtension(Unittest.RepeatedNestedEnumExtension, 0)); - Assert.AreEqual(123, copy.GetExtension(Unittest.RepeatedSfixed32Extension, 0)); - Assert.AreEqual(123, copy.GetExtension(Unittest.RepeatedSfixed64Extension, 0)); - Assert.AreEqual(123, copy.GetExtension(Unittest.RepeatedSint32Extension, 0)); - Assert.AreEqual(123, copy.GetExtension(Unittest.RepeatedSint64Extension, 0)); - Assert.AreEqual("123", copy.GetExtension(Unittest.RepeatedStringExtension, 0)); - Assert.AreEqual("123", copy.GetExtension(Unittest.RepeatedStringPieceExtension, 0)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.RepeatedUint32Extension, 0)); - Assert.AreEqual(123u, copy.GetExtension(Unittest.RepeatedUint64Extension, 0)); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs b/csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs deleted file mode 100644 index 66214221..00000000 --- a/csharp/src/ProtocolBuffers.Test/FieldPresenceTest.cs +++ /dev/null @@ -1,198 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2015 Google Inc. All rights reserved. -// Author: jieluo@google.com (Jie Luo) -// -// 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 -// 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. - -#endregion - -using System; -using Google.ProtocolBuffers.Descriptors; -using Google.ProtocolBuffers.TestProtos.Proto3; -using NUnit.Framework; - -namespace Google.ProtocolBuffers -{ - public class FieldPresenceTest - { - private void CheckHasMethodRemoved(Type proto2Type, Type proto3Type, string name) - { - Assert.NotNull(proto2Type.GetProperty(name)); - Assert.NotNull(proto2Type.GetProperty("Has" + name)); - Assert.NotNull(proto3Type.GetProperty(name)); - Assert.Null(proto3Type.GetProperty("Has" + name)); - } - - [Test] - public void TestHasMethod() - { - // Optional non-message fields don't have HasFoo method generated - Type proto2Type = typeof(Google.ProtocolBuffers.TestProtos.TestAllTypes); - Type proto3Type = typeof(TestAllTypes); - CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalInt32"); - CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalString"); - CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalBytes"); - CheckHasMethodRemoved(proto2Type, proto3Type, "OptionalNestedEnum"); - - Type proto2BuilderType = typeof(Google.ProtocolBuffers.TestProtos.TestAllTypes.Builder); - Type proto3BuilderType = typeof(TestAllTypes.Builder); - CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OptionalInt32"); - CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OptionalString"); - CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OptionalBytes"); - CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OptionalNestedEnum"); - - // message fields still have the HasFoo method generated - Assert.IsFalse(TestAllTypes.CreateBuilder().Build().HasOptionalNestedMessage); - Assert.IsFalse(TestAllTypes.CreateBuilder().HasOptionalNestedMessage); - - // oneof fields don't have the HasFoo method (even for message types) - CheckHasMethodRemoved(proto2Type, proto3Type, "OneofUint32"); - CheckHasMethodRemoved(proto2Type, proto3Type, "OneofString"); - CheckHasMethodRemoved(proto2Type, proto3Type, "OneofNestedMessage"); - - CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OneofUint32"); - CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OneofString"); - CheckHasMethodRemoved(proto2BuilderType, proto3BuilderType, "OneofNestedMessage"); - } - - [Test] - public void TestFieldPresence() - { - // Optional non-message fields set to their default value are treated the same - // way as not set. - - // Serialization will ignore such fields. - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - builder.SetOptionalInt32(0); - builder.SetOptionalString(""); - builder.SetOptionalBytes(ByteString.Empty); - builder.SetOptionalNestedEnum(TestAllTypes.Types.NestedEnum.FOO); - TestAllTypes message = builder.Build(); - Assert.AreEqual(0, message.SerializedSize); - - // Test merge - TestAllTypes.Builder a = TestAllTypes.CreateBuilder(); - a.SetOptionalInt32(1); - a.SetOptionalString("x"); - a.SetOptionalBytes(ByteString.CopyFromUtf8("y")); - a.SetOptionalNestedEnum(TestAllTypes.Types.NestedEnum.BAR); - a.MergeFrom(message); - TestAllTypes messageA = a.Build(); - Assert.AreEqual(1, messageA.OptionalInt32); - Assert.AreEqual("x", messageA.OptionalString); - Assert.AreEqual(ByteString.CopyFromUtf8("y"), messageA.OptionalBytes); - Assert.AreEqual(TestAllTypes.Types.NestedEnum.BAR, messageA.OptionalNestedEnum); - - // equals/hashCode should produce the same results - TestAllTypes empty = TestAllTypes.CreateBuilder().Build(); - Assert.IsTrue(empty.Equals(message)); - Assert.IsTrue(message.Equals(empty)); - Assert.AreEqual(empty.GetHashCode(), message.GetHashCode()); - } - - [Test] - public void TestFieldPresenceReflection() - { - MessageDescriptor descriptor = TestAllTypes.Descriptor; - FieldDescriptor optionalInt32Field = descriptor.FindFieldByName("optional_int32"); - FieldDescriptor optionalStringField = descriptor.FindFieldByName("optional_string"); - FieldDescriptor optionalBytesField = descriptor.FindFieldByName("optional_bytes"); - FieldDescriptor optionalNestedEnumField = descriptor.FindFieldByName("optional_nested_enum"); - FieldDescriptor oneofUint32Field = descriptor.FindFieldByName("oneof_uint32"); - - TestAllTypes message = TestAllTypes.CreateBuilder().Build(); - Assert.IsFalse(message.HasField(optionalInt32Field)); - Assert.IsFalse(message.HasField(optionalStringField)); - Assert.IsFalse(message.HasField(optionalBytesField)); - Assert.IsFalse(message.HasField(optionalNestedEnumField)); - - // Set to default value is seen as not present for optional fields. - // Set to default value is seen as present for oneof fields. - message = TestAllTypes.CreateBuilder() - .SetOptionalInt32(0) - .SetOptionalString("") - .SetOptionalBytes(ByteString.Empty) - .SetOptionalNestedEnum(TestAllTypes.Types.NestedEnum.FOO) - .SetOneofUint32(0U) - .Build(); - Assert.IsFalse(message.HasField(optionalInt32Field)); - Assert.IsFalse(message.HasField(optionalStringField)); - Assert.IsFalse(message.HasField(optionalBytesField)); - Assert.IsFalse(message.HasField(optionalNestedEnumField)); - Assert.IsTrue(message.HasField(oneofUint32Field)); - Assert.AreEqual(1, message.AllFields.Count); - - // Set to non-defalut value is seen as present - message = TestAllTypes.CreateBuilder() - .SetOptionalInt32(1) - .SetOptionalString("x") - .SetOptionalBytes(ByteString.CopyFromUtf8("y")) - .SetOptionalNestedEnum(TestAllTypes.Types.NestedEnum.BAR) - .Build(); - Assert.IsTrue(message.HasField(optionalInt32Field)); - Assert.IsTrue(message.HasField(optionalStringField)); - Assert.IsTrue(message.HasField(optionalBytesField)); - Assert.IsTrue(message.HasField(optionalNestedEnumField)); - Assert.AreEqual(4, message.AllFields.Count); - } - - [Test] - public void TestMessageField() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - Assert.IsFalse(builder.HasOptionalNestedMessage); - Assert.IsFalse(builder.Build().HasOptionalNestedMessage); - - // Unlike non-message fields, if we set default value to message field, the field - // shoule be seem as present. - builder.SetOptionalNestedMessage(TestAllTypes.Types.NestedMessage.DefaultInstance); - Assert.IsTrue(builder.HasOptionalNestedMessage); - Assert.IsTrue(builder.Build().HasOptionalNestedMessage); - } - - [Test] - public void TestSerializeAndParse() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - builder.SetOptionalInt32(1234); - builder.SetOptionalString("hello"); - builder.SetOptionalNestedMessage(TestAllTypes.Types.NestedMessage.DefaultInstance); - builder.SetOneofUint32(0U); - ByteString data = builder.Build().ToByteString(); - - TestAllTypes message = TestAllTypes.ParseFrom(data); - Assert.AreEqual(1234, message.OptionalInt32); - Assert.AreEqual("hello", message.OptionalString); - Assert.AreEqual(ByteString.Empty, message.OptionalBytes); - Assert.AreEqual(TestAllTypes.Types.NestedEnum.FOO, message.OptionalNestedEnum); - Assert.IsTrue(message.HasOptionalNestedMessage); - Assert.AreEqual(0, message.OptionalNestedMessage.Bb); - Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.OneofUint32, message.OneofFieldCase); - } - } -} diff --git a/csharp/src/ProtocolBuffers.Test/GeneratedBuilderTest.cs b/csharp/src/ProtocolBuffers.Test/GeneratedBuilderTest.cs deleted file mode 100644 index 257f5001..00000000 --- a/csharp/src/ProtocolBuffers.Test/GeneratedBuilderTest.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using Google.ProtocolBuffers.TestProtos; -using NUnit.Framework; - -namespace Google.ProtocolBuffers -{ - public class GeneratedBuilderTest - { - class OneTimeEnumerator : IEnumerable - { - readonly T _item; - bool _enumerated; - public OneTimeEnumerator(T item) - { - _item = item; - } - public IEnumerator GetEnumerator() - { - Assert.IsFalse(_enumerated); - _enumerated = true; - yield return _item; - } - System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } - - [Test] - public void DoesNotEnumerateTwiceForMessageList() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - b.AddRangeRepeatedForeignMessage(new OneTimeEnumerator(ForeignMessage.DefaultInstance)); - } - - [Test] - public void DoesNotEnumerateTwiceForPrimitiveList() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - b.AddRangeRepeatedInt32(new OneTimeEnumerator(1)); - } - - [Test] - public void DoesNotEnumerateTwiceForStringList() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - b.AddRangeRepeatedString(new OneTimeEnumerator("test")); - } - - [Test] - public void DoesNotEnumerateTwiceForEnumList() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - b.AddRangeRepeatedForeignEnum(new OneTimeEnumerator(ForeignEnum.FOREIGN_BAR)); - } - - [Test] - public void DoesNotAddNullToMessageListByAddRange() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - Assert.Throws(() => b.AddRangeRepeatedForeignMessage(new ForeignMessage[] { null })); - } - - [Test] - public void DoesNotAddNullToMessageListByAdd() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - Assert.Throws(() => b.AddRepeatedForeignMessage((ForeignMessage)null)); - } - - [Test] - public void DoesNotAddNullToMessageListBySet() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - b.AddRepeatedForeignMessage(ForeignMessage.DefaultInstance); - Assert.Throws(() => b.SetRepeatedForeignMessage(0, (ForeignMessage)null)); - } - - [Test] - public void DoesNotAddNullToStringListByAddRange() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - Assert.Throws(() => b.AddRangeRepeatedString(new String[] { null })); - } - - [Test] - public void DoesNotAddNullToStringListByAdd() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - Assert.Throws(() => b.AddRepeatedString(null)); - } - - [Test] - public void DoesNotAddNullToStringListBySet() - { - TestAllTypes.Builder b = new TestAllTypes.Builder(); - b.AddRepeatedString("one"); - Assert.Throws(() => b.SetRepeatedString(0, null)); - } - } -} diff --git a/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs b/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs index 4f669449..c5564060 100644 --- a/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs +++ b/csharp/src/ProtocolBuffers.Test/GeneratedMessageTest.cs @@ -1,776 +1,153 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; +using System; using System.Collections.Generic; -using Google.ProtocolBuffers.Descriptors; -using Google.ProtocolBuffers.Collections; -using Google.ProtocolBuffers.TestProtos; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Google.Protobuf.TestProtos; using NUnit.Framework; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { + /// + /// Tests around the generated TestAllTypes message. + /// public class GeneratedMessageTest { - private readonly ReflectionTester reflectionTester; - private readonly ReflectionTester extensionsReflectionTester; - - public GeneratedMessageTest() - { - reflectionTester = ReflectionTester.CreateTestAllTypesInstance(); - extensionsReflectionTester = ReflectionTester.CreateTestAllExtensionsInstance(); - } - - [Test] - public void RepeatedAddPrimitiveBeforeBuild() - { - TestAllTypes message = new TestAllTypes.Builder {RepeatedInt32List = {1, 2, 3}}.Build(); - TestUtil.AssertEqual(new int[] {1, 2, 3}, message.RepeatedInt32List); - } - - [Test] - public void AddPrimitiveFailsAfterBuild() - { - TestAllTypes.Builder builder = new TestAllTypes.Builder(); - IList list = builder.RepeatedInt32List; - list.Add(1); // Fine - builder.Build(); - - Assert.Throws(() => list.Add(2)); - } - - [Test] - public void RepeatedAddMessageBeforeBuild() - { - TestAllTypes message = new TestAllTypes.Builder - { - RepeatedNestedMessageList = - {new TestAllTypes.Types.NestedMessage.Builder {Bb = 10}.Build()} - }.Build(); - Assert.AreEqual(1, message.RepeatedNestedMessageCount); - Assert.AreEqual(10, message.RepeatedNestedMessageList[0].Bb); - } - - [Test] - public void AddMessageFailsAfterBuild() - { - TestAllTypes.Builder builder = new TestAllTypes.Builder(); - IList list = builder.RepeatedNestedMessageList; - builder.Build(); - - Assert.Throws(() => list.Add(new TestAllTypes.Types.NestedMessage.Builder { Bb = 10 }.Build())); - } - - [Test] - public void DefaultInstance() - { - Assert.AreSame(TestAllTypes.DefaultInstance, TestAllTypes.DefaultInstance.DefaultInstanceForType); - Assert.AreSame(TestAllTypes.DefaultInstance, TestAllTypes.CreateBuilder().DefaultInstanceForType); - } - - [Test] - public void Accessors() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - TestUtil.SetAllFields(builder); - TestAllTypes message = builder.Build(); - TestUtil.AssertAllFieldsSet(message); - } - - [Test] - public void SettersRejectNull() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - Assert.Throws(() => builder.SetOptionalString(null)); - Assert.Throws(() => builder.SetOptionalBytes(null)); - Assert.Throws( - () => builder.SetOptionalNestedMessage((TestAllTypes.Types.NestedMessage) null)); - Assert.Throws( - () => builder.SetOptionalNestedMessage((TestAllTypes.Types.NestedMessage.Builder) null)); - Assert.Throws(() => builder.AddRepeatedString(null)); - Assert.Throws(() => builder.AddRepeatedBytes(null)); - Assert.Throws( - () => builder.AddRepeatedNestedMessage((TestAllTypes.Types.NestedMessage) null)); - Assert.Throws( - () => builder.AddRepeatedNestedMessage((TestAllTypes.Types.NestedMessage.Builder) null)); - } - - [Test] - public void RepeatedSetters() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - TestUtil.SetAllFields(builder); - TestUtil.ModifyRepeatedFields(builder); - TestAllTypes message = builder.Build(); - TestUtil.AssertRepeatedFieldsModified(message); - } - - [Test] - public void RepeatedAppend() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - - builder.AddRangeRepeatedInt32(new int[] {1, 2, 3, 4}); - builder.AddRangeRepeatedForeignEnum((new ForeignEnum[] {ForeignEnum.FOREIGN_BAZ})); - - ForeignMessage foreignMessage = ForeignMessage.CreateBuilder().SetC(12).Build(); - builder.AddRangeRepeatedForeignMessage(new ForeignMessage[] {foreignMessage}); - - TestAllTypes message = builder.Build(); - TestUtil.AssertEqual(message.RepeatedInt32List, new int[] {1, 2, 3, 4}); - TestUtil.AssertEqual(message.RepeatedForeignEnumList, new ForeignEnum[] {ForeignEnum.FOREIGN_BAZ}); - Assert.AreEqual(1, message.RepeatedForeignMessageCount); - Assert.AreEqual(12, message.GetRepeatedForeignMessage(0).C); - } - - [Test] - public void RepeatedAppendRejectsNull() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - - ForeignMessage foreignMessage = ForeignMessage.CreateBuilder().SetC(12).Build(); - Assert.Throws( - () => builder.AddRangeRepeatedForeignMessage(new[] {foreignMessage, null})); - Assert.Throws(() => builder.AddRangeRepeatedForeignMessage(null)); - Assert.Throws(() => builder.AddRangeRepeatedForeignEnum(null)); - Assert.Throws(() => builder.AddRangeRepeatedString(new[] {"one", null})); - Assert.Throws( - () => builder.AddRangeRepeatedBytes(new[] {TestUtil.ToBytes("one"), null})); - } - - [Test] - public void SettingForeignMessageUsingBuilder() - { - TestAllTypes message = TestAllTypes.CreateBuilder() - // Pass builder for foreign message instance. - .SetOptionalForeignMessage(ForeignMessage.CreateBuilder().SetC(123)) - .Build(); - TestAllTypes expectedMessage = TestAllTypes.CreateBuilder() - // Create expected version passing foreign message instance explicitly. - .SetOptionalForeignMessage(ForeignMessage.CreateBuilder().SetC(123).Build()) - .Build(); - Assert.AreEqual(expectedMessage, message); - } - - [Test] - public void SettingRepeatedForeignMessageUsingBuilder() - { - TestAllTypes message = TestAllTypes.CreateBuilder() - // Pass builder for foreign message instance. - .AddRepeatedForeignMessage(ForeignMessage.CreateBuilder().SetC(456)) - .Build(); - TestAllTypes expectedMessage = TestAllTypes.CreateBuilder() - // Create expected version passing foreign message instance explicitly. - .AddRepeatedForeignMessage(ForeignMessage.CreateBuilder().SetC(456).Build()) - .Build(); - Assert.AreEqual(expectedMessage, message); - } - - [Test] - public void SettingRepeatedValuesUsingRangeInCollectionInitializer() - { - int[] values = {1, 2, 3}; - TestAllTypes message = new TestAllTypes.Builder - { - RepeatedSint32List = {values} - }.Build(); - Assert.IsTrue(Lists.Equals(values, message.RepeatedSint32List)); - } - - [Test] - public void SettingRepeatedValuesUsingIndividualValuesInCollectionInitializer() - { - TestAllTypes message = new TestAllTypes.Builder - { - RepeatedSint32List = {6, 7} - }.Build(); - Assert.IsTrue(Lists.Equals(new int[] {6, 7}, message.RepeatedSint32List)); - } - - [Test] - public void Defaults() - { - TestUtil.AssertClear(TestAllTypes.DefaultInstance); - TestUtil.AssertClear(TestAllTypes.CreateBuilder().Build()); - - Assert.AreEqual("\u1234", TestExtremeDefaultValues.DefaultInstance.Utf8String); - } - - [Test] - public void ReflectionGetters() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - TestUtil.SetAllFields(builder); - TestAllTypes message = builder.Build(); - reflectionTester.AssertAllFieldsSetViaReflection(message); - } - - [Test] - public void ReflectionSetters() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - reflectionTester.SetAllFieldsViaReflection(builder); - TestAllTypes message = builder.Build(); - TestUtil.AssertAllFieldsSet(message); - } - - [Test] - public void ReflectionClear() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - reflectionTester.SetAllFieldsViaReflection(builder); - reflectionTester.ClearAllFieldsViaReflection(builder); - TestAllTypes message = builder.Build(); - TestUtil.AssertClear(message); - } - - [Test] - public void ReflectionSettersRejectNull() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - reflectionTester.AssertReflectionSettersRejectNull(builder); - } - - [Test] - public void ReflectionRepeatedSetters() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - reflectionTester.SetAllFieldsViaReflection(builder); - reflectionTester.ModifyRepeatedFieldsViaReflection(builder); - TestAllTypes message = builder.Build(); - TestUtil.AssertRepeatedFieldsModified(message); - } - - [Test] - public void TestReflectionRepeatedSettersRejectNull() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - reflectionTester.AssertReflectionRepeatedSettersRejectNull(builder); - } - - [Test] - public void ReflectionDefaults() - { - TestUtil.TestInMultipleCultures(() => - { - reflectionTester.AssertClearViaReflection( - TestAllTypes.DefaultInstance); - reflectionTester.AssertClearViaReflection( - TestAllTypes.CreateBuilder().Build()); - }); - } - - [Test] - public void ReflectionGetOneof() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - reflectionTester.SetAllFieldsViaReflection(builder); - Descriptors.OneofDescriptor oneof = TestAllTypes.Descriptor.Oneofs[0]; - Descriptors.FieldDescriptor field = TestAllTypes.Descriptor.FindFieldByName("oneof_bytes"); - Assert.AreSame(field, builder.OneofFieldDescriptor(oneof)); - } - - [Test] - public void ReflectionClearOneof() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - reflectionTester.SetAllFieldsViaReflection(builder); - OneofDescriptor oneof = TestAllTypes.Descriptor.Oneofs[0]; - FieldDescriptor field = TestAllTypes.Descriptor.FindFieldByName("oneof_bytes"); - - Assert.IsTrue(builder.HasOneof(oneof)); - Assert.IsTrue(builder.HasField(field)); - builder.ClearOneof(oneof); - Assert.IsFalse(builder.HasOneof(oneof)); - Assert.IsFalse(builder.HasField(field)); - } - - // ================================================================= - // Extensions. - - [Test] - public void ExtensionAccessors() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); - TestUtil.SetAllExtensions(builder); - TestAllExtensions message = builder.Build(); - TestUtil.AssertAllExtensionsSet(message); - } - - [Test] - public void ExtensionRepeatedSetters() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); - TestUtil.SetAllExtensions(builder); - TestUtil.ModifyRepeatedExtensions(builder); - TestAllExtensions message = builder.Build(); - TestUtil.AssertRepeatedExtensionsModified(message); - } - - [Test] - public void ExtensionDefaults() - { - TestUtil.AssertExtensionsClear(TestAllExtensions.DefaultInstance); - TestUtil.AssertExtensionsClear(TestAllExtensions.CreateBuilder().Build()); - } - - [Test] - public void ExtensionReflectionGetters() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); - TestUtil.SetAllExtensions(builder); - TestAllExtensions message = builder.Build(); - extensionsReflectionTester.AssertAllFieldsSetViaReflection(message); - } - - [Test] - public void ExtensionReflectionSetters() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); - extensionsReflectionTester.SetAllFieldsViaReflection(builder); - TestAllExtensions message = builder.Build(); - TestUtil.AssertAllExtensionsSet(message); - } - [Test] - public void ExtensionReflectionSettersRejectNull() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); - extensionsReflectionTester.AssertReflectionSettersRejectNull(builder); - } - - [Test] - public void ExtensionReflectionRepeatedSetters() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); - extensionsReflectionTester.SetAllFieldsViaReflection(builder); - extensionsReflectionTester.ModifyRepeatedFieldsViaReflection(builder); - TestAllExtensions message = builder.Build(); - TestUtil.AssertRepeatedExtensionsModified(message); - } - - [Test] - public void ExtensionReflectionRepeatedSettersRejectNull() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); - extensionsReflectionTester.AssertReflectionRepeatedSettersRejectNull(builder); - } - - [Test] - public void ExtensionReflectionDefaults() - { - TestUtil.TestInMultipleCultures(() => - { - extensionsReflectionTester.AssertClearViaReflection( - TestAllExtensions.DefaultInstance); - extensionsReflectionTester.AssertClearViaReflection( - TestAllExtensions.CreateBuilder().Build()); - }); - } - - [Test] - public void ClearExtension() - { - // ClearExtension() is not actually used in TestUtil, so try it manually. - Assert.IsFalse(TestAllExtensions.CreateBuilder() - .SetExtension(Unittest.OptionalInt32Extension, 1) - .ClearExtension(Unittest.OptionalInt32Extension) - .HasExtension(Unittest.OptionalInt32Extension)); - Assert.AreEqual(0, TestAllExtensions.CreateBuilder() - .AddExtension(Unittest.RepeatedInt32Extension, 1) - .ClearExtension(Unittest.RepeatedInt32Extension) - .GetExtensionCount(Unittest.RepeatedInt32Extension)); - } - - [Test] - public void ExtensionMergeFrom() - { - TestAllExtensions original = TestAllExtensions.CreateBuilder() - .SetExtension(Unittest.OptionalInt32Extension, 1).Build(); - TestAllExtensions merged = - TestAllExtensions.CreateBuilder().MergeFrom(original).Build(); - Assert.IsTrue((merged.HasExtension(Unittest.OptionalInt32Extension))); - Assert.AreEqual(1, (int) merged.GetExtension(Unittest.OptionalInt32Extension)); - } - - /* Removed multiple files option for the moment - [Test] - public void MultipleFilesOption() { - // We mostly just want to check that things compile. - MessageWithNoOuter message = MessageWithNoOuter.CreateBuilder() - .SetNested(MessageWithNoOuter.Types.NestedMessage.CreateBuilder().SetI(1)) - .AddForeign(TestAllTypes.CreateBuilder().SetOptionalInt32(1)) - .SetNestedEnum(MessageWithNoOuter.Types.NestedEnum.BAZ) - .SetForeignEnum(EnumWithNoOuter.BAR) - .Build(); - Assert.AreEqual(message, MessageWithNoOuter.ParseFrom(message.ToByteString())); - - Assert.AreEqual(MultiFileProto.DescriptorProtoFile, MessageWithNoOuter.DescriptorProtoFile.File); - - FieldDescriptor field = MessageWithNoOuter.DescriptorProtoFile.FindDescriptor("foreign_enum"); - Assert.AreEqual(MultiFileProto.DescriptorProtoFile.FindTypeByName("EnumWithNoOuter") - .FindValueByNumber((int)EnumWithNoOuter.BAR), message[field]); - - Assert.AreEqual(MultiFileProto.DescriptorProtoFile, ServiceWithNoOuter.DescriptorProtoFile.File); - - Assert.IsFalse(TestAllExtensions.DefaultInstance.HasExtension(MultiFileProto.ExtensionWithOuter)); - }*/ - - [Test] - public void OptionalFieldWithRequiredSubfieldsOptimizedForSize() - { - TestOptionalOptimizedForSize message = TestOptionalOptimizedForSize.DefaultInstance; - Assert.IsTrue(message.IsInitialized); - - message = TestOptionalOptimizedForSize.CreateBuilder().SetO( - TestRequiredOptimizedForSize.CreateBuilder().BuildPartial() - ).BuildPartial(); - Assert.IsFalse(message.IsInitialized); - - message = TestOptionalOptimizedForSize.CreateBuilder().SetO( - TestRequiredOptimizedForSize.CreateBuilder().SetX(5).BuildPartial() - ).BuildPartial(); - Assert.IsTrue(message.IsInitialized); - } - - [Test] - public void OptimizedForSizeMergeUsesAllFieldsFromTarget() - { - TestOptimizedForSize withFieldSet = new TestOptimizedForSize.Builder {I = 10}.Build(); - TestOptimizedForSize.Builder builder = new TestOptimizedForSize.Builder(); - builder.MergeFrom(withFieldSet); - TestOptimizedForSize built = builder.Build(); - Assert.AreEqual(10, built.I); - } - - [Test] - public void UninitializedExtensionInOptimizedForSizeMakesMessageUninitialized() - { - TestOptimizedForSize.Builder builder = new TestOptimizedForSize.Builder(); - builder.SetExtension(TestOptimizedForSize.TestExtension2, - new TestRequiredOptimizedForSize.Builder().BuildPartial()); - Assert.IsFalse(builder.IsInitialized); - Assert.IsFalse(builder.BuildPartial().IsInitialized); - - builder = new TestOptimizedForSize.Builder(); - builder.SetExtension(TestOptimizedForSize.TestExtension2, - new TestRequiredOptimizedForSize.Builder {X = 10}.BuildPartial()); - Assert.IsTrue(builder.IsInitialized); - Assert.IsTrue(builder.BuildPartial().IsInitialized); - } - - [Test] - public void ToBuilder() - { - TestAllTypes.Builder builder = TestAllTypes.CreateBuilder(); - TestUtil.SetAllFields(builder); - TestAllTypes message = builder.Build(); - TestUtil.AssertAllFieldsSet(message.ToBuilder().Build()); - } - - [Test] - public void FieldConstantValues() - { - Assert.AreEqual(TestAllTypes.Types.NestedMessage.BbFieldNumber, 1); - Assert.AreEqual(TestAllTypes.OptionalInt32FieldNumber, 1); - Assert.AreEqual(TestAllTypes.OptionalGroupFieldNumber, 16); - Assert.AreEqual(TestAllTypes.OptionalNestedMessageFieldNumber, 18); - Assert.AreEqual(TestAllTypes.OptionalNestedEnumFieldNumber, 21); - Assert.AreEqual(TestAllTypes.RepeatedInt32FieldNumber, 31); - Assert.AreEqual(TestAllTypes.RepeatedGroupFieldNumber, 46); - Assert.AreEqual(TestAllTypes.RepeatedNestedMessageFieldNumber, 48); - Assert.AreEqual(TestAllTypes.RepeatedNestedEnumFieldNumber, 51); - } - - [Test] - public void ExtensionConstantValues() - { - Assert.AreEqual(TestRequired.SingleFieldNumber, 1000); - Assert.AreEqual(TestRequired.MultiFieldNumber, 1001); - Assert.AreEqual(Unittest.OptionalInt32ExtensionFieldNumber, 1); - Assert.AreEqual(Unittest.OptionalGroupExtensionFieldNumber, 16); - Assert.AreEqual(Unittest.OptionalNestedMessageExtensionFieldNumber, 18); - Assert.AreEqual(Unittest.OptionalNestedEnumExtensionFieldNumber, 21); - Assert.AreEqual(Unittest.RepeatedInt32ExtensionFieldNumber, 31); - Assert.AreEqual(Unittest.RepeatedGroupExtensionFieldNumber, 46); - Assert.AreEqual(Unittest.RepeatedNestedMessageExtensionFieldNumber, 48); - Assert.AreEqual(Unittest.RepeatedNestedEnumExtensionFieldNumber, 51); - } - - [Test] - public void EmptyPackedValue() - { - TestPackedTypes empty = new TestPackedTypes.Builder().Build(); - Assert.AreEqual(0, empty.SerializedSize); - } - - // oneof tests - [Test] - public void TestOneofEnumCase() - { - TestOneof2 message = TestOneof2.CreateBuilder() - .SetFooInt(123).SetFooString("foo").SetFooCord("bar").Build(); - TestUtil.AssertAtMostOneFieldSetOneof(message); - } - - [Test] - public void TestClearOneof() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder().SetFooInt(123); - Assert.AreEqual(TestOneof2.FooOneofCase.FooInt, builder.FooCase); - builder.ClearFoo(); - Assert.AreEqual(TestOneof2.FooOneofCase.None, builder.FooCase); - } - - [Test] - public void TestSetOneofClearsOthers() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = - builder.SetFooInt(123).SetFooString("foo").Build(); - Assert.IsTrue(message.HasFooString); - TestUtil.AssertAtMostOneFieldSetOneof(message); - - message = builder.SetFooCord("bar").Build(); - Assert.IsTrue(message.HasFooCord); - TestUtil.AssertAtMostOneFieldSetOneof(message); - - message = builder.SetFooStringPiece("baz").Build(); - Assert.IsTrue(message.HasFooStringPiece); - TestUtil.AssertAtMostOneFieldSetOneof(message); - - message = builder.SetFooBytes(TestUtil.ToBytes("qux")).Build(); - Assert.IsTrue(message.HasFooBytes); - TestUtil.AssertAtMostOneFieldSetOneof(message); - - message = builder.SetFooEnum(TestOneof2.Types.NestedEnum.FOO).Build(); - Assert.IsTrue(message.HasFooEnum); - TestUtil.AssertAtMostOneFieldSetOneof(message); - - message = builder.SetFooMessage( - TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(234).Build()).Build(); - Assert.IsTrue(message.HasFooMessage); - TestUtil.AssertAtMostOneFieldSetOneof(message); - - message = builder.SetFooInt(123).Build(); - Assert.IsTrue(message.HasFooInt); - TestUtil.AssertAtMostOneFieldSetOneof(message); - } - - [Test] - public void TestOneofTypes_Primitive() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - Assert.AreEqual(builder.FooInt, 0); - Assert.IsFalse(builder.HasFooInt); - Assert.IsTrue(builder.SetFooInt(123).HasFooInt); - Assert.AreEqual(builder.FooInt, 123); - TestOneof2 message = builder.BuildPartial(); - Assert.IsTrue(message.HasFooInt); - Assert.AreEqual(message.FooInt, 123); - - Assert.IsFalse(builder.ClearFooInt().HasFooInt); - TestOneof2 message2 = builder.Build(); - Assert.IsFalse(message2.HasFooInt); - Assert.AreEqual(message2.FooInt, 0); - } - - [Test] - public void TestOneofTypes_Enum() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - Assert.AreEqual(builder.FooEnum, TestOneof2.Types.NestedEnum.FOO); - Assert.IsTrue(builder.SetFooEnum(TestOneof2.Types.NestedEnum.BAR).HasFooEnum); - Assert.AreEqual(builder.FooEnum, TestOneof2.Types.NestedEnum.BAR); - TestOneof2 message = builder.BuildPartial(); - Assert.IsTrue(message.HasFooEnum); - Assert.AreEqual(message.FooEnum, TestOneof2.Types.NestedEnum.BAR); - - Assert.IsFalse(builder.ClearFooEnum().HasFooEnum); - TestOneof2 message2 = builder.Build(); - Assert.IsFalse(message2.HasFooEnum); - Assert.AreEqual(message2.FooEnum, TestOneof2.Types.NestedEnum.FOO); - } - - [Test] - public void TestOneofTypes_String() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - Assert.AreEqual(builder.FooString, ""); - Assert.IsTrue(builder.SetFooString("foo").HasFooString); - Assert.AreEqual(builder.FooString, "foo"); - TestOneof2 message = builder.BuildPartial(); - Assert.IsTrue(message.HasFooString); - Assert.AreEqual(message.FooString, "foo"); - - Assert.IsFalse(builder.ClearFooString().HasFooString); - TestOneof2 message2 = builder.Build(); - Assert.IsFalse(message2.HasFooString); - Assert.AreEqual(message2.FooString, ""); - - builder.SetFooInt(123); - Assert.AreEqual(builder.FooString, ""); - Assert.AreEqual(builder.FooInt, 123); - message = builder.Build(); - Assert.AreEqual(message.FooString, ""); - Assert.AreEqual(message.FooInt, 123); - } - - [Test] - public void TestOneofTypes_Message() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - Assert.AreEqual(builder.FooMessage.QuxInt, 0); - builder.SetFooMessage(TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(234).Build()); - Assert.IsTrue(builder.HasFooMessage); - Assert.AreEqual(builder.FooMessage.QuxInt, 234); - TestOneof2 message = builder.BuildPartial(); - Assert.IsTrue(message.HasFooMessage); - Assert.AreEqual(message.FooMessage.QuxInt, 234); - - Assert.IsFalse(builder.ClearFooMessage().HasFooMessage); - message = builder.Build(); - Assert.IsFalse(message.HasFooMessage); - Assert.AreEqual(message.FooMessage.QuxInt, 0); - - builder = TestOneof2.CreateBuilder(); - Assert.IsFalse(builder.HasFooMessage); - builder.SetFooMessage(TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(123)); - Assert.IsTrue(builder.HasFooMessage); - Assert.AreEqual(builder.FooMessage.QuxInt, 123); - message = builder.Build(); - Assert.IsTrue(message.HasFooMessage); - Assert.AreEqual(message.FooMessage.QuxInt, 123); - } - - [Test] - public void TestOneofMerge_Primitive() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooInt(123).Build(); - TestOneof2 message2 = TestOneof2.CreateBuilder().MergeFrom(message).Build(); - Assert.IsTrue(message2.HasFooInt); - Assert.AreEqual(message2.FooInt, 123); - } - - [Test] - public void TestOneofMerge_String() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooString("foo").Build(); - TestOneof2 message2 = TestOneof2.CreateBuilder().MergeFrom(message).Build(); - Assert.IsTrue(message2.HasFooString); - Assert.AreEqual(message2.FooString, "foo"); - } - - [Test] - public void TestOneofMerge_Enum() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooEnum(TestOneof2.Types.NestedEnum.BAR).Build(); - TestOneof2 message2 = TestOneof2.CreateBuilder().MergeFrom(message).Build(); - Assert.IsTrue(message2.HasFooEnum); - Assert.AreEqual(message2.FooEnum, TestOneof2.Types.NestedEnum.BAR); - } - - public void TestOneofMerge_message() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooMessage( - TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(234).Build()).Build(); - TestOneof2 message2 = TestOneof2.CreateBuilder().MergeFrom(message).Build(); - Assert.IsTrue(message2.HasFooMessage); - Assert.AreEqual(message2.FooMessage.QuxInt, 234); - } - - [Test] - public void TestOneofMergeMixed() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooEnum(TestOneof2.Types.NestedEnum.BAR).Build(); - TestOneof2 message2 = - TestOneof2.CreateBuilder().SetFooString("foo").MergeFrom(message).Build(); - Assert.IsFalse(message2.HasFooString); - Assert.IsTrue(message2.HasFooEnum); - Assert.AreEqual(message2.FooEnum, TestOneof2.Types.NestedEnum.BAR); - } - - [Test] - public void TestOneofSerialization_Primitive() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooInt(123).Build(); - ByteString serialized = message.ToByteString(); - TestOneof2 message2 = TestOneof2.ParseFrom(serialized); - Assert.IsTrue(message2.HasFooInt); - Assert.AreEqual(message2.FooInt, 123); - } - - [Test] - public void TestOneofSerialization_String() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooString("foo").Build(); - ByteString serialized = message.ToByteString(); - TestOneof2 message2 = TestOneof2.ParseFrom(serialized); - Assert.IsTrue(message2.HasFooString); - Assert.AreEqual(message2.FooString, "foo"); - } - - [Test] - public void TestOneofSerialization_Enum() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooEnum(TestOneof2.Types.NestedEnum.BAR).Build(); - ByteString serialized = message.ToByteString(); - TestOneof2 message2 = TestOneof2.ParseFrom(serialized); - Assert.IsTrue(message2.HasFooEnum); - Assert.AreEqual(message2.FooEnum, TestOneof2.Types.NestedEnum.BAR); - } - - [Test] - public void TestOneofSerialization_Message() - { - TestOneof2.Builder builder = TestOneof2.CreateBuilder(); - TestOneof2 message = builder.SetFooMessage( - TestOneof2.Types.NestedMessage.CreateBuilder().SetQuxInt(234).Build()).Build(); - ByteString serialized = message.ToByteString(); - TestOneof2 message2 = TestOneof2.ParseFrom(serialized); - Assert.IsTrue(message2.HasFooMessage); - Assert.AreEqual(message2.FooMessage.QuxInt, 234); + public void DefaultValues() + { + // Single fields + var message = new TestAllTypes(); + Assert.AreEqual(false, message.SingleBool); + Assert.AreEqual(ByteString.Empty, message.SingleBytes); + Assert.AreEqual(0.0, message.SingleDouble); + Assert.AreEqual(0, message.SingleFixed32); + Assert.AreEqual(0L, message.SingleFixed64); + Assert.AreEqual(0.0f, message.SingleFloat); + Assert.AreEqual(ForeignEnum.FOREIGN_UNSPECIFIED, message.SingleForeignEnum); + Assert.IsNull(message.SingleForeignMessage); + Assert.AreEqual(ImportEnum.IMPORT_ENUM_UNSPECIFIED, message.SingleImportEnum); + Assert.IsNull(message.SingleImportMessage); + Assert.AreEqual(0, message.SingleInt32); + Assert.AreEqual(0L, message.SingleInt64); + Assert.AreEqual(TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED, message.SingleNestedEnum); + Assert.IsNull(message.SingleNestedMessage); + Assert.IsNull(message.SinglePublicImportMessage); + Assert.AreEqual(0, message.SingleSfixed32); + Assert.AreEqual(0L, message.SingleSfixed64); + Assert.AreEqual(0, message.SingleSint32); + Assert.AreEqual(0L, message.SingleSint64); + Assert.AreEqual("", message.SingleString); + Assert.AreEqual(0U, message.SingleUint32); + Assert.AreEqual(0UL, message.SingleUint64); + + // Repeated fields + Assert.AreEqual(0, message.RepeatedBool.Count); + Assert.AreEqual(0, message.RepeatedBytes.Count); + Assert.AreEqual(0, message.RepeatedDouble.Count); + Assert.AreEqual(0, message.RepeatedFixed32.Count); + Assert.AreEqual(0, message.RepeatedFixed64.Count); + Assert.AreEqual(0, message.RepeatedFloat.Count); + Assert.AreEqual(0, message.RepeatedForeignEnum.Count); + Assert.AreEqual(0, message.RepeatedForeignMessage.Count); + Assert.AreEqual(0, message.RepeatedImportEnum.Count); + Assert.AreEqual(0, message.RepeatedImportMessage.Count); + Assert.AreEqual(0, message.RepeatedNestedEnum.Count); + Assert.AreEqual(0, message.RepeatedNestedMessage.Count); + Assert.AreEqual(0, message.RepeatedPublicImportMessage.Count); + Assert.AreEqual(0, message.RepeatedSfixed32.Count); + Assert.AreEqual(0, message.RepeatedSfixed64.Count); + Assert.AreEqual(0, message.RepeatedSint32.Count); + Assert.AreEqual(0, message.RepeatedSint64.Count); + Assert.AreEqual(0, message.RepeatedString.Count); + Assert.AreEqual(0, message.RepeatedUint32.Count); + Assert.AreEqual(0, message.RepeatedUint64.Count); + + // Oneof fields + Assert.AreEqual(TestAllTypes.OneofFieldOneofCase.None, message.OneofFieldCase); + Assert.AreEqual(0, message.OneofUint32); + Assert.AreEqual("", message.OneofString); + Assert.AreEqual(ByteString.Empty, message.OneofBytes); + Assert.IsNull(message.OneofNestedMessage); + } + + [Test] + public void RoundTrip_Empty() + { + var message = new TestAllTypes(); + // Without setting any values, there's nothing to write. + byte[] bytes = message.ToByteArray(); + Assert.AreEqual(0, bytes.Length); + TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); + Assert.AreEqual(message, parsed); + } + + [Test] + public void RoundTrip_SingleValues() + { + var message = new TestAllTypes + { + SingleBool = true, + SingleBytes = ByteString.CopyFrom(new byte[] { 1, 2, 3, 4 }), + SingleDouble = 23.5, + SingleFixed32 = 23, + SingleFixed64 = 1234567890123, + SingleFloat = 12.25f, + SingleForeignEnum = ForeignEnum.FOREIGN_BAR, + SingleForeignMessage = new ForeignMessage { C = 10 }, + SingleImportEnum = ImportEnum.IMPORT_BAZ, + SingleImportMessage = new ImportMessage { D = 20 }, + SingleInt32 = 100, + SingleInt64 = 3210987654321, + SingleNestedEnum = TestAllTypes.Types.NestedEnum.FOO, + SingleNestedMessage = new TestAllTypes.Types.NestedMessage { Bb = 35 }, + SinglePublicImportMessage = new PublicImportMessage { E = 54 }, + SingleSfixed32 = -123, + SingleSfixed64 = -12345678901234, + SingleSint32 = -456, + SingleSint64 = -12345678901235, + SingleString = "test", + SingleUint32 = uint.MaxValue, + SingleUint64 = ulong.MaxValue + }; + + byte[] bytes = message.ToByteArray(); + TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); + Assert.AreEqual(message, parsed); + } + + [Test] + public void RoundTrip_RepeatedValues() + { + var message = new TestAllTypes + { + RepeatedBool = { true, false }, + RepeatedBytes = { ByteString.CopyFrom(new byte[] { 1, 2, 3, 4 }), ByteString.CopyFrom(new byte[] { 5, 6 }) }, + RepeatedDouble = { -12.25, 23.5 }, + RepeatedFixed32 = { uint.MaxValue, 23 }, + RepeatedFixed64 = { ulong.MaxValue, 1234567890123 }, + RepeatedFloat = { 100f, 12.25f }, + RepeatedForeignEnum = { ForeignEnum.FOREIGN_FOO, ForeignEnum.FOREIGN_BAR }, + RepeatedForeignMessage = { new ForeignMessage(), new ForeignMessage { C = 10 } }, + RepeatedImportEnum = { ImportEnum.IMPORT_BAZ, ImportEnum.IMPORT_ENUM_UNSPECIFIED }, + RepeatedImportMessage = { new ImportMessage { D = 20 }, new ImportMessage { D = 25 } }, + RepeatedInt32 = { 100, 200 }, + RepeatedInt64 = { 3210987654321, long.MaxValue }, + RepeatedNestedEnum = { TestAllTypes.Types.NestedEnum.FOO, TestAllTypes.Types.NestedEnum.NEG }, + RepeatedNestedMessage = { new TestAllTypes.Types.NestedMessage { Bb = 35 }, new TestAllTypes.Types.NestedMessage { Bb = 10 } }, + RepeatedPublicImportMessage = { new PublicImportMessage { E = 54 }, new PublicImportMessage { E = -1 } }, + RepeatedSfixed32 = { -123, 123 }, + RepeatedSfixed64 = { -12345678901234, 12345678901234 }, + RepeatedSint32 = { -456, 100 }, + RepeatedSint64 = { -12345678901235, 123 }, + RepeatedString = { "foo", "bar" }, + RepeatedUint32 = { uint.MaxValue, uint.MinValue }, + RepeatedUint64 = { ulong.MaxValue, uint.MinValue } + }; + + byte[] bytes = message.ToByteArray(); + TestAllTypes parsed = TestAllTypes.Parser.ParseFrom(bytes); + Assert.AreEqual(message, parsed); } } -} \ No newline at end of file +} diff --git a/csharp/src/ProtocolBuffers.Test/IssuesTest.cs b/csharp/src/ProtocolBuffers.Test/IssuesTest.cs index ce7e5f09..87960aab 100644 --- a/csharp/src/ProtocolBuffers.Test/IssuesTest.cs +++ b/csharp/src/ProtocolBuffers.Test/IssuesTest.cs @@ -34,13 +34,12 @@ #endregion - -using Google.ProtocolBuffers.Descriptors; +using Google.Protobuf.Descriptors; using UnitTest.Issues.TestProtos; using NUnit.Framework; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { /// /// Tests for issues which aren't easily compartmentalized into other unit tests. @@ -51,10 +50,11 @@ namespace Google.ProtocolBuffers [Test] public void FieldCalledItem() { - ItemField message = new ItemField.Builder { Item = 3 }.Build(); + ItemField message = new ItemField { Item = 3 }; FieldDescriptor field = ItemField.Descriptor.FindFieldByName("item"); Assert.NotNull(field); - Assert.AreEqual(3, (int)message[field]); + // TODO(jonskeet): Reflection... + // Assert.AreEqual(3, (int)message[field]); } } } diff --git a/csharp/src/ProtocolBuffers.Test/MessageStreamIteratorTest.cs b/csharp/src/ProtocolBuffers.Test/MessageStreamIteratorTest.cs deleted file mode 100644 index 4754ce60..00000000 --- a/csharp/src/ProtocolBuffers.Test/MessageStreamIteratorTest.cs +++ /dev/null @@ -1,90 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System.Collections.Generic; -using System.IO; -using Google.ProtocolBuffers.TestProtos; -using NUnit.Framework; -using NestedMessage = Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage; - -namespace Google.ProtocolBuffers -{ - public class MessageStreamIteratorTest - { - [Test] - public void ThreeMessagesInMemory() - { - MemoryStream stream = new MemoryStream(MessageStreamWriterTest.ThreeMessageData); - IEnumerable iterator = MessageStreamIterator.FromStreamProvider(() => stream); - List messages = new List(iterator); - - Assert.AreEqual(3, messages.Count); - Assert.AreEqual(5, messages[0].Bb); - Assert.AreEqual(1500, messages[1].Bb); - Assert.IsFalse(messages[2].HasBb); - } - - [Test] - public void ManyMessagesShouldNotTriggerSizeAlert() - { - int messageSize = TestUtil.GetAllSet().SerializedSize; - // Enough messages to trigger the alert unless we've reset the size - // Note that currently we need to make this big enough to copy two whole buffers, - // as otherwise when we refill the buffer the second type, the alert triggers instantly. - int correctCount = (CodedInputStream.BufferSize*2)/messageSize + 1; - using (MemoryStream stream = new MemoryStream()) - { - MessageStreamWriter writer = new MessageStreamWriter(stream); - for (int i = 0; i < correctCount; i++) - { - writer.Write(TestUtil.GetAllSet()); - } - writer.Flush(); - - stream.Position = 0; - - int count = 0; - foreach (var message in MessageStreamIterator.FromStreamProvider(() => stream) - .WithSizeLimit(CodedInputStream.BufferSize*2)) - { - count++; - TestUtil.AssertAllFieldsSet(message); - } - Assert.AreEqual(correctCount, count); - } - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/MessageStreamWriterTest.cs b/csharp/src/ProtocolBuffers.Test/MessageStreamWriterTest.cs deleted file mode 100644 index 030804ee..00000000 --- a/csharp/src/ProtocolBuffers.Test/MessageStreamWriterTest.cs +++ /dev/null @@ -1,78 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System.IO; -using NUnit.Framework; -using NestedMessage = Google.ProtocolBuffers.TestProtos.TestAllTypes.Types.NestedMessage; - -namespace Google.ProtocolBuffers -{ - public class MessageStreamWriterTest - { - internal static readonly byte[] ThreeMessageData = new byte[] - { - (1 << 3) | 2, 2, - // Field 1, 2 bytes long (first message) - (1 << 3) | 0, 5, // Field 1, value 5 - (1 << 3) | 2, 3, - // Field 1, 3 bytes long (second message) - (1 << 3) | 0, (1500 & 0x7f) | 0x80, 1500 >> 7, - // Field 1, value 1500 - (1 << 3) | 2, 0, // Field 1, no data (third message) - }; - - [Test] - public void ThreeMessages() - { - NestedMessage message1 = new NestedMessage.Builder {Bb = 5}.Build(); - NestedMessage message2 = new NestedMessage.Builder {Bb = 1500}.Build(); - NestedMessage message3 = new NestedMessage.Builder().Build(); - - byte[] data; - using (MemoryStream stream = new MemoryStream()) - { - MessageStreamWriter writer = new MessageStreamWriter(stream); - writer.Write(message1); - writer.Write(message2); - writer.Write(message3); - writer.Flush(); - data = stream.ToArray(); - } - - TestUtil.AssertEqualBytes(ThreeMessageData, data); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/MessageTest.cs b/csharp/src/ProtocolBuffers.Test/MessageTest.cs deleted file mode 100644 index e746c01a..00000000 --- a/csharp/src/ProtocolBuffers.Test/MessageTest.cs +++ /dev/null @@ -1,344 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System.IO; -using Google.ProtocolBuffers.Descriptors; -using Google.ProtocolBuffers.TestProtos; -using NUnit.Framework; - -namespace Google.ProtocolBuffers -{ - /// - /// Miscellaneous tests for message operations that apply to both - /// generated and dynamic messages. - /// - public class MessageTest - { - // ================================================================= - // Message-merging tests. - - private static readonly TestAllTypes MergeSource = new TestAllTypes.Builder - { - OptionalInt32 = 1, - OptionalString = "foo", - OptionalForeignMessage = - ForeignMessage.DefaultInstance, - }.AddRepeatedString("bar").Build(); - - private static readonly TestAllTypes MergeDest = new TestAllTypes.Builder - { - OptionalInt64 = 2, - OptionalString = "baz", - OptionalForeignMessage = - new ForeignMessage.Builder {C = 3}.Build(), - }.AddRepeatedString("qux").Build(); - - private const string MergeResultText = - "optional_int32: 1\n" + - "optional_int64: 2\n" + - "optional_string: \"foo\"\n" + - "optional_foreign_message {\n" + - " c: 3\n" + - "}\n" + - "repeated_string: \"qux\"\n" + - "repeated_string: \"bar\"\n"; - - [Test] - public void MergeFrom() - { - TestAllTypes result = TestAllTypes.CreateBuilder(MergeDest).MergeFrom(MergeSource).Build(); - - Assert.AreEqual(MergeResultText, result.ToString()); - } - - /// - /// Test merging a DynamicMessage into a GeneratedMessage. - /// As long as they have the same descriptor, this should work, but it is an - /// entirely different code path. - /// - [Test] - public void MergeFromDynamic() - { - TestAllTypes result = (TestAllTypes) TestAllTypes.CreateBuilder(MergeDest) - .MergeFrom(DynamicMessage.CreateBuilder(MergeSource).Build()) - .Build(); - - Assert.AreEqual(MergeResultText, result.ToString()); - } - - /// - /// Test merging two DynamicMessages. - /// - [Test] - public void DynamicMergeFrom() - { - DynamicMessage result = (DynamicMessage) DynamicMessage.CreateBuilder(MergeDest) - .MergeFrom( - (DynamicMessage) - DynamicMessage.CreateBuilder(MergeSource).Build()) - .Build(); - - Assert.AreEqual(MergeResultText, result.ToString()); - } - - // ================================================================= - // Required-field-related tests. - - private static readonly TestRequired TestRequiredUninitialized = TestRequired.DefaultInstance; - - private static readonly TestRequired TestRequiredInitialized = new TestRequired.Builder - { - A = 1, - B = 2, - C = 3 - }.Build(); - - [Test] - public void Initialization() - { - TestRequired.Builder builder = TestRequired.CreateBuilder(); - - Assert.IsFalse(builder.IsInitialized); - builder.A = 1; - Assert.IsFalse(builder.IsInitialized); - builder.B = 1; - Assert.IsFalse(builder.IsInitialized); - builder.C = 1; - Assert.IsTrue(builder.IsInitialized); - } - - [Test] - public void UninitializedBuilderToString() - { - TestRequired.Builder builder = TestRequired.CreateBuilder().SetA(1); - Assert.AreEqual("a: 1\n", builder.ToString()); - } - - [Test] - public void RequiredForeign() - { - TestRequiredForeign.Builder builder = TestRequiredForeign.CreateBuilder(); - - Assert.IsTrue(builder.IsInitialized); - - builder.SetOptionalMessage(TestRequiredUninitialized); - Assert.IsFalse(builder.IsInitialized); - - builder.SetOptionalMessage(TestRequiredInitialized); - Assert.IsTrue(builder.IsInitialized); - - builder.AddRepeatedMessage(TestRequiredUninitialized); - Assert.IsFalse(builder.IsInitialized); - - builder.SetRepeatedMessage(0, TestRequiredInitialized); - Assert.IsTrue(builder.IsInitialized); - } - - [Test] - public void RequiredExtension() - { - TestAllExtensions.Builder builder = TestAllExtensions.CreateBuilder(); - - Assert.IsTrue(builder.IsInitialized); - - builder.SetExtension(TestRequired.Single, TestRequiredUninitialized); - Assert.IsFalse(builder.IsInitialized); - - builder.SetExtension(TestRequired.Single, TestRequiredInitialized); - Assert.IsTrue(builder.IsInitialized); - - builder.AddExtension(TestRequired.Multi, TestRequiredUninitialized); - Assert.IsFalse(builder.IsInitialized); - - builder.SetExtension(TestRequired.Multi, 0, TestRequiredInitialized); - Assert.IsTrue(builder.IsInitialized); - } - - [Test] - public void RequiredDynamic() - { - MessageDescriptor descriptor = TestRequired.Descriptor; - DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor); - - Assert.IsFalse(builder.IsInitialized); - builder[descriptor.FindDescriptor("a")] = 1; - Assert.IsFalse(builder.IsInitialized); - builder[descriptor.FindDescriptor("b")] = 1; - Assert.IsFalse(builder.IsInitialized); - builder[descriptor.FindDescriptor("c")] = 1; - Assert.IsTrue(builder.IsInitialized); - } - - [Test] - public void RequiredDynamicForeign() - { - MessageDescriptor descriptor = TestRequiredForeign.Descriptor; - DynamicMessage.Builder builder = DynamicMessage.CreateBuilder(descriptor); - - Assert.IsTrue(builder.IsInitialized); - - builder[descriptor.FindDescriptor("optional_message")] = TestRequiredUninitialized; - Assert.IsFalse(builder.IsInitialized); - - builder[descriptor.FindDescriptor("optional_message")] = TestRequiredInitialized; - Assert.IsTrue(builder.IsInitialized); - - builder.AddRepeatedField(descriptor.FindDescriptor("repeated_message"), - TestRequiredUninitialized); - Assert.IsFalse(builder.IsInitialized); - - builder.SetRepeatedField(descriptor.FindDescriptor("repeated_message"), 0, - TestRequiredInitialized); - Assert.IsTrue(builder.IsInitialized); - } - - [Test] - public void UninitializedException() - { - var e = Assert.Throws(() => TestRequired.CreateBuilder().Build()); - Assert.AreEqual("Message missing required fields: a, b, c", e.Message); - } - - [Test] - public void BuildPartial() - { - // We're mostly testing that no exception is thrown. - TestRequired message = TestRequired.CreateBuilder().BuildPartial(); - Assert.IsFalse(message.IsInitialized); - } - - [Test] - public void NestedUninitializedException() - { - var e = Assert.Throws(() => TestRequiredForeign.CreateBuilder() - .SetOptionalMessage(TestRequiredUninitialized) - .AddRepeatedMessage(TestRequiredUninitialized) - .AddRepeatedMessage(TestRequiredUninitialized) - .Build()); - Assert.AreEqual( - "Message missing required fields: " + - "optional_message.a, " + - "optional_message.b, " + - "optional_message.c, " + - "repeated_message[0].a, " + - "repeated_message[0].b, " + - "repeated_message[0].c, " + - "repeated_message[1].a, " + - "repeated_message[1].b, " + - "repeated_message[1].c", - e.Message); - } - - [Test] - public void BuildNestedPartial() - { - // We're mostly testing that no exception is thrown. - TestRequiredForeign message = - TestRequiredForeign.CreateBuilder() - .SetOptionalMessage(TestRequiredUninitialized) - .AddRepeatedMessage(TestRequiredUninitialized) - .AddRepeatedMessage(TestRequiredUninitialized) - .BuildPartial(); - Assert.IsFalse(message.IsInitialized); - } - - [Test] - public void ParseUninitialized() - { - var e = Assert.Throws(() => TestRequired.ParseFrom(ByteString.Empty)); - Assert.AreEqual("Message missing required fields: a, b, c", e.Message); - } - - [Test] - public void ParseNestedUnititialized() - { - ByteString data = - TestRequiredForeign.CreateBuilder() - .SetOptionalMessage(TestRequiredUninitialized) - .AddRepeatedMessage(TestRequiredUninitialized) - .AddRepeatedMessage(TestRequiredUninitialized) - .BuildPartial().ToByteString(); - - var e = Assert.Throws(() => TestRequiredForeign.ParseFrom(data)); - Assert.AreEqual( - "Message missing required fields: " + - "optional_message.a, " + - "optional_message.b, " + - "optional_message.c, " + - "repeated_message[0].a, " + - "repeated_message[0].b, " + - "repeated_message[0].c, " + - "repeated_message[1].a, " + - "repeated_message[1].b, " + - "repeated_message[1].c", - e.Message); - } - - [Test] - public void DynamicUninitializedException() - { - var e = Assert.Throws(() => DynamicMessage.CreateBuilder(TestRequired.Descriptor).Build()); - Assert.AreEqual("Message missing required fields: a, b, c", e.Message); - } - - [Test] - public void DynamicBuildPartial() - { - // We're mostly testing that no exception is thrown. - DynamicMessage message = DynamicMessage.CreateBuilder(TestRequired.Descriptor).BuildPartial(); - Assert.IsFalse(message.Initialized); - } - - [Test] - public void DynamicParseUnititialized() - { - MessageDescriptor descriptor = TestRequired.Descriptor; - var e = Assert.Throws(() => DynamicMessage.ParseFrom(descriptor, ByteString.Empty)); - Assert.AreEqual("Message missing required fields: a, b, c", e.Message); - } - - [Test] - public void PackedTypesWrittenDirectlyToStream() - { - TestPackedTypes message = new TestPackedTypes.Builder {PackedInt32List = {0, 1, 2}}.Build(); - MemoryStream stream = new MemoryStream(); - message.WriteTo(stream); - stream.Position = 0; - TestPackedTypes readMessage = TestPackedTypes.ParseFrom(stream); - Assert.AreEqual(message, readMessage); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/MessageUtilTest.cs b/csharp/src/ProtocolBuffers.Test/MessageUtilTest.cs deleted file mode 100644 index 72909660..00000000 --- a/csharp/src/ProtocolBuffers.Test/MessageUtilTest.cs +++ /dev/null @@ -1,82 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using Google.ProtocolBuffers.TestProtos; -using NUnit.Framework; - -namespace Google.ProtocolBuffers -{ - public class MessageUtilTest - { - [Test] - public void NullTypeName() - { - Assert.Throws(() => MessageUtil.GetDefaultMessage((string) null)); - } - - [Test] - public void InvalidTypeName() - { - Assert.Throws(() => MessageUtil.GetDefaultMessage("invalidtypename")); - } - - [Test] - public void ValidTypeName() - { - Assert.AreSame(TestAllTypes.DefaultInstance, - MessageUtil.GetDefaultMessage(typeof(TestAllTypes).AssemblyQualifiedName)); - } - - [Test] - public void NullType() - { - Assert.Throws(() => MessageUtil.GetDefaultMessage((Type)null)); - } - - [Test] - public void NonMessageType() - { - Assert.Throws(() => MessageUtil.GetDefaultMessage(typeof(string))); - } - - [Test] - public void ValidType() - { - Assert.AreSame(TestAllTypes.DefaultInstance, MessageUtil.GetDefaultMessage(typeof(TestAllTypes))); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/NameHelpersTest.cs b/csharp/src/ProtocolBuffers.Test/NameHelpersTest.cs deleted file mode 100644 index edd3ccd9..00000000 --- a/csharp/src/ProtocolBuffers.Test/NameHelpersTest.cs +++ /dev/null @@ -1,81 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using NUnit.Framework; - -namespace Google.ProtocolBuffers -{ - public class NameHelpersTest - { - [Test] - public void UnderscoresToPascalCase() - { - Assert.AreEqual("FooBar", NameHelpers.UnderscoresToPascalCase("Foo_bar")); - Assert.AreEqual("FooBar", NameHelpers.UnderscoresToPascalCase("foo_bar")); - Assert.AreEqual("Foo0Bar", NameHelpers.UnderscoresToPascalCase("Foo0bar")); - Assert.AreEqual("FooBar", NameHelpers.UnderscoresToPascalCase("Foo_+_Bar")); - - Assert.AreEqual("Bar", NameHelpers.UnderscoresToPascalCase("__+bar")); - Assert.AreEqual("Bar", NameHelpers.UnderscoresToPascalCase("bar_")); - Assert.AreEqual("_0Bar", NameHelpers.UnderscoresToPascalCase("_0bar")); - Assert.AreEqual("_1Bar", NameHelpers.UnderscoresToPascalCase("_1_bar")); - } - - [Test] - public void UnderscoresToCamelCase() - { - Assert.AreEqual("fooBar", NameHelpers.UnderscoresToCamelCase("Foo_bar")); - Assert.AreEqual("fooBar", NameHelpers.UnderscoresToCamelCase("foo_bar")); - Assert.AreEqual("foo0Bar", NameHelpers.UnderscoresToCamelCase("Foo0bar")); - Assert.AreEqual("fooBar", NameHelpers.UnderscoresToCamelCase("Foo_+_Bar")); - - Assert.AreEqual("bar", NameHelpers.UnderscoresToCamelCase("__+bar")); - Assert.AreEqual("bar", NameHelpers.UnderscoresToCamelCase("bar_")); - Assert.AreEqual("_0Bar", NameHelpers.UnderscoresToCamelCase("_0bar")); - Assert.AreEqual("_1Bar", NameHelpers.UnderscoresToCamelCase("_1_bar")); - } - - [Test] - public void StripSuffix() - { - string text = "FooBar"; - Assert.IsFalse(NameHelpers.StripSuffix(ref text, "Foo")); - Assert.AreEqual("FooBar", text); - Assert.IsTrue(NameHelpers.StripSuffix(ref text, "Bar")); - Assert.AreEqual("Foo", text); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj b/csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj index b4c562d1..31095a5b 100644 --- a/csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj +++ b/csharp/src/ProtocolBuffers.Test/ProtocolBuffers.Test.csproj @@ -8,8 +8,8 @@ {DD01ED24-3750-4567-9A23-1DB676A15610} Library Properties - Google.ProtocolBuffers - Google.ProtocolBuffers.Test + Google.Protobuf + Google.Protobuf.Test v4.5 512 true @@ -71,79 +71,37 @@ - - - - - - - - - - - - - - - - - - - + + + + - - - - - - + - - - - - - - - - - - - - - - - - - - {231391AF-449C-4a39-986C-AD7F270F4750} - ProtocolBuffers.Serialization - {6908BDCE-D925-43F3-94AC-A531E6DF2591} ProtocolBuffers - - - - + + + - + \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/SortedList.cs b/csharp/src/ProtocolBuffers/SortedList.cs deleted file mode 100644 index 2dd7da92..00000000 --- a/csharp/src/ProtocolBuffers/SortedList.cs +++ /dev/null @@ -1,167 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -#if NOSORTEDLIST -using System.Collections; -using System.Collections.Generic; - -namespace Google.ProtocolBuffers -{ - /// - /// Dictionary implementation which always yields keys in sorted order. - /// This is not particularly efficient: it wraps a normal dictionary - /// for most operations, but sorts by key when either iterating or - /// fetching the Keys/Values properties. - /// - internal sealed class SortedList : IDictionary - { - private readonly IDictionary wrapped = new Dictionary(); - - public SortedList() - { - } - - public SortedList(IDictionary dictionary) - { - foreach (KeyValuePair entry in dictionary) - { - Add(entry.Key, entry.Value); - } - } - - public void Add(TKey key, TValue value) - { - wrapped.Add(key, value); - } - - public bool ContainsKey(TKey key) - { - return wrapped.ContainsKey(key); - } - - public ICollection Keys - { - get - { - List keys = new List(wrapped.Count); - foreach (var pair in this) - { - keys.Add(pair.Key); - } - return keys; - } - } - - public bool Remove(TKey key) - { - return wrapped.Remove(key); - } - - public bool TryGetValue(TKey key, out TValue value) - { - return wrapped.TryGetValue(key, out value); - } - - public ICollection Values - { - get - { - List values = new List(wrapped.Count); - foreach (var pair in this) - { - values.Add(pair.Value); - } - return values; - } - } - - public TValue this[TKey key] - { - get { return wrapped[key]; } - set { wrapped[key] = value; } - } - - public void Add(KeyValuePair item) - { - wrapped.Add(item); - } - - public void Clear() - { - wrapped.Clear(); - } - - public bool Contains(KeyValuePair item) - { - return wrapped.Contains(item); - } - - public void CopyTo(KeyValuePair[] array, int arrayIndex) - { - wrapped.CopyTo(array, arrayIndex); - } - - public int Count - { - get { return wrapped.Count; } - } - - public bool IsReadOnly - { - get { return wrapped.IsReadOnly; } - } - - public bool Remove(KeyValuePair item) - { - return wrapped.Remove(item); - } - - public IEnumerator> GetEnumerator() - { - IComparer comparer = Comparer.Default; - var list = new List>(wrapped); - list.Sort((x, y) => comparer.Compare(x.Key, y.Key)); - return list.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} - -#endif \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/TextFormat.cs b/csharp/src/ProtocolBuffers/TextFormat.cs deleted file mode 100644 index 6a9180f3..00000000 --- a/csharp/src/ProtocolBuffers/TextFormat.cs +++ /dev/null @@ -1,893 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Text; -using Google.ProtocolBuffers.Descriptors; - -namespace Google.ProtocolBuffers -{ - /// - /// Provides ASCII text formatting support for messages. - /// TODO(jonskeet): Support for alternative line endings. - /// (Easy to print, via TextGenerator. Not sure about parsing.) - /// - public static class TextFormat - { - /// - /// Outputs a textual representation of the Protocol Message supplied into - /// the parameter output. - /// - public static void Print(IMessage message, TextWriter output) - { - TextGenerator generator = new TextGenerator(output, "\n"); - Print(message, generator); - } - - /// - /// Outputs a textual representation of the Protocol Message builder supplied into - /// the parameter output. - /// - public static void Print(IBuilder builder, TextWriter output) - { - TextGenerator generator = new TextGenerator(output, "\n"); - Print(builder, generator); - } - - /// - /// Outputs a textual representation of to . - /// - public static void Print(UnknownFieldSet fields, TextWriter output) - { - TextGenerator generator = new TextGenerator(output, "\n"); - PrintUnknownFields(fields, generator); - } - - public static string PrintToString(IMessage message) - { - StringWriter text = new StringWriter(); - Print(message, text); - return text.ToString(); - } - - public static string PrintToString(IBuilder builder) - { - StringWriter text = new StringWriter(); - Print(builder, text); - return text.ToString(); - } - - public static string PrintToString(UnknownFieldSet fields) - { - StringWriter text = new StringWriter(); - Print(fields, text); - return text.ToString(); - } - - private static void Print(IMessage message, TextGenerator generator) - { - foreach (KeyValuePair entry in message.AllFields) - { - PrintField(entry.Key, entry.Value, generator); - } - PrintUnknownFields(message.UnknownFields, generator); - } - - private static void Print(IBuilder message, TextGenerator generator) - { - foreach (KeyValuePair entry in message.AllFields) - { - PrintField(entry.Key, entry.Value, generator); - } - PrintUnknownFields(message.UnknownFields, generator); - } - - internal static void PrintField(FieldDescriptor field, object value, TextGenerator generator) - { - if (field.IsRepeated) - { - // Repeated field. Print each element. - foreach (object element in (IEnumerable) value) - { - PrintSingleField(field, element, generator); - } - } - else - { - PrintSingleField(field, value, generator); - } - } - - private static void PrintSingleField(FieldDescriptor field, Object value, TextGenerator generator) - { - if (field.IsExtension) - { - generator.Print("["); - // We special-case MessageSet elements for compatibility with proto1. - if (field.ContainingType.Options.MessageSetWireFormat - && field.FieldType == FieldType.Message - && field.IsOptional - // object equality (TODO(jonskeet): Work out what this comment means!) - && field.ExtensionScope == field.MessageType) - { - generator.Print(field.MessageType.FullName); - } - else - { - generator.Print(field.FullName); - } - generator.Print("]"); - } - else - { - if (field.FieldType == FieldType.Group) - { - // Groups must be serialized with their original capitalization. - generator.Print(field.MessageType.Name); - } - else - { - generator.Print(field.Name); - } - } - - if (field.MappedType == MappedType.Message) - { - generator.Print(" {\n"); - generator.Indent(); - } - else - { - generator.Print(": "); - } - - PrintFieldValue(field, value, generator); - - if (field.MappedType == MappedType.Message) - { - generator.Outdent(); - generator.Print("}"); - } - generator.Print("\n"); - } - - private static void PrintFieldValue(FieldDescriptor field, object value, TextGenerator generator) - { - switch (field.FieldType) - { - // The Float and Double types must specify the "r" format to preserve their precision, otherwise, - // the double to/from string will trim the precision to 6 places. As with other numeric formats - // below, always use the invariant culture so it's predictable. - case FieldType.Float: - generator.Print(((float)value).ToString("r", FrameworkPortability.InvariantCulture)); - break; - case FieldType.Double: - generator.Print(((double)value).ToString("r", FrameworkPortability.InvariantCulture)); - break; - - case FieldType.Int32: - case FieldType.Int64: - case FieldType.SInt32: - case FieldType.SInt64: - case FieldType.SFixed32: - case FieldType.SFixed64: - case FieldType.UInt32: - case FieldType.UInt64: - case FieldType.Fixed32: - case FieldType.Fixed64: - // The simple Object.ToString converts using the current culture. - // We want to always use the invariant culture so it's predictable. - generator.Print(((IConvertible)value).ToString(FrameworkPortability.InvariantCulture)); - break; - case FieldType.Bool: - // Explicitly use the Java true/false - generator.Print((bool) value ? "true" : "false"); - break; - - case FieldType.String: - generator.Print("\""); - generator.Print(EscapeText((string) value)); - generator.Print("\""); - break; - - case FieldType.Bytes: - { - generator.Print("\""); - generator.Print(EscapeBytes((ByteString) value)); - generator.Print("\""); - break; - } - - case FieldType.Enum: - { - if (value is IEnumLite && !(value is EnumValueDescriptor)) - { - throw new NotSupportedException("Lite enumerations are not supported."); - } - generator.Print(((EnumValueDescriptor) value).Name); - break; - } - - case FieldType.Message: - case FieldType.Group: - if (value is IMessageLite && !(value is IMessage)) - { - throw new NotSupportedException("Lite messages are not supported."); - } - Print((IMessage) value, generator); - break; - } - } - - private static void PrintUnknownFields(UnknownFieldSet unknownFields, TextGenerator generator) - { - foreach (KeyValuePair entry in unknownFields.FieldDictionary) - { - String prefix = entry.Key.ToString() + ": "; - UnknownField field = entry.Value; - - foreach (ulong value in field.VarintList) - { - generator.Print(prefix); - generator.Print(value.ToString()); - generator.Print("\n"); - } - foreach (uint value in field.Fixed32List) - { - generator.Print(prefix); - generator.Print(string.Format("0x{0:x8}", value)); - generator.Print("\n"); - } - foreach (ulong value in field.Fixed64List) - { - generator.Print(prefix); - generator.Print(string.Format("0x{0:x16}", value)); - generator.Print("\n"); - } - foreach (ByteString value in field.LengthDelimitedList) - { - generator.Print(entry.Key.ToString()); - generator.Print(": \""); - generator.Print(EscapeBytes(value)); - generator.Print("\"\n"); - } - foreach (UnknownFieldSet value in field.GroupList) - { - generator.Print(entry.Key.ToString()); - generator.Print(" {\n"); - generator.Indent(); - PrintUnknownFields(value, generator); - generator.Outdent(); - generator.Print("}\n"); - } - } - } - - public static ulong ParseUInt64(string text) - { - return (ulong) ParseInteger(text, false, true); - } - - public static long ParseInt64(string text) - { - return ParseInteger(text, true, true); - } - - public static uint ParseUInt32(string text) - { - return (uint) ParseInteger(text, false, false); - } - - public static int ParseInt32(string text) - { - return (int) ParseInteger(text, true, false); - } - - public static float ParseFloat(string text) - { - switch (text) - { - case "-inf": - case "-infinity": - case "-inff": - case "-infinityf": - return float.NegativeInfinity; - case "inf": - case "infinity": - case "inff": - case "infinityf": - return float.PositiveInfinity; - case "nan": - case "nanf": - return float.NaN; - default: - return float.Parse(text, FrameworkPortability.InvariantCulture); - } - } - - public static double ParseDouble(string text) - { - switch (text) - { - case "-inf": - case "-infinity": - return double.NegativeInfinity; - case "inf": - case "infinity": - return double.PositiveInfinity; - case "nan": - return double.NaN; - default: - return double.Parse(text, FrameworkPortability.InvariantCulture); - } - } - - /// - /// Parses an integer in hex (leading 0x), decimal (no prefix) or octal (leading 0). - /// Only a negative sign is permitted, and it must come before the radix indicator. - /// - private static long ParseInteger(string text, bool isSigned, bool isLong) - { - string original = text; - bool negative = false; - if (text.StartsWith("-")) - { - if (!isSigned) - { - throw new FormatException("Number must be positive: " + original); - } - negative = true; - text = text.Substring(1); - } - - int radix = 10; - if (text.StartsWith("0x")) - { - radix = 16; - text = text.Substring(2); - } - else if (text.StartsWith("0")) - { - radix = 8; - } - - ulong result; - try - { - // Workaround for https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=278448 - // We should be able to use Convert.ToUInt64 for all cases. - result = radix == 10 ? ulong.Parse(text) : Convert.ToUInt64(text, radix); - } - catch (OverflowException) - { - // Convert OverflowException to FormatException so there's a single exception type this method can throw. - string numberDescription = string.Format("{0}-bit {1}signed integer", isLong ? 64 : 32, - isSigned ? "" : "un"); - throw new FormatException("Number out of range for " + numberDescription + ": " + original); - } - - if (negative) - { - ulong max = isLong ? 0x8000000000000000UL : 0x80000000L; - if (result > max) - { - string numberDescription = string.Format("{0}-bit signed integer", isLong ? 64 : 32); - throw new FormatException("Number out of range for " + numberDescription + ": " + original); - } - return -((long) result); - } - else - { - ulong max = isSigned - ? (isLong ? (ulong) long.MaxValue : int.MaxValue) - : (isLong ? ulong.MaxValue : uint.MaxValue); - if (result > max) - { - string numberDescription = string.Format("{0}-bit {1}signed integer", isLong ? 64 : 32, - isSigned ? "" : "un"); - throw new FormatException("Number out of range for " + numberDescription + ": " + original); - } - return (long) result; - } - } - - /// - /// Tests a character to see if it's an octal digit. - /// - private static bool IsOctal(char c) - { - return '0' <= c && c <= '7'; - } - - /// - /// Tests a character to see if it's a hex digit. - /// - private static bool IsHex(char c) - { - return ('0' <= c && c <= '9') || - ('a' <= c && c <= 'f') || - ('A' <= c && c <= 'F'); - } - - /// - /// Interprets a character as a digit (in any base up to 36) and returns the - /// numeric value. - /// - private static int ParseDigit(char c) - { - if ('0' <= c && c <= '9') - { - return c - '0'; - } - else if ('a' <= c && c <= 'z') - { - return c - 'a' + 10; - } - else - { - return c - 'A' + 10; - } - } - - /// - /// Unescapes a text string as escaped using . - /// Two-digit hex escapes (starting with "\x" are also recognised. - /// - public static string UnescapeText(string input) - { - return UnescapeBytes(input).ToStringUtf8(); - } - - /// - /// Like but escapes a text string. - /// The string is first encoded as UTF-8, then each byte escaped individually. - /// The returned value is guaranteed to be entirely ASCII. - /// - public static string EscapeText(string input) - { - return EscapeBytes(ByteString.CopyFromUtf8(input)); - } - - /// - /// Escapes bytes in the format used in protocol buffer text format, which - /// is the same as the format used for C string literals. All bytes - /// that are not printable 7-bit ASCII characters are escaped, as well as - /// backslash, single-quote, and double-quote characters. Characters for - /// which no defined short-hand escape sequence is defined will be escaped - /// using 3-digit octal sequences. - /// The returned value is guaranteed to be entirely ASCII. - /// - public static String EscapeBytes(ByteString input) - { - StringBuilder builder = new StringBuilder(input.Length); - foreach (byte b in input) - { - switch (b) - { - // C# does not use \a or \v - case 0x07: - builder.Append("\\a"); - break; - case (byte) '\b': - builder.Append("\\b"); - break; - case (byte) '\f': - builder.Append("\\f"); - break; - case (byte) '\n': - builder.Append("\\n"); - break; - case (byte) '\r': - builder.Append("\\r"); - break; - case (byte) '\t': - builder.Append("\\t"); - break; - case 0x0b: - builder.Append("\\v"); - break; - case (byte) '\\': - builder.Append("\\\\"); - break; - case (byte) '\'': - builder.Append("\\\'"); - break; - case (byte) '"': - builder.Append("\\\""); - break; - default: - if (b >= 0x20 && b < 128) - { - builder.Append((char) b); - } - else - { - builder.Append('\\'); - builder.Append((char) ('0' + ((b >> 6) & 3))); - builder.Append((char) ('0' + ((b >> 3) & 7))); - builder.Append((char) ('0' + (b & 7))); - } - break; - } - } - return builder.ToString(); - } - - /// - /// Performs string unescaping from C style (octal, hex, form feeds, tab etc) into a byte string. - /// - public static ByteString UnescapeBytes(string input) - { - byte[] result = new byte[input.Length]; - int pos = 0; - for (int i = 0; i < input.Length; i++) - { - char c = input[i]; - if (c > 127 || c < 32) - { - throw new FormatException("Escaped string must only contain ASCII"); - } - if (c != '\\') - { - result[pos++] = (byte) c; - continue; - } - if (i + 1 >= input.Length) - { - throw new FormatException("Invalid escape sequence: '\\' at end of string."); - } - - i++; - c = input[i]; - if (c >= '0' && c <= '7') - { - // Octal escape. - int code = ParseDigit(c); - if (i + 1 < input.Length && IsOctal(input[i + 1])) - { - i++; - code = code*8 + ParseDigit(input[i]); - } - if (i + 1 < input.Length && IsOctal(input[i + 1])) - { - i++; - code = code*8 + ParseDigit(input[i]); - } - result[pos++] = (byte) code; - } - else - { - switch (c) - { - case 'a': - result[pos++] = 0x07; - break; - case 'b': - result[pos++] = (byte) '\b'; - break; - case 'f': - result[pos++] = (byte) '\f'; - break; - case 'n': - result[pos++] = (byte) '\n'; - break; - case 'r': - result[pos++] = (byte) '\r'; - break; - case 't': - result[pos++] = (byte) '\t'; - break; - case 'v': - result[pos++] = 0x0b; - break; - case '\\': - result[pos++] = (byte) '\\'; - break; - case '\'': - result[pos++] = (byte) '\''; - break; - case '"': - result[pos++] = (byte) '\"'; - break; - - case 'x': - // hex escape - int code; - if (i + 1 < input.Length && IsHex(input[i + 1])) - { - i++; - code = ParseDigit(input[i]); - } - else - { - throw new FormatException("Invalid escape sequence: '\\x' with no digits"); - } - if (i + 1 < input.Length && IsHex(input[i + 1])) - { - ++i; - code = code*16 + ParseDigit(input[i]); - } - result[pos++] = (byte) code; - break; - - default: - throw new FormatException("Invalid escape sequence: '\\" + c + "'"); - } - } - } - - return ByteString.CopyFrom(result, 0, pos); - } - - public static void Merge(string text, IBuilder builder) - { - Merge(text, ExtensionRegistry.Empty, builder); - } - - public static void Merge(TextReader reader, IBuilder builder) - { - Merge(reader, ExtensionRegistry.Empty, builder); - } - - public static void Merge(TextReader reader, ExtensionRegistry registry, IBuilder builder) - { - Merge(reader.ReadToEnd(), registry, builder); - } - - public static void Merge(string text, ExtensionRegistry registry, IBuilder builder) - { - TextTokenizer tokenizer = new TextTokenizer(text); - - while (!tokenizer.AtEnd) - { - MergeField(tokenizer, registry, builder); - } - } - - /// - /// Parses a single field from the specified tokenizer and merges it into - /// the builder. - /// - private static void MergeField(TextTokenizer tokenizer, ExtensionRegistry extensionRegistry, - IBuilder builder) - { - FieldDescriptor field; - MessageDescriptor type = builder.DescriptorForType; - ExtensionInfo extension = null; - - if (tokenizer.TryConsume("[")) - { - // An extension. - StringBuilder name = new StringBuilder(tokenizer.ConsumeIdentifier()); - while (tokenizer.TryConsume(".")) - { - name.Append("."); - name.Append(tokenizer.ConsumeIdentifier()); - } - - extension = extensionRegistry.FindByName(type, name.ToString()); - - if (extension == null) - { - throw tokenizer.CreateFormatExceptionPreviousToken("Extension \"" + name + - "\" not found in the ExtensionRegistry."); - } - else if (extension.Descriptor.ContainingType != type) - { - throw tokenizer.CreateFormatExceptionPreviousToken("Extension \"" + name + - "\" does not extend message type \"" + - type.FullName + "\"."); - } - - tokenizer.Consume("]"); - - field = extension.Descriptor; - } - else - { - String name = tokenizer.ConsumeIdentifier(); - field = type.FindDescriptor(name); - - // Group names are expected to be capitalized as they appear in the - // .proto file, which actually matches their type names, not their field - // names. - if (field == null) - { - // Explicitly specify the invariant culture so that this code does not break when - // executing in Turkey. - String lowerName = name.ToLowerInvariant(); - field = type.FindDescriptor(lowerName); - // If the case-insensitive match worked but the field is NOT a group, - // TODO(jonskeet): What? Java comment ends here! - if (field != null && field.FieldType != FieldType.Group) - { - field = null; - } - } - // Again, special-case group names as described above. - if (field != null && field.FieldType == FieldType.Group && field.MessageType.Name != name) - { - field = null; - } - - if (field == null) - { - throw tokenizer.CreateFormatExceptionPreviousToken( - "Message type \"" + type.FullName + "\" has no field named \"" + name + "\"."); - } - } - - object value = null; - - if (field.MappedType == MappedType.Message) - { - tokenizer.TryConsume(":"); // optional - - String endToken; - if (tokenizer.TryConsume("<")) - { - endToken = ">"; - } - else - { - tokenizer.Consume("{"); - endToken = "}"; - } - - IBuilder subBuilder; - if (extension == null) - { - subBuilder = builder.CreateBuilderForField(field); - } - else - { - subBuilder = extension.DefaultInstance.WeakCreateBuilderForType() as IBuilder; - if (subBuilder == null) - { - throw new NotSupportedException("Lite messages are not supported."); - } - } - - while (!tokenizer.TryConsume(endToken)) - { - if (tokenizer.AtEnd) - { - throw tokenizer.CreateFormatException("Expected \"" + endToken + "\"."); - } - MergeField(tokenizer, extensionRegistry, subBuilder); - } - - value = subBuilder.WeakBuild(); - } - else - { - tokenizer.Consume(":"); - - switch (field.FieldType) - { - case FieldType.Int32: - case FieldType.SInt32: - case FieldType.SFixed32: - value = tokenizer.ConsumeInt32(); - break; - - case FieldType.Int64: - case FieldType.SInt64: - case FieldType.SFixed64: - value = tokenizer.ConsumeInt64(); - break; - - case FieldType.UInt32: - case FieldType.Fixed32: - value = tokenizer.ConsumeUInt32(); - break; - - case FieldType.UInt64: - case FieldType.Fixed64: - value = tokenizer.ConsumeUInt64(); - break; - - case FieldType.Float: - value = tokenizer.ConsumeFloat(); - break; - - case FieldType.Double: - value = tokenizer.ConsumeDouble(); - break; - - case FieldType.Bool: - value = tokenizer.ConsumeBoolean(); - break; - - case FieldType.String: - value = tokenizer.ConsumeString(); - break; - - case FieldType.Bytes: - value = tokenizer.ConsumeByteString(); - break; - - case FieldType.Enum: - { - EnumDescriptor enumType = field.EnumType; - - if (tokenizer.LookingAtInteger()) - { - int number = tokenizer.ConsumeInt32(); - value = enumType.FindValueByNumber(number); - if (value == null) - { - throw tokenizer.CreateFormatExceptionPreviousToken( - "Enum type \"" + enumType.FullName + - "\" has no value with number " + number + "."); - } - } - else - { - String id = tokenizer.ConsumeIdentifier(); - value = enumType.FindValueByName(id); - if (value == null) - { - throw tokenizer.CreateFormatExceptionPreviousToken( - "Enum type \"" + enumType.FullName + - "\" has no value named \"" + id + "\"."); - } - } - - break; - } - - case FieldType.Message: - case FieldType.Group: - throw new InvalidOperationException("Can't get here."); - } - } - - if (field.IsRepeated) - { - builder.WeakAddRepeatedField(field, value); - } - else - { - builder.SetField(field, value); - } - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/TextGenerator.cs b/csharp/src/ProtocolBuffers/TextGenerator.cs index 30cbf0fd..80910ba1 100644 --- a/csharp/src/ProtocolBuffers/TextGenerator.cs +++ b/csharp/src/ProtocolBuffers/TextGenerator.cs @@ -38,7 +38,7 @@ using System; using System.IO; using System.Text; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { /// /// Helper class to control indentation. Used for TextFormat and by ProtoGen. diff --git a/csharp/src/ProtocolBuffers/TextTokenizer.cs b/csharp/src/ProtocolBuffers/TextTokenizer.cs deleted file mode 100644 index 5bb27fd0..00000000 --- a/csharp/src/ProtocolBuffers/TextTokenizer.cs +++ /dev/null @@ -1,501 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Globalization; -using System.Text.RegularExpressions; - -namespace Google.ProtocolBuffers -{ - /// - /// Represents a stream of tokens parsed from a string. - /// - internal sealed class TextTokenizer - { - private readonly string text; - private string currentToken; - - /// - /// The character index within the text to perform the next regex match at. - /// - private int matchPos = 0; - - /// - /// The character index within the text at which the current token begins. - /// - private int pos = 0; - - /// - /// The line number of the current token. - /// - private int line = 0; - - /// - /// The column number of the current token. - /// - private int column = 0; - - /// - /// The line number of the previous token. - /// - private int previousLine = 0; - - /// - /// The column number of the previous token. - /// - private int previousColumn = 0; - - // Note: atomic groups used to mimic possessive quantifiers in Java in both of these regexes - internal static readonly Regex WhitespaceAndCommentPattern = new Regex("\\G(?>(\\s|(#.*$))+)", - FrameworkPortability. - CompiledRegexWhereAvailable | - RegexOptions.Multiline); - - private static readonly Regex TokenPattern = new Regex( - "\\G[a-zA-Z_](?>[0-9a-zA-Z_+-]*)|" + // an identifier - "\\G[0-9+-](?>[0-9a-zA-Z_.+-]*)|" + // a number - "\\G\"(?>([^\"\\\n\\\\]|\\\\.)*)(\"|\\\\?$)|" + // a double-quoted string - "\\G\'(?>([^\"\\\n\\\\]|\\\\.)*)(\'|\\\\?$)", // a single-quoted string - FrameworkPortability.CompiledRegexWhereAvailable | RegexOptions.Multiline); - - private static readonly Regex DoubleInfinity = new Regex("^-?inf(inity)?$", - FrameworkPortability.CompiledRegexWhereAvailable | - RegexOptions.IgnoreCase); - - private static readonly Regex FloatInfinity = new Regex("^-?inf(inity)?f?$", - FrameworkPortability.CompiledRegexWhereAvailable | - RegexOptions.IgnoreCase); - - private static readonly Regex FloatNan = new Regex("^nanf?$", - FrameworkPortability.CompiledRegexWhereAvailable | - RegexOptions.IgnoreCase); - - /** Construct a tokenizer that parses tokens from the given text. */ - - public TextTokenizer(string text) - { - this.text = text; - SkipWhitespace(); - NextToken(); - } - - /// - /// Are we at the end of the input? - /// - public bool AtEnd - { - get { return currentToken.Length == 0; } - } - - /// - /// Advances to the next token. - /// - public void NextToken() - { - previousLine = line; - previousColumn = column; - - // Advance the line counter to the current position. - while (pos < matchPos) - { - if (text[pos] == '\n') - { - ++line; - column = 0; - } - else - { - ++column; - } - ++pos; - } - - // Match the next token. - if (matchPos == text.Length) - { - // EOF - currentToken = ""; - } - else - { - Match match = TokenPattern.Match(text, matchPos); - if (match.Success) - { - currentToken = match.Value; - matchPos += match.Length; - } - else - { - // Take one character. - currentToken = text[matchPos].ToString(); - matchPos++; - } - - SkipWhitespace(); - } - } - - /// - /// Skip over any whitespace so that matchPos starts at the next token. - /// - private void SkipWhitespace() - { - Match match = WhitespaceAndCommentPattern.Match(text, matchPos); - if (match.Success) - { - matchPos += match.Length; - } - } - - /// - /// If the next token exactly matches the given token, consume it and return - /// true. Otherwise, return false without doing anything. - /// - public bool TryConsume(string token) - { - if (currentToken == token) - { - NextToken(); - return true; - } - return false; - } - - /* - * If the next token exactly matches {@code token}, consume it. Otherwise, - * throw a {@link ParseException}. - */ - - /// - /// If the next token exactly matches the specified one, consume it. - /// Otherwise, throw a FormatException. - /// - /// - public void Consume(string token) - { - if (!TryConsume(token)) - { - throw CreateFormatException("Expected \"" + token + "\"."); - } - } - - /// - /// Returns true if the next token is an integer, but does not consume it. - /// - public bool LookingAtInteger() - { - if (currentToken.Length == 0) - { - return false; - } - - char c = currentToken[0]; - return ('0' <= c && c <= '9') || c == '-' || c == '+'; - } - - /// - /// If the next token is an identifier, consume it and return its value. - /// Otherwise, throw a FormatException. - /// - public string ConsumeIdentifier() - { - foreach (char c in currentToken) - { - if (('a' <= c && c <= 'z') || - ('A' <= c && c <= 'Z') || - ('0' <= c && c <= '9') || - (c == '_') || (c == '.')) - { - // OK - } - else - { - throw CreateFormatException("Expected identifier."); - } - } - - string result = currentToken; - NextToken(); - return result; - } - - /// - /// If the next token is a 32-bit signed integer, consume it and return its - /// value. Otherwise, throw a FormatException. - /// - public int ConsumeInt32() - { - try - { - int result = TextFormat.ParseInt32(currentToken); - NextToken(); - return result; - } - catch (FormatException e) - { - throw CreateIntegerParseException(e); - } - } - - /// - /// If the next token is a 32-bit unsigned integer, consume it and return its - /// value. Otherwise, throw a FormatException. - /// - public uint ConsumeUInt32() - { - try - { - uint result = TextFormat.ParseUInt32(currentToken); - NextToken(); - return result; - } - catch (FormatException e) - { - throw CreateIntegerParseException(e); - } - } - - /// - /// If the next token is a 64-bit signed integer, consume it and return its - /// value. Otherwise, throw a FormatException. - /// - public long ConsumeInt64() - { - try - { - long result = TextFormat.ParseInt64(currentToken); - NextToken(); - return result; - } - catch (FormatException e) - { - throw CreateIntegerParseException(e); - } - } - - /// - /// If the next token is a 64-bit unsigned integer, consume it and return its - /// value. Otherwise, throw a FormatException. - /// - public ulong ConsumeUInt64() - { - try - { - ulong result = TextFormat.ParseUInt64(currentToken); - NextToken(); - return result; - } - catch (FormatException e) - { - throw CreateIntegerParseException(e); - } - } - - /// - /// If the next token is a double, consume it and return its value. - /// Otherwise, throw a FormatException. - /// - public double ConsumeDouble() - { - // We need to parse infinity and nan separately because - // double.Parse() does not accept "inf", "infinity", or "nan". - if (DoubleInfinity.IsMatch(currentToken)) - { - bool negative = currentToken.StartsWith("-"); - NextToken(); - return negative ? double.NegativeInfinity : double.PositiveInfinity; - } - if (currentToken.Equals("nan", StringComparison.OrdinalIgnoreCase)) - { - NextToken(); - return Double.NaN; - } - - try - { - double result = double.Parse(currentToken, FrameworkPortability.InvariantCulture); - NextToken(); - return result; - } - catch (FormatException e) - { - throw CreateFloatParseException(e); - } - catch (OverflowException e) - { - throw CreateFloatParseException(e); - } - } - - /// - /// If the next token is a float, consume it and return its value. - /// Otherwise, throw a FormatException. - /// - public float ConsumeFloat() - { - // We need to parse infinity and nan separately because - // Float.parseFloat() does not accept "inf", "infinity", or "nan". - if (FloatInfinity.IsMatch(currentToken)) - { - bool negative = currentToken.StartsWith("-"); - NextToken(); - return negative ? float.NegativeInfinity : float.PositiveInfinity; - } - if (FloatNan.IsMatch(currentToken)) - { - NextToken(); - return float.NaN; - } - - if (currentToken.EndsWith("f")) - { - currentToken = currentToken.TrimEnd('f'); - } - - try - { - float result = float.Parse(currentToken, FrameworkPortability.InvariantCulture); - NextToken(); - return result; - } - catch (FormatException e) - { - throw CreateFloatParseException(e); - } - catch (OverflowException e) - { - throw CreateFloatParseException(e); - } - } - - /// - /// If the next token is a Boolean, consume it and return its value. - /// Otherwise, throw a FormatException. - /// - public bool ConsumeBoolean() - { - if (currentToken == "true") - { - NextToken(); - return true; - } - if (currentToken == "false") - { - NextToken(); - return false; - } - throw CreateFormatException("Expected \"true\" or \"false\"."); - } - - /// - /// If the next token is a string, consume it and return its (unescaped) value. - /// Otherwise, throw a FormatException. - /// - public string ConsumeString() - { - return ConsumeByteString().ToStringUtf8(); - } - - /// - /// If the next token is a string, consume it, unescape it as a - /// ByteString and return it. Otherwise, throw a FormatException. - /// - public ByteString ConsumeByteString() - { - char quote = currentToken.Length > 0 ? currentToken[0] : '\0'; - if (quote != '\"' && quote != '\'') - { - throw CreateFormatException("Expected string."); - } - - if (currentToken.Length < 2 || - currentToken[currentToken.Length - 1] != quote) - { - throw CreateFormatException("String missing ending quote."); - } - - try - { - string escaped = currentToken.Substring(1, currentToken.Length - 2); - ByteString result = TextFormat.UnescapeBytes(escaped); - NextToken(); - return result; - } - catch (FormatException e) - { - throw CreateFormatException(e.Message); - } - } - - /// - /// Returns a format exception with the current line and column numbers - /// in the description, suitable for throwing. - /// - public FormatException CreateFormatException(string description) - { - // Note: People generally prefer one-based line and column numbers. - return new FormatException((line + 1) + ":" + (column + 1) + ": " + description); - } - - /// - /// Returns a format exception with the line and column numbers of the - /// previous token in the description, suitable for throwing. - /// - public FormatException CreateFormatExceptionPreviousToken(string description) - { - // Note: People generally prefer one-based line and column numbers. - return new FormatException((previousLine + 1) + ":" + (previousColumn + 1) + ": " + description); - } - - /// - /// Constructs an appropriate FormatException for the given existing exception - /// when trying to parse an integer. - /// - private FormatException CreateIntegerParseException(FormatException e) - { - return CreateFormatException("Couldn't parse integer: " + e.Message); - } - - /// - /// Constructs an appropriate FormatException for the given existing exception - /// when trying to parse a float or double. - /// - private FormatException CreateFloatParseException(Exception e) - { - return CreateFormatException("Couldn't parse number: " + e.Message); - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/ThrowHelper.cs b/csharp/src/ProtocolBuffers/ThrowHelper.cs index 69e5f569..097b5032 100644 --- a/csharp/src/ProtocolBuffers/ThrowHelper.cs +++ b/csharp/src/ProtocolBuffers/ThrowHelper.cs @@ -37,7 +37,7 @@ using System; using System.Collections.Generic; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { /// /// Helper methods for throwing exceptions diff --git a/csharp/src/ProtocolBuffers/UninitializedMessageException.cs b/csharp/src/ProtocolBuffers/UninitializedMessageException.cs deleted file mode 100644 index 9e4f856e..00000000 --- a/csharp/src/ProtocolBuffers/UninitializedMessageException.cs +++ /dev/null @@ -1,208 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Text; - -#if !LITE -using Google.ProtocolBuffers.Collections; -using Google.ProtocolBuffers.Descriptors; - -#endif - -namespace Google.ProtocolBuffers -{ - /// - /// TODO(jonskeet): Write summary text. - /// - public sealed class UninitializedMessageException : Exception - { - private readonly IList missingFields; - - private UninitializedMessageException(IList missingFields) - : base(BuildDescription(missingFields)) - { - this.missingFields = new List(missingFields); - } - - /// - /// Returns a read-only list of human-readable names of - /// required fields missing from this message. Each name - /// is a full path to a field, e.g. "foo.bar[5].baz" - /// - public IList MissingFields - { - get { return missingFields; } - } - - /// - /// Converts this exception into an InvalidProtocolBufferException. - /// When a parsed message is missing required fields, this should be thrown - /// instead of UninitializedMessageException. - /// - public InvalidProtocolBufferException AsInvalidProtocolBufferException() - { - return new InvalidProtocolBufferException(Message); - } - - /// - /// Constructs the description string for a given list of missing fields. - /// - private static string BuildDescription(IEnumerable missingFields) - { - StringBuilder description = new StringBuilder("Message missing required fields: "); - bool first = true; - foreach (string field in missingFields) - { - if (first) - { - first = false; - } - else - { - description.Append(", "); - } - description.Append(field); - } - return description.ToString(); - } - - /// - /// For Lite exceptions that do not known how to enumerate missing fields - /// - public UninitializedMessageException(IMessageLite message) - : base(String.Format("Message {0} is missing required fields", message.GetType())) - { - missingFields = new List(); - } - -#if !LITE - public UninitializedMessageException(IMessage message) - : this(FindMissingFields(message)) - { - } - - /// - /// Returns a list of the full "paths" of missing required - /// fields in the specified message. - /// - private static IList FindMissingFields(IMessage message) - { - List results = new List(); - FindMissingFields(message, "", results); - return results; - } - - /// - /// Recursive helper implementing FindMissingFields. - /// - private static void FindMissingFields(IMessage message, String prefix, List results) - { - foreach (FieldDescriptor field in message.DescriptorForType.Fields) - { - if (field.IsRequired && !message.HasField(field)) - { - results.Add(prefix + field.Name); - } - } - - foreach (KeyValuePair entry in message.AllFields) - { - FieldDescriptor field = entry.Key; - object value = entry.Value; - - if (field.MappedType == MappedType.Message) - { - if (field.IsRepeated) - { - int i = 0; - foreach (object element in (IEnumerable) value) - { - if (element is IMessage) - { - FindMissingFields((IMessage) element, SubMessagePrefix(prefix, field, i++), results); - } - else - { - results.Add(prefix + field.Name); - } - } - } - else - { - if (message.HasField(field)) - { - if (value is IMessage) - { - FindMissingFields((IMessage) value, SubMessagePrefix(prefix, field, -1), results); - } - else - { - results.Add(prefix + field.Name); - } - } - } - } - } - } - - private static String SubMessagePrefix(String prefix, FieldDescriptor field, int index) - { - StringBuilder result = new StringBuilder(prefix); - if (field.IsExtension) - { - result.Append('(') - .Append(field.FullName) - .Append(')'); - } - else - { - result.Append(field.Name); - } - if (index != -1) - { - result.Append('[') - .Append(index) - .Append(']'); - } - result.Append('.'); - return result.ToString(); - } -#endif - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/UnknownField.cs b/csharp/src/ProtocolBuffers/UnknownField.cs deleted file mode 100644 index 7650b9df..00000000 --- a/csharp/src/ProtocolBuffers/UnknownField.cs +++ /dev/null @@ -1,415 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Google.ProtocolBuffers.Collections; - -namespace Google.ProtocolBuffers -{ - /// - /// Represents a single field in an UnknownFieldSet. - /// - /// An UnknownField consists of five lists of values. The lists correspond - /// to the five "wire types" used in the protocol buffer binary format. - /// The wire type of each field can be determined from the encoded form alone, - /// without knowing the field's declared type. So, we are able to parse - /// unknown values at least this far and separate them. Normally, only one - /// of the five lists will contain any values, since it is impossible to - /// define a valid message type that declares two different types for the - /// same field number. However, the code is designed to allow for the case - /// where the same unknown field number is encountered using multiple different - /// wire types. - /// - /// UnknownField is an immutable class. To construct one, you must use an - /// UnknownField.Builder. - /// - public sealed class UnknownField - { - public const string UnknownFieldName = "unknown_field"; - private static readonly UnknownField defaultInstance = CreateBuilder().Build(); - private readonly ReadOnlyCollection varintList; - private readonly ReadOnlyCollection fixed32List; - private readonly ReadOnlyCollection fixed64List; - private readonly ReadOnlyCollection lengthDelimitedList; - private readonly ReadOnlyCollection groupList; - - private UnknownField(ReadOnlyCollection varintList, - ReadOnlyCollection fixed32List, - ReadOnlyCollection fixed64List, - ReadOnlyCollection lengthDelimitedList, - ReadOnlyCollection groupList) - { - this.varintList = varintList; - this.fixed32List = fixed32List; - this.fixed64List = fixed64List; - this.lengthDelimitedList = lengthDelimitedList; - this.groupList = groupList; - } - - public static UnknownField DefaultInstance - { - get { return defaultInstance; } - } - - /// - /// The list of varint values for this field. - /// - public IList VarintList - { - get { return varintList; } - } - - /// - /// The list of fixed32 values for this field. - /// - public IList Fixed32List - { - get { return fixed32List; } - } - - /// - /// The list of fixed64 values for this field. - /// - public IList Fixed64List - { - get { return fixed64List; } - } - - /// - /// The list of length-delimited values for this field. - /// - public IList LengthDelimitedList - { - get { return lengthDelimitedList; } - } - - /// - /// The list of embedded group values for this field. These - /// are represented using UnknownFieldSets rather than Messages - /// since the group's type is presumably unknown. - /// - public IList GroupList - { - get { return groupList; } - } - - public override bool Equals(object other) - { - if (ReferenceEquals(this, other)) - { - return true; - } - UnknownField otherField = other as UnknownField; - return otherField != null - && Lists.Equals(varintList, otherField.varintList) - && Lists.Equals(fixed32List, otherField.fixed32List) - && Lists.Equals(fixed64List, otherField.fixed64List) - && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList) - && Lists.Equals(groupList, otherField.groupList); - } - - public override int GetHashCode() - { - int hash = 43; - hash = hash*47 + Lists.GetHashCode(varintList); - hash = hash*47 + Lists.GetHashCode(fixed32List); - hash = hash*47 + Lists.GetHashCode(fixed64List); - hash = hash*47 + Lists.GetHashCode(lengthDelimitedList); - hash = hash*47 + Lists.GetHashCode(groupList); - return hash; - } - - /// - /// Constructs a new Builder. - /// - public static Builder CreateBuilder() - { - return new Builder(); - } - - /// - /// Constructs a new Builder and initializes it to a copy of . - /// - public static Builder CreateBuilder(UnknownField copyFrom) - { - return new Builder().MergeFrom(copyFrom); - } - - /// - /// Serializes the field, including the field number, and writes it to - /// . - /// - public void WriteTo(int fieldNumber, ICodedOutputStream output) - { - foreach (ulong value in varintList) - { - output.WriteUnknownField(fieldNumber, WireFormat.WireType.Varint, value); - } - foreach (uint value in fixed32List) - { - output.WriteUnknownField(fieldNumber, WireFormat.WireType.Fixed32, value); - } - foreach (ulong value in fixed64List) - { - output.WriteUnknownField(fieldNumber, WireFormat.WireType.Fixed64, value); - } - foreach (ByteString value in lengthDelimitedList) - { - output.WriteUnknownBytes(fieldNumber, value); - } - foreach (UnknownFieldSet value in groupList) - { -#pragma warning disable 0612 - output.WriteUnknownGroup(fieldNumber, value); -#pragma warning restore 0612 - } - } - - /// - /// Computes the number of bytes required to encode this field, including field - /// number. - /// - public int GetSerializedSize(int fieldNumber) - { - int result = 0; - foreach (ulong value in varintList) - { - result += CodedOutputStream.ComputeUInt64Size(fieldNumber, value); - } - foreach (uint value in fixed32List) - { - result += CodedOutputStream.ComputeFixed32Size(fieldNumber, value); - } - foreach (ulong value in fixed64List) - { - result += CodedOutputStream.ComputeFixed64Size(fieldNumber, value); - } - foreach (ByteString value in lengthDelimitedList) - { - result += CodedOutputStream.ComputeBytesSize(fieldNumber, value); - } - foreach (UnknownFieldSet value in groupList) - { -#pragma warning disable 0612 - result += CodedOutputStream.ComputeUnknownGroupSize(fieldNumber, value); -#pragma warning restore 0612 - } - return result; - } - - /// - /// Serializes the length-delimited values of the field, including field - /// number, and writes them to using the MessageSet wire format. - /// - /// - /// - public void WriteAsMessageSetExtensionTo(int fieldNumber, ICodedOutputStream output) - { - foreach (ByteString value in lengthDelimitedList) - { - output.WriteMessageSetExtension(fieldNumber, UnknownFieldName, value); - } - } - - /// - /// Get the number of bytes required to encode this field, incuding field number, - /// using the MessageSet wire format. - /// - public int GetSerializedSizeAsMessageSetExtension(int fieldNumber) - { - int result = 0; - foreach (ByteString value in lengthDelimitedList) - { - result += CodedOutputStream.ComputeRawMessageSetExtensionSize(fieldNumber, value); - } - return result; - } - - /// - /// Used to build instances of UnknownField. - /// - public sealed class Builder - { - private List varintList; - private List fixed32List; - private List fixed64List; - private List lengthDelimitedList; - private List groupList; - - /// - /// Builds the field. After building, the builder is reset to an empty - /// state. (This is actually easier than making it unusable.) - /// - public UnknownField Build() - { - return new UnknownField(MakeReadOnly(ref varintList), - MakeReadOnly(ref fixed32List), - MakeReadOnly(ref fixed64List), - MakeReadOnly(ref lengthDelimitedList), - MakeReadOnly(ref groupList)); - } - - /// - /// Merge the values in into this field. For each list - /// of values, 's values are append to the ones in this - /// field. - /// - public Builder MergeFrom(UnknownField other) - { - varintList = AddAll(varintList, other.VarintList); - fixed32List = AddAll(fixed32List, other.Fixed32List); - fixed64List = AddAll(fixed64List, other.Fixed64List); - lengthDelimitedList = AddAll(lengthDelimitedList, other.LengthDelimitedList); - groupList = AddAll(groupList, other.GroupList); - return this; - } - - /// - /// Returns a new list containing all of the given specified values from - /// both the and lists. - /// If is null and is empty, - /// null is returned. Otherwise, either a new list is created (if - /// is null) or the elements of are added to . - /// - private static List AddAll(List current, IList extras) - { - if (extras.Count == 0) - { - return current; - } - if (current == null) - { - current = new List(extras); - } - else - { - current.AddRange(extras); - } - return current; - } - - /// - /// Clears the contents of this builder. - /// - public Builder Clear() - { - varintList = null; - fixed32List = null; - fixed64List = null; - lengthDelimitedList = null; - groupList = null; - return this; - } - - /// - /// Adds a varint value. - /// - public Builder AddVarint(ulong value) - { - varintList = Add(varintList, value); - return this; - } - - /// - /// Adds a fixed32 value. - /// - public Builder AddFixed32(uint value) - { - fixed32List = Add(fixed32List, value); - return this; - } - - /// - /// Adds a fixed64 value. - /// - public Builder AddFixed64(ulong value) - { - fixed64List = Add(fixed64List, value); - return this; - } - - /// - /// Adds a length-delimited value. - /// - public Builder AddLengthDelimited(ByteString value) - { - lengthDelimitedList = Add(lengthDelimitedList, value); - return this; - } - - /// - /// Adds an embedded group. - /// - /// - /// - public Builder AddGroup(UnknownFieldSet value) - { - groupList = Add(groupList, value); - return this; - } - - /// - /// Adds to the , creating - /// a new list if is null. The list is returned - either - /// the original reference or the new list. - /// - private static List Add(List list, T value) - { - if (list == null) - { - list = new List(); - } - list.Add(value); - return list; - } - - /// - /// Returns a read-only version of the given IList, and clears - /// the field used for . If the value - /// is null, an empty list is produced using Lists.Empty. - /// - /// - private static ReadOnlyCollection MakeReadOnly(ref List list) - { - ReadOnlyCollection ret = list == null ? Lists.Empty : new ReadOnlyCollection(list); - list = null; - return ret; - } - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/UnknownFieldSet.cs b/csharp/src/ProtocolBuffers/UnknownFieldSet.cs deleted file mode 100644 index d5d0675d..00000000 --- a/csharp/src/ProtocolBuffers/UnknownFieldSet.cs +++ /dev/null @@ -1,1061 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections.Generic; -using System.IO; -using Google.ProtocolBuffers.Collections; -using Google.ProtocolBuffers.Descriptors; - -namespace Google.ProtocolBuffers -{ - /// - /// Used to keep track of fields which were seen when parsing a protocol message - /// but whose field numbers or types are unrecognized. This most frequently - /// occurs when new fields are added to a message type and then messages containing - /// those fields are read by old software that was built before the new types were - /// added. - /// - /// Every message contains an UnknownFieldSet. - /// - /// Most users will never need to use this class directly. - /// - public sealed partial class UnknownFieldSet : IMessageLite - { - private static readonly UnknownFieldSet defaultInstance = - new UnknownFieldSet(new Dictionary()); - - private readonly IDictionary fields; - - private UnknownFieldSet(IDictionary fields) - { - this.fields = fields; - } - - /// - /// Creates a new unknown field set builder. - /// - public static Builder CreateBuilder() - { - return new Builder(); - } - - /// - /// Creates a new unknown field set builder - /// and initialize it from . - /// - public static Builder CreateBuilder(UnknownFieldSet original) - { - return new Builder().MergeFrom(original); - } - - public static UnknownFieldSet DefaultInstance - { - get { return defaultInstance; } - } - - /// - /// Returns a read-only view of the mapping from field numbers to values. - /// - public IDictionary FieldDictionary - { - get { return Dictionaries.AsReadOnly(fields); } - } - - /// - /// Checks whether or not the given field number is present in the set. - /// - public bool HasField(int field) - { - return fields.ContainsKey(field); - } - - /// - /// Fetches a field by number, returning an empty field if not present. - /// Never returns null. - /// - public UnknownField this[int number] - { - get - { - UnknownField ret; - if (!fields.TryGetValue(number, out ret)) - { - ret = UnknownField.DefaultInstance; - } - return ret; - } - } - - /// - /// Serializes the set and writes it to . - /// - public void WriteTo(ICodedOutputStream output) - { - // Avoid creating enumerator for the most common code path. - if (fields.Count > 0) - { - foreach (KeyValuePair entry in fields) - { - entry.Value.WriteTo(entry.Key, output); - } - } - } - - /// - /// Gets the number of bytes required to encode this set. - /// - public int SerializedSize - { - get - { - // Avoid creating enumerator for the most common code path. - if (fields.Count == 0) - { - return 0; - } - - int result = 0; - foreach (KeyValuePair entry in fields) - { - result += entry.Value.GetSerializedSize(entry.Key); - } - return result; - } - } - - /// - /// Converts the set to a string in protocol buffer text format. This - /// is just a trivial wrapper around TextFormat.PrintToString. - /// - public override String ToString() - { - return TextFormat.PrintToString(this); - } - - /// - /// Converts the set to a string in protocol buffer text format. This - /// is just a trivial wrapper around TextFormat.PrintToString. - /// - public void PrintTo(TextWriter writer) - { - TextFormat.Print(this, writer); - } - - /// - /// Serializes the message to a ByteString and returns it. This is - /// just a trivial wrapper around WriteTo(ICodedOutputStream). - /// - /// - public ByteString ToByteString() - { - ByteString.CodedBuilder codedBuilder = new ByteString.CodedBuilder(SerializedSize); - WriteTo(codedBuilder.CodedOutput); - return codedBuilder.Build(); - } - - /// - /// Serializes the message to a byte array and returns it. This is - /// just a trivial wrapper around WriteTo(ICodedOutputStream). - /// - /// - public byte[] ToByteArray() - { - byte[] data = new byte[SerializedSize]; - CodedOutputStream output = CodedOutputStream.CreateInstance(data); - WriteTo(output); - output.CheckNoSpaceLeft(); - return data; - } - - /// - /// Serializes the message and writes it to . This is - /// just a trivial wrapper around WriteTo(ICodedOutputStream). - /// - /// - public void WriteTo(Stream output) - { - CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output); - WriteTo(codedOutput); - codedOutput.Flush(); - } - - /// - /// Serializes the set and writes it to using - /// the MessageSet wire format. - /// - public void WriteAsMessageSetTo(ICodedOutputStream output) - { - // Avoid creating enumerator for the most common code path. - if (fields.Count > 0) - { - foreach (KeyValuePair entry in fields) - { - entry.Value.WriteAsMessageSetExtensionTo(entry.Key, output); - } - } - } - - /// - /// Gets the number of bytes required to encode this set using the MessageSet - /// wire format. - /// - public int SerializedSizeAsMessageSet - { - get - { - // Avoid creating enumerator for the most common code path. - if (fields.Count == 0) - { - return 0; - } - - int result = 0; - foreach (KeyValuePair entry in fields) - { - result += entry.Value.GetSerializedSizeAsMessageSetExtension(entry.Key); - } - return result; - } - } - - public override bool Equals(object other) - { - if (ReferenceEquals(this, other)) - { - return true; - } - UnknownFieldSet otherSet = other as UnknownFieldSet; - return otherSet != null && Dictionaries.Equals(fields, otherSet.fields); - } - - public override int GetHashCode() - { - return Dictionaries.GetHashCode(fields); - } - - /// - /// Parses an UnknownFieldSet from the given input. - /// - public static UnknownFieldSet ParseFrom(ICodedInputStream input) - { - return CreateBuilder().MergeFrom(input).Build(); - } - - /// - /// Parses an UnknownFieldSet from the given data. - /// - public static UnknownFieldSet ParseFrom(ByteString data) - { - return CreateBuilder().MergeFrom(data).Build(); - } - - /// - /// Parses an UnknownFieldSet from the given data. - /// - public static UnknownFieldSet ParseFrom(byte[] data) - { - return CreateBuilder().MergeFrom(data).Build(); - } - - /// - /// Parses an UnknownFieldSet from the given input. - /// - public static UnknownFieldSet ParseFrom(Stream input) - { - return CreateBuilder().MergeFrom(input).Build(); - } - - #region IMessageLite Members - - public bool IsInitialized - { - get { return fields != null; } - } - - public void WriteDelimitedTo(Stream output) - { - CodedOutputStream codedOutput = CodedOutputStream.CreateInstance(output); - codedOutput.WriteRawVarint32((uint) SerializedSize); - WriteTo(codedOutput); - codedOutput.Flush(); - } - - public IBuilderLite WeakCreateBuilderForType() - { - return new Builder(); - } - - public IBuilderLite WeakToBuilder() - { - return new Builder(fields); - } - - public IMessageLite WeakDefaultInstanceForType - { - get { return defaultInstance; } - } - - #endregion - - /// - /// Builder for UnknownFieldSets. - /// - public sealed partial class Builder : IBuilderLite - { - /// - /// Mapping from number to field. Note that by using a SortedList we ensure - /// that the fields will be serialized in ascending order. - /// - private IDictionary fields; - - // Optimization: We keep around a builder for the last field that was - // modified so that we can efficiently add to it multiple times in a - // row (important when parsing an unknown repeated field). - private int lastFieldNumber; - private UnknownField.Builder lastField; - - internal Builder() - { - fields = new SortedDictionary(); - } - - internal Builder(IDictionary dictionary) - { - fields = new SortedDictionary(dictionary); - } - - /// - /// Returns a field builder for the specified field number, including any values - /// which already exist. - /// - private UnknownField.Builder GetFieldBuilder(int number) - { - if (lastField != null) - { - if (number == lastFieldNumber) - { - return lastField; - } - // Note: AddField() will reset lastField and lastFieldNumber. - AddField(lastFieldNumber, lastField.Build()); - } - if (number == 0) - { - return null; - } - - lastField = UnknownField.CreateBuilder(); - UnknownField existing; - if (fields.TryGetValue(number, out existing)) - { - lastField.MergeFrom(existing); - } - lastFieldNumber = number; - return lastField; - } - - /// - /// Build the UnknownFieldSet and return it. Once this method has been called, - /// this instance will no longer be usable. Calling any method after this - /// will throw a NullReferenceException. - /// - public UnknownFieldSet Build() - { - GetFieldBuilder(0); // Force lastField to be built. - UnknownFieldSet result = fields.Count == 0 ? DefaultInstance : new UnknownFieldSet(fields); - fields = null; - return result; - } - - /// - /// Adds a field to the set. If a field with the same number already exists, it - /// is replaced. - /// - public Builder AddField(int number, UnknownField field) - { - if (number == 0) - { - throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); - } - if (lastField != null && lastFieldNumber == number) - { - // Discard this. - lastField = null; - lastFieldNumber = 0; - } - fields[number] = field; - return this; - } - - /// - /// Resets the builder to an empty set. - /// - public Builder Clear() - { - fields.Clear(); - lastFieldNumber = 0; - lastField = null; - return this; - } - - /// - /// Parse an entire message from and merge - /// its fields into this set. - /// - public Builder MergeFrom(ICodedInputStream input) - { - uint tag; - string name; - while (input.ReadTag(out tag, out name)) - { - if (tag == 0) - { - if (input.SkipField()) - { - continue; //can't merge unknown without field tag - } - break; - } - - if (!MergeFieldFrom(tag, input)) - { - break; - } - } - return this; - } - - /// - /// Parse a single field from and merge it - /// into this set. - /// - /// The field's tag number, which was already parsed. - /// The coded input stream containing the field - /// false if the tag is an "end group" tag, true otherwise - public bool MergeFieldFrom(uint tag, ICodedInputStream input) - { - if (tag == 0) - { - input.SkipField(); - return true; - } - - int number = WireFormat.GetTagFieldNumber(tag); - switch (WireFormat.GetTagWireType(tag)) - { - case WireFormat.WireType.Varint: - { - ulong uint64 = 0; - if (input.ReadUInt64(ref uint64)) - { - GetFieldBuilder(number).AddVarint(uint64); - } - return true; - } - case WireFormat.WireType.Fixed32: - { - uint uint32 = 0; - if (input.ReadFixed32(ref uint32)) - { - GetFieldBuilder(number).AddFixed32(uint32); - } - return true; - } - case WireFormat.WireType.Fixed64: - { - ulong uint64 = 0; - if (input.ReadFixed64(ref uint64)) - { - GetFieldBuilder(number).AddFixed64(uint64); - } - return true; - } - case WireFormat.WireType.LengthDelimited: - { - ByteString bytes = null; - if (input.ReadBytes(ref bytes)) - { - GetFieldBuilder(number).AddLengthDelimited(bytes); - } - return true; - } - case WireFormat.WireType.StartGroup: - { - Builder subBuilder = CreateBuilder(); -#pragma warning disable 0612 - input.ReadUnknownGroup(number, subBuilder); -#pragma warning restore 0612 - GetFieldBuilder(number).AddGroup(subBuilder.Build()); - return true; - } - case WireFormat.WireType.EndGroup: - return false; - default: - throw InvalidProtocolBufferException.InvalidWireType(); - } - } - - /// - /// Parses as an UnknownFieldSet and merge it - /// with the set being built. This is just a small wrapper around - /// MergeFrom(ICodedInputStream). - /// - public Builder MergeFrom(Stream input) - { - CodedInputStream codedInput = CodedInputStream.CreateInstance(input); - MergeFrom(codedInput); - codedInput.CheckLastTagWas(0); - return this; - } - - /// - /// Parses as an UnknownFieldSet and merge it - /// with the set being built. This is just a small wrapper around - /// MergeFrom(ICodedInputStream). - /// - public Builder MergeFrom(ByteString data) - { - CodedInputStream input = data.CreateCodedInput(); - MergeFrom(input); - input.CheckLastTagWas(0); - return this; - } - - /// - /// Parses as an UnknownFieldSet and merge it - /// with the set being built. This is just a small wrapper around - /// MergeFrom(ICodedInputStream). - /// - public Builder MergeFrom(byte[] data) - { - CodedInputStream input = CodedInputStream.CreateInstance(data); - MergeFrom(input); - input.CheckLastTagWas(0); - return this; - } - - /// - /// Convenience method for merging a new field containing a single varint - /// value. This is used in particular when an unknown enum value is - /// encountered. - /// - public Builder MergeVarintField(int number, ulong value) - { - if (number == 0) - { - throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); - } - GetFieldBuilder(number).AddVarint(value); - return this; - } - - /// - /// Merges the fields from into this set. - /// If a field number exists in both sets, the values in - /// will be appended to the values in this set. - /// - public Builder MergeFrom(UnknownFieldSet other) - { - if (other != DefaultInstance) - { - foreach (KeyValuePair entry in other.fields) - { - MergeField(entry.Key, entry.Value); - } - } - return this; - } - - /// - /// Checks if the given field number is present in the set. - /// - public bool HasField(int number) - { - if (number == 0) - { - throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); - } - return number == lastFieldNumber || fields.ContainsKey(number); - } - - /// - /// Adds a field to the unknown field set. If a field with the same - /// number already exists, the two are merged. - /// - public Builder MergeField(int number, UnknownField field) - { - if (number == 0) - { - throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number."); - } - if (HasField(number)) - { - GetFieldBuilder(number).MergeFrom(field); - } - else - { - // Optimization: We could call getFieldBuilder(number).mergeFrom(field) - // in this case, but that would create a copy of the Field object. - // We'd rather reuse the one passed to us, so call AddField() instead. - AddField(number, field); - } - return this; - } - - internal void MergeFrom(ICodedInputStream input, ExtensionRegistry extensionRegistry, IBuilder builder) - { - uint tag; - string name; - while (input.ReadTag(out tag, out name)) - { - if (tag == 0 && name != null) - { - FieldDescriptor fieldByName = builder.DescriptorForType.FindFieldByName(name); - if (fieldByName != null) - { - tag = WireFormat.MakeTag(fieldByName); - } - else - { - ExtensionInfo extension = extensionRegistry.FindByName(builder.DescriptorForType, name); - if (extension != null) - { - tag = WireFormat.MakeTag(extension.Descriptor); - } - } - } - if (tag == 0) - { - if (input.SkipField()) - { - continue; //can't merge unknown without field tag - } - break; - } - - if (!MergeFieldFrom(input, extensionRegistry, builder, tag, name)) - { - // end group tag - break; - } - } - } - - /// - /// Like - /// but parses a single field. - /// - /// The input to read the field from - /// Registry to use when an extension field is encountered - /// Builder to merge field into, if it's a known field - /// The tag, which should already have been read from the input - /// true unless the tag is an end-group tag - internal bool MergeFieldFrom(ICodedInputStream input, - ExtensionRegistry extensionRegistry, IBuilder builder, uint tag, - string fieldName) - { - if (tag == 0 && fieldName != null) - { - FieldDescriptor fieldByName = builder.DescriptorForType.FindFieldByName(fieldName); - if (fieldByName != null) - { - tag = WireFormat.MakeTag(fieldByName); - } - else - { - ExtensionInfo extension = extensionRegistry.FindByName(builder.DescriptorForType, fieldName); - if (extension != null) - { - tag = WireFormat.MakeTag(extension.Descriptor); - } - } - } - - MessageDescriptor type = builder.DescriptorForType; - if (type.Options.MessageSetWireFormat && tag == WireFormat.MessageSetTag.ItemStart) - { - MergeMessageSetExtensionFromCodedStream(input, extensionRegistry, builder); - return true; - } - - WireFormat.WireType wireType = WireFormat.GetTagWireType(tag); - int fieldNumber = WireFormat.GetTagFieldNumber(tag); - - FieldDescriptor field; - IMessageLite defaultFieldInstance = null; - - if (type.IsExtensionNumber(fieldNumber)) - { - ExtensionInfo extension = extensionRegistry[type, fieldNumber]; - if (extension == null) - { - field = null; - } - else - { - field = extension.Descriptor; - defaultFieldInstance = extension.DefaultInstance; - } - } - else - { - field = type.FindFieldByNumber(fieldNumber); - } - - // Unknown field or wrong wire type. Skip. - if (field == null) - { - return MergeFieldFrom(tag, input); - } - if (wireType != WireFormat.GetWireType(field)) - { - WireFormat.WireType expectedType = WireFormat.GetWireType(field.FieldType); - if (wireType == expectedType) - { - //Allowed as of 2.3, this is unpacked data for a packed array - } - else if (field.IsRepeated && wireType == WireFormat.WireType.LengthDelimited && - (expectedType == WireFormat.WireType.Varint || expectedType == WireFormat.WireType.Fixed32 || - expectedType == WireFormat.WireType.Fixed64)) - { - //Allowed as of 2.3, this is packed data for an unpacked array - } - else - { - return MergeFieldFrom(tag, input); - } - } - - switch (field.FieldType) - { - case FieldType.Group: - case FieldType.Message: - { - IBuilderLite subBuilder = (defaultFieldInstance != null) - ? defaultFieldInstance.WeakCreateBuilderForType() - : builder.CreateBuilderForField(field); - if (!field.IsRepeated) - { - subBuilder.WeakMergeFrom((IMessageLite) builder[field]); - if (field.FieldType == FieldType.Group) - { - input.ReadGroup(field.FieldNumber, subBuilder, extensionRegistry); - } - else - { - input.ReadMessage(subBuilder, extensionRegistry); - } - builder[field] = subBuilder.WeakBuild(); - } - else - { - List list = new List(); - if (field.FieldType == FieldType.Group) - { - input.ReadGroupArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, - extensionRegistry); - } - else - { - input.ReadMessageArray(tag, fieldName, list, subBuilder.WeakDefaultInstanceForType, - extensionRegistry); - } - - foreach (IMessageLite m in list) - { - builder.WeakAddRepeatedField(field, m); - } - return true; - } - break; - } - case FieldType.Enum: - { - if (!field.IsRepeated) - { - object unknown; - IEnumLite value = null; - if (input.ReadEnum(ref value, out unknown, field.EnumType)) - { - builder[field] = value; - } - else if (unknown is int) - { - MergeVarintField(fieldNumber, (ulong) (int) unknown); - } - } - else - { - ICollection unknown; - List list = new List(); - input.ReadEnumArray(tag, fieldName, list, out unknown, field.EnumType); - - foreach (IEnumLite en in list) - { - builder.WeakAddRepeatedField(field, en); - } - - if (unknown != null) - { - foreach (object oval in unknown) - { - if (oval is int) - { - MergeVarintField(fieldNumber, (ulong) (int) oval); - } - } - } - } - break; - } - default: - { - if (!field.IsRepeated) - { - object value = null; - if (input.ReadPrimitiveField(field.FieldType, ref value)) - { - builder[field] = value; - } - } - else - { - List list = new List(); - input.ReadPrimitiveArray(field.FieldType, tag, fieldName, list); - foreach (object oval in list) - { - builder.WeakAddRepeatedField(field, oval); - } - } - break; - } - } - return true; - } - - /// - /// Called by MergeFieldFrom to parse a MessageSet extension. - /// - private void MergeMessageSetExtensionFromCodedStream(ICodedInputStream input, - ExtensionRegistry extensionRegistry, IBuilder builder) - { - MessageDescriptor type = builder.DescriptorForType; - - // The wire format for MessageSet is: - // message MessageSet { - // repeated group Item = 1 { - // required int32 typeId = 2; - // required bytes message = 3; - // } - // } - // "typeId" is the extension's field number. The extension can only be - // a message type, where "message" contains the encoded bytes of that - // message. - // - // In practice, we will probably never see a MessageSet item in which - // the message appears before the type ID, or where either field does not - // appear exactly once. However, in theory such cases are valid, so we - // should be prepared to accept them. - - int typeId = 0; - ByteString rawBytes = null; // If we encounter "message" before "typeId" - IBuilderLite subBuilder = null; - FieldDescriptor field = null; - - uint lastTag = WireFormat.MessageSetTag.ItemStart; - uint tag; - string name; - while (input.ReadTag(out tag, out name)) - { - if (tag == 0 && name != null) - { - if (name == "type_id") - { - tag = WireFormat.MessageSetTag.TypeID; - } - else if (name == "message") - { - tag = WireFormat.MessageSetTag.Message; - } - } - if (tag == 0) - { - if (input.SkipField()) - { - continue; //can't merge unknown without field tag - } - break; - } - - lastTag = tag; - if (tag == WireFormat.MessageSetTag.TypeID) - { - typeId = 0; - // Zero is not a valid type ID. - if (input.ReadInt32(ref typeId) && typeId != 0) - { - ExtensionInfo extension = extensionRegistry[type, typeId]; - if (extension != null) - { - field = extension.Descriptor; - subBuilder = extension.DefaultInstance.WeakCreateBuilderForType(); - IMessageLite originalMessage = (IMessageLite) builder[field]; - if (originalMessage != null) - { - subBuilder.WeakMergeFrom(originalMessage); - } - if (rawBytes != null) - { - // We already encountered the message. Parse it now. - // TODO(jonskeet): Check this is okay. It's subtly different from the Java, as it doesn't create an input stream from rawBytes. - // In fact, why don't we just call MergeFrom(rawBytes)? And what about the extension registry? - subBuilder.WeakMergeFrom(rawBytes.CreateCodedInput()); - rawBytes = null; - } - } - else - { - // Unknown extension number. If we already saw data, put it - // in rawBytes. - if (rawBytes != null) - { - MergeField(typeId, UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build()); - rawBytes = null; - } - } - } - } - else if (tag == WireFormat.MessageSetTag.Message) - { - if (subBuilder != null) - { - // We already know the type, so we can parse directly from the input - // with no copying. Hooray! - input.ReadMessage(subBuilder, extensionRegistry); - } - else if (input.ReadBytes(ref rawBytes)) - { - if (typeId != 0) - { - // We don't know how to parse this. Ignore it. - MergeField(typeId, - UnknownField.CreateBuilder().AddLengthDelimited(rawBytes).Build()); - } - } - } - else - { - // Unknown tag. Skip it. - if (!input.SkipField()) - { - break; // end of group - } - } - } - - if (lastTag != WireFormat.MessageSetTag.ItemEnd) - { - throw InvalidProtocolBufferException.InvalidEndTag(); - } - - if (subBuilder != null) - { - builder[field] = subBuilder.WeakBuild(); - } - } - - #region IBuilderLite Members - - bool IBuilderLite.IsInitialized - { - get { return fields != null; } - } - - IBuilderLite IBuilderLite.WeakClear() - { - return Clear(); - } - - IBuilderLite IBuilderLite.WeakMergeFrom(IMessageLite message) - { - return MergeFrom((UnknownFieldSet) message); - } - - IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data) - { - return MergeFrom(data); - } - - IBuilderLite IBuilderLite.WeakMergeFrom(ByteString data, ExtensionRegistry registry) - { - return MergeFrom(data); - } - - IBuilderLite IBuilderLite.WeakMergeFrom(ICodedInputStream input) - { - return MergeFrom(input); - } - - IBuilderLite IBuilderLite.WeakMergeFrom(ICodedInputStream input, ExtensionRegistry registry) - { - return MergeFrom(input); - } - - IMessageLite IBuilderLite.WeakBuild() - { - return Build(); - } - - IMessageLite IBuilderLite.WeakBuildPartial() - { - return Build(); - } - - IBuilderLite IBuilderLite.WeakClone() - { - return Build().WeakToBuilder(); - } - - IMessageLite IBuilderLite.WeakDefaultInstanceForType - { - get { return DefaultInstance; } - } - - #endregion - } - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/WireFormat.cs b/csharp/src/ProtocolBuffers/WireFormat.cs index b9daa328..87f7c358 100644 --- a/csharp/src/ProtocolBuffers/WireFormat.cs +++ b/csharp/src/ProtocolBuffers/WireFormat.cs @@ -35,9 +35,9 @@ #endregion using System; -using Google.ProtocolBuffers.Descriptors; +using Google.Protobuf.Descriptors; -namespace Google.ProtocolBuffers +namespace Google.Protobuf { /// /// This class is used internally by the Protocol Buffer Library and generated diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 8865702d..ee9d6a1d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -61,7 +61,7 @@ void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, fieldNames[$field_ordinal$], (long) $property_name$, $property_name$);\n" + " output.WriteEnum($number$, fieldNames[$field_ordinal$], $property_name$);\n" "}\n"); } @@ -69,7 +69,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (long) $property_name$);\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, $property_name$);\n" "}\n"); } @@ -87,8 +87,8 @@ void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { variables_, "$type_name$ enumValue = $default_value$;\n" "if(input.ReadEnum(ref enumValue)) {\n" - " result.$oneof_name$_ = enumValue;\n" - " result.$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" + " $oneof_name$_ = enumValue;\n" + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc index 367e54c2..ec0d51ca 100644 --- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc +++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -51,6 +52,11 @@ namespace csharp { void FieldGeneratorBase::SetCommonFieldVariables( map* variables) { + // Note: this will be valid even though the tag emitted for packed and unpacked versions of + // repeated fields varies by wire format. The wire format is encoded in the bottom 3 bits, which + // never effects the tag size. + int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); + (*variables)["tag_size"] = SimpleItoa(tagSize); (*variables)["property_name"] = property_name(); (*variables)["type_name"] = type_name(); (*variables)["name"] = name(); @@ -65,15 +71,10 @@ void FieldGeneratorBase::SetCommonFieldVariables( (*variables)["capitalized_type_name"] = capitalized_type_name(); (*variables)["number"] = number(); (*variables)["field_ordinal"] = field_ordinal(); - if (SupportFieldPresence(descriptor_->file())) { - (*variables)["has_property_check"] = "has" + (*variables)["property_name"]; - (*variables)["other_has_property_check"] = "other.Has" + (*variables)["property_name"]; - } else { - (*variables)["has_property_check"] = - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - (*variables)["other_has_property_check"] = "other." + - (*variables)["property_name"] + " != " + (*variables)["default_value"]; - } + (*variables)["has_property_check"] = + (*variables)["property_name"] + " != " + (*variables)["default_value"]; + (*variables)["other_has_property_check"] = "other." + + (*variables)["property_name"] + " != " + (*variables)["default_value"]; } void FieldGeneratorBase::SetCommonOneofFieldVariables( diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index 1defcf94..b5929bcd 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -179,10 +179,14 @@ void MessageGenerator::Generate(io::Printer* printer) { WriteGeneratedCodeAttributes(printer); printer->Print( vars, - "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$> {\n"); + "$access_level$ sealed partial class $class_name$ : pb::IMessage<$class_name$>, global::System.IEquatable<$class_name$> {\n"); printer->Indent(); // All static fields and properties + printer->Print( + vars, + "private static readonly pb::MessageParser<$class_name$> _parser = new pb::MessageParser<$class_name$>(() => new $class_name$());\n" + "public static pb::MessageParser<$class_name$> Parser { get { return _parser; } }\n\n"); printer->Print( "private static readonly string[] _fieldNames = " "new string[] { $slash$$field_names$$slash$ };\n", @@ -204,7 +208,7 @@ void MessageGenerator::Generate(io::Printer* printer) { " get { return $umbrella_class_name$.internal__$identifier$__Descriptor; }\n" "}\n" "\n" - "protected override pb::FieldAccess.FieldAccessorTable<$class_name$> InternalFieldAccessors {\n" + "public pb::FieldAccess.FieldAccessorTable<$class_name$> Fields {\n" " get { return $umbrella_class_name$.internal__$identifier$__FieldAccessorTable; }\n" "}\n" "\n"); @@ -217,7 +221,7 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print( vars, "public $class_name$($class_name$ other) {\n" - " MergeWith(other);\n" + " MergeFrom(other);\n" "}\n"); // Merge ctor. // Fields/properties @@ -259,15 +263,16 @@ void MessageGenerator::Generate(io::Printer* printer) { "public $property_name$OneofCase $property_name$Case {\n" " get { return $name$Case_; }\n" "}\n\n" - "private Clear$property_name$() {;\n" - " $name$Case_ = $property_name$OneofCase.None;" - " $name$_ = null;" + "public void Clear$property_name$() {\n" + " $name$Case_ = $property_name$OneofCase.None;\n" + " $name$_ = null;\n" "}\n\n"); } // TODO(jonskeet): Map properties // Standard methods + GenerateFrameworkMethods(printer); GenerateMessageSerializationMethods(printer); GenerateMergingMethods(printer); @@ -298,6 +303,51 @@ void MessageGenerator::Generate(io::Printer* printer) { } +void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { + map vars; + vars["class_name"] = class_name(); + + // Equality + printer->Print( + vars, + "public override bool Equals(object other) {\n" + " return Equals(other as $class_name$);\n" + "}\n\n" + "public bool Equals($class_name$ other) {\n" + " if (ReferenceEquals(other, null)) {\n" + " return false;\n" + " }\n" + " if (ReferenceEquals(other, this)) {\n" + " return true;\n" + " }\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteEquals(printer); + } + printer->Outdent(); + printer->Print( + " return true;\n" + "}\n\n"); + + // GetHashCode + printer->Print( + "public override int GetHashCode() {\n" + " int hash = 0;\n"); + printer->Indent(); + for (int i = 0; i < descriptor_->field_count(); i++) { + scoped_ptr generator( + CreateFieldGeneratorInternal(descriptor_->field(i))); + generator->WriteHash(printer); + } + printer->Print("return hash;\n"); + printer->Outdent(); + printer->Print("}\n\n"); + + // TODO(jonskeet): ToString. +} + void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "public void WriteTo(pb::ICodedOutputStream output) {\n"); @@ -316,7 +366,7 @@ void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) printer->Print( "}\n" "\n" - "public int CalculateSerializedSize() {\n"); + "public int CalculateSize() {\n"); printer->Indent(); printer->Print("int size = 0;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { @@ -338,7 +388,7 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print( vars, - "public void MergeWith($class_name$ other) {\n"); + "public void MergeFrom($class_name$ other) {\n"); printer->Indent(); printer->Print( "if (other == null) {\n" @@ -378,39 +428,38 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Print( "uint tag;\n" "string fieldName;\n" - "while (input.ReadTag(out tag, out fieldName)) {\n" - " if (tag == 0 && fieldName != null) {"); - printer->Indent(); + "while (input.ReadTag(out tag, out fieldName)) {\n"); printer->Indent(); printer->Print( - "int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.String.String.Ordinal);\n" - "if (fieldOrdinal >= 0) {\n" - " tag = _fieldTags[fieldOrdinal];\n" + "if (tag == 0 && fieldName != null) {\n" + " int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal);\n" + " if (fieldOrdinal >= 0) {\n" + " tag = _fieldTags[fieldOrdinal];\n" + " }\n" "}\n" "switch(tag) {\n"); printer->Indent(); printer->Print( - "case 0: {\n" // 0 signals EOF / limit reached + "case 0:\n" // 0 signals EOF / limit reached " throw pb::InvalidProtocolBufferException.InvalidTag();\n" - "}\n" "default:\n" " if (pb::WireFormat.IsEndGroupTag(tag)) {\n" " return;\n" " }\n" - " break;"); // Note: we're ignoring unknown fields here. + " break;\n"); // Note: we're ignoring unknown fields here. for (int i = 0; i < fields_by_number().size(); i++) { const FieldDescriptor* field = fields_by_number()[i]; internal::WireFormatLite::WireType wt = internal::WireFormat::WireTypeForFieldType(field->type()); uint32 tag = internal::WireFormatLite::MakeTag(field->number(), wt); - // TODO(jonskeet): Understand what this is trying to do - if (field->is_repeated() - && (wt == internal::WireFormatLite::WIRETYPE_VARINT - || wt == internal::WireFormatLite::WIRETYPE_FIXED32 - || wt == internal::WireFormatLite::WIRETYPE_FIXED64)) { + // Handle both packed and unpacked repeated fields with the same Read*Array call; + // the two generated cases are the packed and unpacked tags. + // TODO(jonskeet): Check that is_packable is equivalent to is_repeated && wt in { VARINT, FIXED32, FIXED64 }. + // It looks like it is... + if (field->is_packable()) { printer->Print( - "case $number$:\n", - "number", + "case $packed_tag$:\n", + "packed_tag", SimpleItoa( internal::WireFormatLite::MakeTag( field->number(), @@ -429,8 +478,6 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { printer->Outdent(); printer->Print("}\n"); // switch printer->Outdent(); - printer->Print("}\n"); // if - printer->Outdent(); printer->Print("}\n"); // while printer->Outdent(); printer->Print("}\n\n"); // method diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h index f5f41c73..eb90ce67 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.h +++ b/src/google/protobuf/compiler/csharp/csharp_message.h @@ -50,6 +50,7 @@ class MessageGenerator : public SourceGeneratorBase { MessageGenerator(const Descriptor* descriptor); ~MessageGenerator(); + void GenerateFrameworkMethods(io::Printer* printer); void GenerateStaticVariables(io::Printer* printer); void GenerateStaticVariableInitializers(io::Printer* printer); void Generate(io::Printer* printer); diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 90aa201b..4b7ac88f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -49,8 +49,8 @@ namespace csharp { MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { - variables_["has_property_check"] = property_name() + "_ != null"; - variables_["has_not_property_check"] = property_name() + "_ == null"; + variables_["has_property_check"] = name() + "_ != null"; + variables_["has_not_property_check"] = name() + "_ == null"; } MessageFieldGenerator::~MessageFieldGenerator() { @@ -66,7 +66,7 @@ void MessageFieldGenerator::GenerateMembers(io::Printer* printer) { variables_, "public $type_name$ $property_name$ {\n" " get { return $name$_; }\n" - " set { return $name$_ = value; }\n" + " set { $name$_ = value; }\n" "}\n"); } @@ -74,17 +74,17 @@ void MessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { printer->Print( variables_, "if (other.$has_property_check$) {\n" - " if ($has_not_property_check) {\n" + " if ($has_not_property_check$) {\n" " $name$_ = new $type_name$();\n" " }\n" - " $property_name$.MergeWith(other.$property_name);\n" + " $property_name$.MergeFrom(other.$property_name$);\n" "}\n"); } void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "if ($has_not_property_check) {\n" + "if ($has_not_property_check$) {\n" " $name$_ = new $type_name$();\n" "}\n" "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... @@ -110,12 +110,12 @@ void MessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { void MessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) hash ^= $name$_.GetHashCode();\n"); + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); } void MessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if (!object.Equals($property_name$_, other.$property_name$_)) return false;\n"); + "if (!object.Equals($property_name$, other.$property_name$)) return false;"); } void MessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); @@ -140,10 +140,10 @@ void MessageOneofFieldGenerator::GenerateMembers(io::Printer* printer) { variables_, "public $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : null; }\n" - " set { \n" - " $name$_ = value;" - " $oneof_name$Case_ = value == null ? $oneof_property_name$Case.None : $oneof_property_name$Case.$property_name$; }\n" - " } \n" + " set {\n" + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n" + " }\n" "}\n"); } @@ -151,12 +151,12 @@ void MessageOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { // TODO(jonskeet): We may be able to do better than this printer->Print( variables_, - "$type_name$ subBuilder = new type_name$();\n" + "$type_name$ subBuilder = new $type_name$();\n" "if ($has_property_check$) {\n" - " subBuilder.MergeWith($property_name$);\n" + " subBuilder.MergeFrom($property_name$);\n" "}\n" "input.ReadMessage(subBuilder);\n" // No support of TYPE_GROUP - "$oneof_property_name$ = subBuilder;\n"); + "$property_name$ = subBuilder;\n"); } void MessageOneofFieldGenerator::WriteToString(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index bc4858fc..f2b66a00 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -93,7 +93,7 @@ void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.Read$capitalized_type_name$(ref result.$name$_);\n"); + "input.Read$capitalized_type_name$(ref $name$_);\n"); } void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -115,9 +115,7 @@ void PrimitiveFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { void PrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "if ($has_property_check$) {\n" - " hash ^= $property_name$.GetHashCode();\n" - "}\n"); + "if ($has_property_check$) hash ^= $property_name$.GetHashCode();\n"); } void PrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( @@ -147,17 +145,17 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { variables_, "public $type_name$ $property_name$ {\n" " get { return $has_property_check$ ? ($type_name$) $oneof_name$_ : $default_value$; }\n" - " set {"); + " set {\n"); if (is_value_type) { printer->Print( variables_, - " $oneof_name$_ = value;\n" - " $oneof_name$Case_ = $oneof_property_name$Case.$property_name$;\n"); + " $oneof_name$_ = value;\n" + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); } else { printer->Print( variables_, - " $oneof_name$_ = value ?? $default_value$;\n" - " $oneof_name$Case_ = value == null ? $oneof_property_name$Case.None : $oneof_property_name$Case.$property_name$;\n"); + " $oneof_name$_ = value ?? $default_value$;\n" + " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"); } printer->Print( " }\n" diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index f5d5a126..ebbbf3be 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -49,6 +49,7 @@ namespace csharp { RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + variables_["packed"] = descriptor->is_packed() ? "Packed" : ""; } RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() { @@ -75,27 +76,21 @@ void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.ReadEnumArray<$type_name$>(tag, fieldName, result.$name$_);\n"); + "input.ReadEnumArray<$type_name$>(tag, fieldName, $name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { // TODO(jonskeet): Originally, this checked for Count > 0 first. // The Write* call should make that cheap though - no need to generate it every time. - if (descriptor_->is_packed()) { - printer->Print( - variables_, - "output.WritePackedEnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); - } else { - printer->Print(variables_, - "output.WriteEnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); - } - printer->Print("}\n"); + printer->Print( + variables_, + "output.Write$packed$EnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { + // TODO(jonskeet): Move all this code into CodedOutputStream? It's a lot to repeat everywhere... printer->Print("{\n"); printer->Indent(); - // TODO(jonskeet): Move all this code into CodedOutputStream? It's a lot to repeat everywhere... printer->Print( variables_, "int dataSize = 0;\n" @@ -104,7 +99,7 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer printer->Print( variables_, "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((long) element);\n" + " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element);\n" "}\n" "size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); @@ -127,15 +122,13 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_) {\n" - " hash ^= i.GetHashCode();\n" - "}\n"); + "hash ^= $name$_.GetHashCode();\n"); } void RepeatedEnumFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if(!$name$_.Equals(other.$name$)) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } void RepeatedEnumFieldGenerator::WriteToString(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 2a6a01f5..963f841e 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -64,21 +64,6 @@ void RepeatedMessageFieldGenerator::GenerateMembers(io::Printer* printer) { "public pbc::RepeatedField<$type_name$> $property_name$ {\n" " get { return $name$_; }\n" "}\n"); - - // TODO(jonskeet): Redundant API calls? Possibly - include for portability though. Maybe create an option. - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public int $property_name$Count {\n" - " get { return $name$_.Count; }\n" - "}\n"); - - AddDeprecatedFlag(printer); - printer->Print( - variables_, - "public $type_name$ Get$property_name$(int index) {\n" - " return $name$_[index];\n" - "}\n"); } void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { @@ -90,7 +75,7 @@ void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.ReadMessageArray(tag, fieldName, $name$_);\n"); + "input.ReadMessageArray(tag, fieldName, $name$_, $type_name$.Parser);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -105,7 +90,7 @@ void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* prin // TODO(jonskeet): Put this into CodedOutputStream. printer->Print( variables_, - "foreach ($type_name$ element in $property_name$) {\n" + "foreach ($type_name$ element in $name$_) {\n" " size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n" "}\n"); } @@ -113,15 +98,15 @@ void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* prin void RepeatedMessageFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_) {\n" - " hash ^= i.GetHashCode();\n" - "}\n"); + "hash ^= $name$_.GetHashCode();\n"); } + void RepeatedMessageFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if(!$name$_.Equals(other.$name$)) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } + void RepeatedMessageFieldGenerator::WriteToString(io::Printer* printer) { variables_["field_name"] = GetFieldName(descriptor_); printer->Print( diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 2001b849..0a91c3c6 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -92,7 +92,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( io::Printer* printer) { - // TODO(jonskeet): Get rid of most of this - move it into the runtime. + // TODO(jonskeet): Do this in the runtime if possible. It's a pain, but it must be feasible... printer->Print("{\n"); printer->Indent(); printer->Print("int dataSize = 0;\n"); @@ -100,7 +100,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( if (fixedSize == -1) { printer->Print( variables_, - "foreach ($type_name$ element in $property_name$List) {\n" + "foreach ($type_name$ element in $name$_) {\n" " dataSize += pb::CodedOutputStream.Compute$capitalized_type_name$SizeNoTag(element);\n" "}\n"); } else { @@ -128,14 +128,12 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( void RepeatedPrimitiveFieldGenerator::WriteHash(io::Printer* printer) { printer->Print( variables_, - "foreach($type_name$ i in $name$_)\n {" - " hash ^= i.GetHashCode();\n" - "}\n"); + "hash ^= $name$_.GetHashCode();\n"); } void RepeatedPrimitiveFieldGenerator::WriteEquals(io::Printer* printer) { printer->Print( variables_, - "if(!$name$_.Equals(other.$name$)) return false;\n"); + "if(!$name$_.Equals(other.$name$_)) return false;\n"); } void RepeatedPrimitiveFieldGenerator::WriteToString(io::Printer* printer) { printer->Print(variables_, diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index 20a60080..97741b6a 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -42,7 +42,7 @@ syntax = "proto2"; package google.protobuf; option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; -option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos"; +option csharp_namespace = "Google.Protobuf.DescriptorProtos"; option objc_class_prefix = "GPB"; // descriptor.proto must be optimized for speed because reflection-based diff --git a/src/google/protobuf/unittest_import_proto3.proto b/src/google/protobuf/unittest_import_proto3.proto new file mode 100644 index 00000000..59673eaf --- /dev/null +++ b/src/google/protobuf/unittest_import_proto3.proto @@ -0,0 +1,68 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file which is imported by unittest_proto3.proto to test importing. + +syntax = "proto3"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do +// "using namespace unittest_import = protobuf_unittest_import". +package protobuf_unittest_import; + +option optimize_for = SPEED; +option cc_enable_arenas = true; + +// Exercise the java_package option. +option java_package = "com.google.protobuf.test"; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +// Do not set a java_outer_classname here to verify that Proto2 works without +// one. + +// Test public import +import public "google/protobuf/unittest_import_public_proto3.proto"; + +message ImportMessage { + int32 d = 1; +} + +enum ImportEnum { + IMPORT_ENUM_UNSPECIFIED = 0; + IMPORT_FOO = 7; + IMPORT_BAR = 8; + IMPORT_BAZ = 9; +} + diff --git a/src/google/protobuf/unittest_import_public_proto3.proto b/src/google/protobuf/unittest_import_public_proto3.proto new file mode 100644 index 00000000..d6f11e28 --- /dev/null +++ b/src/google/protobuf/unittest_import_public_proto3.proto @@ -0,0 +1,42 @@ +// 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. + +// Author: liujisi@google.com (Pherl Liu) + +syntax = "proto3"; + +package protobuf_unittest_import; + +option java_package = "com.google.protobuf.test"; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +message PublicImportMessage { + int32 e = 1; +} diff --git a/src/google/protobuf/unittest_proto3.proto b/src/google/protobuf/unittest_proto3.proto new file mode 100644 index 00000000..f59d2178 --- /dev/null +++ b/src/google/protobuf/unittest_proto3.proto @@ -0,0 +1,388 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// A proto file we will use for unit testing. + +syntax = "proto3"; + +// Some generic_services option(s) added automatically. +// See: http://go/proto2-generic-services-default +option cc_generic_services = true; // auto-added +option java_generic_services = true; // auto-added +option py_generic_services = true; // auto-added +option cc_enable_arenas = true; +option csharp_namespace = "Google.Protobuf.TestProtos"; + +import "google/protobuf/unittest_import_proto3.proto"; + +// We don't put this in a package within proto2 because we need to make sure +// that the generated code doesn't depend on being in the proto2 namespace. +// In test_util.h we do "using namespace unittest = protobuf_unittest". +package protobuf_unittest; + +// Protos optimized for SPEED use a strict superset of the generated code +// of equivalent ones optimized for CODE_SIZE, so we should optimize all our +// tests for speed unless explicitly testing code size optimization. +option optimize_for = SPEED; + +option java_outer_classname = "UnittestProto"; + +// This proto includes every type of field in both singular and repeated +// forms. +message TestAllTypes { + message NestedMessage { + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + enum NestedEnum { + NESTED_ENUM_UNSPECIFIED = 0; + FOO = 1; + BAR = 2; + BAZ = 3; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 single_int32 = 1; + int64 single_int64 = 2; + uint32 single_uint32 = 3; + uint64 single_uint64 = 4; + sint32 single_sint32 = 5; + sint64 single_sint64 = 6; + fixed32 single_fixed32 = 7; + fixed64 single_fixed64 = 8; + sfixed32 single_sfixed32 = 9; + sfixed64 single_sfixed64 = 10; + float single_float = 11; + double single_double = 12; + bool single_bool = 13; + string single_string = 14; + bytes single_bytes = 15; + + NestedMessage single_nested_message = 18; + ForeignMessage single_foreign_message = 19; + protobuf_unittest_import.ImportMessage single_import_message = 20; + + NestedEnum single_nested_enum = 21; + ForeignEnum single_foreign_enum = 22; + protobuf_unittest_import.ImportEnum single_import_enum = 23; + + // Defined in unittest_import_public.proto + protobuf_unittest_import.PublicImportMessage + single_public_import_message = 26; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + repeated protobuf_unittest_import.ImportMessage repeated_import_message = 50; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + repeated protobuf_unittest_import.ImportEnum repeated_import_enum = 53; + // Defined in unittest_import_public.proto + repeated protobuf_unittest_import.PublicImportMessage + repeated_public_import_message = 54; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + NestedTestAllTypes child = 1; + TestAllTypes payload = 2; + repeated NestedTestAllTypes repeated_child = 3; +} + +message TestDeprecatedFields { + int32 deprecated_int32 = 1 [deprecated=true]; +} + +// Define these after TestAllTypes to make sure the compiler can handle +// that. +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_UNSPECIFIED = 0; + FOREIGN_FOO = 4; + FOREIGN_BAR = 5; + FOREIGN_BAZ = 6; +} + +message TestReservedFields { + reserved 2, 15, 9 to 11; + reserved "bar", "baz"; +} + + +// Test that we can use NestedMessage from outside TestAllTypes. +message TestForeignNested { + TestAllTypes.NestedMessage foreign_nested = 1; +} + +// Test that really large tag numbers don't break anything. +message TestReallyLargeTagNumber { + // The largest possible tag number is 2^28 - 1, since the wire format uses + // three bits to communicate wire type. + int32 a = 1; + int32 bb = 268435455; +} + +message TestRecursiveMessage { + TestRecursiveMessage a = 1; + int32 i = 2; +} + +// Test that mutual recursion works. +message TestMutualRecursionA { + TestMutualRecursionB bb = 1; +} + +message TestMutualRecursionB { + TestMutualRecursionA a = 1; + int32 optional_int32 = 2; +} + + +// Test an enum that has multiple values with the same number. +enum TestEnumWithDupValue { + TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0; + option allow_alias = true; + + FOO1 = 1; + BAR1 = 2; + BAZ = 3; + FOO2 = 1; + BAR2 = 2; +} + +// Test an enum with large, unordered values. +enum TestSparseEnum { + TEST_SPARSE_ENUM_UNSPECIFIED = 0; + SPARSE_A = 123; + SPARSE_B = 62374; + SPARSE_C = 12589234; + SPARSE_D = -15; + SPARSE_E = -53452; + // In proto3, value 0 must be the first one specified + // SPARSE_F = 0; + SPARSE_G = 2; +} + +// Test message with CamelCase field names. This violates Protocol Buffer +// standard style. +message TestCamelCaseFieldNames { + int32 PrimitiveField = 1; + string StringField = 2; + ForeignEnum EnumField = 3; + ForeignMessage MessageField = 4; + + repeated int32 RepeatedPrimitiveField = 7; + repeated string RepeatedStringField = 8; + repeated ForeignEnum RepeatedEnumField = 9; + repeated ForeignMessage RepeatedMessageField = 10; +} + + +// We list fields out of order, to ensure that we're using field number and not +// field index to determine serialization order. +message TestFieldOrderings { + string my_string = 11; + int64 my_int = 1; + float my_float = 101; + message NestedMessage { + int64 oo = 2; + // The field name "b" fails to compile in proto1 because it conflicts with + // a local variable named "b" in one of the generated methods. Doh. + // This file needs to compile in proto1 to test backwards-compatibility. + int32 bb = 1; + } + + NestedMessage single_nested_message = 200; +} + +message SparseEnumMessage { + TestSparseEnum sparse_enum = 1; +} + +// Test String and Bytes: string is for valid UTF-8 strings +message OneString { + string data = 1; +} + +message MoreString { + repeated string data = 1; +} + +message OneBytes { + bytes data = 1; +} + +message MoreBytes { + bytes data = 1; +} + +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + int32 data = 1; +} + +message Uint32Message { + uint32 data = 1; +} + +message Int64Message { + int64 data = 1; +} + +message Uint64Message { + uint64 data = 1; +} + +message BoolMessage { + bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + } +} + +// Test messages for packed fields + +message TestPackedTypes { + repeated int32 packed_int32 = 90 [packed = true]; + repeated int64 packed_int64 = 91 [packed = true]; + repeated uint32 packed_uint32 = 92 [packed = true]; + repeated uint64 packed_uint64 = 93 [packed = true]; + repeated sint32 packed_sint32 = 94 [packed = true]; + repeated sint64 packed_sint64 = 95 [packed = true]; + repeated fixed32 packed_fixed32 = 96 [packed = true]; + repeated fixed64 packed_fixed64 = 97 [packed = true]; + repeated sfixed32 packed_sfixed32 = 98 [packed = true]; + repeated sfixed64 packed_sfixed64 = 99 [packed = true]; + repeated float packed_float = 100 [packed = true]; + repeated double packed_double = 101 [packed = true]; + repeated bool packed_bool = 102 [packed = true]; + repeated ForeignEnum packed_enum = 103 [packed = true]; +} + +// A message with the same fields as TestPackedTypes, but without packing. Used +// to test packed <-> unpacked wire compatibility. +message TestUnpackedTypes { + repeated int32 unpacked_int32 = 90 [packed = false]; + repeated int64 unpacked_int64 = 91 [packed = false]; + repeated uint32 unpacked_uint32 = 92 [packed = false]; + repeated uint64 unpacked_uint64 = 93 [packed = false]; + repeated sint32 unpacked_sint32 = 94 [packed = false]; + repeated sint64 unpacked_sint64 = 95 [packed = false]; + repeated fixed32 unpacked_fixed32 = 96 [packed = false]; + repeated fixed64 unpacked_fixed64 = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32 = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64 = 99 [packed = false]; + repeated float unpacked_float = 100 [packed = false]; + repeated double unpacked_double = 101 [packed = false]; + repeated bool unpacked_bool = 102 [packed = false]; + repeated ForeignEnum unpacked_enum = 103 [packed = false]; +} + +message TestRepeatedScalarDifferentTagSizes { + // Parsing repeated fixed size values used to fail. This message needs to be + // used in order to get a tag of the right size; all of the repeated fields + // in TestAllTypes didn't trigger the check. + repeated fixed32 repeated_fixed32 = 12; + // Check for a varint type, just for good measure. + repeated int32 repeated_int32 = 13; + + // These have two-byte tags. + repeated fixed64 repeated_fixed64 = 2046; + repeated int64 repeated_int64 = 2047; + + // Three byte tags. + repeated float repeated_float = 262142; + repeated uint64 repeated_uint64 = 262143; +} + +message TestCommentInjectionMessage { + // */ <- This should not close the generated doc comment + string a = 1; +} + + +// Test that RPC services work. +message FooRequest {} +message FooResponse {} + +message FooClientMessage {} +message FooServerMessage{} + +service TestService { + rpc Foo(FooRequest) returns (FooResponse); + rpc Bar(BarRequest) returns (BarResponse); +} + + +message BarRequest {} +message BarResponse {} + -- cgit v1.2.3 From 1ecef1a2f5b1063e2f8f4616508386543905466f Mon Sep 17 00:00:00 2001 From: Austin Schuh Date: Wed, 10 Jun 2015 23:33:07 -0700 Subject: Modified FindRubyTestDir to use GOOGLE_THIRD_PARTY_PROTOBUF --- src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index 6c203ab6..1b04cb32 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -47,6 +47,7 @@ namespace { string FindRubyTestDir(const string& file) { // Inspired by TestSourceDir() in src/google/protobuf/testing/googletest.cc. +#ifndef GOOGLE_THIRD_PARTY_PROTOBUF string prefix = "."; while (!File::Exists(prefix + "/src/google/protobuf/compiler/ruby" + file)) { if (!File::Exists(prefix)) { @@ -57,6 +58,9 @@ string FindRubyTestDir(const string& file) { prefix += "/.."; } return prefix + "/src/google/protobuf/compiler/ruby"; +#else + return "third_party/protobuf/src/google/protobuf/compiler/ruby"; +#endif // GOOGLE_THIRD_PARTY_PROTOBUF } // This test is a simple golden-file test over the output of the Ruby code -- cgit v1.2.3 From 39aaf21d5194fdc07c296847def8e7795279e041 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Thu, 11 Jun 2015 21:15:36 +0100 Subject: Reimplement enums as int values, and get rid of EnumHelper. This makes repeated fields really awkward at the moment - but when we reimplement RepeatedField to be backed by an array, we can cast the array directly... --- .../ProtocolBuffers.Test/CodedInputStreamTest.cs | 6 +- .../ProtocolBuffers.Test/CodedOutputStreamTest.cs | 10 +-- .../TestProtos/UnittestImportProto3.cs | 2 +- .../TestProtos/UnittestIssues.cs | 28 ++++--- .../TestProtos/UnittestProto3.cs | 65 ++++++++------- csharp/src/ProtocolBuffers/CodedInputStream.cs | 17 ++-- .../CodedOutputStream.ComputeSize.cs | 12 +-- csharp/src/ProtocolBuffers/CodedOutputStream.cs | 24 ++++-- .../DescriptorProtos/DescriptorProtoFile.cs | 55 +++++++------ csharp/src/ProtocolBuffers/EnumHelper.cs | 93 ---------------------- csharp/src/ProtocolBuffers/ICodedInputStream.cs | 11 +-- csharp/src/ProtocolBuffers/ICodedOutputStream.cs | 2 +- csharp/src/ProtocolBuffers/ProtocolBuffers.csproj | 1 - src/google/protobuf/compiler/csharp/csharp_enum.cc | 2 +- .../protobuf/compiler/csharp/csharp_enum_field.cc | 15 ++-- .../compiler/csharp/csharp_repeated_enum_field.cc | 2 +- 16 files changed, 137 insertions(+), 208 deletions(-) delete mode 100644 csharp/src/ProtocolBuffers/EnumHelper.cs (limited to 'src/google/protobuf/compiler') diff --git a/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs b/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs index 57650049..aa2da330 100644 --- a/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs +++ b/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs @@ -466,18 +466,18 @@ namespace Google.Protobuf } } - enum TestNegEnum : long { None = 0, Value = -2 } + enum TestNegEnum { None = 0, Value = -2 } [Test] public void TestNegativeEnum() { byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 }; CodedInputStream input = CodedInputStream.CreateInstance(bytes); - TestNegEnum val = TestNegEnum.None; + int val = 0; Assert.IsTrue(input.ReadEnum(ref val)); Assert.IsTrue(input.IsAtEnd); - Assert.AreEqual(TestNegEnum.Value, val); + Assert.AreEqual((int) TestNegEnum.Value, val); } [Test] diff --git a/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs b/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs index df80b3af..fcbb7f8d 100644 --- a/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs +++ b/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs @@ -296,27 +296,27 @@ namespace Google.Protobuf public void TestNegativeEnumNoTag() { Assert.AreEqual(10, CodedOutputStream.ComputeInt32SizeNoTag(-2)); - Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag(TestNegEnum.Value)); + Assert.AreEqual(10, CodedOutputStream.ComputeEnumSizeNoTag((int) TestNegEnum.Value)); byte[] bytes = new byte[10]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnumNoTag(TestNegEnum.Value); + output.WriteEnumNoTag((int) TestNegEnum.Value); Assert.AreEqual(0, output.SpaceLeft); Assert.AreEqual("FE-FF-FF-FF-FF-FF-FF-FF-FF-01", BitConverter.ToString(bytes)); } - enum TestNegEnum : long { None = 0, Value = -2 } + enum TestNegEnum { None = 0, Value = -2 } [Test] public void TestNegativeEnumWithTag() { Assert.AreEqual(11, CodedOutputStream.ComputeInt32Size(8, -2)); - Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, TestNegEnum.Value)); + Assert.AreEqual(11, CodedOutputStream.ComputeEnumSize(8, (int) TestNegEnum.Value)); byte[] bytes = new byte[11]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnum(8, "", TestNegEnum.Value); + output.WriteEnum(8, "", (int) TestNegEnum.Value); Assert.AreEqual(0, output.SpaceLeft); //fyi, 0x40 == 0x08 << 3 + 0, field num + wire format shift diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs index 1eb87f05..4b62794a 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs @@ -49,7 +49,7 @@ namespace Google.Protobuf.TestProtos { } #region Enums - public enum ImportEnum : long { + public enum ImportEnum { IMPORT_ENUM_UNSPECIFIED = 0, IMPORT_FOO = 7, IMPORT_BAR = 8, diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs index fc696cf0..14ca78a4 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs @@ -75,13 +75,13 @@ namespace UnitTest.Issues.TestProtos { } #region Enums - public enum NegativeEnum : long { + public enum NegativeEnum { NEGATIVE_ENUM_ZERO = 0, FiveBelow = -5, MinusOne = -1, } - public enum DeprecatedEnum : long { + public enum DeprecatedEnum { DEPRECATED_ZERO = 0, one = 1, } @@ -156,7 +156,7 @@ namespace UnitTest.Issues.TestProtos { public void WriteTo(pb::ICodedOutputStream output) { string[] fieldNames = _fieldNames; if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { - output.WriteEnum(1, fieldNames[1], Value); + output.WriteEnum(1, fieldNames[1], (int) Value); } output.WriteEnumArray(2, fieldNames[2], values_); output.WritePackedEnumArray(3, fieldNames[0], packedValues_); @@ -165,13 +165,13 @@ namespace UnitTest.Issues.TestProtos { public int CalculateSize() { int size = 0; if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { - size += pb::CodedOutputStream.ComputeEnumSize(1, Value); + size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Value); } { int dataSize = 0; if (values_.Count > 0) { foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in values_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 1 * values_.Count; @@ -181,7 +181,7 @@ namespace UnitTest.Issues.TestProtos { int dataSize = 0; if (packedValues_.Count > 0) { foreach (global::UnitTest.Issues.TestProtos.NegativeEnum element in packedValues_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 1; @@ -220,8 +220,9 @@ namespace UnitTest.Issues.TestProtos { } break; case 8: { - input.ReadEnum(ref value_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) tmp;break; } case 18: case 16: { @@ -422,7 +423,7 @@ namespace UnitTest.Issues.TestProtos { } output.WriteMessageArray(4, fieldNames[2], messageArray_); if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { - output.WriteEnum(5, fieldNames[1], EnumValue); + output.WriteEnum(5, fieldNames[1], (int) EnumValue); } output.WritePackedEnumArray(6, fieldNames[0], enumArray_); } @@ -449,13 +450,13 @@ namespace UnitTest.Issues.TestProtos { size += pb::CodedOutputStream.ComputeMessageSize(4, element); } if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { - size += pb::CodedOutputStream.ComputeEnumSize(5, EnumValue); + size += pb::CodedOutputStream.ComputeEnumSize(5, (int) EnumValue); } { int dataSize = 0; if (enumArray_.Count > 0) { foreach (global::UnitTest.Issues.TestProtos.DeprecatedEnum element in enumArray_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 1; @@ -524,8 +525,9 @@ namespace UnitTest.Issues.TestProtos { break; } case 40: { - input.ReadEnum(ref enumValue_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) tmp;break; } case 50: case 48: { diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs index e231bb95..3e5bb8b6 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs @@ -372,14 +372,14 @@ namespace Google.Protobuf.TestProtos { } #region Enums - public enum ForeignEnum : long { + public enum ForeignEnum { FOREIGN_UNSPECIFIED = 0, FOREIGN_FOO = 4, FOREIGN_BAR = 5, FOREIGN_BAZ = 6, } - public enum TestEnumWithDupValue : long { + public enum TestEnumWithDupValue { TEST_ENUM_WITH_DUP_VALUE_UNSPECIFIED = 0, FOO1 = 1, BAR1 = 2, @@ -388,7 +388,7 @@ namespace Google.Protobuf.TestProtos { BAR2 = 2, } - public enum TestSparseEnum : long { + public enum TestSparseEnum { TEST_SPARSE_ENUM_UNSPECIFIED = 0, SPARSE_A = 123, SPARSE_B = 62374, @@ -945,13 +945,13 @@ namespace Google.Protobuf.TestProtos { output.WriteMessage(20, fieldNames[35], SingleImportMessage); } if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) { - output.WriteEnum(21, fieldNames[38], SingleNestedEnum); + output.WriteEnum(21, fieldNames[38], (int) SingleNestedEnum); } if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - output.WriteEnum(22, fieldNames[32], SingleForeignEnum); + output.WriteEnum(22, fieldNames[32], (int) SingleForeignEnum); } if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) { - output.WriteEnum(23, fieldNames[34], SingleImportEnum); + output.WriteEnum(23, fieldNames[34], (int) SingleImportEnum); } if (singlePublicImportMessage_ != null) { output.WriteMessage(26, fieldNames[40], SinglePublicImportMessage); @@ -1049,13 +1049,13 @@ namespace Google.Protobuf.TestProtos { size += pb::CodedOutputStream.ComputeMessageSize(20, SingleImportMessage); } if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(21, SingleNestedEnum); + size += pb::CodedOutputStream.ComputeEnumSize(21, (int) SingleNestedEnum); } if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(22, SingleForeignEnum); + size += pb::CodedOutputStream.ComputeEnumSize(22, (int) SingleForeignEnum); } if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(23, SingleImportEnum); + size += pb::CodedOutputStream.ComputeEnumSize(23, (int) SingleImportEnum); } if (singlePublicImportMessage_ != null) { size += pb::CodedOutputStream.ComputeMessageSize(26, SinglePublicImportMessage); @@ -1205,7 +1205,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (repeatedNestedEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum element in repeatedNestedEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2; @@ -1216,7 +1216,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (repeatedForeignEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ForeignEnum element in repeatedForeignEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2; @@ -1227,7 +1227,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (repeatedImportEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ImportEnum element in repeatedImportEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2; @@ -1472,16 +1472,19 @@ namespace Google.Protobuf.TestProtos { break; } case 168: { - input.ReadEnum(ref singleNestedEnum_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) tmp;break; } case 176: { - input.ReadEnum(ref singleForeignEnum_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) tmp;break; } case 184: { - input.ReadEnum(ref singleImportEnum_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) tmp;break; } case 210: { if (singlePublicImportMessage_ == null) { @@ -1634,7 +1637,7 @@ namespace Google.Protobuf.TestProtos { #region Nested types [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { - public enum NestedEnum : long { + public enum NestedEnum { NESTED_ENUM_UNSPECIFIED = 0, FOO = 1, BAR = 2, @@ -2865,7 +2868,7 @@ namespace Google.Protobuf.TestProtos { output.WriteString(2, fieldNames[7], StringField); } if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - output.WriteEnum(3, fieldNames[0], EnumField); + output.WriteEnum(3, fieldNames[0], (int) EnumField); } if (messageField_ != null) { output.WriteMessage(4, fieldNames[1], MessageField); @@ -2885,7 +2888,7 @@ namespace Google.Protobuf.TestProtos { size += pb::CodedOutputStream.ComputeStringSize(2, StringField); } if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(3, EnumField); + size += pb::CodedOutputStream.ComputeEnumSize(3, (int) EnumField); } if (messageField_ != null) { size += pb::CodedOutputStream.ComputeMessageSize(4, MessageField); @@ -2912,7 +2915,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (repeatedEnumField_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ForeignEnum element in repeatedEnumField_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 1; @@ -2976,8 +2979,9 @@ namespace Google.Protobuf.TestProtos { break; } case 24: { - input.ReadEnum(ref enumField_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) tmp;break; } case 34: { if (messageField_ == null) { @@ -3361,14 +3365,14 @@ namespace Google.Protobuf.TestProtos { public void WriteTo(pb::ICodedOutputStream output) { string[] fieldNames = _fieldNames; if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) { - output.WriteEnum(1, fieldNames[0], SparseEnum); + output.WriteEnum(1, fieldNames[0], (int) SparseEnum); } } public int CalculateSize() { int size = 0; if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) { - size += pb::CodedOutputStream.ComputeEnumSize(1, SparseEnum); + size += pb::CodedOutputStream.ComputeEnumSize(1, (int) SparseEnum); } return size; } @@ -3400,8 +3404,9 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadEnum(ref sparseEnum_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) tmp;break; } } } @@ -4769,7 +4774,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (packedEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ForeignEnum element in packedEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2; @@ -5156,7 +5161,7 @@ namespace Google.Protobuf.TestProtos { int dataSize = 0; if (unpackedEnum_.Count > 0) { foreach (global::Google.Protobuf.TestProtos.ForeignEnum element in unpackedEnum_) { - dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element); + dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element); } size += dataSize; size += 2 * unpackedEnum_.Count; diff --git a/csharp/src/ProtocolBuffers/CodedInputStream.cs b/csharp/src/ProtocolBuffers/CodedInputStream.cs index 685d7702..d5cab6fd 100644 --- a/csharp/src/ProtocolBuffers/CodedInputStream.cs +++ b/csharp/src/ProtocolBuffers/CodedInputStream.cs @@ -434,11 +434,10 @@ namespace Google.Protobuf /// then the ref value is set and it returns true. Otherwise the unknown output /// value is set and this method returns false. /// - public bool ReadEnum(ref T value) - where T : struct, IComparable, IFormattable + public bool ReadEnum(ref int value) { - int number = (int) ReadRawVarint32(); - value = EnumHelper.FromInt32(number); + // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. + value = (int) ReadRawVarint32(); return true; } @@ -796,7 +795,7 @@ namespace Google.Protobuf public void ReadEnumArray(uint fieldTag, string fieldName, ICollection list) where T : struct, IComparable, IFormattable { - T value = default(T); + int value = 0; WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag); // 2.3 allows packed form even if the field is not declared packed. @@ -806,8 +805,9 @@ namespace Google.Protobuf int limit = PushLimit(length); while (!ReachedLimit) { - ReadEnum(ref value); - list.Add(value); + ReadEnum(ref value); + // TODO(jonskeet): Avoid this horrible boxing! + list.Add((T)(object)value); } PopLimit(limit); } @@ -816,7 +816,8 @@ namespace Google.Protobuf do { ReadEnum(ref value); - list.Add(value); + // TODO(jonskeet): Avoid this horrible boxing! + list.Add((T)(object) value); } while (ContinueArray(fieldTag)); } } diff --git a/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs b/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs index 58475ff7..96be9db5 100644 --- a/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs +++ b/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs @@ -196,7 +196,7 @@ namespace Google.Protobuf /// enum field, including the tag. The caller is responsible for /// converting the enum value to its numeric value. /// - public static int ComputeEnumSize(int fieldNumber, T value) where T : struct, IComparable, IFormattable + public static int ComputeEnumSize(int fieldNumber, int value) { return ComputeTagSize(fieldNumber) + ComputeEnumSizeNoTag(value); } @@ -371,10 +371,10 @@ namespace Google.Protobuf /// enum field, including the tag. The caller is responsible for /// converting the enum value to its numeric value. /// - public static int ComputeEnumSizeNoTag(T value) where T : struct, IComparable, IFormattable + public static int ComputeEnumSizeNoTag(int value) { - int serializedValue = EnumHelper.ToInt32(value); - return ComputeInt32SizeNoTag(serializedValue); + // Currently just a pass-through, but it's nice to separate it logically. + return ComputeInt32SizeNoTag(value); } /// @@ -555,7 +555,7 @@ namespace Google.Protobuf case FieldType.SInt64: return ComputeSInt64Size(fieldNumber, (long) value); case FieldType.Enum: - return ComputeEnumSize(fieldNumber, Convert.ToInt64(value)); + return ComputeEnumSize(fieldNumber, (int) value); default: throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); } @@ -605,7 +605,7 @@ namespace Google.Protobuf case FieldType.SInt64: return ComputeSInt64SizeNoTag((long) value); case FieldType.Enum: - return ComputeEnumSizeNoTag(Convert.ToInt64(value)); + return ComputeEnumSizeNoTag((int) value); default: throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); } diff --git a/csharp/src/ProtocolBuffers/CodedOutputStream.cs b/csharp/src/ProtocolBuffers/CodedOutputStream.cs index f55f8ca2..e3f0c700 100644 --- a/csharp/src/ProtocolBuffers/CodedOutputStream.cs +++ b/csharp/src/ProtocolBuffers/CodedOutputStream.cs @@ -37,6 +37,7 @@ using System; using System.Collections; using System.IO; +using System.Linq; using System.Text; using Google.Protobuf.Collections; using Google.Protobuf.Descriptors; @@ -350,10 +351,11 @@ namespace Google.Protobuf WriteRawVarint32(value); } - public void WriteEnum(int fieldNumber, string fieldName, T value) where T : struct, IComparable, IFormattable + public void WriteEnum(int fieldNumber, string fieldName, int value) { + // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. WriteTag(fieldNumber, WireFormat.WireType.Varint); - WriteInt32NoTag(EnumHelper.ToInt32(value)); + WriteInt32NoTag(value); } public void WriteSFixed32(int fieldNumber, string fieldName, int value) @@ -595,9 +597,9 @@ namespace Google.Protobuf WriteRawVarint32(value); } - public void WriteEnumNoTag(T value) where T : struct, IComparable, IFormattable + public void WriteEnumNoTag(int value) { - WriteInt32NoTag(EnumHelper.ToInt32(value)); + WriteInt32NoTag(value); } public void WriteSFixed32NoTag(int value) @@ -774,7 +776,12 @@ namespace Google.Protobuf public void WriteEnumArray(int fieldNumber, string fieldName, RepeatedField list) where T : struct, IComparable, IFormattable { - foreach (T value in list) + if (list.Count == 0) + { + return; + } + // TODO(jonskeet): Avoid the Cast call here. Work out a better mass "T to int" conversion. + foreach (int value in list.Cast()) { WriteEnum(fieldNumber, fieldName, value); } @@ -1005,10 +1012,13 @@ namespace Google.Protobuf { return; } - uint size = list.CalculateSize(ComputeEnumSizeNoTag); + // Obviously, we'll want to get rid of this hack... + var temporaryHack = new RepeatedField(); + temporaryHack.Add(list.Cast()); + uint size = temporaryHack.CalculateSize(ComputeEnumSizeNoTag); WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); WriteRawVarint32(size); - foreach (T value in list) + foreach (int value in temporaryHack) { WriteEnumNoTag(value); } diff --git a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs index b18b63bf..eb96dfcf 100644 --- a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs +++ b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs @@ -1360,10 +1360,10 @@ namespace Google.Protobuf.DescriptorProtos { output.WriteInt32(3, fieldNames[4], Number); } if (Label != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) { - output.WriteEnum(4, fieldNames[2], Label); + output.WriteEnum(4, fieldNames[2], (int) Label); } if (Type != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) { - output.WriteEnum(5, fieldNames[7], Type); + output.WriteEnum(5, fieldNames[7], (int) Type); } if (TypeName != "") { output.WriteString(6, fieldNames[8], TypeName); @@ -1388,10 +1388,10 @@ namespace Google.Protobuf.DescriptorProtos { size += pb::CodedOutputStream.ComputeInt32Size(3, Number); } if (Label != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) { - size += pb::CodedOutputStream.ComputeEnumSize(4, Label); + size += pb::CodedOutputStream.ComputeEnumSize(4, (int) Label); } if (Type != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) { - size += pb::CodedOutputStream.ComputeEnumSize(5, Type); + size += pb::CodedOutputStream.ComputeEnumSize(5, (int) Type); } if (TypeName != "") { size += pb::CodedOutputStream.ComputeStringSize(6, TypeName); @@ -1477,12 +1477,14 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 32: { - input.ReadEnum(ref label_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + label_ = (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label) tmp;break; } case 40: { - input.ReadEnum(ref type_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + type_ = (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type) tmp;break; } case 50: { input.ReadString(ref typeName_); @@ -1510,7 +1512,7 @@ namespace Google.Protobuf.DescriptorProtos { #region Nested types [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { - public enum Type : long { + public enum Type { TYPE_DOUBLE = 1, TYPE_FLOAT = 2, TYPE_INT64 = 3, @@ -1531,7 +1533,7 @@ namespace Google.Protobuf.DescriptorProtos { TYPE_SINT64 = 18, } - public enum Label : long { + public enum Label { LABEL_OPTIONAL = 1, LABEL_REQUIRED = 2, LABEL_REPEATED = 3, @@ -2489,7 +2491,7 @@ namespace Google.Protobuf.DescriptorProtos { output.WriteString(8, fieldNames[8], JavaOuterClassname); } if (OptimizeFor != global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED) { - output.WriteEnum(9, fieldNames[12], OptimizeFor); + output.WriteEnum(9, fieldNames[12], (int) OptimizeFor); } if (JavaMultipleFiles != false) { output.WriteBool(10, fieldNames[7], JavaMultipleFiles); @@ -2545,7 +2547,7 @@ namespace Google.Protobuf.DescriptorProtos { size += pb::CodedOutputStream.ComputeBoolSize(27, JavaStringCheckUtf8); } if (OptimizeFor != global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED) { - size += pb::CodedOutputStream.ComputeEnumSize(9, OptimizeFor); + size += pb::CodedOutputStream.ComputeEnumSize(9, (int) OptimizeFor); } if (GoPackage != "") { size += pb::CodedOutputStream.ComputeStringSize(11, GoPackage); @@ -2652,8 +2654,9 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 72: { - input.ReadEnum(ref optimizeFor_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + optimizeFor_ = (global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode) tmp;break; } case 80: { input.ReadBool(ref javaMultipleFiles_); @@ -2710,7 +2713,7 @@ namespace Google.Protobuf.DescriptorProtos { #region Nested types [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { - public enum OptimizeMode : long { + public enum OptimizeMode { SPEED = 1, CODE_SIZE = 2, LITE_RUNTIME = 3, @@ -3015,7 +3018,7 @@ namespace Google.Protobuf.DescriptorProtos { public void WriteTo(pb::ICodedOutputStream output) { string[] fieldNames = _fieldNames; if (Ctype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING) { - output.WriteEnum(1, fieldNames[0], Ctype); + output.WriteEnum(1, fieldNames[0], (int) Ctype); } if (Packed != false) { output.WriteBool(2, fieldNames[4], Packed); @@ -3027,7 +3030,7 @@ namespace Google.Protobuf.DescriptorProtos { output.WriteBool(5, fieldNames[3], Lazy); } if (Jstype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL) { - output.WriteEnum(6, fieldNames[2], Jstype); + output.WriteEnum(6, fieldNames[2], (int) Jstype); } if (Weak != false) { output.WriteBool(10, fieldNames[6], Weak); @@ -3038,13 +3041,13 @@ namespace Google.Protobuf.DescriptorProtos { public int CalculateSize() { int size = 0; if (Ctype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING) { - size += pb::CodedOutputStream.ComputeEnumSize(1, Ctype); + size += pb::CodedOutputStream.ComputeEnumSize(1, (int) Ctype); } if (Packed != false) { size += pb::CodedOutputStream.ComputeBoolSize(2, Packed); } if (Jstype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL) { - size += pb::CodedOutputStream.ComputeEnumSize(6, Jstype); + size += pb::CodedOutputStream.ComputeEnumSize(6, (int) Jstype); } if (Lazy != false) { size += pb::CodedOutputStream.ComputeBoolSize(5, Lazy); @@ -3104,8 +3107,9 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 8: { - input.ReadEnum(ref ctype_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + ctype_ = (global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType) tmp;break; } case 16: { input.ReadBool(ref packed_); @@ -3120,8 +3124,9 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 48: { - input.ReadEnum(ref jstype_); - break; + int tmp = 0; + input.ReadEnum(ref tmp); + jstype_ = (global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType) tmp;break; } case 80: { input.ReadBool(ref weak_); @@ -3138,13 +3143,13 @@ namespace Google.Protobuf.DescriptorProtos { #region Nested types [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] public static partial class Types { - public enum CType : long { + public enum CType { STRING = 0, CORD = 1, STRING_PIECE = 2, } - public enum JSType : long { + public enum JSType { JS_NORMAL = 0, JS_STRING = 1, JS_NUMBER = 2, diff --git a/csharp/src/ProtocolBuffers/EnumHelper.cs b/csharp/src/ProtocolBuffers/EnumHelper.cs deleted file mode 100644 index 1cf18985..00000000 --- a/csharp/src/ProtocolBuffers/EnumHelper.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Linq.Expressions; -using System.Text; - -namespace Google.Protobuf -{ - public class EnumHelper where T : struct, IComparable, IFormattable - { - // TODO(jonskeet): For snmall enums, use something lighter-weight than a dictionary? - private static readonly Dictionary _byNumber; - private static readonly Dictionary _byName; - private static readonly Func toRawValue; - private static readonly Func fromRawValue; - - private const long UnknownValueBase = 0x100000000L; - - static EnumHelper() - { - if (!typeof(T).IsEnum) - { - throw new InvalidOperationException(string.Format("{0} is not an enum type", typeof(T).FullName)); - } - if (Enum.GetUnderlyingType(typeof(T)) != typeof(long)) - { - throw new InvalidOperationException(string.Format("{0} does not have long as an underlying type", typeof(T).FullName)); - } - // It will actually be a T[], but the CLR will let us convert. - long[] array = (long[])Enum.GetValues(typeof(T)); - _byNumber = new Dictionary(array.Length); - foreach (long i in array) - { - _byNumber[(int) i] = (T)(object)i; - } - string[] names = (string[])Enum.GetNames(typeof(T)); - _byName = new Dictionary(); - foreach (var name in names) - { - _byName[name] = (T) Enum.Parse(typeof(T), name, false); - } - - ParameterExpression param1 = Expression.Parameter(typeof(T), "x"); - ParameterExpression param2 = Expression.Parameter(typeof(long), "x"); - Expression convertedParam1 = Expression.Convert(param1, typeof(long)); - Expression convertedParam2 = Expression.Convert(param2, typeof(T)); - toRawValue = Expression.Lambda>(convertedParam1, param1).Compile(); - fromRawValue = Expression.Lambda>(convertedParam2, param2).Compile(); - } - - /// - /// Converts the given 32-bit integer into a value of the enum type. - /// If the integer is a known, named value, that is returned; otherwise, - /// a value which is outside the range of 32-bit integers but which preserves - /// the original integer is returned. - /// - public static T FromInt32(int value) - { - T validValue; - return _byNumber.TryGetValue(value, out validValue) ? validValue : FromRawValue((long) value | UnknownValueBase); - } - - /// - /// Converts a value of the enum type to a 32-bit integer. This reverses - /// . - /// - public static int ToInt32(T value) - { - return (int)GetRawValue(value); - } - - public static bool IsKnownValue(T value) - { - long raw = GetRawValue(value); - if (raw >= int.MinValue && raw <= int.MaxValue) - { - return _byNumber.ContainsKey((int)raw); - } - return false; - } - - private static long GetRawValue(T value) - { - return toRawValue(value); - } - - private static T FromRawValue(long value) - { - return fromRawValue(value); - } - - } -} diff --git a/csharp/src/ProtocolBuffers/ICodedInputStream.cs b/csharp/src/ProtocolBuffers/ICodedInputStream.cs index 748589a0..d962e62b 100644 --- a/csharp/src/ProtocolBuffers/ICodedInputStream.cs +++ b/csharp/src/ProtocolBuffers/ICodedInputStream.cs @@ -146,14 +146,11 @@ namespace Google.Protobuf bool ReadUInt32(ref uint value); /// - /// Reads an enum field value from the stream. If the enum is valid for type T, - /// then the ref value is set and it returns true. Otherwise, if a value is present - /// but invalid for the proto enum, it is still set in the field as a "preserved - /// but invalid" value, and the method returns true. If no value can be read, the - /// method does not affect the parameter and returns false. + /// Reads an enum field value from the stream. This performs no checking + /// as to whether the enum value is known to the enum type as it was present + /// when the code was generated. /// - bool ReadEnum(ref T value) - where T : struct, IComparable, IFormattable; + bool ReadEnum(ref int value); /// /// Reads an sfixed32 field value from the stream. diff --git a/csharp/src/ProtocolBuffers/ICodedOutputStream.cs b/csharp/src/ProtocolBuffers/ICodedOutputStream.cs index e51c10a4..921400ac 100644 --- a/csharp/src/ProtocolBuffers/ICodedOutputStream.cs +++ b/csharp/src/ProtocolBuffers/ICodedOutputStream.cs @@ -148,7 +148,7 @@ namespace Google.Protobuf /// /// Writes an enum field value, including tag, to the stream. /// - void WriteEnum(int fieldNumber, string fieldName, T value) where T : struct, IComparable, IFormattable; + void WriteEnum(int fieldNumber, string fieldName, int value); /// /// Writes a fixed 32-bit field value, including tag, to the stream. diff --git a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj index d15f1306..efd387a2 100644 --- a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj +++ b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj @@ -84,7 +84,6 @@ - diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index d511bba3..0e8f9836 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -58,7 +58,7 @@ EnumGenerator::~EnumGenerator() { void EnumGenerator::Generate(io::Printer* printer) { WriteGeneratedCodeAttributes(printer); - printer->Print("$access_level$ enum $name$ : long {\n", + printer->Print("$access_level$ enum $name$ {\n", "access_level", class_access_level(), "name", descriptor_->name()); printer->Indent(); diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index ee9d6a1d..3494b228 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -54,14 +54,17 @@ EnumFieldGenerator::~EnumFieldGenerator() { } void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // TODO(jonskeet): Get rid of the temporary variable when we sanitize CodedInputStream not to use ref. printer->Print(variables_, - "input.ReadEnum(ref $name$_);\n"); + "int tmp = 0;\n" + "input.ReadEnum(ref tmp);\n" + "$name$_ = ($type_name$) tmp;"); } void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, fieldNames[$field_ordinal$], $property_name$);\n" + " output.WriteEnum($number$, fieldNames[$field_ordinal$], (int) $property_name$);\n" "}\n"); } @@ -69,7 +72,7 @@ void EnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, $property_name$);\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" "}\n"); } @@ -85,7 +88,7 @@ void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { // TODO(jonskeet): What about if we read the default value? printer->Print( variables_, - "$type_name$ enumValue = $default_value$;\n" + "int enumValue = 0;\n" "if(input.ReadEnum(ref enumValue)) {\n" " $oneof_name$_ = enumValue;\n" " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" @@ -96,7 +99,7 @@ void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, fieldNames[$field_ordinal$], (long) $property_name$, $property_name$);\n" + " output.WriteEnum($number$, fieldNames[$field_ordinal$], (int) $property_name$);\n" "}\n"); } @@ -104,7 +107,7 @@ void EnumOneofFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " size += pb::CodedOutputStream.ComputeEnumSize($number$, (long) $property_name$);\n" + " size += pb::CodedOutputStream.ComputeEnumSize($number$, (int) $property_name$);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index ebbbf3be..937d675a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -99,7 +99,7 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer printer->Print( variables_, "foreach ($type_name$ element in $name$_) {\n" - " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag(element);\n" + " dataSize += pb::CodedOutputStream.ComputeEnumSizeNoTag((int) element);\n" "}\n" "size += dataSize;\n"); int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); -- cgit v1.2.3 From 96ddf01aed1a49d73a7fda50e28c431ffc977e5a Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 12 Jun 2015 09:53:12 +0100 Subject: Coded*Stream streamlining. Remove ICodedInputStream and ICodedOutputStream, and rewrite CodedInputStream and CodedOutputStream to be specific to the binary format. If we want to support text-based formats, that can be a whole different serialization mechanism. --- .../ProtocolBuffers.Test/CodedInputStreamTest.cs | 53 +- .../ProtocolBuffers.Test/CodedOutputStreamTest.cs | 43 +- .../TestProtos/UnittestImportProto3.cs | 18 +- .../TestProtos/UnittestImportPublicProto3.cs | 18 +- .../TestProtos/UnittestIssues.cs | 100 +- .../TestProtos/UnittestProto3.cs | 1000 +++++++------------- csharp/src/ProtocolBuffers/CodedInputStream.cs | 427 ++------- .../CodedOutputStream.ComputeSize.cs | 132 +-- csharp/src/ProtocolBuffers/CodedOutputStream.cs | 249 ++--- .../DescriptorProtos/DescriptorProtoFile.cs | 719 ++++++-------- csharp/src/ProtocolBuffers/Extensions.cs | 2 +- csharp/src/ProtocolBuffers/ICodedInputStream.cs | 293 ------ csharp/src/ProtocolBuffers/ICodedOutputStream.cs | 347 ------- csharp/src/ProtocolBuffers/IMessage.cs | 4 +- csharp/src/ProtocolBuffers/MessageParser.cs | 2 +- csharp/src/ProtocolBuffers/ProtocolBuffers.csproj | 2 - .../protobuf/compiler/csharp/csharp_enum_field.cc | 16 +- .../protobuf/compiler/csharp/csharp_message.cc | 17 +- .../compiler/csharp/csharp_message_field.cc | 3 +- .../compiler/csharp/csharp_primitive_field.cc | 16 +- .../compiler/csharp/csharp_repeated_enum_field.cc | 4 +- .../csharp/csharp_repeated_message_field.cc | 4 +- .../csharp/csharp_repeated_primitive_field.cc | 6 +- 23 files changed, 879 insertions(+), 2596 deletions(-) delete mode 100644 csharp/src/ProtocolBuffers/ICodedInputStream.cs delete mode 100644 csharp/src/ProtocolBuffers/ICodedOutputStream.cs (limited to 'src/google/protobuf/compiler') diff --git a/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs b/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs index aa2da330..450662a6 100644 --- a/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs +++ b/csharp/src/ProtocolBuffers.Test/CodedInputStreamTest.cs @@ -336,13 +336,11 @@ namespace Google.Protobuf CodedInputStream input = CodedInputStream.CreateInstance(ms); uint testtag; - string ignore; - Assert.IsTrue(input.ReadTag(out testtag, out ignore)); + Assert.IsTrue(input.ReadTag(out testtag)); Assert.AreEqual(tag, testtag); - ByteString bytes = null; // TODO(jonskeet): Should this be ArgumentNullException instead? - Assert.Throws(() => input.ReadBytes(ref bytes)); + Assert.Throws(() => input.ReadBytes()); } private static TestRecursiveMessage MakeRecursiveMessage(int depth) @@ -435,13 +433,10 @@ namespace Google.Protobuf CodedInputStream input = CodedInputStream.CreateInstance(ms); - uint testtag; - string ignored; - - Assert.IsTrue(input.ReadTag(out testtag, out ignored)); - Assert.AreEqual(tag, testtag); - string text = null; - input.ReadString(ref text); + uint actualTag; + Assert.IsTrue(input.ReadTag(out actualTag)); + Assert.AreEqual(tag, actualTag); + string text = input.ReadString(); Assert.AreEqual('\ufffd', text[0]); } @@ -473,11 +468,8 @@ namespace Google.Protobuf { byte[] bytes = new byte[10] { 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 }; CodedInputStream input = CodedInputStream.CreateInstance(bytes); - int val = 0; - - Assert.IsTrue(input.ReadEnum(ref val)); + Assert.AreEqual((int)TestNegEnum.Value, input.ReadEnum()); Assert.IsTrue(input.IsAtEnd); - Assert.AreEqual((int) TestNegEnum.Value, val); } [Test] @@ -487,17 +479,16 @@ namespace Google.Protobuf int msgSize = 1 + 1 + arraySize; byte[] bytes = new byte[msgSize]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WritePackedInt32Array(8, "", new RepeatedField { 0, -1, -2, -3, -4, -5 }); + output.WritePackedInt32Array(8, new RepeatedField { 0, -1, -2, -3, -4, -5 }); Assert.AreEqual(0, output.SpaceLeft); CodedInputStream input = CodedInputStream.CreateInstance(bytes); uint tag; - string name; - Assert.IsTrue(input.ReadTag(out tag, out name)); + Assert.IsTrue(input.ReadTag(out tag)); List values = new List(); - input.ReadEnumArray(tag, name, values); + input.ReadEnumArray(tag, values); Assert.AreEqual(6, values.Count); Assert.AreEqual(TestNegEnum.None, values[0]); @@ -512,17 +503,16 @@ namespace Google.Protobuf int msgSize = arraySize; byte[] bytes = new byte[msgSize]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteInt32Array(8, "", new RepeatedField { 0, -1, -2, -3, -4, -5 }); + output.WriteInt32Array(8, new RepeatedField { 0, -1, -2, -3, -4, -5 }); Assert.AreEqual(0, output.SpaceLeft); CodedInputStream input = CodedInputStream.CreateInstance(bytes); uint tag; - string name; - Assert.IsTrue(input.ReadTag(out tag, out name)); + Assert.IsTrue(input.ReadTag(out tag)); List values = new List(); - input.ReadEnumArray(tag, name, values); + input.ReadEnumArray(tag, values); Assert.AreEqual(6, values.Count); Assert.AreEqual(TestNegEnum.None, values[0]); @@ -537,26 +527,21 @@ namespace Google.Protobuf using (var ms = new MemoryStream()) { CodedOutputStream output = CodedOutputStream.CreateInstance(ms); - output.WriteField(FieldType.Bytes, 1, "bytes", ByteString.CopyFrom(new byte[100])); - output.WriteField(FieldType.Bytes, 2, "bytes", ByteString.CopyFrom(new byte[100])); + output.WriteBytes(1, ByteString.CopyFrom(new byte[100])); + output.WriteBytes(2, ByteString.CopyFrom(new byte[100])); output.Flush(); ms.Position = 0; CodedInputStream input = CodedInputStream.CreateInstance(ms, new byte[ms.Length / 2]); uint tag; - string ignore; - ByteString value; - - Assert.IsTrue(input.ReadTag(out tag, out ignore)); + Assert.IsTrue(input.ReadTag(out tag)); Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag)); - value = ByteString.Empty; - Assert.IsTrue(input.ReadBytes(ref value) && value.Length == 100); + Assert.AreEqual(100, input.ReadBytes().Length); - Assert.IsTrue(input.ReadTag(out tag, out ignore)); + Assert.IsTrue(input.ReadTag(out tag)); Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag)); - value = ByteString.Empty; - Assert.IsTrue(input.ReadBytes(ref value) && value.Length == 100); + Assert.AreEqual(100, input.ReadBytes().Length); } } } diff --git a/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs b/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs index fcbb7f8d..682c005a 100644 --- a/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs +++ b/csharp/src/ProtocolBuffers.Test/CodedOutputStreamTest.cs @@ -316,7 +316,7 @@ namespace Google.Protobuf byte[] bytes = new byte[11]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnum(8, "", (int) TestNegEnum.Value); + output.WriteEnum(8, (int) TestNegEnum.Value); Assert.AreEqual(0, output.SpaceLeft); //fyi, 0x40 == 0x08 << 3 + 0, field num + wire format shift @@ -330,18 +330,17 @@ namespace Google.Protobuf int msgSize = 1 + 1 + arraySize; byte[] bytes = new byte[msgSize]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WritePackedEnumArray(8, "", new RepeatedField { + output.WritePackedEnumArray(8, new RepeatedField { 0, (TestNegEnum) (-1), TestNegEnum.Value, (TestNegEnum) (-3), (TestNegEnum) (-4), (TestNegEnum) (-5) }); Assert.AreEqual(0, output.SpaceLeft); CodedInputStream input = CodedInputStream.CreateInstance(bytes); uint tag; - string name; - Assert.IsTrue(input.ReadTag(out tag, out name)); + Assert.IsTrue(input.ReadTag(out tag)); List values = new List(); - input.ReadInt32Array(tag, name, values); + input.ReadInt32Array(tag, values); Assert.AreEqual(6, values.Count); for (int i = 0; i > -6; i--) @@ -355,17 +354,16 @@ namespace Google.Protobuf int msgSize = arraySize; byte[] bytes = new byte[msgSize]; CodedOutputStream output = CodedOutputStream.CreateInstance(bytes); - output.WriteEnumArray(8, "", new RepeatedField { + output.WriteEnumArray(8, new RepeatedField { 0, (TestNegEnum) (-1), TestNegEnum.Value, (TestNegEnum) (-3), (TestNegEnum) (-4), (TestNegEnum) (-5) }); Assert.AreEqual(0, output.SpaceLeft); CodedInputStream input = CodedInputStream.CreateInstance(bytes); uint tag; - string name; - Assert.IsTrue(input.ReadTag(out tag, out name)); + Assert.IsTrue(input.ReadTag(out tag)); List values = new List(); - input.ReadInt32Array(tag, name, values); + input.ReadInt32Array(tag, values); Assert.AreEqual(6, values.Count); for (int i = 0; i > -6; i--) @@ -425,16 +423,14 @@ namespace Google.Protobuf { CodedInputStream cin = CodedInputStream.CreateInstance(new MemoryStream(bytes), new byte[50]); uint tag; - int intValue = 0; - string ignore; Assert.AreEqual(0, cin.Position); // Field 1: - Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 1); + Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 1); Assert.AreEqual(1, cin.Position); - Assert.IsTrue(cin.ReadInt32(ref intValue) && intValue == 500); + Assert.AreEqual(500, cin.ReadInt32()); Assert.AreEqual(3, cin.Position); //Field 2: - Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 2); + Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 2); Assert.AreEqual(4, cin.Position); uint childlen = cin.ReadRawVarint32(); Assert.AreEqual(120u, childlen); @@ -444,30 +440,31 @@ namespace Google.Protobuf // Now we are reading child message { // Field 11: numeric value: 500 - Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 11); + Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 11); Assert.AreEqual(6, cin.Position); - Assert.IsTrue(cin.ReadInt32(ref intValue) && intValue == 500); + Assert.AreEqual(500, cin.ReadInt32()); Assert.AreEqual(8, cin.Position); //Field 12: length delimited 120 bytes - Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 12); + Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 12); Assert.AreEqual(9, cin.Position); - ByteString bstr = null; - Assert.IsTrue(cin.ReadBytes(ref bstr) && bstr.Length == 110 && bstr.ToByteArray()[109] == 109); + ByteString bstr = cin.ReadBytes(); + Assert.AreEqual(110, bstr.Length); + Assert.AreEqual((byte) 109, bstr[109]); Assert.AreEqual(120, cin.Position); // Field 13: fixed numeric value: 501 - Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 13); + Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 13); // ROK - Previously broken here, this returned 126 failing to account for bufferSizeAfterLimit Assert.AreEqual(121, cin.Position); - Assert.IsTrue(cin.ReadSFixed32(ref intValue) && intValue == 501); + Assert.AreEqual(501, cin.ReadSFixed32()); Assert.AreEqual(125, cin.Position); Assert.IsTrue(cin.IsAtEnd); } cin.PopLimit(oldlimit); Assert.AreEqual(125, cin.Position); // Field 3: fixed numeric value: 501 - Assert.IsTrue(cin.ReadTag(out tag, out ignore) && tag >> 3 == 3); + Assert.IsTrue(cin.ReadTag(out tag) && tag >> 3 == 3); Assert.AreEqual(126, cin.Position); - Assert.IsTrue(cin.ReadSFixed32(ref intValue) && intValue == 501); + Assert.AreEqual(501, cin.ReadSFixed32()); Assert.AreEqual(130, cin.Position); Assert.IsTrue(cin.IsAtEnd); } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs index 4b62794a..1bd4e22b 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportProto3.cs @@ -107,10 +107,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (D != 0) { - output.WriteInt32(1, fieldNames[0], D); + output.WriteInt32(1, D); } } @@ -130,16 +129,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -149,7 +141,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref d_); + d_ = input.ReadInt32(); break; } } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs index 2f7f8699..32123d53 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestImportPublicProto3.cs @@ -92,10 +92,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (E != 0) { - output.WriteInt32(1, fieldNames[0], E); + output.WriteInt32(1, E); } } @@ -115,16 +114,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -134,7 +126,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref e_); + e_ = input.ReadInt32(); break; } } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs index 14ca78a4..d8c8995b 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestIssues.cs @@ -153,13 +153,12 @@ namespace UnitTest.Issues.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Value != global::UnitTest.Issues.TestProtos.NegativeEnum.NEGATIVE_ENUM_ZERO) { - output.WriteEnum(1, fieldNames[1], (int) Value); + output.WriteEnum(1, (int) Value); } - output.WriteEnumArray(2, fieldNames[2], values_); - output.WritePackedEnumArray(3, fieldNames[0], packedValues_); + output.WriteEnumArray(2, values_); + output.WritePackedEnumArray(3, packedValues_); } public int CalculateSize() { @@ -201,16 +200,9 @@ namespace UnitTest.Issues.TestProtos { packedValues_.Add(other.packedValues_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -220,18 +212,17 @@ namespace UnitTest.Issues.TestProtos { } break; case 8: { - int tmp = 0; - input.ReadEnum(ref tmp); - value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) tmp;break; + value_ = (global::UnitTest.Issues.TestProtos.NegativeEnum) input.ReadEnum(); + break; } case 18: case 16: { - input.ReadEnumArray(tag, fieldName, values_); + input.ReadEnumArray(tag, values_); break; } case 26: case 24: { - input.ReadEnumArray(tag, fieldName, packedValues_); + input.ReadEnumArray(tag, packedValues_); break; } } @@ -278,8 +269,7 @@ namespace UnitTest.Issues.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { } public int CalculateSize() { @@ -292,16 +282,9 @@ namespace UnitTest.Issues.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -412,20 +395,19 @@ namespace UnitTest.Issues.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (PrimitiveValue != 0) { - output.WriteInt32(1, fieldNames[5], PrimitiveValue); + output.WriteInt32(1, PrimitiveValue); } - output.WritePackedInt32Array(2, fieldNames[4], primitiveArray_); + output.WritePackedInt32Array(2, primitiveArray_); if (messageValue_ != null) { - output.WriteMessage(3, fieldNames[3], MessageValue); + output.WriteMessage(3, MessageValue); } - output.WriteMessageArray(4, fieldNames[2], messageArray_); + output.WriteMessageArray(4, messageArray_); if (EnumValue != global::UnitTest.Issues.TestProtos.DeprecatedEnum.DEPRECATED_ZERO) { - output.WriteEnum(5, fieldNames[1], (int) EnumValue); + output.WriteEnum(5, (int) EnumValue); } - output.WritePackedEnumArray(6, fieldNames[0], enumArray_); + output.WritePackedEnumArray(6, enumArray_); } public int CalculateSize() { @@ -486,16 +468,9 @@ namespace UnitTest.Issues.TestProtos { enumArray_.Add(other.enumArray_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -505,12 +480,12 @@ namespace UnitTest.Issues.TestProtos { } break; case 8: { - input.ReadInt32(ref primitiveValue_); + primitiveValue_ = input.ReadInt32(); break; } case 18: case 16: { - input.ReadInt32Array(tag, fieldName, primitiveArray_); + input.ReadInt32Array(tag, primitiveArray_); break; } case 26: { @@ -521,17 +496,16 @@ namespace UnitTest.Issues.TestProtos { break; } case 34: { - input.ReadMessageArray(tag, fieldName, messageArray_, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser); + input.ReadMessageArray(tag, messageArray_, global::UnitTest.Issues.TestProtos.DeprecatedChild.Parser); break; } case 40: { - int tmp = 0; - input.ReadEnum(ref tmp); - enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) tmp;break; + enumValue_ = (global::UnitTest.Issues.TestProtos.DeprecatedEnum) input.ReadEnum(); + break; } case 50: case 48: { - input.ReadEnumArray(tag, fieldName, enumArray_); + input.ReadEnumArray(tag, enumArray_); break; } } @@ -588,10 +562,9 @@ namespace UnitTest.Issues.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Item != 0) { - output.WriteInt32(1, fieldNames[0], Item); + output.WriteInt32(1, Item); } } @@ -611,16 +584,9 @@ namespace UnitTest.Issues.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -630,7 +596,7 @@ namespace UnitTest.Issues.TestProtos { } break; case 8: { - input.ReadInt32(ref item_); + item_ = input.ReadInt32(); break; } } diff --git a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs index 3e5bb8b6..4c4dabab 100644 --- a/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs +++ b/csharp/src/ProtocolBuffers.Test/TestProtos/UnittestProto3.cs @@ -888,107 +888,106 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (SingleInt32 != 0) { - output.WriteInt32(1, fieldNames[36], SingleInt32); + output.WriteInt32(1, SingleInt32); } if (SingleInt64 != 0L) { - output.WriteInt64(2, fieldNames[37], SingleInt64); + output.WriteInt64(2, SingleInt64); } if (SingleUint32 != 0) { - output.WriteUInt32(3, fieldNames[46], SingleUint32); + output.WriteUInt32(3, SingleUint32); } if (SingleUint64 != 0UL) { - output.WriteUInt64(4, fieldNames[47], SingleUint64); + output.WriteUInt64(4, SingleUint64); } if (SingleSint32 != 0) { - output.WriteSInt32(5, fieldNames[43], SingleSint32); + output.WriteSInt32(5, SingleSint32); } if (SingleSint64 != 0L) { - output.WriteSInt64(6, fieldNames[44], SingleSint64); + output.WriteSInt64(6, SingleSint64); } if (SingleFixed32 != 0) { - output.WriteFixed32(7, fieldNames[29], SingleFixed32); + output.WriteFixed32(7, SingleFixed32); } if (SingleFixed64 != 0UL) { - output.WriteFixed64(8, fieldNames[30], SingleFixed64); + output.WriteFixed64(8, SingleFixed64); } if (SingleSfixed32 != 0) { - output.WriteSFixed32(9, fieldNames[41], SingleSfixed32); + output.WriteSFixed32(9, SingleSfixed32); } if (SingleSfixed64 != 0L) { - output.WriteSFixed64(10, fieldNames[42], SingleSfixed64); + output.WriteSFixed64(10, SingleSfixed64); } if (SingleFloat != 0F) { - output.WriteFloat(11, fieldNames[31], SingleFloat); + output.WriteFloat(11, SingleFloat); } if (SingleDouble != 0D) { - output.WriteDouble(12, fieldNames[28], SingleDouble); + output.WriteDouble(12, SingleDouble); } if (SingleBool != false) { - output.WriteBool(13, fieldNames[26], SingleBool); + output.WriteBool(13, SingleBool); } if (SingleString != "") { - output.WriteString(14, fieldNames[45], SingleString); + output.WriteString(14, SingleString); } if (SingleBytes != pb::ByteString.Empty) { - output.WriteBytes(15, fieldNames[27], SingleBytes); + output.WriteBytes(15, SingleBytes); } if (singleNestedMessage_ != null) { - output.WriteMessage(18, fieldNames[39], SingleNestedMessage); + output.WriteMessage(18, SingleNestedMessage); } if (singleForeignMessage_ != null) { - output.WriteMessage(19, fieldNames[33], SingleForeignMessage); + output.WriteMessage(19, SingleForeignMessage); } if (singleImportMessage_ != null) { - output.WriteMessage(20, fieldNames[35], SingleImportMessage); + output.WriteMessage(20, SingleImportMessage); } if (SingleNestedEnum != global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum.NESTED_ENUM_UNSPECIFIED) { - output.WriteEnum(21, fieldNames[38], (int) SingleNestedEnum); + output.WriteEnum(21, (int) SingleNestedEnum); } if (SingleForeignEnum != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - output.WriteEnum(22, fieldNames[32], (int) SingleForeignEnum); + output.WriteEnum(22, (int) SingleForeignEnum); } if (SingleImportEnum != global::Google.Protobuf.TestProtos.ImportEnum.IMPORT_ENUM_UNSPECIFIED) { - output.WriteEnum(23, fieldNames[34], (int) SingleImportEnum); + output.WriteEnum(23, (int) SingleImportEnum); } if (singlePublicImportMessage_ != null) { - output.WriteMessage(26, fieldNames[40], SinglePublicImportMessage); - } - output.WritePackedInt32Array(31, fieldNames[14], repeatedInt32_); - output.WritePackedInt64Array(32, fieldNames[15], repeatedInt64_); - output.WritePackedUInt32Array(33, fieldNames[24], repeatedUint32_); - output.WritePackedUInt64Array(34, fieldNames[25], repeatedUint64_); - output.WritePackedSInt32Array(35, fieldNames[21], repeatedSint32_); - output.WritePackedSInt64Array(36, fieldNames[22], repeatedSint64_); - output.WritePackedFixed32Array(37, fieldNames[7], repeatedFixed32_); - output.WritePackedFixed64Array(38, fieldNames[8], repeatedFixed64_); - output.WritePackedSFixed32Array(39, fieldNames[19], repeatedSfixed32_); - output.WritePackedSFixed64Array(40, fieldNames[20], repeatedSfixed64_); - output.WritePackedFloatArray(41, fieldNames[9], repeatedFloat_); - output.WritePackedDoubleArray(42, fieldNames[6], repeatedDouble_); - output.WritePackedBoolArray(43, fieldNames[4], repeatedBool_); - output.WriteStringArray(44, fieldNames[23], repeatedString_); - output.WriteBytesArray(45, fieldNames[5], repeatedBytes_); - output.WriteMessageArray(48, fieldNames[17], repeatedNestedMessage_); - output.WriteMessageArray(49, fieldNames[11], repeatedForeignMessage_); - output.WriteMessageArray(50, fieldNames[13], repeatedImportMessage_); - output.WritePackedEnumArray(51, fieldNames[16], repeatedNestedEnum_); - output.WritePackedEnumArray(52, fieldNames[10], repeatedForeignEnum_); - output.WritePackedEnumArray(53, fieldNames[12], repeatedImportEnum_); - output.WriteMessageArray(54, fieldNames[18], repeatedPublicImportMessage_); + output.WriteMessage(26, SinglePublicImportMessage); + } + output.WritePackedInt32Array(31, repeatedInt32_); + output.WritePackedInt64Array(32, repeatedInt64_); + output.WritePackedUInt32Array(33, repeatedUint32_); + output.WritePackedUInt64Array(34, repeatedUint64_); + output.WritePackedSInt32Array(35, repeatedSint32_); + output.WritePackedSInt64Array(36, repeatedSint64_); + output.WritePackedFixed32Array(37, repeatedFixed32_); + output.WritePackedFixed64Array(38, repeatedFixed64_); + output.WritePackedSFixed32Array(39, repeatedSfixed32_); + output.WritePackedSFixed64Array(40, repeatedSfixed64_); + output.WritePackedFloatArray(41, repeatedFloat_); + output.WritePackedDoubleArray(42, repeatedDouble_); + output.WritePackedBoolArray(43, repeatedBool_); + output.WriteStringArray(44, repeatedString_); + output.WriteBytesArray(45, repeatedBytes_); + output.WriteMessageArray(48, repeatedNestedMessage_); + output.WriteMessageArray(49, repeatedForeignMessage_); + output.WriteMessageArray(50, repeatedImportMessage_); + output.WritePackedEnumArray(51, repeatedNestedEnum_); + output.WritePackedEnumArray(52, repeatedForeignEnum_); + output.WritePackedEnumArray(53, repeatedImportEnum_); + output.WriteMessageArray(54, repeatedPublicImportMessage_); if (oneofFieldCase_ == OneofFieldOneofCase.OneofUint32) { - output.WriteUInt32(111, fieldNames[3], OneofUint32); + output.WriteUInt32(111, OneofUint32); } if (oneofFieldCase_ == OneofFieldOneofCase.OneofNestedMessage) { - output.WriteMessage(112, fieldNames[1], OneofNestedMessage); + output.WriteMessage(112, OneofNestedMessage); } if (oneofFieldCase_ == OneofFieldOneofCase.OneofString) { - output.WriteString(113, fieldNames[2], OneofString); + output.WriteString(113, OneofString); } if (oneofFieldCase_ == OneofFieldOneofCase.OneofBytes) { - output.WriteBytes(114, fieldNames[0], OneofBytes); + output.WriteBytes(114, OneofBytes); } } @@ -1372,16 +1371,9 @@ namespace Google.Protobuf.TestProtos { } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1391,63 +1383,63 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref singleInt32_); + singleInt32_ = input.ReadInt32(); break; } case 16: { - input.ReadInt64(ref singleInt64_); + singleInt64_ = input.ReadInt64(); break; } case 24: { - input.ReadUInt32(ref singleUint32_); + singleUint32_ = input.ReadUInt32(); break; } case 32: { - input.ReadUInt64(ref singleUint64_); + singleUint64_ = input.ReadUInt64(); break; } case 40: { - input.ReadSInt32(ref singleSint32_); + singleSint32_ = input.ReadSInt32(); break; } case 48: { - input.ReadSInt64(ref singleSint64_); + singleSint64_ = input.ReadSInt64(); break; } case 61: { - input.ReadFixed32(ref singleFixed32_); + singleFixed32_ = input.ReadFixed32(); break; } case 65: { - input.ReadFixed64(ref singleFixed64_); + singleFixed64_ = input.ReadFixed64(); break; } case 77: { - input.ReadSFixed32(ref singleSfixed32_); + singleSfixed32_ = input.ReadSFixed32(); break; } case 81: { - input.ReadSFixed64(ref singleSfixed64_); + singleSfixed64_ = input.ReadSFixed64(); break; } case 93: { - input.ReadFloat(ref singleFloat_); + singleFloat_ = input.ReadFloat(); break; } case 97: { - input.ReadDouble(ref singleDouble_); + singleDouble_ = input.ReadDouble(); break; } case 104: { - input.ReadBool(ref singleBool_); + singleBool_ = input.ReadBool(); break; } case 114: { - input.ReadString(ref singleString_); + singleString_ = input.ReadString(); break; } case 122: { - input.ReadBytes(ref singleBytes_); + singleBytes_ = input.ReadBytes(); break; } case 146: { @@ -1472,19 +1464,16 @@ namespace Google.Protobuf.TestProtos { break; } case 168: { - int tmp = 0; - input.ReadEnum(ref tmp); - singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) tmp;break; + singleNestedEnum_ = (global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedEnum) input.ReadEnum(); + break; } case 176: { - int tmp = 0; - input.ReadEnum(ref tmp); - singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) tmp;break; + singleForeignEnum_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum(); + break; } case 184: { - int tmp = 0; - input.ReadEnum(ref tmp); - singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) tmp;break; + singleImportEnum_ = (global::Google.Protobuf.TestProtos.ImportEnum) input.ReadEnum(); + break; } case 210: { if (singlePublicImportMessage_ == null) { @@ -1495,114 +1484,111 @@ namespace Google.Protobuf.TestProtos { } case 250: case 248: { - input.ReadInt32Array(tag, fieldName, repeatedInt32_); + input.ReadInt32Array(tag, repeatedInt32_); break; } case 258: case 256: { - input.ReadInt64Array(tag, fieldName, repeatedInt64_); + input.ReadInt64Array(tag, repeatedInt64_); break; } case 266: case 264: { - input.ReadUInt32Array(tag, fieldName, repeatedUint32_); + input.ReadUInt32Array(tag, repeatedUint32_); break; } case 274: case 272: { - input.ReadUInt64Array(tag, fieldName, repeatedUint64_); + input.ReadUInt64Array(tag, repeatedUint64_); break; } case 282: case 280: { - input.ReadSInt32Array(tag, fieldName, repeatedSint32_); + input.ReadSInt32Array(tag, repeatedSint32_); break; } case 290: case 288: { - input.ReadSInt64Array(tag, fieldName, repeatedSint64_); + input.ReadSInt64Array(tag, repeatedSint64_); break; } case 298: case 301: { - input.ReadFixed32Array(tag, fieldName, repeatedFixed32_); + input.ReadFixed32Array(tag, repeatedFixed32_); break; } case 306: case 305: { - input.ReadFixed64Array(tag, fieldName, repeatedFixed64_); + input.ReadFixed64Array(tag, repeatedFixed64_); break; } case 314: case 317: { - input.ReadSFixed32Array(tag, fieldName, repeatedSfixed32_); + input.ReadSFixed32Array(tag, repeatedSfixed32_); break; } case 322: case 321: { - input.ReadSFixed64Array(tag, fieldName, repeatedSfixed64_); + input.ReadSFixed64Array(tag, repeatedSfixed64_); break; } case 330: case 333: { - input.ReadFloatArray(tag, fieldName, repeatedFloat_); + input.ReadFloatArray(tag, repeatedFloat_); break; } case 338: case 337: { - input.ReadDoubleArray(tag, fieldName, repeatedDouble_); + input.ReadDoubleArray(tag, repeatedDouble_); break; } case 346: case 344: { - input.ReadBoolArray(tag, fieldName, repeatedBool_); + input.ReadBoolArray(tag, repeatedBool_); break; } case 354: { - input.ReadStringArray(tag, fieldName, repeatedString_); + input.ReadStringArray(tag, repeatedString_); break; } case 362: { - input.ReadBytesArray(tag, fieldName, repeatedBytes_); + input.ReadBytesArray(tag, repeatedBytes_); break; } case 386: { - input.ReadMessageArray(tag, fieldName, repeatedNestedMessage_, global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser); + input.ReadMessageArray(tag, repeatedNestedMessage_, global::Google.Protobuf.TestProtos.TestAllTypes.Types.NestedMessage.Parser); break; } case 394: { - input.ReadMessageArray(tag, fieldName, repeatedForeignMessage_, global::Google.Protobuf.TestProtos.ForeignMessage.Parser); + input.ReadMessageArray(tag, repeatedForeignMessage_, global::Google.Protobuf.TestProtos.ForeignMessage.Parser); break; } case 402: { - input.ReadMessageArray(tag, fieldName, repeatedImportMessage_, global::Google.Protobuf.TestProtos.ImportMessage.Parser); + input.ReadMessageArray(tag, repeatedImportMessage_, global::Google.Protobuf.TestProtos.ImportMessage.Parser); break; } case 410: case 408: { - input.ReadEnumArray(tag, fieldName, repeatedNestedEnum_); + input.ReadEnumArray(tag, repeatedNestedEnum_); break; } case 418: case 416: { - input.ReadEnumArray(tag, fieldName, repeatedForeignEnum_); + input.ReadEnumArray(tag, repeatedForeignEnum_); break; } case 426: case 424: { - input.ReadEnumArray(tag, fieldName, repeatedImportEnum_); + input.ReadEnumArray(tag, repeatedImportEnum_); break; } case 434: { - input.ReadMessageArray(tag, fieldName, repeatedPublicImportMessage_, global::Google.Protobuf.TestProtos.PublicImportMessage.Parser); + input.ReadMessageArray(tag, repeatedPublicImportMessage_, global::Google.Protobuf.TestProtos.PublicImportMessage.Parser); break; } case 888: { - uint value = 0; - if (input.ReadUInt32(ref value)) { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; - } + oneofField_ = input.ReadUInt32() + ;oneofFieldCase_ = OneofFieldOneofCase.OneofUint32; break; } case 898: { @@ -1615,19 +1601,13 @@ namespace Google.Protobuf.TestProtos { break; } case 906: { - string value = ""; - if (input.ReadString(ref value)) { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofString; - } + oneofField_ = input.ReadString() + ;oneofFieldCase_ = OneofFieldOneofCase.OneofString; break; } case 914: { - pb::ByteString value = pb::ByteString.Empty; - if (input.ReadBytes(ref value)) { - oneofField_ = value; - oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; - } + oneofField_ = input.ReadBytes() + ;oneofFieldCase_ = OneofFieldOneofCase.OneofBytes; break; } } @@ -1693,10 +1673,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Bb != 0) { - output.WriteInt32(1, fieldNames[0], Bb); + output.WriteInt32(1, Bb); } } @@ -1716,16 +1695,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1735,7 +1707,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref bb_); + bb_ = input.ReadInt32(); break; } } @@ -1811,15 +1783,14 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (child_ != null) { - output.WriteMessage(1, fieldNames[0], Child); + output.WriteMessage(1, Child); } if (payload_ != null) { - output.WriteMessage(2, fieldNames[1], Payload); + output.WriteMessage(2, Payload); } - output.WriteMessageArray(3, fieldNames[2], repeatedChild_); + output.WriteMessageArray(3, repeatedChild_); } public int CalculateSize() { @@ -1854,16 +1825,9 @@ namespace Google.Protobuf.TestProtos { repeatedChild_.Add(other.repeatedChild_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1887,7 +1851,7 @@ namespace Google.Protobuf.TestProtos { break; } case 26: { - input.ReadMessageArray(tag, fieldName, repeatedChild_, global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser); + input.ReadMessageArray(tag, repeatedChild_, global::Google.Protobuf.TestProtos.NestedTestAllTypes.Parser); break; } } @@ -1945,10 +1909,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (DeprecatedInt32 != 0) { - output.WriteInt32(1, fieldNames[0], DeprecatedInt32); + output.WriteInt32(1, DeprecatedInt32); } } @@ -1968,16 +1931,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1987,7 +1943,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref deprecatedInt32_); + deprecatedInt32_ = input.ReadInt32(); break; } } @@ -2044,10 +2000,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (C != 0) { - output.WriteInt32(1, fieldNames[0], C); + output.WriteInt32(1, C); } } @@ -2067,16 +2022,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2086,7 +2034,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref c_); + c_ = input.ReadInt32(); break; } } @@ -2133,8 +2081,7 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { } public int CalculateSize() { @@ -2147,16 +2094,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2217,10 +2157,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (foreignNested_ != null) { - output.WriteMessage(1, fieldNames[0], ForeignNested); + output.WriteMessage(1, ForeignNested); } } @@ -2243,16 +2182,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2332,13 +2264,12 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (A != 0) { - output.WriteInt32(1, fieldNames[0], A); + output.WriteInt32(1, A); } if (Bb != 0) { - output.WriteInt32(268435455, fieldNames[1], Bb); + output.WriteInt32(268435455, Bb); } } @@ -2364,16 +2295,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2383,11 +2307,11 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref a_); + a_ = input.ReadInt32(); break; } case 2147483640: { - input.ReadInt32(ref bb_); + bb_ = input.ReadInt32(); break; } } @@ -2452,13 +2376,12 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (a_ != null) { - output.WriteMessage(1, fieldNames[0], A); + output.WriteMessage(1, A); } if (I != 0) { - output.WriteInt32(2, fieldNames[1], I); + output.WriteInt32(2, I); } } @@ -2487,16 +2410,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2513,7 +2429,7 @@ namespace Google.Protobuf.TestProtos { break; } case 16: { - input.ReadInt32(ref i_); + i_ = input.ReadInt32(); break; } } @@ -2568,10 +2484,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (bb_ != null) { - output.WriteMessage(1, fieldNames[0], Bb); + output.WriteMessage(1, Bb); } } @@ -2594,16 +2509,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2681,13 +2589,12 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (a_ != null) { - output.WriteMessage(1, fieldNames[0], A); + output.WriteMessage(1, A); } if (OptionalInt32 != 0) { - output.WriteInt32(2, fieldNames[1], OptionalInt32); + output.WriteInt32(2, OptionalInt32); } } @@ -2716,16 +2623,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2742,7 +2642,7 @@ namespace Google.Protobuf.TestProtos { break; } case 16: { - input.ReadInt32(ref optionalInt32_); + optionalInt32_ = input.ReadInt32(); break; } } @@ -2859,24 +2759,23 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (PrimitiveField != 0) { - output.WriteInt32(1, fieldNames[2], PrimitiveField); + output.WriteInt32(1, PrimitiveField); } if (StringField != "") { - output.WriteString(2, fieldNames[7], StringField); + output.WriteString(2, StringField); } if (EnumField != global::Google.Protobuf.TestProtos.ForeignEnum.FOREIGN_UNSPECIFIED) { - output.WriteEnum(3, fieldNames[0], (int) EnumField); + output.WriteEnum(3, (int) EnumField); } if (messageField_ != null) { - output.WriteMessage(4, fieldNames[1], MessageField); + output.WriteMessage(4, MessageField); } - output.WritePackedInt32Array(7, fieldNames[5], repeatedPrimitiveField_); - output.WriteStringArray(8, fieldNames[6], repeatedStringField_); - output.WritePackedEnumArray(9, fieldNames[3], repeatedEnumField_); - output.WriteMessageArray(10, fieldNames[4], repeatedMessageField_); + output.WritePackedInt32Array(7, repeatedPrimitiveField_); + output.WriteStringArray(8, repeatedStringField_); + output.WritePackedEnumArray(9, repeatedEnumField_); + output.WriteMessageArray(10, repeatedMessageField_); } public int CalculateSize() { @@ -2952,16 +2851,9 @@ namespace Google.Protobuf.TestProtos { repeatedMessageField_.Add(other.repeatedMessageField_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2971,17 +2863,16 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref primitiveField_); + primitiveField_ = input.ReadInt32(); break; } case 18: { - input.ReadString(ref stringField_); + stringField_ = input.ReadString(); break; } case 24: { - int tmp = 0; - input.ReadEnum(ref tmp); - enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) tmp;break; + enumField_ = (global::Google.Protobuf.TestProtos.ForeignEnum) input.ReadEnum(); + break; } case 34: { if (messageField_ == null) { @@ -2992,20 +2883,20 @@ namespace Google.Protobuf.TestProtos { } case 58: case 56: { - input.ReadInt32Array(tag, fieldName, repeatedPrimitiveField_); + input.ReadInt32Array(tag, repeatedPrimitiveField_); break; } case 66: { - input.ReadStringArray(tag, fieldName, repeatedStringField_); + input.ReadStringArray(tag, repeatedStringField_); break; } case 74: case 72: { - input.ReadEnumArray(tag, fieldName, repeatedEnumField_); + input.ReadEnumArray(tag, repeatedEnumField_); break; } case 82: { - input.ReadMessageArray(tag, fieldName, repeatedMessageField_, global::Google.Protobuf.TestProtos.ForeignMessage.Parser); + input.ReadMessageArray(tag, repeatedMessageField_, global::Google.Protobuf.TestProtos.ForeignMessage.Parser); break; } } @@ -3090,19 +2981,18 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (MyInt != 0L) { - output.WriteInt64(1, fieldNames[1], MyInt); + output.WriteInt64(1, MyInt); } if (MyString != "") { - output.WriteString(11, fieldNames[2], MyString); + output.WriteString(11, MyString); } if (MyFloat != 0F) { - output.WriteFloat(101, fieldNames[0], MyFloat); + output.WriteFloat(101, MyFloat); } if (singleNestedMessage_ != null) { - output.WriteMessage(200, fieldNames[3], SingleNestedMessage); + output.WriteMessage(200, SingleNestedMessage); } } @@ -3143,16 +3033,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3162,15 +3045,15 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt64(ref myInt_); + myInt_ = input.ReadInt64(); break; } case 90: { - input.ReadString(ref myString_); + myString_ = input.ReadString(); break; } case 813: { - input.ReadFloat(ref myFloat_); + myFloat_ = input.ReadFloat(); break; } case 1602: { @@ -3245,13 +3128,12 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Bb != 0) { - output.WriteInt32(1, fieldNames[0], Bb); + output.WriteInt32(1, Bb); } if (Oo != 0L) { - output.WriteInt64(2, fieldNames[1], Oo); + output.WriteInt64(2, Oo); } } @@ -3277,16 +3159,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3296,11 +3171,11 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref bb_); + bb_ = input.ReadInt32(); break; } case 16: { - input.ReadInt64(ref oo_); + oo_ = input.ReadInt64(); break; } } @@ -3362,10 +3237,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (SparseEnum != global::Google.Protobuf.TestProtos.TestSparseEnum.TEST_SPARSE_ENUM_UNSPECIFIED) { - output.WriteEnum(1, fieldNames[0], (int) SparseEnum); + output.WriteEnum(1, (int) SparseEnum); } } @@ -3385,16 +3259,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3404,9 +3271,8 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - int tmp = 0; - input.ReadEnum(ref tmp); - sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) tmp;break; + sparseEnum_ = (global::Google.Protobuf.TestProtos.TestSparseEnum) input.ReadEnum(); + break; } } } @@ -3462,10 +3328,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Data != "") { - output.WriteString(1, fieldNames[0], Data); + output.WriteString(1, Data); } } @@ -3485,16 +3350,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3504,7 +3362,7 @@ namespace Google.Protobuf.TestProtos { } break; case 10: { - input.ReadString(ref data_); + data_ = input.ReadString(); break; } } @@ -3559,9 +3417,8 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; - output.WriteStringArray(1, fieldNames[0], data_); + public void WriteTo(pb::CodedOutputStream output) { + output.WriteStringArray(1, data_); } public int CalculateSize() { @@ -3583,16 +3440,9 @@ namespace Google.Protobuf.TestProtos { data_.Add(other.data_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3602,7 +3452,7 @@ namespace Google.Protobuf.TestProtos { } break; case 10: { - input.ReadStringArray(tag, fieldName, data_); + input.ReadStringArray(tag, data_); break; } } @@ -3659,10 +3509,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Data != pb::ByteString.Empty) { - output.WriteBytes(1, fieldNames[0], Data); + output.WriteBytes(1, Data); } } @@ -3682,16 +3531,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3701,7 +3543,7 @@ namespace Google.Protobuf.TestProtos { } break; case 10: { - input.ReadBytes(ref data_); + data_ = input.ReadBytes(); break; } } @@ -3758,10 +3600,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Data != pb::ByteString.Empty) { - output.WriteBytes(1, fieldNames[0], Data); + output.WriteBytes(1, Data); } } @@ -3781,16 +3622,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3800,7 +3634,7 @@ namespace Google.Protobuf.TestProtos { } break; case 10: { - input.ReadBytes(ref data_); + data_ = input.ReadBytes(); break; } } @@ -3857,10 +3691,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Data != 0) { - output.WriteInt32(1, fieldNames[0], Data); + output.WriteInt32(1, Data); } } @@ -3880,16 +3713,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3899,7 +3725,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt32(ref data_); + data_ = input.ReadInt32(); break; } } @@ -3956,10 +3782,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Data != 0) { - output.WriteUInt32(1, fieldNames[0], Data); + output.WriteUInt32(1, Data); } } @@ -3979,16 +3804,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3998,7 +3816,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadUInt32(ref data_); + data_ = input.ReadUInt32(); break; } } @@ -4055,10 +3873,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Data != 0L) { - output.WriteInt64(1, fieldNames[0], Data); + output.WriteInt64(1, Data); } } @@ -4078,16 +3895,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -4097,7 +3907,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadInt64(ref data_); + data_ = input.ReadInt64(); break; } } @@ -4154,10 +3964,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Data != 0UL) { - output.WriteUInt64(1, fieldNames[0], Data); + output.WriteUInt64(1, Data); } } @@ -4177,16 +3986,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -4196,7 +3998,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadUInt64(ref data_); + data_ = input.ReadUInt64(); break; } } @@ -4253,10 +4055,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Data != false) { - output.WriteBool(1, fieldNames[0], Data); + output.WriteBool(1, Data); } } @@ -4276,16 +4077,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -4295,7 +4089,7 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - input.ReadBool(ref data_); + data_ = input.ReadBool(); break; } } @@ -4391,16 +4185,15 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (fooCase_ == FooOneofCase.FooInt) { - output.WriteInt32(1, fieldNames[0], FooInt); + output.WriteInt32(1, FooInt); } if (fooCase_ == FooOneofCase.FooString) { - output.WriteString(2, fieldNames[2], FooString); + output.WriteString(2, FooString); } if (fooCase_ == FooOneofCase.FooMessage) { - output.WriteMessage(3, fieldNames[1], FooMessage); + output.WriteMessage(3, FooMessage); } } @@ -4435,16 +4228,9 @@ namespace Google.Protobuf.TestProtos { } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -4454,19 +4240,13 @@ namespace Google.Protobuf.TestProtos { } break; case 8: { - int value = 0; - if (input.ReadInt32(ref value)) { - foo_ = value; - fooCase_ = FooOneofCase.FooInt; - } + foo_ = input.ReadInt32() + ;fooCase_ = FooOneofCase.FooInt; break; } case 18: { - string value = ""; - if (input.ReadString(ref value)) { - foo_ = value; - fooCase_ = FooOneofCase.FooString; - } + foo_ = input.ReadString() + ;fooCase_ = FooOneofCase.FooString; break; } case 26: { @@ -4634,22 +4414,21 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; - output.WritePackedInt32Array(90, fieldNames[6], packedInt32_); - output.WritePackedInt64Array(91, fieldNames[7], packedInt64_); - output.WritePackedUInt32Array(92, fieldNames[12], packedUint32_); - output.WritePackedUInt64Array(93, fieldNames[13], packedUint64_); - output.WritePackedSInt32Array(94, fieldNames[10], packedSint32_); - output.WritePackedSInt64Array(95, fieldNames[11], packedSint64_); - output.WritePackedFixed32Array(96, fieldNames[3], packedFixed32_); - output.WritePackedFixed64Array(97, fieldNames[4], packedFixed64_); - output.WritePackedSFixed32Array(98, fieldNames[8], packedSfixed32_); - output.WritePackedSFixed64Array(99, fieldNames[9], packedSfixed64_); - output.WritePackedFloatArray(100, fieldNames[5], packedFloat_); - output.WritePackedDoubleArray(101, fieldNames[1], packedDouble_); - output.WritePackedBoolArray(102, fieldNames[0], packedBool_); - output.WritePackedEnumArray(103, fieldNames[2], packedEnum_); + public void WriteTo(pb::CodedOutputStream output) { + output.WritePackedInt32Array(90, packedInt32_); + output.WritePackedInt64Array(91, packedInt64_); + output.WritePackedUInt32Array(92, packedUint32_); + output.WritePackedUInt64Array(93, packedUint64_); + output.WritePackedSInt32Array(94, packedSint32_); + output.WritePackedSInt64Array(95, packedSint64_); + output.WritePackedFixed32Array(96, packedFixed32_); + output.WritePackedFixed64Array(97, packedFixed64_); + output.WritePackedSFixed32Array(98, packedSfixed32_); + output.WritePackedSFixed64Array(99, packedSfixed64_); + output.WritePackedFloatArray(100, packedFloat_); + output.WritePackedDoubleArray(101, packedDouble_); + output.WritePackedBoolArray(102, packedBool_); + output.WritePackedEnumArray(103, packedEnum_); } public int CalculateSize() { @@ -4803,16 +4582,9 @@ namespace Google.Protobuf.TestProtos { packedEnum_.Add(other.packedEnum_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -4823,72 +4595,72 @@ namespace Google.Protobuf.TestProtos { break; case 722: case 720: { - input.ReadInt32Array(tag, fieldName, packedInt32_); + input.ReadInt32Array(tag, packedInt32_); break; } case 730: case 728: { - input.ReadInt64Array(tag, fieldName, packedInt64_); + input.ReadInt64Array(tag, packedInt64_); break; } case 738: case 736: { - input.ReadUInt32Array(tag, fieldName, packedUint32_); + input.ReadUInt32Array(tag, packedUint32_); break; } case 746: case 744: { - input.ReadUInt64Array(tag, fieldName, packedUint64_); + input.ReadUInt64Array(tag, packedUint64_); break; } case 754: case 752: { - input.ReadSInt32Array(tag, fieldName, packedSint32_); + input.ReadSInt32Array(tag, packedSint32_); break; } case 762: case 760: { - input.ReadSInt64Array(tag, fieldName, packedSint64_); + input.ReadSInt64Array(tag, packedSint64_); break; } case 770: case 773: { - input.ReadFixed32Array(tag, fieldName, packedFixed32_); + input.ReadFixed32Array(tag, packedFixed32_); break; } case 778: case 777: { - input.ReadFixed64Array(tag, fieldName, packedFixed64_); + input.ReadFixed64Array(tag, packedFixed64_); break; } case 786: case 789: { - input.ReadSFixed32Array(tag, fieldName, packedSfixed32_); + input.ReadSFixed32Array(tag, packedSfixed32_); break; } case 794: case 793: { - input.ReadSFixed64Array(tag, fieldName, packedSfixed64_); + input.ReadSFixed64Array(tag, packedSfixed64_); break; } case 802: case 805: { - input.ReadFloatArray(tag, fieldName, packedFloat_); + input.ReadFloatArray(tag, packedFloat_); break; } case 810: case 809: { - input.ReadDoubleArray(tag, fieldName, packedDouble_); + input.ReadDoubleArray(tag, packedDouble_); break; } case 818: case 816: { - input.ReadBoolArray(tag, fieldName, packedBool_); + input.ReadBoolArray(tag, packedBool_); break; } case 826: case 824: { - input.ReadEnumArray(tag, fieldName, packedEnum_); + input.ReadEnumArray(tag, packedEnum_); break; } } @@ -5047,22 +4819,21 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; - output.WriteInt32Array(90, fieldNames[6], unpackedInt32_); - output.WriteInt64Array(91, fieldNames[7], unpackedInt64_); - output.WriteUInt32Array(92, fieldNames[12], unpackedUint32_); - output.WriteUInt64Array(93, fieldNames[13], unpackedUint64_); - output.WriteSInt32Array(94, fieldNames[10], unpackedSint32_); - output.WriteSInt64Array(95, fieldNames[11], unpackedSint64_); - output.WriteFixed32Array(96, fieldNames[3], unpackedFixed32_); - output.WriteFixed64Array(97, fieldNames[4], unpackedFixed64_); - output.WriteSFixed32Array(98, fieldNames[8], unpackedSfixed32_); - output.WriteSFixed64Array(99, fieldNames[9], unpackedSfixed64_); - output.WriteFloatArray(100, fieldNames[5], unpackedFloat_); - output.WriteDoubleArray(101, fieldNames[1], unpackedDouble_); - output.WriteBoolArray(102, fieldNames[0], unpackedBool_); - output.WriteEnumArray(103, fieldNames[2], unpackedEnum_); + public void WriteTo(pb::CodedOutputStream output) { + output.WriteInt32Array(90, unpackedInt32_); + output.WriteInt64Array(91, unpackedInt64_); + output.WriteUInt32Array(92, unpackedUint32_); + output.WriteUInt64Array(93, unpackedUint64_); + output.WriteSInt32Array(94, unpackedSint32_); + output.WriteSInt64Array(95, unpackedSint64_); + output.WriteFixed32Array(96, unpackedFixed32_); + output.WriteFixed64Array(97, unpackedFixed64_); + output.WriteSFixed32Array(98, unpackedSfixed32_); + output.WriteSFixed64Array(99, unpackedSfixed64_); + output.WriteFloatArray(100, unpackedFloat_); + output.WriteDoubleArray(101, unpackedDouble_); + output.WriteBoolArray(102, unpackedBool_); + output.WriteEnumArray(103, unpackedEnum_); } public int CalculateSize() { @@ -5189,16 +4960,9 @@ namespace Google.Protobuf.TestProtos { unpackedEnum_.Add(other.unpackedEnum_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -5209,72 +4973,72 @@ namespace Google.Protobuf.TestProtos { break; case 722: case 720: { - input.ReadInt32Array(tag, fieldName, unpackedInt32_); + input.ReadInt32Array(tag, unpackedInt32_); break; } case 730: case 728: { - input.ReadInt64Array(tag, fieldName, unpackedInt64_); + input.ReadInt64Array(tag, unpackedInt64_); break; } case 738: case 736: { - input.ReadUInt32Array(tag, fieldName, unpackedUint32_); + input.ReadUInt32Array(tag, unpackedUint32_); break; } case 746: case 744: { - input.ReadUInt64Array(tag, fieldName, unpackedUint64_); + input.ReadUInt64Array(tag, unpackedUint64_); break; } case 754: case 752: { - input.ReadSInt32Array(tag, fieldName, unpackedSint32_); + input.ReadSInt32Array(tag, unpackedSint32_); break; } case 762: case 760: { - input.ReadSInt64Array(tag, fieldName, unpackedSint64_); + input.ReadSInt64Array(tag, unpackedSint64_); break; } case 770: case 773: { - input.ReadFixed32Array(tag, fieldName, unpackedFixed32_); + input.ReadFixed32Array(tag, unpackedFixed32_); break; } case 778: case 777: { - input.ReadFixed64Array(tag, fieldName, unpackedFixed64_); + input.ReadFixed64Array(tag, unpackedFixed64_); break; } case 786: case 789: { - input.ReadSFixed32Array(tag, fieldName, unpackedSfixed32_); + input.ReadSFixed32Array(tag, unpackedSfixed32_); break; } case 794: case 793: { - input.ReadSFixed64Array(tag, fieldName, unpackedSfixed64_); + input.ReadSFixed64Array(tag, unpackedSfixed64_); break; } case 802: case 805: { - input.ReadFloatArray(tag, fieldName, unpackedFloat_); + input.ReadFloatArray(tag, unpackedFloat_); break; } case 810: case 809: { - input.ReadDoubleArray(tag, fieldName, unpackedDouble_); + input.ReadDoubleArray(tag, unpackedDouble_); break; } case 818: case 816: { - input.ReadBoolArray(tag, fieldName, unpackedBool_); + input.ReadBoolArray(tag, unpackedBool_); break; } case 826: case 824: { - input.ReadEnumArray(tag, fieldName, unpackedEnum_); + input.ReadEnumArray(tag, unpackedEnum_); break; } } @@ -5369,14 +5133,13 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; - output.WritePackedFixed32Array(12, fieldNames[0], repeatedFixed32_); - output.WritePackedInt32Array(13, fieldNames[3], repeatedInt32_); - output.WritePackedFixed64Array(2046, fieldNames[1], repeatedFixed64_); - output.WritePackedInt64Array(2047, fieldNames[4], repeatedInt64_); - output.WritePackedFloatArray(262142, fieldNames[2], repeatedFloat_); - output.WritePackedUInt64Array(262143, fieldNames[5], repeatedUint64_); + public void WriteTo(pb::CodedOutputStream output) { + output.WritePackedFixed32Array(12, repeatedFixed32_); + output.WritePackedInt32Array(13, repeatedInt32_); + output.WritePackedFixed64Array(2046, repeatedFixed64_); + output.WritePackedInt64Array(2047, repeatedInt64_); + output.WritePackedFloatArray(262142, repeatedFloat_); + output.WritePackedUInt64Array(262143, repeatedUint64_); } public int CalculateSize() { @@ -5449,16 +5212,9 @@ namespace Google.Protobuf.TestProtos { repeatedUint64_.Add(other.repeatedUint64_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -5469,32 +5225,32 @@ namespace Google.Protobuf.TestProtos { break; case 98: case 101: { - input.ReadFixed32Array(tag, fieldName, repeatedFixed32_); + input.ReadFixed32Array(tag, repeatedFixed32_); break; } case 106: case 104: { - input.ReadInt32Array(tag, fieldName, repeatedInt32_); + input.ReadInt32Array(tag, repeatedInt32_); break; } case 16370: case 16369: { - input.ReadFixed64Array(tag, fieldName, repeatedFixed64_); + input.ReadFixed64Array(tag, repeatedFixed64_); break; } case 16378: case 16376: { - input.ReadInt64Array(tag, fieldName, repeatedInt64_); + input.ReadInt64Array(tag, repeatedInt64_); break; } case 2097138: case 2097141: { - input.ReadFloatArray(tag, fieldName, repeatedFloat_); + input.ReadFloatArray(tag, repeatedFloat_); break; } case 2097146: case 2097144: { - input.ReadUInt64Array(tag, fieldName, repeatedUint64_); + input.ReadUInt64Array(tag, repeatedUint64_); break; } } @@ -5551,10 +5307,9 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (A != "") { - output.WriteString(1, fieldNames[0], A); + output.WriteString(1, A); } } @@ -5574,16 +5329,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -5593,7 +5341,7 @@ namespace Google.Protobuf.TestProtos { } break; case 10: { - input.ReadString(ref a_); + a_ = input.ReadString(); break; } } @@ -5640,8 +5388,7 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { } public int CalculateSize() { @@ -5654,16 +5401,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -5716,8 +5456,7 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { } public int CalculateSize() { @@ -5730,16 +5469,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -5792,8 +5524,7 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { } public int CalculateSize() { @@ -5806,16 +5537,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -5868,8 +5592,7 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { } public int CalculateSize() { @@ -5882,16 +5605,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -5944,8 +5660,7 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { } public int CalculateSize() { @@ -5958,16 +5673,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -6020,8 +5728,7 @@ namespace Google.Protobuf.TestProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { } public int CalculateSize() { @@ -6034,16 +5741,9 @@ namespace Google.Protobuf.TestProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); diff --git a/csharp/src/ProtocolBuffers/CodedInputStream.cs b/csharp/src/ProtocolBuffers/CodedInputStream.cs index d5cab6fd..cb47f1c2 100644 --- a/csharp/src/ProtocolBuffers/CodedInputStream.cs +++ b/csharp/src/ProtocolBuffers/CodedInputStream.cs @@ -58,7 +58,7 @@ namespace Google.Protobuf /// TODO(jonskeet): Consider whether recursion and size limits shouldn't be readonly, /// set at construction time. /// - public sealed class CodedInputStream : ICodedInputStream + public sealed class CodedInputStream { private readonly byte[] buffer; private int bufferSize; @@ -173,10 +173,6 @@ namespace Google.Protobuf } } - - void ICodedInputStream.ReadMessageStart() { } - void ICodedInputStream.ReadMessageEnd() { } - #region Validation /// @@ -201,17 +197,16 @@ namespace Google.Protobuf /// /// Attempt to peek at the next field tag. /// - public bool PeekNextTag(out uint fieldTag, out string fieldName) + public bool PeekNextTag(out uint fieldTag) { if (hasNextTag) { - fieldName = null; fieldTag = nextTag; return true; } uint savedLast = lastTag; - hasNextTag = ReadTag(out nextTag, out fieldName); + hasNextTag = ReadTag(out nextTag); lastTag = savedLast; fieldTag = nextTag; return hasNextTag; @@ -222,12 +217,9 @@ namespace Google.Protobuf /// of the input data. /// /// The 'tag' of the field (id * 8 + wire-format) - /// Not Supported - For protobuffer streams, this parameter is always null /// true if the next fieldTag was read - public bool ReadTag(out uint fieldTag, out string fieldName) + public bool ReadTag(out uint fieldTag) { - fieldName = null; - if (hasNextTag) { fieldTag = nextTag; @@ -256,21 +248,21 @@ namespace Google.Protobuf /// /// Read a double field from the stream. /// - public bool ReadDouble(ref double value) + public double ReadDouble() { - value = FrameworkPortability.Int64ToDouble((long) ReadRawLittleEndian64()); - return true; + return FrameworkPortability.Int64ToDouble((long) ReadRawLittleEndian64()); } /// /// Read a float field from the stream. /// - public bool ReadFloat(ref float value) + public float ReadFloat() { if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos) { - value = BitConverter.ToSingle(buffer, bufferPos); + float ret = BitConverter.ToSingle(buffer, bufferPos); bufferPos += 4; + return ret; } else { @@ -279,76 +271,68 @@ namespace Google.Protobuf { ByteArray.Reverse(rawBytes); } - value = BitConverter.ToSingle(rawBytes, 0); + return BitConverter.ToSingle(rawBytes, 0); } - return true; } /// /// Read a uint64 field from the stream. /// - public bool ReadUInt64(ref ulong value) + public ulong ReadUInt64() { - value = ReadRawVarint64(); - return true; + return ReadRawVarint64(); } /// /// Read an int64 field from the stream. /// - public bool ReadInt64(ref long value) + public long ReadInt64() { - value = (long) ReadRawVarint64(); - return true; + return (long) ReadRawVarint64(); } /// /// Read an int32 field from the stream. /// - public bool ReadInt32(ref int value) + public int ReadInt32() { - value = (int) ReadRawVarint32(); - return true; + return (int) ReadRawVarint32(); } /// /// Read a fixed64 field from the stream. /// - public bool ReadFixed64(ref ulong value) + public ulong ReadFixed64() { - value = ReadRawLittleEndian64(); - return true; + return ReadRawLittleEndian64(); } /// /// Read a fixed32 field from the stream. /// - public bool ReadFixed32(ref uint value) + public uint ReadFixed32() { - value = ReadRawLittleEndian32(); - return true; + return ReadRawLittleEndian32(); } /// /// Read a bool field from the stream. /// - public bool ReadBool(ref bool value) + public bool ReadBool() { - value = ReadRawVarint32() != 0; - return true; + return ReadRawVarint32() != 0; } /// /// Reads a string field from the stream. /// - public bool ReadString(ref string value) + public string ReadString() { int size = (int) ReadRawVarint32(); // No need to read any data for an empty string. if (size == 0) { - value = ""; - return true; + return ""; } if (size <= bufferSize - bufferPos) { @@ -356,12 +340,10 @@ namespace Google.Protobuf // just copy directly from it. String result = Encoding.UTF8.GetString(buffer, bufferPos, size); bufferPos += size; - value = result; - return true; + return result; } // Slow path: Build a byte array first then copy it. - value = Encoding.UTF8.GetString(ReadRawBytes(size), 0, size); - return true; + return Encoding.UTF8.GetString(ReadRawBytes(size), 0, size); } /// @@ -400,7 +382,7 @@ namespace Google.Protobuf /// /// Reads a bytes field value from the stream. /// - public bool ReadBytes(ref ByteString value) + public ByteString ReadBytes() { int size = (int) ReadRawVarint32(); if (size <= bufferSize - bufferPos && size > 0) @@ -409,24 +391,21 @@ namespace Google.Protobuf // just copy directly from it. ByteString result = ByteString.CopyFrom(buffer, bufferPos, size); bufferPos += size; - value = result; - return true; + return result; } else { // Slow path: Build a byte array and attach it to a new ByteString. - value = ByteString.AttachBytes(ReadRawBytes(size)); - return true; + return ByteString.AttachBytes(ReadRawBytes(size)); } } /// /// Reads a uint32 field value from the stream. /// - public bool ReadUInt32(ref uint value) + public uint ReadUInt32() { - value = ReadRawVarint32(); - return true; + return ReadRawVarint32(); } /// @@ -434,47 +413,42 @@ namespace Google.Protobuf /// then the ref value is set and it returns true. Otherwise the unknown output /// value is set and this method returns false. /// - public bool ReadEnum(ref int value) + public int ReadEnum() { // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. - value = (int) ReadRawVarint32(); - return true; + return (int) ReadRawVarint32(); } /// /// Reads an sfixed32 field value from the stream. /// - public bool ReadSFixed32(ref int value) + public int ReadSFixed32() { - value = (int) ReadRawLittleEndian32(); - return true; + return (int) ReadRawLittleEndian32(); } /// /// Reads an sfixed64 field value from the stream. /// - public bool ReadSFixed64(ref long value) + public long ReadSFixed64() { - value = (long) ReadRawLittleEndian64(); - return true; + return (long) ReadRawLittleEndian64(); } /// /// Reads an sint32 field value from the stream. /// - public bool ReadSInt32(ref int value) + public int ReadSInt32() { - value = DecodeZigZag32(ReadRawVarint32()); - return true; + return DecodeZigZag32(ReadRawVarint32()); } /// /// Reads an sint64 field value from the stream. /// - public bool ReadSInt64(ref long value) + public long ReadSInt64() { - value = DecodeZigZag64(ReadRawVarint64()); - return true; + return DecodeZigZag64(ReadRawVarint64()); } private bool BeginArray(uint fieldTag, out bool isPacked, out int oldLimit) @@ -502,9 +476,8 @@ namespace Google.Protobuf /// private bool ContinueArray(uint currentTag) { - string ignore; uint next; - if (PeekNextTag(out next, out ignore)) + if (PeekNextTag(out next)) { if (next == currentTag) { @@ -530,9 +503,8 @@ namespace Google.Protobuf return true; } - string ignore; uint next; - if (PeekNextTag(out next, out ignore)) + if (PeekNextTag(out next)) { if (next == currentTag) { @@ -543,259 +515,194 @@ namespace Google.Protobuf return false; } - public void ReadPrimitiveArray(FieldType fieldType, uint fieldTag, string fieldName, ICollection list) - { - WireFormat.WireType normal = WireFormat.GetWireType(fieldType); - WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag); - - // 2.3 allows packed form even if the field is not declared packed. - if (normal != wformat && wformat == WireFormat.WireType.LengthDelimited) - { - int length = (int) (ReadRawVarint32() & int.MaxValue); - int limit = PushLimit(length); - while (!ReachedLimit) - { - Object value = null; - if (ReadPrimitiveField(fieldType, ref value)) - { - list.Add(value); - } - } - PopLimit(limit); - } - else - { - Object value = null; - do - { - if (ReadPrimitiveField(fieldType, ref value)) - { - list.Add(value); - } - } while (ContinueArray(fieldTag)); - } - } - - public void ReadStringArray(uint fieldTag, string fieldName, ICollection list) + public void ReadStringArray(uint fieldTag, ICollection list) { - string tmp = null; do { - ReadString(ref tmp); - list.Add(tmp); + list.Add(ReadString()); } while (ContinueArray(fieldTag)); } - public void ReadBytesArray(uint fieldTag, string fieldName, ICollection list) + public void ReadBytesArray(uint fieldTag, ICollection list) { - ByteString tmp = null; do { - ReadBytes(ref tmp); - list.Add(tmp); + list.Add(ReadBytes()); } while (ContinueArray(fieldTag)); } - public void ReadBoolArray(uint fieldTag, string fieldName, ICollection list) + public void ReadBoolArray(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - bool tmp = false; do { - ReadBool(ref tmp); - list.Add(tmp); + list.Add(ReadBool()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadInt32Array(uint fieldTag, string fieldName, ICollection list) + public void ReadInt32Array(uint fieldTag, ICollection list) { - // TODO(jonskeet): Work out how this works for non-packed values. (It doesn't look like it does...) bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - int tmp = 0; do { - ReadInt32(ref tmp); - list.Add(tmp); + list.Add(ReadInt32()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadSInt32Array(uint fieldTag, string fieldName, ICollection list) + public void ReadSInt32Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - int tmp = 0; do { - ReadSInt32(ref tmp); - list.Add(tmp); + list.Add(ReadSInt32()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadUInt32Array(uint fieldTag, string fieldName, ICollection list) + public void ReadUInt32Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - uint tmp = 0; do { - ReadUInt32(ref tmp); - list.Add(tmp); + list.Add(ReadUInt32()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadFixed32Array(uint fieldTag, string fieldName, ICollection list) + public void ReadFixed32Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - uint tmp = 0; do { - ReadFixed32(ref tmp); - list.Add(tmp); + list.Add(ReadFixed32()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadSFixed32Array(uint fieldTag, string fieldName, ICollection list) + public void ReadSFixed32Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - int tmp = 0; do { - ReadSFixed32(ref tmp); - list.Add(tmp); + list.Add(ReadSFixed32()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadInt64Array(uint fieldTag, string fieldName, ICollection list) + public void ReadInt64Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - long tmp = 0; do { - ReadInt64(ref tmp); - list.Add(tmp); + list.Add(ReadInt64()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadSInt64Array(uint fieldTag, string fieldName, ICollection list) + public void ReadSInt64Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - long tmp = 0; do { - ReadSInt64(ref tmp); - list.Add(tmp); + list.Add(ReadSInt64()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadUInt64Array(uint fieldTag, string fieldName, ICollection list) + public void ReadUInt64Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - ulong tmp = 0; do { - ReadUInt64(ref tmp); - list.Add(tmp); + list.Add(ReadUInt64()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadFixed64Array(uint fieldTag, string fieldName, ICollection list) + public void ReadFixed64Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - ulong tmp = 0; do { - ReadFixed64(ref tmp); - list.Add(tmp); + list.Add(ReadFixed64()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadSFixed64Array(uint fieldTag, string fieldName, ICollection list) + public void ReadSFixed64Array(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - long tmp = 0; do { - ReadSFixed64(ref tmp); - list.Add(tmp); + list.Add(ReadSFixed64()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadDoubleArray(uint fieldTag, string fieldName, ICollection list) + public void ReadDoubleArray(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - double tmp = 0; do { - ReadDouble(ref tmp); - list.Add(tmp); + list.Add(ReadDouble()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadFloatArray(uint fieldTag, string fieldName, ICollection list) + public void ReadFloatArray(uint fieldTag, ICollection list) { bool isPacked; int holdLimit; if (BeginArray(fieldTag, out isPacked, out holdLimit)) { - float tmp = 0; do { - ReadFloat(ref tmp); - list.Add(tmp); + list.Add(ReadFloat()); } while (ContinueArray(fieldTag, isPacked, holdLimit)); } } - public void ReadEnumArray(uint fieldTag, string fieldName, ICollection list) + public void ReadEnumArray(uint fieldTag, ICollection list) where T : struct, IComparable, IFormattable { - int value = 0; WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag); // 2.3 allows packed form even if the field is not declared packed. @@ -805,9 +712,8 @@ namespace Google.Protobuf int limit = PushLimit(length); while (!ReachedLimit) { - ReadEnum(ref value); // TODO(jonskeet): Avoid this horrible boxing! - list.Add((T)(object)value); + list.Add((T)(object) ReadEnum()); } PopLimit(limit); } @@ -815,14 +721,12 @@ namespace Google.Protobuf { do { - ReadEnum(ref value); - // TODO(jonskeet): Avoid this horrible boxing! - list.Add((T)(object) value); + list.Add((T)(object) ReadEnum()); } while (ContinueArray(fieldTag)); } } - public void ReadMessageArray(uint fieldTag, string fieldName, ICollection list, MessageParser messageParser) + public void ReadMessageArray(uint fieldTag, ICollection list, MessageParser messageParser) where T : IMessage { do @@ -833,7 +737,7 @@ namespace Google.Protobuf } while (ContinueArray(fieldTag)); } - public void ReadGroupArray(uint fieldTag, string fieldName, ICollection list, MessageParser messageParser) + public void ReadGroupArray(uint fieldTag, ICollection list, MessageParser messageParser) where T : IMessage { do @@ -843,178 +747,6 @@ namespace Google.Protobuf list.Add(message); } while (ContinueArray(fieldTag)); } - - /// - /// Reads a field of any primitive type. Enums, groups and embedded - /// messages are not handled by this method. - /// - public bool ReadPrimitiveField(FieldType fieldType, ref object value) - { - switch (fieldType) - { - case FieldType.Double: - { - double tmp = 0; - if (ReadDouble(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.Float: - { - float tmp = 0; - if (ReadFloat(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.Int64: - { - long tmp = 0; - if (ReadInt64(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.UInt64: - { - ulong tmp = 0; - if (ReadUInt64(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.Int32: - { - int tmp = 0; - if (ReadInt32(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.Fixed64: - { - ulong tmp = 0; - if (ReadFixed64(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.Fixed32: - { - uint tmp = 0; - if (ReadFixed32(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.Bool: - { - bool tmp = false; - if (ReadBool(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.String: - { - string tmp = null; - if (ReadString(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.Bytes: - { - ByteString tmp = null; - if (ReadBytes(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.UInt32: - { - uint tmp = 0; - if (ReadUInt32(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.SFixed32: - { - int tmp = 0; - if (ReadSFixed32(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.SFixed64: - { - long tmp = 0; - if (ReadSFixed64(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.SInt32: - { - int tmp = 0; - if (ReadSInt32(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.SInt64: - { - long tmp = 0; - if (ReadSInt64(ref tmp)) - { - value = tmp; - return true; - } - return false; - } - case FieldType.Group: - throw new ArgumentException("ReadPrimitiveField() cannot handle nested groups."); - case FieldType.Message: - throw new ArgumentException("ReadPrimitiveField() cannot handle embedded messages."); - // We don't handle enums because we don't know what to do if the - // value is not recognized. - case FieldType.Enum: - throw new ArgumentException("ReadPrimitiveField() cannot handle enums."); - default: - throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); - } - } - #endregion #region Underlying reading primitives @@ -1622,8 +1354,7 @@ namespace Google.Protobuf public void SkipMessage() { uint tag; - string name; - while (ReadTag(out tag, out name)) + while (ReadTag(out tag)) { if (!SkipField()) { diff --git a/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs b/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs index 96be9db5..b7629d7c 100644 --- a/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs +++ b/csharp/src/ProtocolBuffers/CodedOutputStream.ComputeSize.cs @@ -413,41 +413,12 @@ namespace Google.Protobuf return ComputeRawVarint64Size(EncodeZigZag64(value)); } - /* - * Compute the number of bytes that would be needed to encode a - * MessageSet extension to the stream. For historical reasons, - * the wire format differs from normal fields. - */ - - /// - /// Compute the number of bytes that would be needed to encode a - /// MessageSet extension to the stream. For historical reasons, - /// the wire format differs from normal fields. - /// - public static int ComputeMessageSetExtensionSize(int fieldNumber, IMessage value) - { - return ComputeTagSize(WireFormat.MessageSetField.Item)*2 + - ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) + - ComputeMessageSize(WireFormat.MessageSetField.Message, value); - } - - /// - /// Compute the number of bytes that would be needed to encode an - /// unparsed MessageSet extension field to the stream. For - /// historical reasons, the wire format differs from normal fields. - /// - public static int ComputeRawMessageSetExtensionSize(int fieldNumber, ByteString value) - { - return ComputeTagSize(WireFormat.MessageSetField.Item)*2 + - ComputeUInt32Size(WireFormat.MessageSetField.TypeID, (uint) fieldNumber) + - ComputeBytesSize(WireFormat.MessageSetField.Message, value); - } - /// /// Compute the number of bytes that would be needed to encode a varint. /// public static int ComputeRawVarint32Size(uint value) { + // TODO(jonskeet): Look at optimizing this to just hard-coded comparisons. if ((value & (0xffffffff << 7)) == 0) { return 1; @@ -472,6 +443,7 @@ namespace Google.Protobuf /// public static int ComputeRawVarint64Size(ulong value) { + // TODO(jonskeet): Look at optimizing this to just hard-coded comparisons. if ((value & (0xffffffffffffffffL << 7)) == 0) { return 1; @@ -511,106 +483,6 @@ namespace Google.Protobuf return 10; } - /// - /// Compute the number of bytes that would be needed to encode a - /// field of arbitrary type, including the tag, to the stream. - /// - // TODO(jonskeet): Why do we need this? - public static int ComputeFieldSize(FieldType fieldType, int fieldNumber, Object value) - { - switch (fieldType) - { - case FieldType.Double: - return ComputeDoubleSize(fieldNumber, (double) value); - case FieldType.Float: - return ComputeFloatSize(fieldNumber, (float) value); - case FieldType.Int64: - return ComputeInt64Size(fieldNumber, (long) value); - case FieldType.UInt64: - return ComputeUInt64Size(fieldNumber, (ulong) value); - case FieldType.Int32: - return ComputeInt32Size(fieldNumber, (int) value); - case FieldType.Fixed64: - return ComputeFixed64Size(fieldNumber, (ulong) value); - case FieldType.Fixed32: - return ComputeFixed32Size(fieldNumber, (uint) value); - case FieldType.Bool: - return ComputeBoolSize(fieldNumber, (bool) value); - case FieldType.String: - return ComputeStringSize(fieldNumber, (string) value); - case FieldType.Group: - return ComputeGroupSize(fieldNumber, (IMessage) value); - case FieldType.Message: - return ComputeMessageSize(fieldNumber, (IMessage) value); - case FieldType.Bytes: - return ComputeBytesSize(fieldNumber, (ByteString) value); - case FieldType.UInt32: - return ComputeUInt32Size(fieldNumber, (uint) value); - case FieldType.SFixed32: - return ComputeSFixed32Size(fieldNumber, (int) value); - case FieldType.SFixed64: - return ComputeSFixed64Size(fieldNumber, (long) value); - case FieldType.SInt32: - return ComputeSInt32Size(fieldNumber, (int) value); - case FieldType.SInt64: - return ComputeSInt64Size(fieldNumber, (long) value); - case FieldType.Enum: - return ComputeEnumSize(fieldNumber, (int) value); - default: - throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); - } - } - - /// - /// Compute the number of bytes that would be needed to encode a - /// field of arbitrary type, excluding the tag, to the stream. - /// - // TODO(jonskeet): Why do we need this? - public static int ComputeFieldSizeNoTag(FieldType fieldType, Object value) - { - switch (fieldType) - { - case FieldType.Double: - return ComputeDoubleSizeNoTag((double) value); - case FieldType.Float: - return ComputeFloatSizeNoTag((float) value); - case FieldType.Int64: - return ComputeInt64SizeNoTag((long) value); - case FieldType.UInt64: - return ComputeUInt64SizeNoTag((ulong) value); - case FieldType.Int32: - return ComputeInt32SizeNoTag((int) value); - case FieldType.Fixed64: - return ComputeFixed64SizeNoTag((ulong) value); - case FieldType.Fixed32: - return ComputeFixed32SizeNoTag((uint) value); - case FieldType.Bool: - return ComputeBoolSizeNoTag((bool) value); - case FieldType.String: - return ComputeStringSizeNoTag((string) value); - case FieldType.Group: - return ComputeGroupSizeNoTag((IMessage) value); - case FieldType.Message: - return ComputeMessageSizeNoTag((IMessage) value); - case FieldType.Bytes: - return ComputeBytesSizeNoTag((ByteString) value); - case FieldType.UInt32: - return ComputeUInt32SizeNoTag((uint) value); - case FieldType.SFixed32: - return ComputeSFixed32SizeNoTag((int) value); - case FieldType.SFixed64: - return ComputeSFixed64SizeNoTag((long) value); - case FieldType.SInt32: - return ComputeSInt32SizeNoTag((int) value); - case FieldType.SInt64: - return ComputeSInt64SizeNoTag((long) value); - case FieldType.Enum: - return ComputeEnumSizeNoTag((int) value); - default: - throw new ArgumentOutOfRangeException("Invalid field type " + fieldType); - } - } - /// /// Compute the number of bytes that would be needed to encode a tag. /// diff --git a/csharp/src/ProtocolBuffers/CodedOutputStream.cs b/csharp/src/ProtocolBuffers/CodedOutputStream.cs index e3f0c700..132f8067 100644 --- a/csharp/src/ProtocolBuffers/CodedOutputStream.cs +++ b/csharp/src/ProtocolBuffers/CodedOutputStream.cs @@ -57,7 +57,7 @@ namespace Google.Protobuf /// methods are taken from the protocol buffer type names, not .NET types. /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.) /// - public sealed partial class CodedOutputStream : ICodedOutputStream + public sealed partial class CodedOutputStream { private static readonly Encoding UTF8 = Encoding.UTF8; @@ -143,76 +143,11 @@ namespace Google.Protobuf } } - void ICodedOutputStream.WriteMessageStart() { } - void ICodedOutputStream.WriteMessageEnd() { Flush(); } - #region Writing of tags and fields - - // TODO(jonskeet): Do we need this? - public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value) - { - switch (fieldType) - { - case FieldType.String: - WriteString(fieldNumber, fieldName, (string) value); - break; - case FieldType.Message: - WriteMessage(fieldNumber, fieldName, (IMessage) value); - break; - case FieldType.Group: - WriteGroup(fieldNumber, fieldName, (IMessage) value); - break; - case FieldType.Bytes: - WriteBytes(fieldNumber, fieldName, (ByteString) value); - break; - case FieldType.Bool: - WriteBool(fieldNumber, fieldName, (bool) value); - break; - case FieldType.Enum: - throw new NotImplementedException(); - case FieldType.Int32: - WriteInt32(fieldNumber, fieldName, (int) value); - break; - case FieldType.Int64: - WriteInt64(fieldNumber, fieldName, (long) value); - break; - case FieldType.UInt32: - WriteUInt32(fieldNumber, fieldName, (uint) value); - break; - case FieldType.UInt64: - WriteUInt64(fieldNumber, fieldName, (ulong) value); - break; - case FieldType.SInt32: - WriteSInt32(fieldNumber, fieldName, (int) value); - break; - case FieldType.SInt64: - WriteSInt64(fieldNumber, fieldName, (long) value); - break; - case FieldType.Fixed32: - WriteFixed32(fieldNumber, fieldName, (uint) value); - break; - case FieldType.Fixed64: - WriteFixed64(fieldNumber, fieldName, (ulong) value); - break; - case FieldType.SFixed32: - WriteSFixed32(fieldNumber, fieldName, (int) value); - break; - case FieldType.SFixed64: - WriteSFixed64(fieldNumber, fieldName, (long) value); - break; - case FieldType.Double: - WriteDouble(fieldNumber, fieldName, (double) value); - break; - case FieldType.Float: - WriteFloat(fieldNumber, fieldName, (float) value); - break; - } - } - /// /// Writes a double field value, including tag, to the stream. /// - public void WriteDouble(int fieldNumber, string fieldName, double value) + public void WriteDouble(int fieldNumber, double value) { WriteTag(fieldNumber, WireFormat.WireType.Fixed64); WriteDoubleNoTag(value); @@ -221,7 +156,7 @@ namespace Google.Protobuf /// /// Writes a float field value, including tag, to the stream. /// - public void WriteFloat(int fieldNumber, string fieldName, float value) + public void WriteFloat(int fieldNumber, float value) { WriteTag(fieldNumber, WireFormat.WireType.Fixed32); WriteFloatNoTag(value); @@ -230,7 +165,7 @@ namespace Google.Protobuf /// /// Writes a uint64 field value, including tag, to the stream. /// - public void WriteUInt64(int fieldNumber, string fieldName, ulong value) + public void WriteUInt64(int fieldNumber, ulong value) { WriteTag(fieldNumber, WireFormat.WireType.Varint); WriteRawVarint64(value); @@ -239,7 +174,7 @@ namespace Google.Protobuf /// /// Writes an int64 field value, including tag, to the stream. /// - public void WriteInt64(int fieldNumber, string fieldName, long value) + public void WriteInt64(int fieldNumber, long value) { WriteTag(fieldNumber, WireFormat.WireType.Varint); WriteRawVarint64((ulong) value); @@ -248,7 +183,7 @@ namespace Google.Protobuf /// /// Writes an int32 field value, including tag, to the stream. /// - public void WriteInt32(int fieldNumber, string fieldName, int value) + public void WriteInt32(int fieldNumber, int value) { WriteTag(fieldNumber, WireFormat.WireType.Varint); if (value >= 0) @@ -265,7 +200,7 @@ namespace Google.Protobuf /// /// Writes a fixed64 field value, including tag, to the stream. /// - public void WriteFixed64(int fieldNumber, string fieldName, ulong value) + public void WriteFixed64(int fieldNumber, ulong value) { WriteTag(fieldNumber, WireFormat.WireType.Fixed64); WriteRawLittleEndian64(value); @@ -274,7 +209,7 @@ namespace Google.Protobuf /// /// Writes a fixed32 field value, including tag, to the stream. /// - public void WriteFixed32(int fieldNumber, string fieldName, uint value) + public void WriteFixed32(int fieldNumber, uint value) { WriteTag(fieldNumber, WireFormat.WireType.Fixed32); WriteRawLittleEndian32(value); @@ -283,7 +218,7 @@ namespace Google.Protobuf /// /// Writes a bool field value, including tag, to the stream. /// - public void WriteBool(int fieldNumber, string fieldName, bool value) + public void WriteBool(int fieldNumber, bool value) { WriteTag(fieldNumber, WireFormat.WireType.Varint); WriteRawByte(value ? (byte) 1 : (byte) 0); @@ -292,7 +227,7 @@ namespace Google.Protobuf /// /// Writes a string field value, including tag, to the stream. /// - public void WriteString(int fieldNumber, string fieldName, string value) + public void WriteString(int fieldNumber, string value) { WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); // Optimise the case where we have enough space to write @@ -324,80 +259,63 @@ namespace Google.Protobuf /// /// Writes a group field value, including tag, to the stream. /// - public void WriteGroup(int fieldNumber, string fieldName, IMessage value) + public void WriteGroup(int fieldNumber, IMessage value) { WriteTag(fieldNumber, WireFormat.WireType.StartGroup); value.WriteTo(this); WriteTag(fieldNumber, WireFormat.WireType.EndGroup); } - public void WriteMessage(int fieldNumber, string fieldName, IMessage value) + public void WriteMessage(int fieldNumber, IMessage value) { WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); WriteRawVarint32((uint) value.CalculateSize()); value.WriteTo(this); } - public void WriteBytes(int fieldNumber, string fieldName, ByteString value) + public void WriteBytes(int fieldNumber, ByteString value) { WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); WriteRawVarint32((uint) value.Length); value.WriteRawBytesTo(this); } - public void WriteUInt32(int fieldNumber, string fieldName, uint value) + public void WriteUInt32(int fieldNumber, uint value) { WriteTag(fieldNumber, WireFormat.WireType.Varint); WriteRawVarint32(value); } - public void WriteEnum(int fieldNumber, string fieldName, int value) + public void WriteEnum(int fieldNumber, int value) { // Currently just a pass-through, but it's nice to separate it logically from WriteInt32. WriteTag(fieldNumber, WireFormat.WireType.Varint); WriteInt32NoTag(value); } - public void WriteSFixed32(int fieldNumber, string fieldName, int value) + public void WriteSFixed32(int fieldNumber, int value) { WriteTag(fieldNumber, WireFormat.WireType.Fixed32); WriteRawLittleEndian32((uint) value); } - public void WriteSFixed64(int fieldNumber, string fieldName, long value) + public void WriteSFixed64(int fieldNumber, long value) { WriteTag(fieldNumber, WireFormat.WireType.Fixed64); WriteRawLittleEndian64((ulong) value); } - public void WriteSInt32(int fieldNumber, string fieldName, int value) + public void WriteSInt32(int fieldNumber, int value) { WriteTag(fieldNumber, WireFormat.WireType.Varint); WriteRawVarint32(EncodeZigZag32(value)); } - public void WriteSInt64(int fieldNumber, string fieldName, long value) + public void WriteSInt64(int fieldNumber, long value) { WriteTag(fieldNumber, WireFormat.WireType.Varint); WriteRawVarint64(EncodeZigZag64(value)); } - - public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessage value) - { - WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup); - WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber); - WriteMessage(WireFormat.MessageSetField.Message, "message", value); - WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup); - } - - public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value) - { - WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup); - WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber); - WriteBytes(WireFormat.MessageSetField.Message, "message", value); - WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup); - } - #endregion #region Writing of values without tags @@ -625,155 +543,145 @@ namespace Google.Protobuf #endregion #region Write array members - - // TODO(jonskeet): Remove? - public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list) - { - foreach (object element in list) - { - WriteField(fieldType, fieldNumber, fieldName, element); - } - } - - public void WriteGroupArray(int fieldNumber, string fieldName, RepeatedField list) + public void WriteGroupArray(int fieldNumber, RepeatedField list) where T : IMessage { foreach (IMessage value in list) { - WriteGroup(fieldNumber, fieldName, value); + WriteGroup(fieldNumber, value); } } - public void WriteMessageArray(int fieldNumber, string fieldName, RepeatedField list) + public void WriteMessageArray(int fieldNumber, RepeatedField list) where T : IMessage { foreach (IMessage value in list) { - WriteMessage(fieldNumber, fieldName, value); + WriteMessage(fieldNumber, value); } } - public void WriteStringArray(int fieldNumber, string fieldName, RepeatedField list) + public void WriteStringArray(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteString(fieldNumber, fieldName, value); + WriteString(fieldNumber, value); } } - public void WriteBytesArray(int fieldNumber, string fieldName, RepeatedField list) + public void WriteBytesArray(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteBytes(fieldNumber, fieldName, value); + WriteBytes(fieldNumber, value); } } - public void WriteBoolArray(int fieldNumber, string fieldName, RepeatedField list) + public void WriteBoolArray(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteBool(fieldNumber, fieldName, value); + WriteBool(fieldNumber, value); } } - public void WriteInt32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteInt32Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteInt32(fieldNumber, fieldName, value); + WriteInt32(fieldNumber, value); } } - public void WriteSInt32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteSInt32Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteSInt32(fieldNumber, fieldName, value); + WriteSInt32(fieldNumber, value); } } - public void WriteUInt32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteUInt32Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteUInt32(fieldNumber, fieldName, value); + WriteUInt32(fieldNumber, value); } } - public void WriteFixed32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteFixed32Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteFixed32(fieldNumber, fieldName, value); + WriteFixed32(fieldNumber, value); } } - public void WriteSFixed32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteSFixed32Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteSFixed32(fieldNumber, fieldName, value); + WriteSFixed32(fieldNumber, value); } } - public void WriteInt64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteInt64Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteInt64(fieldNumber, fieldName, value); + WriteInt64(fieldNumber, value); } } - public void WriteSInt64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteSInt64Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteSInt64(fieldNumber, fieldName, value); + WriteSInt64(fieldNumber, value); } } - public void WriteUInt64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteUInt64Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteUInt64(fieldNumber, fieldName, value); + WriteUInt64(fieldNumber, value); } } - public void WriteFixed64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteFixed64Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteFixed64(fieldNumber, fieldName, value); + WriteFixed64(fieldNumber, value); } } - public void WriteSFixed64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WriteSFixed64Array(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteSFixed64(fieldNumber, fieldName, value); + WriteSFixed64(fieldNumber, value); } } - public void WriteDoubleArray(int fieldNumber, string fieldName, RepeatedField list) + public void WriteDoubleArray(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteDouble(fieldNumber, fieldName, value); + WriteDouble(fieldNumber, value); } } - public void WriteFloatArray(int fieldNumber, string fieldName, RepeatedField list) + public void WriteFloatArray(int fieldNumber, RepeatedField list) { foreach (var value in list) { - WriteFloat(fieldNumber, fieldName, value); + WriteFloat(fieldNumber, value); } } - public void WriteEnumArray(int fieldNumber, string fieldName, RepeatedField list) + public void WriteEnumArray(int fieldNumber, RepeatedField list) where T : struct, IComparable, IFormattable { if (list.Count == 0) @@ -783,34 +691,15 @@ namespace Google.Protobuf // TODO(jonskeet): Avoid the Cast call here. Work out a better mass "T to int" conversion. foreach (int value in list.Cast()) { - WriteEnum(fieldNumber, fieldName, value); + WriteEnum(fieldNumber, value); } } #endregion #region Write packed array members - - // TODO(jonskeet): Remove? - public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list) - { - int calculatedSize = 0; - foreach (object element in list) - { - calculatedSize += ComputeFieldSizeNoTag(fieldType, element); - } - - WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited); - WriteRawVarint32((uint) calculatedSize); - - foreach (object element in list) - { - WriteFieldNoTag(fieldType, element); - } - } - // TODO(jonskeet): A lot of these are really inefficient, due to method group conversions. Fix! - public void WritePackedBoolArray(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedBoolArray(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -825,7 +714,7 @@ namespace Google.Protobuf } } - public void WritePackedInt32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedInt32Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -840,7 +729,7 @@ namespace Google.Protobuf } } - public void WritePackedSInt32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedSInt32Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -855,7 +744,7 @@ namespace Google.Protobuf } } - public void WritePackedUInt32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedUInt32Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -870,7 +759,7 @@ namespace Google.Protobuf } } - public void WritePackedFixed32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedFixed32Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -885,7 +774,7 @@ namespace Google.Protobuf } } - public void WritePackedSFixed32Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedSFixed32Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -900,7 +789,7 @@ namespace Google.Protobuf } } - public void WritePackedInt64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedInt64Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -915,7 +804,7 @@ namespace Google.Protobuf } } - public void WritePackedSInt64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedSInt64Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -930,7 +819,7 @@ namespace Google.Protobuf } } - public void WritePackedUInt64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedUInt64Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -945,7 +834,7 @@ namespace Google.Protobuf } } - public void WritePackedFixed64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedFixed64Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -960,7 +849,7 @@ namespace Google.Protobuf } } - public void WritePackedSFixed64Array(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedSFixed64Array(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -975,7 +864,7 @@ namespace Google.Protobuf } } - public void WritePackedDoubleArray(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedDoubleArray(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -990,7 +879,7 @@ namespace Google.Protobuf } } - public void WritePackedFloatArray(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedFloatArray(int fieldNumber, RepeatedField list) { if (list.Count == 0) { @@ -1005,7 +894,7 @@ namespace Google.Protobuf } } - public void WritePackedEnumArray(int fieldNumber, string fieldName, RepeatedField list) + public void WritePackedEnumArray(int fieldNumber, RepeatedField list) where T : struct, IComparable, IFormattable { if (list.Count == 0) diff --git a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs index eb96dfcf..f4af4e2c 100644 --- a/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs +++ b/csharp/src/ProtocolBuffers/DescriptorProtos/DescriptorProtoFile.cs @@ -323,9 +323,8 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; - output.WriteMessageArray(1, fieldNames[0], file_); + public void WriteTo(pb::CodedOutputStream output) { + output.WriteMessageArray(1, file_); } public int CalculateSize() { @@ -342,16 +341,9 @@ namespace Google.Protobuf.DescriptorProtos { file_.Add(other.file_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -361,7 +353,7 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadMessageArray(tag, fieldName, file_, global::Google.Protobuf.DescriptorProtos.FileDescriptorProto.Parser); + input.ReadMessageArray(tag, file_, global::Google.Protobuf.DescriptorProtos.FileDescriptorProto.Parser); break; } } @@ -510,29 +502,28 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Name != "") { - output.WriteString(1, fieldNames[4], Name); + output.WriteString(1, Name); } if (Package != "") { - output.WriteString(2, fieldNames[6], Package); + output.WriteString(2, Package); } - output.WriteStringArray(3, fieldNames[0], dependency_); - output.WriteMessageArray(4, fieldNames[3], messageType_); - output.WriteMessageArray(5, fieldNames[1], enumType_); - output.WriteMessageArray(6, fieldNames[8], service_); - output.WriteMessageArray(7, fieldNames[2], extension_); + output.WriteStringArray(3, dependency_); + output.WriteMessageArray(4, messageType_); + output.WriteMessageArray(5, enumType_); + output.WriteMessageArray(6, service_); + output.WriteMessageArray(7, extension_); if (options_ != null) { - output.WriteMessage(8, fieldNames[5], Options); + output.WriteMessage(8, Options); } if (sourceCodeInfo_ != null) { - output.WriteMessage(9, fieldNames[9], SourceCodeInfo); + output.WriteMessage(9, SourceCodeInfo); } - output.WriteInt32Array(10, fieldNames[7], publicDependency_); - output.WriteInt32Array(11, fieldNames[11], weakDependency_); + output.WriteInt32Array(10, publicDependency_); + output.WriteInt32Array(11, weakDependency_); if (Syntax != "") { - output.WriteString(12, fieldNames[10], Syntax); + output.WriteString(12, Syntax); } } @@ -625,16 +616,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -644,31 +628,31 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref name_); + name_ = input.ReadString(); break; } case 18: { - input.ReadString(ref package_); + package_ = input.ReadString(); break; } case 26: { - input.ReadStringArray(tag, fieldName, dependency_); + input.ReadStringArray(tag, dependency_); break; } case 34: { - input.ReadMessageArray(tag, fieldName, messageType_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser); + input.ReadMessageArray(tag, messageType_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser); break; } case 42: { - input.ReadMessageArray(tag, fieldName, enumType_, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser); + input.ReadMessageArray(tag, enumType_, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser); break; } case 50: { - input.ReadMessageArray(tag, fieldName, service_, global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto.Parser); + input.ReadMessageArray(tag, service_, global::Google.Protobuf.DescriptorProtos.ServiceDescriptorProto.Parser); break; } case 58: { - input.ReadMessageArray(tag, fieldName, extension_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser); + input.ReadMessageArray(tag, extension_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser); break; } case 66: { @@ -687,16 +671,16 @@ namespace Google.Protobuf.DescriptorProtos { } case 82: case 80: { - input.ReadInt32Array(tag, fieldName, publicDependency_); + input.ReadInt32Array(tag, publicDependency_); break; } case 90: case 88: { - input.ReadInt32Array(tag, fieldName, weakDependency_); + input.ReadInt32Array(tag, weakDependency_); break; } case 98: { - input.ReadString(ref syntax_); + syntax_ = input.ReadString(); break; } } @@ -825,22 +809,21 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Name != "") { - output.WriteString(1, fieldNames[4], Name); + output.WriteString(1, Name); } - output.WriteMessageArray(2, fieldNames[3], field_); - output.WriteMessageArray(3, fieldNames[5], nestedType_); - output.WriteMessageArray(4, fieldNames[0], enumType_); - output.WriteMessageArray(5, fieldNames[2], extensionRange_); - output.WriteMessageArray(6, fieldNames[1], extension_); + output.WriteMessageArray(2, field_); + output.WriteMessageArray(3, nestedType_); + output.WriteMessageArray(4, enumType_); + output.WriteMessageArray(5, extensionRange_); + output.WriteMessageArray(6, extension_); if (options_ != null) { - output.WriteMessage(7, fieldNames[7], Options); + output.WriteMessage(7, Options); } - output.WriteMessageArray(8, fieldNames[6], oneofDecl_); - output.WriteMessageArray(9, fieldNames[9], reservedRange_); - output.WriteStringArray(10, fieldNames[8], reservedName_); + output.WriteMessageArray(8, oneofDecl_); + output.WriteMessageArray(9, reservedRange_); + output.WriteStringArray(10, reservedName_); } public int CalculateSize() { @@ -905,16 +888,9 @@ namespace Google.Protobuf.DescriptorProtos { reservedName_.Add(other.reservedName_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -924,27 +900,27 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref name_); + name_ = input.ReadString(); break; } case 18: { - input.ReadMessageArray(tag, fieldName, field_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser); + input.ReadMessageArray(tag, field_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser); break; } case 26: { - input.ReadMessageArray(tag, fieldName, nestedType_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser); + input.ReadMessageArray(tag, nestedType_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Parser); break; } case 34: { - input.ReadMessageArray(tag, fieldName, enumType_, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser); + input.ReadMessageArray(tag, enumType_, global::Google.Protobuf.DescriptorProtos.EnumDescriptorProto.Parser); break; } case 42: { - input.ReadMessageArray(tag, fieldName, extensionRange_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Parser); + input.ReadMessageArray(tag, extensionRange_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ExtensionRange.Parser); break; } case 50: { - input.ReadMessageArray(tag, fieldName, extension_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser); + input.ReadMessageArray(tag, extension_, global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Parser); break; } case 58: { @@ -955,15 +931,15 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 66: { - input.ReadMessageArray(tag, fieldName, oneofDecl_, global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto.Parser); + input.ReadMessageArray(tag, oneofDecl_, global::Google.Protobuf.DescriptorProtos.OneofDescriptorProto.Parser); break; } case 74: { - input.ReadMessageArray(tag, fieldName, reservedRange_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange.Parser); + input.ReadMessageArray(tag, reservedRange_, global::Google.Protobuf.DescriptorProtos.DescriptorProto.Types.ReservedRange.Parser); break; } case 82: { - input.ReadStringArray(tag, fieldName, reservedName_); + input.ReadStringArray(tag, reservedName_); break; } } @@ -1031,13 +1007,12 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Start != 0) { - output.WriteInt32(1, fieldNames[1], Start); + output.WriteInt32(1, Start); } if (End != 0) { - output.WriteInt32(2, fieldNames[0], End); + output.WriteInt32(2, End); } } @@ -1063,16 +1038,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1082,11 +1050,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 8: { - input.ReadInt32(ref start_); + start_ = input.ReadInt32(); break; } case 16: { - input.ReadInt32(ref end_); + end_ = input.ReadInt32(); break; } } @@ -1153,13 +1121,12 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Start != 0) { - output.WriteInt32(1, fieldNames[1], Start); + output.WriteInt32(1, Start); } if (End != 0) { - output.WriteInt32(2, fieldNames[0], End); + output.WriteInt32(2, End); } } @@ -1185,16 +1152,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1204,11 +1164,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 8: { - input.ReadInt32(ref start_); + start_ = input.ReadInt32(); break; } case 16: { - input.ReadInt32(ref end_); + end_ = input.ReadInt32(); break; } } @@ -1348,34 +1308,33 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Name != "") { - output.WriteString(1, fieldNames[3], Name); + output.WriteString(1, Name); } if (Extendee != "") { - output.WriteString(2, fieldNames[1], Extendee); + output.WriteString(2, Extendee); } if (Number != 0) { - output.WriteInt32(3, fieldNames[4], Number); + output.WriteInt32(3, Number); } if (Label != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label.LABEL_OPTIONAL) { - output.WriteEnum(4, fieldNames[2], (int) Label); + output.WriteEnum(4, (int) Label); } if (Type != global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type.TYPE_DOUBLE) { - output.WriteEnum(5, fieldNames[7], (int) Type); + output.WriteEnum(5, (int) Type); } if (TypeName != "") { - output.WriteString(6, fieldNames[8], TypeName); + output.WriteString(6, TypeName); } if (DefaultValue != "") { - output.WriteString(7, fieldNames[0], DefaultValue); + output.WriteString(7, DefaultValue); } if (options_ != null) { - output.WriteMessage(8, fieldNames[6], Options); + output.WriteMessage(8, Options); } if (OneofIndex != 0) { - output.WriteInt32(9, fieldNames[5], OneofIndex); + output.WriteInt32(9, OneofIndex); } } @@ -1446,16 +1405,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1465,33 +1417,31 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref name_); + name_ = input.ReadString(); break; } case 18: { - input.ReadString(ref extendee_); + extendee_ = input.ReadString(); break; } case 24: { - input.ReadInt32(ref number_); + number_ = input.ReadInt32(); break; } case 32: { - int tmp = 0; - input.ReadEnum(ref tmp); - label_ = (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label) tmp;break; + label_ = (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Label) input.ReadEnum(); + break; } case 40: { - int tmp = 0; - input.ReadEnum(ref tmp); - type_ = (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type) tmp;break; + type_ = (global::Google.Protobuf.DescriptorProtos.FieldDescriptorProto.Types.Type) input.ReadEnum(); + break; } case 50: { - input.ReadString(ref typeName_); + typeName_ = input.ReadString(); break; } case 58: { - input.ReadString(ref defaultValue_); + defaultValue_ = input.ReadString(); break; } case 66: { @@ -1502,7 +1452,7 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 72: { - input.ReadInt32(ref oneofIndex_); + oneofIndex_ = input.ReadInt32(); break; } } @@ -1592,10 +1542,9 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Name != "") { - output.WriteString(1, fieldNames[0], Name); + output.WriteString(1, Name); } } @@ -1615,16 +1564,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1634,7 +1576,7 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref name_); + name_ = input.ReadString(); break; } } @@ -1707,14 +1649,13 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Name != "") { - output.WriteString(1, fieldNames[0], Name); + output.WriteString(1, Name); } - output.WriteMessageArray(2, fieldNames[2], value_); + output.WriteMessageArray(2, value_); if (options_ != null) { - output.WriteMessage(3, fieldNames[1], Options); + output.WriteMessage(3, Options); } } @@ -1747,16 +1688,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1766,11 +1700,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref name_); + name_ = input.ReadString(); break; } case 18: { - input.ReadMessageArray(tag, fieldName, value_, global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto.Parser); + input.ReadMessageArray(tag, value_, global::Google.Protobuf.DescriptorProtos.EnumValueDescriptorProto.Parser); break; } case 26: { @@ -1852,16 +1786,15 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Name != "") { - output.WriteString(1, fieldNames[0], Name); + output.WriteString(1, Name); } if (Number != 0) { - output.WriteInt32(2, fieldNames[1], Number); + output.WriteInt32(2, Number); } if (options_ != null) { - output.WriteMessage(3, fieldNames[2], Options); + output.WriteMessage(3, Options); } } @@ -1896,16 +1829,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -1915,11 +1841,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref name_); + name_ = input.ReadString(); break; } case 16: { - input.ReadInt32(ref number_); + number_ = input.ReadInt32(); break; } case 26: { @@ -1999,14 +1925,13 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Name != "") { - output.WriteString(1, fieldNames[1], Name); + output.WriteString(1, Name); } - output.WriteMessageArray(2, fieldNames[0], method_); + output.WriteMessageArray(2, method_); if (options_ != null) { - output.WriteMessage(3, fieldNames[2], Options); + output.WriteMessage(3, Options); } } @@ -2039,16 +1964,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2058,11 +1976,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref name_); + name_ = input.ReadString(); break; } case 18: { - input.ReadMessageArray(tag, fieldName, method_, global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto.Parser); + input.ReadMessageArray(tag, method_, global::Google.Protobuf.DescriptorProtos.MethodDescriptorProto.Parser); break; } case 26: { @@ -2174,25 +2092,24 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Name != "") { - output.WriteString(1, fieldNames[2], Name); + output.WriteString(1, Name); } if (InputType != "") { - output.WriteString(2, fieldNames[1], InputType); + output.WriteString(2, InputType); } if (OutputType != "") { - output.WriteString(3, fieldNames[4], OutputType); + output.WriteString(3, OutputType); } if (options_ != null) { - output.WriteMessage(4, fieldNames[3], Options); + output.WriteMessage(4, Options); } if (ClientStreaming != false) { - output.WriteBool(5, fieldNames[0], ClientStreaming); + output.WriteBool(5, ClientStreaming); } if (ServerStreaming != false) { - output.WriteBool(6, fieldNames[5], ServerStreaming); + output.WriteBool(6, ServerStreaming); } } @@ -2245,16 +2162,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2264,15 +2174,15 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref name_); + name_ = input.ReadString(); break; } case 18: { - input.ReadString(ref inputType_); + inputType_ = input.ReadString(); break; } case 26: { - input.ReadString(ref outputType_); + outputType_ = input.ReadString(); break; } case 34: { @@ -2283,11 +2193,11 @@ namespace Google.Protobuf.DescriptorProtos { break; } case 40: { - input.ReadBool(ref clientStreaming_); + clientStreaming_ = input.ReadBool(); break; } case 48: { - input.ReadBool(ref serverStreaming_); + serverStreaming_ = input.ReadBool(); break; } } @@ -2482,51 +2392,50 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (JavaPackage != "") { - output.WriteString(1, fieldNames[9], JavaPackage); + output.WriteString(1, JavaPackage); } if (JavaOuterClassname != "") { - output.WriteString(8, fieldNames[8], JavaOuterClassname); + output.WriteString(8, JavaOuterClassname); } if (OptimizeFor != global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode.SPEED) { - output.WriteEnum(9, fieldNames[12], (int) OptimizeFor); + output.WriteEnum(9, (int) OptimizeFor); } if (JavaMultipleFiles != false) { - output.WriteBool(10, fieldNames[7], JavaMultipleFiles); + output.WriteBool(10, JavaMultipleFiles); } if (GoPackage != "") { - output.WriteString(11, fieldNames[4], GoPackage); + output.WriteString(11, GoPackage); } if (CcGenericServices != false) { - output.WriteBool(16, fieldNames[1], CcGenericServices); + output.WriteBool(16, CcGenericServices); } if (JavaGenericServices != false) { - output.WriteBool(17, fieldNames[6], JavaGenericServices); + output.WriteBool(17, JavaGenericServices); } if (PyGenericServices != false) { - output.WriteBool(18, fieldNames[13], PyGenericServices); + output.WriteBool(18, PyGenericServices); } if (JavaGenerateEqualsAndHash != false) { - output.WriteBool(20, fieldNames[5], JavaGenerateEqualsAndHash); + output.WriteBool(20, JavaGenerateEqualsAndHash); } if (Deprecated != false) { - output.WriteBool(23, fieldNames[3], Deprecated); + output.WriteBool(23, Deprecated); } if (JavaStringCheckUtf8 != false) { - output.WriteBool(27, fieldNames[10], JavaStringCheckUtf8); + output.WriteBool(27, JavaStringCheckUtf8); } if (CcEnableArenas != false) { - output.WriteBool(31, fieldNames[0], CcEnableArenas); + output.WriteBool(31, CcEnableArenas); } if (ObjcClassPrefix != "") { - output.WriteString(36, fieldNames[11], ObjcClassPrefix); + output.WriteString(36, ObjcClassPrefix); } if (CsharpNamespace != "") { - output.WriteString(37, fieldNames[2], CsharpNamespace); + output.WriteString(37, CsharpNamespace); } - output.WriteMessageArray(999, fieldNames[14], uninterpretedOption_); + output.WriteMessageArray(999, uninterpretedOption_); } public int CalculateSize() { @@ -2627,16 +2536,9 @@ namespace Google.Protobuf.DescriptorProtos { uninterpretedOption_.Add(other.uninterpretedOption_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2646,64 +2548,63 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref javaPackage_); + javaPackage_ = input.ReadString(); break; } case 66: { - input.ReadString(ref javaOuterClassname_); + javaOuterClassname_ = input.ReadString(); break; } case 72: { - int tmp = 0; - input.ReadEnum(ref tmp); - optimizeFor_ = (global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode) tmp;break; + optimizeFor_ = (global::Google.Protobuf.DescriptorProtos.FileOptions.Types.OptimizeMode) input.ReadEnum(); + break; } case 80: { - input.ReadBool(ref javaMultipleFiles_); + javaMultipleFiles_ = input.ReadBool(); break; } case 90: { - input.ReadString(ref goPackage_); + goPackage_ = input.ReadString(); break; } case 128: { - input.ReadBool(ref ccGenericServices_); + ccGenericServices_ = input.ReadBool(); break; } case 136: { - input.ReadBool(ref javaGenericServices_); + javaGenericServices_ = input.ReadBool(); break; } case 144: { - input.ReadBool(ref pyGenericServices_); + pyGenericServices_ = input.ReadBool(); break; } case 160: { - input.ReadBool(ref javaGenerateEqualsAndHash_); + javaGenerateEqualsAndHash_ = input.ReadBool(); break; } case 184: { - input.ReadBool(ref deprecated_); + deprecated_ = input.ReadBool(); break; } case 216: { - input.ReadBool(ref javaStringCheckUtf8_); + javaStringCheckUtf8_ = input.ReadBool(); break; } case 248: { - input.ReadBool(ref ccEnableArenas_); + ccEnableArenas_ = input.ReadBool(); break; } case 290: { - input.ReadString(ref objcClassPrefix_); + objcClassPrefix_ = input.ReadString(); break; } case 298: { - input.ReadString(ref csharpNamespace_); + csharpNamespace_ = input.ReadString(); break; } case 7994: { - input.ReadMessageArray(tag, fieldName, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); + input.ReadMessageArray(tag, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); break; } } @@ -2810,21 +2711,20 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (MessageSetWireFormat != false) { - output.WriteBool(1, fieldNames[2], MessageSetWireFormat); + output.WriteBool(1, MessageSetWireFormat); } if (NoStandardDescriptorAccessor != false) { - output.WriteBool(2, fieldNames[3], NoStandardDescriptorAccessor); + output.WriteBool(2, NoStandardDescriptorAccessor); } if (Deprecated != false) { - output.WriteBool(3, fieldNames[0], Deprecated); + output.WriteBool(3, Deprecated); } if (MapEntry != false) { - output.WriteBool(7, fieldNames[1], MapEntry); + output.WriteBool(7, MapEntry); } - output.WriteMessageArray(999, fieldNames[4], uninterpretedOption_); + output.WriteMessageArray(999, uninterpretedOption_); } public int CalculateSize() { @@ -2865,16 +2765,9 @@ namespace Google.Protobuf.DescriptorProtos { uninterpretedOption_.Add(other.uninterpretedOption_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -2884,23 +2777,23 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 8: { - input.ReadBool(ref messageSetWireFormat_); + messageSetWireFormat_ = input.ReadBool(); break; } case 16: { - input.ReadBool(ref noStandardDescriptorAccessor_); + noStandardDescriptorAccessor_ = input.ReadBool(); break; } case 24: { - input.ReadBool(ref deprecated_); + deprecated_ = input.ReadBool(); break; } case 56: { - input.ReadBool(ref mapEntry_); + mapEntry_ = input.ReadBool(); break; } case 7994: { - input.ReadMessageArray(tag, fieldName, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); + input.ReadMessageArray(tag, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); break; } } @@ -3015,27 +2908,26 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Ctype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType.STRING) { - output.WriteEnum(1, fieldNames[0], (int) Ctype); + output.WriteEnum(1, (int) Ctype); } if (Packed != false) { - output.WriteBool(2, fieldNames[4], Packed); + output.WriteBool(2, Packed); } if (Deprecated != false) { - output.WriteBool(3, fieldNames[1], Deprecated); + output.WriteBool(3, Deprecated); } if (Lazy != false) { - output.WriteBool(5, fieldNames[3], Lazy); + output.WriteBool(5, Lazy); } if (Jstype != global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType.JS_NORMAL) { - output.WriteEnum(6, fieldNames[2], (int) Jstype); + output.WriteEnum(6, (int) Jstype); } if (Weak != false) { - output.WriteBool(10, fieldNames[6], Weak); + output.WriteBool(10, Weak); } - output.WriteMessageArray(999, fieldNames[5], uninterpretedOption_); + output.WriteMessageArray(999, uninterpretedOption_); } public int CalculateSize() { @@ -3088,16 +2980,9 @@ namespace Google.Protobuf.DescriptorProtos { uninterpretedOption_.Add(other.uninterpretedOption_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3107,33 +2992,31 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 8: { - int tmp = 0; - input.ReadEnum(ref tmp); - ctype_ = (global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType) tmp;break; + ctype_ = (global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.CType) input.ReadEnum(); + break; } case 16: { - input.ReadBool(ref packed_); + packed_ = input.ReadBool(); break; } case 24: { - input.ReadBool(ref deprecated_); + deprecated_ = input.ReadBool(); break; } case 40: { - input.ReadBool(ref lazy_); + lazy_ = input.ReadBool(); break; } case 48: { - int tmp = 0; - input.ReadEnum(ref tmp); - jstype_ = (global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType) tmp;break; + jstype_ = (global::Google.Protobuf.DescriptorProtos.FieldOptions.Types.JSType) input.ReadEnum(); + break; } case 80: { - input.ReadBool(ref weak_); + weak_ = input.ReadBool(); break; } case 7994: { - input.ReadMessageArray(tag, fieldName, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); + input.ReadMessageArray(tag, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); break; } } @@ -3226,15 +3109,14 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (AllowAlias != false) { - output.WriteBool(2, fieldNames[0], AllowAlias); + output.WriteBool(2, AllowAlias); } if (Deprecated != false) { - output.WriteBool(3, fieldNames[1], Deprecated); + output.WriteBool(3, Deprecated); } - output.WriteMessageArray(999, fieldNames[2], uninterpretedOption_); + output.WriteMessageArray(999, uninterpretedOption_); } public int CalculateSize() { @@ -3263,16 +3145,9 @@ namespace Google.Protobuf.DescriptorProtos { uninterpretedOption_.Add(other.uninterpretedOption_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3282,15 +3157,15 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 16: { - input.ReadBool(ref allowAlias_); + allowAlias_ = input.ReadBool(); break; } case 24: { - input.ReadBool(ref deprecated_); + deprecated_ = input.ReadBool(); break; } case 7994: { - input.ReadMessageArray(tag, fieldName, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); + input.ReadMessageArray(tag, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); break; } } @@ -3355,12 +3230,11 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Deprecated != false) { - output.WriteBool(1, fieldNames[0], Deprecated); + output.WriteBool(1, Deprecated); } - output.WriteMessageArray(999, fieldNames[1], uninterpretedOption_); + output.WriteMessageArray(999, uninterpretedOption_); } public int CalculateSize() { @@ -3383,16 +3257,9 @@ namespace Google.Protobuf.DescriptorProtos { uninterpretedOption_.Add(other.uninterpretedOption_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3402,11 +3269,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 8: { - input.ReadBool(ref deprecated_); + deprecated_ = input.ReadBool(); break; } case 7994: { - input.ReadMessageArray(tag, fieldName, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); + input.ReadMessageArray(tag, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); break; } } @@ -3471,12 +3338,11 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Deprecated != false) { - output.WriteBool(33, fieldNames[0], Deprecated); + output.WriteBool(33, Deprecated); } - output.WriteMessageArray(999, fieldNames[1], uninterpretedOption_); + output.WriteMessageArray(999, uninterpretedOption_); } public int CalculateSize() { @@ -3499,16 +3365,9 @@ namespace Google.Protobuf.DescriptorProtos { uninterpretedOption_.Add(other.uninterpretedOption_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3518,11 +3377,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 264: { - input.ReadBool(ref deprecated_); + deprecated_ = input.ReadBool(); break; } case 7994: { - input.ReadMessageArray(tag, fieldName, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); + input.ReadMessageArray(tag, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); break; } } @@ -3587,12 +3446,11 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (Deprecated != false) { - output.WriteBool(33, fieldNames[0], Deprecated); + output.WriteBool(33, Deprecated); } - output.WriteMessageArray(999, fieldNames[1], uninterpretedOption_); + output.WriteMessageArray(999, uninterpretedOption_); } public int CalculateSize() { @@ -3615,16 +3473,9 @@ namespace Google.Protobuf.DescriptorProtos { uninterpretedOption_.Add(other.uninterpretedOption_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3634,11 +3485,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 264: { - input.ReadBool(ref deprecated_); + deprecated_ = input.ReadBool(); break; } case 7994: { - input.ReadMessageArray(tag, fieldName, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); + input.ReadMessageArray(tag, uninterpretedOption_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Parser); break; } } @@ -3753,26 +3604,25 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; - output.WriteMessageArray(2, fieldNames[3], name_); + public void WriteTo(pb::CodedOutputStream output) { + output.WriteMessageArray(2, name_); if (IdentifierValue != "") { - output.WriteString(3, fieldNames[2], IdentifierValue); + output.WriteString(3, IdentifierValue); } if (PositiveIntValue != 0UL) { - output.WriteUInt64(4, fieldNames[5], PositiveIntValue); + output.WriteUInt64(4, PositiveIntValue); } if (NegativeIntValue != 0L) { - output.WriteInt64(5, fieldNames[4], NegativeIntValue); + output.WriteInt64(5, NegativeIntValue); } if (DoubleValue != 0D) { - output.WriteDouble(6, fieldNames[1], DoubleValue); + output.WriteDouble(6, DoubleValue); } if (StringValue != pb::ByteString.Empty) { - output.WriteBytes(7, fieldNames[6], StringValue); + output.WriteBytes(7, StringValue); } if (AggregateValue != "") { - output.WriteString(8, fieldNames[0], AggregateValue); + output.WriteString(8, AggregateValue); } } @@ -3826,16 +3676,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3845,31 +3688,31 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 18: { - input.ReadMessageArray(tag, fieldName, name_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart.Parser); + input.ReadMessageArray(tag, name_, global::Google.Protobuf.DescriptorProtos.UninterpretedOption.Types.NamePart.Parser); break; } case 26: { - input.ReadString(ref identifierValue_); + identifierValue_ = input.ReadString(); break; } case 32: { - input.ReadUInt64(ref positiveIntValue_); + positiveIntValue_ = input.ReadUInt64(); break; } case 40: { - input.ReadInt64(ref negativeIntValue_); + negativeIntValue_ = input.ReadInt64(); break; } case 49: { - input.ReadDouble(ref doubleValue_); + doubleValue_ = input.ReadDouble(); break; } case 58: { - input.ReadBytes(ref stringValue_); + stringValue_ = input.ReadBytes(); break; } case 66: { - input.ReadString(ref aggregateValue_); + aggregateValue_ = input.ReadString(); break; } } @@ -3937,13 +3780,12 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; + public void WriteTo(pb::CodedOutputStream output) { if (NamePart_ != "") { - output.WriteString(1, fieldNames[1], NamePart_); + output.WriteString(1, NamePart_); } if (IsExtension != false) { - output.WriteBool(2, fieldNames[0], IsExtension); + output.WriteBool(2, IsExtension); } } @@ -3969,16 +3811,9 @@ namespace Google.Protobuf.DescriptorProtos { } } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -3988,11 +3823,11 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadString(ref namePart_); + namePart_ = input.ReadString(); break; } case 16: { - input.ReadBool(ref isExtension_); + isExtension_ = input.ReadBool(); break; } } @@ -4052,9 +3887,8 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; - output.WriteMessageArray(1, fieldNames[0], location_); + public void WriteTo(pb::CodedOutputStream output) { + output.WriteMessageArray(1, location_); } public int CalculateSize() { @@ -4071,16 +3905,9 @@ namespace Google.Protobuf.DescriptorProtos { location_.Add(other.location_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -4090,7 +3917,7 @@ namespace Google.Protobuf.DescriptorProtos { } break; case 10: { - input.ReadMessageArray(tag, fieldName, location_, global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location.Parser); + input.ReadMessageArray(tag, location_, global::Google.Protobuf.DescriptorProtos.SourceCodeInfo.Types.Location.Parser); break; } } @@ -4182,17 +4009,16 @@ namespace Google.Protobuf.DescriptorProtos { return hash; } - public void WriteTo(pb::ICodedOutputStream output) { - string[] fieldNames = _fieldNames; - output.WritePackedInt32Array(1, fieldNames[2], path_); - output.WritePackedInt32Array(2, fieldNames[3], span_); + public void WriteTo(pb::CodedOutputStream output) { + output.WritePackedInt32Array(1, path_); + output.WritePackedInt32Array(2, span_); if (LeadingComments != "") { - output.WriteString(3, fieldNames[0], LeadingComments); + output.WriteString(3, LeadingComments); } if (TrailingComments != "") { - output.WriteString(4, fieldNames[4], TrailingComments); + output.WriteString(4, TrailingComments); } - output.WriteStringArray(6, fieldNames[1], leadingDetachedComments_); + output.WriteStringArray(6, leadingDetachedComments_); } public int CalculateSize() { @@ -4248,16 +4074,9 @@ namespace Google.Protobuf.DescriptorProtos { leadingDetachedComments_.Add(other.leadingDetachedComments_); } - public void MergeFrom(pb::ICodedInputStream input) { + public void MergeFrom(pb::CodedInputStream input) { uint tag; - string fieldName; - while (input.ReadTag(out tag, out fieldName)) { - if (tag == 0 && fieldName != null) { - int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal); - if (fieldOrdinal >= 0) { - tag = _fieldTags[fieldOrdinal]; - } - } + while (input.ReadTag(out tag)) { switch(tag) { case 0: throw pb::InvalidProtocolBufferException.InvalidTag(); @@ -4268,24 +4087,24 @@ namespace Google.Protobuf.DescriptorProtos { break; case 10: case 8: { - input.ReadInt32Array(tag, fieldName, path_); + input.ReadInt32Array(tag, path_); break; } case 18: case 16: { - input.ReadInt32Array(tag, fieldName, span_); + input.ReadInt32Array(tag, span_); break; } case 26: { - input.ReadString(ref leadingComments_); + leadingComments_ = input.ReadString(); break; } case 34: { - input.ReadString(ref trailingComments_); + trailingComments_ = input.ReadString(); break; } case 50: { - input.ReadStringArray(tag, fieldName, leadingDetachedComments_); + input.ReadStringArray(tag, leadingDetachedComments_); break; } } diff --git a/csharp/src/ProtocolBuffers/Extensions.cs b/csharp/src/ProtocolBuffers/Extensions.cs index 29288f51..7f23057e 100644 --- a/csharp/src/ProtocolBuffers/Extensions.cs +++ b/csharp/src/ProtocolBuffers/Extensions.cs @@ -49,7 +49,7 @@ namespace Google.Protobuf codedOutput.Flush(); } - public static void WriteTo(this IMessage message, ICodedOutputStream output) + public static void WriteTo(this IMessage message, CodedOutputStream output) { message.WriteTo(output); } diff --git a/csharp/src/ProtocolBuffers/ICodedInputStream.cs b/csharp/src/ProtocolBuffers/ICodedInputStream.cs deleted file mode 100644 index d962e62b..00000000 --- a/csharp/src/ProtocolBuffers/ICodedInputStream.cs +++ /dev/null @@ -1,293 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections.Generic; -using Google.Protobuf.Descriptors; - -//Disable warning CS3010: CLS-compliant interfaces must have only CLS-compliant members -#pragma warning disable 3010 - -namespace Google.Protobuf -{ - public interface ICodedInputStream - { - /// - /// Reads any message initialization data expected from the input stream - /// - /// - /// This is primarily used by text formats and unnecessary for protobuffers' own - /// binary format. The API for MessageStart/End was added for consistent handling - /// of output streams regardless of the actual writer implementation. - /// - void ReadMessageStart(); - /// - /// Reads any message finalization data expected from the input stream - /// - /// - /// This is primarily used by text formats and unnecessary for protobuffers' own - /// binary format. The API for MessageStart/End was added for consistent handling - /// of output streams regardless of the actual writer implementation. - /// - void ReadMessageEnd(); - /// - /// Attempt to read a field tag, returning false if we have reached the end - /// of the input data. - /// - /// - /// - /// If fieldTag is non-zero and ReadTag returns true then the value in fieldName - /// may or may not be populated. However, if fieldTag is zero and ReadTag returns - /// true, then fieldName should be populated with a non-null field name. - /// - /// In other words if ReadTag returns true then either fieldTag will be non-zero OR - /// fieldName will be non-zero. In some cases both may be populated, however the - /// builders will always prefer the fieldTag over fieldName. - /// - /// - bool ReadTag(out uint fieldTag, out string fieldName); - - /// - /// Read a double field from the stream. - /// - bool ReadDouble(ref double value); - - /// - /// Read a float field from the stream. - /// - bool ReadFloat(ref float value); - - /// - /// Read a uint64 field from the stream. - /// - bool ReadUInt64(ref ulong value); - - /// - /// Read an int64 field from the stream. - /// - bool ReadInt64(ref long value); - - /// - /// Read an int32 field from the stream. - /// - bool ReadInt32(ref int value); - - /// - /// Read a fixed64 field from the stream. - /// - bool ReadFixed64(ref ulong value); - - /// - /// Read a fixed32 field from the stream. - /// - bool ReadFixed32(ref uint value); - - /// - /// Read a bool field from the stream. - /// - bool ReadBool(ref bool value); - - /// - /// Reads a string field from the stream. - /// - bool ReadString(ref string value); - - /// - /// Reads a group field value from the stream. - /// - void ReadGroup(int fieldNumber, IMessage message); - - /// - /// Reads an embedded message field value from the stream. - /// - void ReadMessage(IMessage message); - - /// - /// Reads a bytes field value from the stream. - /// - bool ReadBytes(ref ByteString value); - - /// - /// Reads a uint32 field value from the stream. - /// - bool ReadUInt32(ref uint value); - - /// - /// Reads an enum field value from the stream. This performs no checking - /// as to whether the enum value is known to the enum type as it was present - /// when the code was generated. - /// - bool ReadEnum(ref int value); - - /// - /// Reads an sfixed32 field value from the stream. - /// - bool ReadSFixed32(ref int value); - - /// - /// Reads an sfixed64 field value from the stream. - /// - bool ReadSFixed64(ref long value); - - /// - /// Reads an sint32 field value from the stream. - /// - bool ReadSInt32(ref int value); - - /// - /// Reads an sint64 field value from the stream. - /// - bool ReadSInt64(ref long value); - - /// - /// Reads an array of primitive values into the list, if the wire-type of fieldTag is length-prefixed and the - /// type is numeric, it will read a packed array. - /// - void ReadPrimitiveArray(FieldType fieldType, uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads an array of primitive values into the list, if the wire-type of fieldTag is length-prefixed, it will - /// read a packed array. - /// - void ReadEnumArray(uint fieldTag, string fieldName, ICollection list) - where T : struct, IComparable, IFormattable; - - /// - /// Reads a set of messages using the to read individual messages. - /// - void ReadMessageArray(uint fieldTag, string fieldName, ICollection list, MessageParser parser) where T : IMessage; - - /// - /// Reads a set of messages using the as a template. - /// - void ReadGroupArray(uint fieldTag, string fieldName, ICollection list, MessageParser parser) where T : IMessage; - - /// - /// Reads a field of any primitive type. Enums, groups and embedded - /// messages are not handled by this method. - /// - bool ReadPrimitiveField(FieldType fieldType, ref object value); - - /// - /// Returns true if the stream has reached the end of the input. This is the - /// case if either the end of the underlying input source has been reached or - /// the stream has reached a limit created using PushLimit. - /// - bool IsAtEnd { get; } - - /// - /// Reads and discards a single field, given its tag value. - /// - /// false if the tag is an end-group tag, in which case - /// nothing is skipped. Otherwise, returns true. - bool SkipField(); - - /// - /// Reads one or more repeated string field values from the stream. - /// - void ReadStringArray(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated ByteString field values from the stream. - /// - void ReadBytesArray(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated boolean field values from the stream. - /// - void ReadBoolArray(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated Int32 field values from the stream. - /// - void ReadInt32Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated SInt32 field values from the stream. - /// - void ReadSInt32Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated UInt32 field values from the stream. - /// - void ReadUInt32Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated Fixed32 field values from the stream. - /// - void ReadFixed32Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated SFixed32 field values from the stream. - /// - void ReadSFixed32Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated Int64 field values from the stream. - /// - void ReadInt64Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated SInt64 field values from the stream. - /// - void ReadSInt64Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated UInt64 field values from the stream. - /// - void ReadUInt64Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated Fixed64 field values from the stream. - /// - void ReadFixed64Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated SFixed64 field values from the stream. - /// - void ReadSFixed64Array(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated Double field values from the stream. - /// - void ReadDoubleArray(uint fieldTag, string fieldName, ICollection list); - - /// - /// Reads one or more repeated Float field values from the stream. - /// - void ReadFloatArray(uint fieldTag, string fieldName, ICollection list); - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/ICodedOutputStream.cs b/csharp/src/ProtocolBuffers/ICodedOutputStream.cs deleted file mode 100644 index 921400ac..00000000 --- a/csharp/src/ProtocolBuffers/ICodedOutputStream.cs +++ /dev/null @@ -1,347 +0,0 @@ -#region Copyright notice and license - -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://github.com/jskeet/dotnet-protobufs/ -// Original C++/Java/Python code: -// http://code.google.com/p/protobuf/ -// -// 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. - -#endregion - -using System; -using System.Collections; -using Google.Protobuf.Collections; -using Google.Protobuf.Descriptors; - -//Disable warning CS3010: CLS-compliant interfaces must have only CLS-compliant members -#pragma warning disable 3010 - -namespace Google.Protobuf -{ - /// - /// Provides an interface that is used write a message. Most often proto buffers are written - /// in their binary form by creating a instance via the CodedOutputStream.CreateInstance - /// static factory. - /// - public interface ICodedOutputStream - { - /// - /// Writes any message initialization data needed to the output stream - /// - /// - /// This is primarily used by text formats and unnecessary for protobuffers' own - /// binary format. The API for MessageStart/End was added for consistent handling - /// of output streams regardless of the actual writer implementation. - /// - void WriteMessageStart(); - /// - /// Writes any message finalization data needed to the output stream - /// - /// - /// This is primarily used by text formats and unnecessary for protobuffers' own - /// binary format. The API for MessageStart/End was added for consistent handling - /// of output streams regardless of the actual writer implementation. - /// - void WriteMessageEnd(); - - /// - /// Indicates that all temporary buffers be written to the final output. - /// - void Flush(); - - /// - /// Writes a field value, including tag, to the stream. - /// - void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value); - - /// - /// Writes a double field value, including tag, to the stream. - /// - void WriteDouble(int fieldNumber, string fieldName, double value); - - /// - /// Writes a float field value, including tag, to the stream. - /// - void WriteFloat(int fieldNumber, string fieldName, float value); - - /// - /// Writes a uint64 field value, including tag, to the stream. - /// - void WriteUInt64(int fieldNumber, string fieldName, ulong value); - - /// - /// Writes an int64 field value, including tag, to the stream. - /// - void WriteInt64(int fieldNumber, string fieldName, long value); - - /// - /// Writes an int32 field value, including tag, to the stream. - /// - void WriteInt32(int fieldNumber, string fieldName, int value); - - /// - /// Writes a fixed64 field value, including tag, to the stream. - /// - void WriteFixed64(int fieldNumber, string fieldName, ulong value); - - /// - /// Writes a fixed32 field value, including tag, to the stream. - /// - void WriteFixed32(int fieldNumber, string fieldName, uint value); - - /// - /// Writes a bool field value, including tag, to the stream. - /// - void WriteBool(int fieldNumber, string fieldName, bool value); - - /// - /// Writes a string field value, including tag, to the stream. - /// - void WriteString(int fieldNumber, string fieldName, string value); - - /// - /// Writes a group field value, including tag, to the stream. - /// - void WriteGroup(int fieldNumber, string fieldName, IMessage value); - - /// - /// Writes a message field value, including tag, to the stream. - /// - void WriteMessage(int fieldNumber, string fieldName, IMessage value); - - /// - /// Writes a byte array field value, including tag, to the stream. - /// - void WriteBytes(int fieldNumber, string fieldName, ByteString value); - - /// - /// Writes a UInt32 field value, including tag, to the stream. - /// - void WriteUInt32(int fieldNumber, string fieldName, uint value); - - /// - /// Writes an enum field value, including tag, to the stream. - /// - void WriteEnum(int fieldNumber, string fieldName, int value); - - /// - /// Writes a fixed 32-bit field value, including tag, to the stream. - /// - void WriteSFixed32(int fieldNumber, string fieldName, int value); - - /// - /// Writes a signed fixed 64-bit field value, including tag, to the stream. - /// - void WriteSFixed64(int fieldNumber, string fieldName, long value); - - /// - /// Writes a signed 32-bit field value, including tag, to the stream. - /// - void WriteSInt32(int fieldNumber, string fieldName, int value); - - /// - /// Writes a signed 64-bit field value, including tag, to the stream. - /// - void WriteSInt64(int fieldNumber, string fieldName, long value); - - /// - /// Writes a repeated field value, including tag(s), to the stream. - /// - void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list); - - /// - /// Writes a repeated group value, including tag(s), to the stream. - /// - void WriteGroupArray(int fieldNumber, string fieldName, RepeatedField list) - where T : IMessage; - - /// - /// Writes a repeated message value, including tag(s), to the stream. - /// - void WriteMessageArray(int fieldNumber, string fieldName, RepeatedField list) - where T : IMessage; - - /// - /// Writes a repeated string value, including tag(s), to the stream. - /// - void WriteStringArray(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated ByteString value, including tag(s), to the stream. - /// - void WriteBytesArray(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated boolean value, including tag(s), to the stream. - /// - void WriteBoolArray(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated Int32 value, including tag(s), to the stream. - /// - void WriteInt32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated SInt32 value, including tag(s), to the stream. - /// - void WriteSInt32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated UInt32 value, including tag(s), to the stream. - /// - void WriteUInt32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated Fixed32 value, including tag(s), to the stream. - /// - void WriteFixed32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated SFixed32 value, including tag(s), to the stream. - /// - void WriteSFixed32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated Int64 value, including tag(s), to the stream. - /// - void WriteInt64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated SInt64 value, including tag(s), to the stream. - /// - void WriteSInt64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated UInt64 value, including tag(s), to the stream. - /// - void WriteUInt64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated Fixed64 value, including tag(s), to the stream. - /// - void WriteFixed64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated SFixed64 value, including tag(s), to the stream. - /// - void WriteSFixed64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated Double value, including tag(s), to the stream. - /// - void WriteDoubleArray(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated Float value, including tag(s), to the stream. - /// - void WriteFloatArray(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a repeated enumeration value of type T, including tag(s), to the stream. - /// - void WriteEnumArray(int fieldNumber, string fieldName, RepeatedField list) - where T : struct, IComparable, IFormattable; - - /// - /// Writes a packed repeated primitive, including tag and length, to the stream. - /// - void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list); - - /// - /// Writes a packed repeated boolean, including tag and length, to the stream. - /// - void WritePackedBoolArray(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated Int32, including tag and length, to the stream. - /// - void WritePackedInt32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated SInt32, including tag and length, to the stream. - /// - void WritePackedSInt32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated UInt32, including tag and length, to the stream. - /// - void WritePackedUInt32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated Fixed32, including tag and length, to the stream. - /// - void WritePackedFixed32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated SFixed32, including tag and length, to the stream. - /// - void WritePackedSFixed32Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated Int64, including tag and length, to the stream. - /// - void WritePackedInt64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated SInt64, including tag and length, to the stream. - /// - void WritePackedSInt64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated UInt64, including tag and length, to the stream. - /// - void WritePackedUInt64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated Fixed64, including tag and length, to the stream. - /// - void WritePackedFixed64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated SFixed64, including tag and length, to the stream. - /// - void WritePackedSFixed64Array(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated Double, including tag and length, to the stream. - /// - void WritePackedDoubleArray(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated Float, including tag and length, to the stream. - /// - void WritePackedFloatArray(int fieldNumber, string fieldName, RepeatedField list); - - /// - /// Writes a packed repeated enumeration of type T, including tag and length, to the stream. - /// - void WritePackedEnumArray(int fieldNumber, string fieldName, RepeatedField list) - where T : struct, IComparable, IFormattable; - } -} \ No newline at end of file diff --git a/csharp/src/ProtocolBuffers/IMessage.cs b/csharp/src/ProtocolBuffers/IMessage.cs index 4e06f6e8..55b6fc5d 100644 --- a/csharp/src/ProtocolBuffers/IMessage.cs +++ b/csharp/src/ProtocolBuffers/IMessage.cs @@ -51,8 +51,8 @@ namespace Google.Protobuf public interface IMessage { - void MergeFrom(ICodedInputStream input); - void WriteTo(ICodedOutputStream output); + void MergeFrom(CodedInputStream input); + void WriteTo(CodedOutputStream output); int CalculateSize(); } diff --git a/csharp/src/ProtocolBuffers/MessageParser.cs b/csharp/src/ProtocolBuffers/MessageParser.cs index 399a9043..722435cc 100644 --- a/csharp/src/ProtocolBuffers/MessageParser.cs +++ b/csharp/src/ProtocolBuffers/MessageParser.cs @@ -47,7 +47,7 @@ namespace Google.Protobuf return message; } - public T ParseFrom(ICodedInputStream input) + public T ParseFrom(CodedInputStream input) { T message = factory(); message.MergeFrom(input); diff --git a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj index efd387a2..3a07e87f 100644 --- a/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj +++ b/csharp/src/ProtocolBuffers/ProtocolBuffers.csproj @@ -93,8 +93,6 @@ - - diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc index 3494b228..19fd50cf 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc @@ -54,17 +54,14 @@ EnumFieldGenerator::~EnumFieldGenerator() { } void EnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { - // TODO(jonskeet): Get rid of the temporary variable when we sanitize CodedInputStream not to use ref. printer->Print(variables_, - "int tmp = 0;\n" - "input.ReadEnum(ref tmp);\n" - "$name$_ = ($type_name$) tmp;"); + "$name$_ = ($type_name$) input.ReadEnum();\n"); } void EnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print(variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, fieldNames[$field_ordinal$], (int) $property_name$);\n" + " output.WriteEnum($number$, (int) $property_name$);\n" "}\n"); } @@ -88,18 +85,15 @@ void EnumOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { // TODO(jonskeet): What about if we read the default value? printer->Print( variables_, - "int enumValue = 0;\n" - "if(input.ReadEnum(ref enumValue)) {\n" - " $oneof_name$_ = enumValue;\n" - " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - "}\n"); + "$oneof_name$_ = input.ReadEnum();\n" + "$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); } void EnumOneofFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteEnum($number$, fieldNames[$field_ordinal$], (int) $property_name$);\n" + " output.WriteEnum($number$, (int) $property_name$);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc index b5929bcd..aca68fb7 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message.cc @@ -350,9 +350,8 @@ void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) { void MessageGenerator::GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( - "public void WriteTo(pb::ICodedOutputStream output) {\n"); + "public void WriteTo(pb::CodedOutputStream output) {\n"); printer->Indent(); - printer->Print("string[] fieldNames = _fieldNames;\n"); // Serialize all the fields for (int i = 0; i < fields_by_number().size(); i++) { @@ -423,21 +422,13 @@ void MessageGenerator::GenerateMergingMethods(io::Printer* printer) { } printer->Outdent(); printer->Print("}\n\n"); - printer->Print("public void MergeFrom(pb::ICodedInputStream input) {\n"); + printer->Print("public void MergeFrom(pb::CodedInputStream input) {\n"); printer->Indent(); printer->Print( "uint tag;\n" - "string fieldName;\n" - "while (input.ReadTag(out tag, out fieldName)) {\n"); + "while (input.ReadTag(out tag)) {\n" + " switch(tag) {\n"); printer->Indent(); - printer->Print( - "if (tag == 0 && fieldName != null) {\n" - " int fieldOrdinal = global::System.Array.BinarySearch(_fieldNames, fieldName, global::System.StringComparer.Ordinal);\n" - " if (fieldOrdinal >= 0) {\n" - " tag = _fieldTags[fieldOrdinal];\n" - " }\n" - "}\n" - "switch(tag) {\n"); printer->Indent(); printer->Print( "case 0:\n" // 0 signals EOF / limit reached diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc index 4b7ac88f..804a5ae2 100644 --- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc @@ -87,6 +87,7 @@ void MessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { "if ($has_not_property_check$) {\n" " $name$_ = new $type_name$();\n" "}\n" + // TODO(jonskeet): Do we really need merging behaviour like this? "input.ReadMessage($name$_);\n"); // No need to support TYPE_GROUP... } @@ -95,7 +96,7 @@ void MessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.WriteMessage($number$, fieldNames[$field_ordinal$], $property_name$);\n" + " output.WriteMessage($number$, $property_name$);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index f2b66a00..cb7e1b5a 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -73,7 +73,6 @@ void PrimitiveFieldGenerator::GenerateMembers(io::Printer* printer) { printer->Print( variables_, " set { $name$_ = value; }\n"); - } else { printer->Print( variables_, @@ -93,14 +92,14 @@ void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.Read$capitalized_type_name$(ref $name$_);\n"); + "$name$_ = input.Read$capitalized_type_name$();\n"); } void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { printer->Print( variables_, "if ($has_property_check$) {\n" - " output.Write$capitalized_type_name$($number$, fieldNames[$field_ordinal$], $property_name$);\n" + " output.Write$capitalized_type_name$($number$, $property_name$);\n" "}\n"); } @@ -169,13 +168,10 @@ void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { // TODO(jonskeet): What if the value we read is the default value for the type? - printer->Print( - variables_, - "$type_name$ value = $default_value$;\n" - "if (input.Read$capitalized_type_name$(ref value)) {\n" - " $oneof_name$_ = value;\n" - " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" - "}\n"); + printer->Print( + variables_, + "$oneof_name$_ = input.Read$capitalized_type_name$()\n;" + "$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); } } // namespace csharp diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index 937d675a..15e92ab9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -76,7 +76,7 @@ void RepeatedEnumFieldGenerator::GenerateMergingCode(io::Printer* printer) { void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.ReadEnumArray<$type_name$>(tag, fieldName, $name$_);\n"); + "input.ReadEnumArray<$type_name$>(tag, $name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -84,7 +84,7 @@ void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) // The Write* call should make that cheap though - no need to generate it every time. printer->Print( variables_, - "output.Write$packed$EnumArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); + "output.Write$packed$EnumArray($number$, $name$_);\n"); } void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 963f841e..6228aa67 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -75,7 +75,7 @@ void RepeatedMessageFieldGenerator::GenerateMergingCode(io::Printer* printer) { void RepeatedMessageFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print( variables_, - "input.ReadMessageArray(tag, fieldName, $name$_, $type_name$.Parser);\n"); + "input.ReadMessageArray(tag, $name$_, $type_name$.Parser);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* printer) { @@ -83,7 +83,7 @@ void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* print // The Write* call should make that cheap though - no need to generate it every time. printer->Print( variables_, - "output.WriteMessageArray($number$, fieldNames[$field_ordinal$], $name$_);\n"); + "output.WriteMessageArray($number$, $name$_);\n"); } void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 0a91c3c6..f62ea09d 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -74,7 +74,7 @@ void RepeatedPrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { printer->Print(variables_, - "input.Read$capitalized_type_name$Array(tag, fieldName, $name$_);\n"); + "input.Read$capitalized_type_name$Array(tag, $name$_);\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( @@ -83,10 +83,10 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( // The Write* call should make that cheap though - no need to generate it every time. if (descriptor_->is_packed()) { printer->Print(variables_, - "output.WritePacked$capitalized_type_name$Array($number$, fieldNames[$field_ordinal$], $name$_);\n"); + "output.WritePacked$capitalized_type_name$Array($number$, $name$_);\n"); } else { printer->Print(variables_, - "output.Write$capitalized_type_name$Array($number$, fieldNames[$field_ordinal$], $name$_);\n"); + "output.Write$capitalized_type_name$Array($number$, $name$_);\n"); } } -- cgit v1.2.3 From 8fcde2cabd02ffe6ea061e259f67241f277368de Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 12 Jun 2015 11:17:07 +0100 Subject: Fix oneof behaviour in the face of default values. --- .../protobuf/compiler/csharp/csharp_primitive_field.cc | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index cb7e1b5a..69056790 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -137,8 +137,6 @@ PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() { } void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { - // TODO(jonskeet): What should foo.OneofIntField = 0; do? Clear the oneof? - // Currently foo.OneOfStringField = null will clear the oneof, but foo.OneOfStringField = "" won't. Ick. AddDeprecatedFlag(printer); printer->Print( variables_, @@ -148,15 +146,14 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { if (is_value_type) { printer->Print( variables_, - " $oneof_name$_ = value;\n" - " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); + " $oneof_name$_ = value;\n"); } else { printer->Print( variables_, - " $oneof_name$_ = value ?? $default_value$;\n" - " $oneof_name$Case_ = value == null ? $oneof_property_name$OneofCase.None : $oneof_property_name$OneofCase.$property_name$;\n"); + " $oneof_name$_ = value ?? $default_value$;\n"); } printer->Print( + " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); } @@ -167,11 +164,9 @@ void PrimitiveOneofFieldGenerator::WriteToString(io::Printer* printer) { } void PrimitiveOneofFieldGenerator::GenerateParsingCode(io::Printer* printer) { - // TODO(jonskeet): What if the value we read is the default value for the type? printer->Print( variables_, - "$oneof_name$_ = input.Read$capitalized_type_name$()\n;" - "$oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n"); + "$property_name$ = input.Read$capitalized_type_name$()\n;"); } } // namespace csharp -- cgit v1.2.3 From 43527448595b2e19a03747c494d1b33bced6086a Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 12 Jun 2015 11:18:37 +0100 Subject: Use Length to check string/bytes fields for emptiness - it's faster than an equality check. --- src/google/protobuf/compiler/csharp/csharp_primitive_field.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index 69056790..e48c6ba9 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -52,6 +52,10 @@ PrimitiveFieldGenerator::PrimitiveFieldGenerator( // TODO(jonskeet): Make this cleaner... is_value_type = descriptor->type() != FieldDescriptor::TYPE_STRING && descriptor->type() != FieldDescriptor::TYPE_BYTES; + if (!is_value_type) { + variables_["has_property_check"] = variables_["property_name"] + ".Length != 0"; + variables_["other_has_property_check"] = "other." + variables_["property_name"] + ".Length != 0"; + } } PrimitiveFieldGenerator::~PrimitiveFieldGenerator() { @@ -90,9 +94,11 @@ void PrimitiveFieldGenerator::GenerateMergingCode(io::Printer* printer) { } void PrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) { + // Note: invoke the property setter rather than writing straight to the field, + // so that we can normalize "null to empty" for strings and bytes. printer->Print( variables_, - "$name$_ = input.Read$capitalized_type_name$();\n"); + "$property_name$ = input.Read$capitalized_type_name$();\n"); } void PrimitiveFieldGenerator::GenerateSerializationCode(io::Printer* printer) { -- cgit v1.2.3 From 1b71db1180953e592e134ddd509f54d6024df593 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 12 Jun 2015 11:19:50 +0100 Subject: Optimization of CalculateSize: avoid foreach over empty lists. --- .../protobuf/compiler/csharp/csharp_repeated_enum_field.cc | 6 +----- .../protobuf/compiler/csharp/csharp_repeated_message_field.cc | 6 ++++-- .../compiler/csharp/csharp_repeated_primitive_field.cc | 10 +++++----- 3 files changed, 10 insertions(+), 12 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index 15e92ab9..3fe5ab21 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -89,13 +89,11 @@ void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { // TODO(jonskeet): Move all this code into CodedOutputStream? It's a lot to repeat everywhere... - printer->Print("{\n"); - printer->Indent(); printer->Print( variables_, - "int dataSize = 0;\n" "if ($name$_.Count > 0) {\n"); printer->Indent(); + printer->Print("int dataSize = 0;\n"); printer->Print( variables_, "foreach ($type_name$ element in $name$_) {\n" @@ -115,8 +113,6 @@ void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer } printer->Outdent(); printer->Print("}\n"); - printer->Outdent(); - printer->Print("}\n"); } void RepeatedEnumFieldGenerator::WriteHash(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index 6228aa67..d7e4d80f 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -90,8 +90,10 @@ void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* prin // TODO(jonskeet): Put this into CodedOutputStream. printer->Print( variables_, - "foreach ($type_name$ element in $name$_) {\n" - " size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n" + "if ($name$_.Count > 0) {\n" + " foreach ($type_name$ element in $name$_) {\n" + " size += pb::CodedOutputStream.ComputeMessageSize($number$, element);\n" + " }\n" "}\n"); } diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index f62ea09d..2dd879fe 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -93,7 +93,9 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( io::Printer* printer) { // TODO(jonskeet): Do this in the runtime if possible. It's a pain, but it must be feasible... - printer->Print("{\n"); + printer->Print( + "if ($name$_.Count > 0) {\n", + "name", name()); printer->Indent(); printer->Print("int dataSize = 0;\n"); int fixedSize = GetFixedSize(descriptor_->type()); @@ -112,10 +114,8 @@ void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( int tagSize = internal::WireFormat::TagSize(descriptor_->number(), descriptor_->type()); if (descriptor_->is_packed()) { printer->Print( - "if ($name$_.Count != 0) {\n" - " size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n" - "}\n", - "name", name(), "tag_size", SimpleItoa(tagSize)); + "size += $tag_size$ + pb::CodedOutputStream.ComputeInt32SizeNoTag(dataSize);\n", + "tag_size", SimpleItoa(tagSize)); } else { printer->Print( "size += $tag_size$ * $name$_.Count;\n", -- cgit v1.2.3 From 5a33827eec75b980fb152c531e4c6b75ce5af015 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 12 Jun 2015 11:52:14 +0100 Subject: Move Count checks into the serialization code I wouldn't expect this to affect anything, but it appears to. --- .../compiler/csharp/csharp_repeated_enum_field.cc | 6 +++--- .../compiler/csharp/csharp_repeated_message_field.cc | 4 +++- .../compiler/csharp/csharp_repeated_primitive_field.cc | 15 ++++++--------- 3 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc index 3fe5ab21..22dec710 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc @@ -80,11 +80,11 @@ void RepeatedEnumFieldGenerator::GenerateParsingCode(io::Printer* printer) { } void RepeatedEnumFieldGenerator::GenerateSerializationCode(io::Printer* printer) { - // TODO(jonskeet): Originally, this checked for Count > 0 first. - // The Write* call should make that cheap though - no need to generate it every time. printer->Print( variables_, - "output.Write$packed$EnumArray($number$, $name$_);\n"); + "if ($name$_.Count > 0) {\n" + " output.Write$packed$EnumArray($number$, $name$_);\n" + "}\n"); } void RepeatedEnumFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc index d7e4d80f..4b570d3b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc @@ -83,7 +83,9 @@ void RepeatedMessageFieldGenerator::GenerateSerializationCode(io::Printer* print // The Write* call should make that cheap though - no need to generate it every time. printer->Print( variables_, - "output.WriteMessageArray($number$, $name$_);\n"); + "if ($name$_.Count > 0) {\n" + " output.WriteMessageArray($number$, $name$_);\n" + "}\n"); } void RepeatedMessageFieldGenerator::GenerateSerializedSizeCode(io::Printer* printer) { diff --git a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc index 2dd879fe..a5457785 100644 --- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc @@ -49,6 +49,7 @@ namespace csharp { RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator( const FieldDescriptor* descriptor, int fieldOrdinal) : FieldGeneratorBase(descriptor, fieldOrdinal) { + variables_["packed"] = descriptor->is_packed() ? "Packed" : ""; } RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() { @@ -79,15 +80,11 @@ void RepeatedPrimitiveFieldGenerator::GenerateParsingCode(io::Printer* printer) void RepeatedPrimitiveFieldGenerator::GenerateSerializationCode( io::Printer* printer) { - // TODO(jonskeet): Originally, this checked for Count > 0 first. - // The Write* call should make that cheap though - no need to generate it every time. - if (descriptor_->is_packed()) { - printer->Print(variables_, - "output.WritePacked$capitalized_type_name$Array($number$, $name$_);\n"); - } else { - printer->Print(variables_, - "output.Write$capitalized_type_name$Array($number$, $name$_);\n"); - } + printer->Print( + variables_, + "if ($name$_.Count > 0) {\n" + " output.Write$packed$$capitalized_type_name$Array($number$, $name$_);\n" + "}\n"); } void RepeatedPrimitiveFieldGenerator::GenerateSerializedSizeCode( -- cgit v1.2.3 From a8dae140c60d9b29c72a7f342ec7081b2116fea9 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Fri, 12 Jun 2015 13:11:16 +0100 Subject: Fix oneof generator - forgot to provide variables... --- src/google/protobuf/compiler/csharp/csharp_primitive_field.cc | 1 + 1 file changed, 1 insertion(+) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc index e48c6ba9..0164cdca 100644 --- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc +++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc @@ -159,6 +159,7 @@ void PrimitiveOneofFieldGenerator::GenerateMembers(io::Printer* printer) { " $oneof_name$_ = value ?? $default_value$;\n"); } printer->Print( + variables_, " $oneof_name$Case_ = $oneof_property_name$OneofCase.$property_name$;\n" " }\n" "}\n"); -- cgit v1.2.3 From 2fe6d7bc5773b6888d0db80eca75e392b3549814 Mon Sep 17 00:00:00 2001 From: Qartar Date: Sun, 7 Jun 2015 14:22:51 -0700 Subject: Workaround for MSVC's string literal compiler limit. Escape characters don't count for string literal size, no need to pre-generate escape string. Added unit test to touch enormous cpp generated descriptor. Updated makefile to include enormous_descriptor.proto Fixed language compatibility error. --- cmake/tests.cmake | 1 + src/Makefile.am | 6 ++- src/google/protobuf/compiler/cpp/cpp_file.cc | 58 ++++++++++++++++++------ src/google/protobuf/compiler/cpp/cpp_unittest.cc | 12 +++++ 4 files changed, 62 insertions(+), 15 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 24891521..8fb5eef1 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -25,6 +25,7 @@ set(tests_protos google/protobuf/unittest_drop_unknown_fields.proto google/protobuf/unittest_embed_optimize_for.proto google/protobuf/unittest_empty.proto + google/protobuf/unittest_enormous_descriptor.proto google/protobuf/unittest_import.proto google/protobuf/unittest_import_public.proto google/protobuf/unittest_lite_imports_nonlite.proto diff --git a/src/Makefile.am b/src/Makefile.am index 33894dc1..b8946bac 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -412,6 +412,7 @@ protoc_inputs = \ google/protobuf/unittest_drop_unknown_fields.proto \ google/protobuf/unittest_embed_optimize_for.proto \ google/protobuf/unittest_empty.proto \ + google/protobuf/unittest_enormous_descriptor.proto \ google/protobuf/unittest_import_lite.proto \ google/protobuf/unittest_import.proto \ google/protobuf/unittest_import_public_lite.proto \ @@ -453,8 +454,7 @@ EXTRA_DIST = \ google/protobuf/compiler/ruby/ruby_generated_code.proto \ google/protobuf/compiler/ruby/ruby_generated_code.rb \ google/protobuf/compiler/package_info.h \ - google/protobuf/compiler/zip_output_unittest.sh \ - google/protobuf/unittest_enormous_descriptor.proto + google/protobuf/compiler/zip_output_unittest.sh protoc_lite_outputs = \ google/protobuf/map_lite_unittest.pb.cc \ @@ -486,6 +486,8 @@ protoc_outputs = \ google/protobuf/unittest_embed_optimize_for.pb.h \ google/protobuf/unittest_empty.pb.cc \ google/protobuf/unittest_empty.pb.h \ + google/protobuf/unittest_enormous_descriptor.pb.cc \ + google/protobuf/unittest_enormous_descriptor.pb.h \ google/protobuf/unittest_import.pb.cc \ google/protobuf/unittest_import.pb.h \ google/protobuf/unittest_import_public.pb.cc \ diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index b997a51a..1f0a8205 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -434,20 +434,52 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { string file_data; file_proto.SerializeToString(&file_data); - printer->Print( - "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); - - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - printer->Print("\n \"$data$\"", - "data", - EscapeTrigraphs( - CEscape(file_data.substr(i, kBytesPerLine)))); + // Workaround for MSVC: "Error C1091: compiler limit: string exceeds 65535 + // bytes in length". Declare a static array of characters rather than use a + // string literal. + if (file_data.size() > 65535) { + printer->Print( + "static const char descriptor[] = {\n"); + printer->Indent(); + + // Only write 25 bytes per line. + static const int kBytesPerLine = 25; + for (int i = 0; i < file_data.size();) { + for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) { + printer->Print( + "$char$, ", + "char", SimpleItoa(file_data[i])); + } + printer->Print( + "\n"); + } + + printer->Outdent(); + printer->Print( + "};\n"); + + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile(descriptor, $size$);\n", + "size", SimpleItoa(file_data.size())); + + } else { + + printer->Print( + "::google::protobuf::DescriptorPool::InternalAddGeneratedFile("); + + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + printer->Print("\n \"$data$\"", + "data", + EscapeTrigraphs( + CEscape(file_data.substr(i, kBytesPerLine)))); + } + printer->Print( + ", $size$);\n", + "size", SimpleItoa(file_data.size())); + } - printer->Print( - ", $size$);\n", - "size", SimpleItoa(file_data.size())); // Call MessageFactory::InternalRegisterGeneratedFile(). printer->Print( diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index b11fb21a..bd1c0fde 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -130,6 +131,17 @@ TEST(GeneratedDescriptorTest, IdenticalDescriptors) { generated_decsriptor_proto.DebugString()); } +// Test that generated code has proper descriptors: +// Touch a descriptor generated from an enormous message to validate special +// handling for descriptors exceeding the C++ standard's recommended minimum +// limit for string literal size +TEST(GeneratedDescriptorTest, EnormousDescriptor) { + const Descriptor* generated_descriptor = + TestEnormousDescriptor::descriptor(); + + EXPECT_TRUE(generated_descriptor != NULL); +} + #endif // !PROTOBUF_TEST_NO_DESCRIPTORS // =================================================================== -- cgit v1.2.3 From a269a6d397b5bee9df0a73f186400ba2228a68d4 Mon Sep 17 00:00:00 2001 From: Bo Yang Date: Mon, 15 Jun 2015 16:54:02 -0700 Subject: Implement parsing for proto3 primitive repeated fields. Previously, for proto3 primitive repeated fields, packed data cannot be parsed if definition is unpacked. Neither is the other way. --- src/google/protobuf/compiler/cpp/cpp_message.cc | 10 +- src/google/protobuf/wire_format.h | 2 +- src/google/protobuf/wire_format_unittest.cc | 144 +++++++++++++++--------- 3 files changed, 94 insertions(+), 62 deletions(-) (limited to 'src/google/protobuf/compiler') diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index af85919a..9802a165 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -2932,7 +2932,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { "commontag", SimpleItoa(WireFormat::MakeTag(field))); if (need_label || - (field->is_repeated() && !field->options().packed() && !loops)) { + (field->is_repeated() && !field->is_packed() && !loops)) { printer->Print( " parse_$name$:\n", "name", field->name()); @@ -2945,7 +2945,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } printer->Indent(); - if (field->options().packed()) { + if (field->is_packed()) { field_generator.GenerateMergeFromCodedStreamWithPacking(printer); } else { field_generator.GenerateMergeFromCodedStream(printer); @@ -2953,7 +2953,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Outdent(); // Emit code to parse unexpectedly packed or unpacked values. - if (field->is_packable() && field->options().packed()) { + if (field->is_packed()) { internal::WireFormatLite::WireType wiretype = WireFormat::WireTypeForFieldType(field->type()); printer->Print("} else if (tag == $uncommontag$) {\n", @@ -2963,7 +2963,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Indent(); field_generator.GenerateMergeFromCodedStream(printer); printer->Outdent(); - } else if (field->is_packable() && !field->options().packed()) { + } else if (field->is_packable() && !field->is_packed()) { internal::WireFormatLite::WireType wiretype = internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; printer->Print("} else if (tag == $uncommontag$) {\n", @@ -2988,7 +2988,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { "if (input->ExpectTag($tag$)) goto parse_loop_$name$;\n", "tag", SimpleItoa(WireFormat::MakeTag(field)), "name", field->name()); - } else if (field->is_repeated() && !field->options().packed()) { + } else if (field->is_repeated() && !field->is_packed()) { printer->Print( "if (input->ExpectTag($tag$)) goto parse_$name$;\n", "tag", SimpleItoa(WireFormat::MakeTag(field)), diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index 8de491a6..84270fee 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h @@ -290,7 +290,7 @@ class LIBPROTOBUF_EXPORT UnknownFieldSetFieldSkipper : public FieldSkipper { inline WireFormatLite::WireType WireFormat::WireTypeForField( const FieldDescriptor* field) { - if (field->options().packed()) { + if (field->is_packed()) { return WireFormatLite::WIRETYPE_LENGTH_DELIMITED; } else { return WireTypeForFieldType(field->type()); diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc index 4b151f97..aef22b29 100644 --- a/src/google/protobuf/wire_format_unittest.cc +++ b/src/google/protobuf/wire_format_unittest.cc @@ -795,9 +795,73 @@ TEST(WireFormatTest, CompatibleTypes) { ASSERT_EQ(static_cast(data), msg5.data()); } -class Proto3PrimitiveRepeatedWireFormatTest - : public ::testing::TestWithParam { +class Proto3PrimitiveRepeatedWireFormatTest : public ::testing::Test { protected: + Proto3PrimitiveRepeatedWireFormatTest() + : packedTestAllTypes_( + "\xFA\x01\x01\x01" + "\x82\x02\x01\x01" + "\x8A\x02\x01\x01" + "\x92\x02\x01\x01" + "\x9A\x02\x01\x02" + "\xA2\x02\x01\x02" + "\xAA\x02\x04\x01\x00\x00\x00" + "\xB2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00" + "\xBA\x02\x04\x01\x00\x00\x00" + "\xC2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00" + "\xCA\x02\x04\x00\x00\x80\x3f" + "\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xf0\x3f" + "\xDA\x02\x01\x01" + "\x9A\x03\x01\x01", + 86), + packedTestUnpackedTypes_( + "\x0A\x01\x01" + "\x12\x01\x01" + "\x1A\x01\x01" + "\x22\x01\x01" + "\x2A\x01\x02" + "\x32\x01\x02" + "\x3A\x04\x01\x00\x00\x00" + "\x42\x08\x01\x00\x00\x00\x00\x00\x00\x00" + "\x4A\x04\x01\x00\x00\x00" + "\x52\x08\x01\x00\x00\x00\x00\x00\x00\x00" + "\x5A\x04\x00\x00\x80\x3f" + "\x62\x08\x00\x00\x00\x00\x00\x00\xf0\x3f" + "\x6A\x01\x01" + "\x72\x01\x01", + 72), + unpackedTestAllTypes_( + "\xF8\x01\x01" + "\x80\x02\x01" + "\x88\x02\x01" + "\x90\x02\x01" + "\x98\x02\x02" + "\xA0\x02\x02" + "\xAD\x02\x01\x00\x00\x00" + "\xB1\x02\x01\x00\x00\x00\x00\x00\x00\x00" + "\xBD\x02\x01\x00\x00\x00" + "\xC1\x02\x01\x00\x00\x00\x00\x00\x00\x00" + "\xCD\x02\x00\x00\x80\x3f" + "\xD1\x02\x00\x00\x00\x00\x00\x00\xf0\x3f" + "\xD8\x02\x01" + "\x98\x03\x01", + 72), + unpackedTestUnpackedTypes_( + "\x08\x01" + "\x10\x01" + "\x18\x01" + "\x20\x01" + "\x28\x02" + "\x30\x02" + "\x3D\x01\x00\x00\x00" + "\x41\x01\x00\x00\x00\x00\x00\x00\x00" + "\x4D\x01\x00\x00\x00" + "\x51\x01\x00\x00\x00\x00\x00\x00\x00" + "\x5D\x00\x00\x80\x3f" + "\x61\x00\x00\x00\x00\x00\x00\xf0\x3f" + "\x68\x01" + "\x70\x01", + 58) {} template void SetProto3PrimitiveRepeatedFields(Proto* message) { message->add_repeated_int32(1); @@ -837,8 +901,7 @@ class Proto3PrimitiveRepeatedWireFormatTest } template - void TestProto3PrimitiveRepeatedFields(Proto* message, - const string& expected) { + void TestSerialization(Proto* message, const string& expected) { SetProto3PrimitiveRepeatedFields(message); int size = message->ByteSize(); @@ -851,13 +914,8 @@ class Proto3PrimitiveRepeatedWireFormatTest message->SerializeWithCachedSizes(&output); ASSERT_FALSE(output.HadError()); } - EXPECT_TRUE(expected == generated_data); - message->Clear(); - message->ParseFromString(generated_data); - ExpectProto3PrimitiveRepeatedFieldsSet(*message); - // Serialize using the dynamic code. string dynamic_data; { @@ -866,64 +924,38 @@ class Proto3PrimitiveRepeatedWireFormatTest WireFormat::SerializeWithCachedSizes(*message, size, &output); ASSERT_FALSE(output.HadError()); } - EXPECT_TRUE(expected == dynamic_data); + } + + template + void TestParsing(Proto* message, const string& compatible_data) { + message->Clear(); + message->ParseFromString(compatible_data); + ExpectProto3PrimitiveRepeatedFieldsSet(*message); message->Clear(); io::CodedInputStream input( - reinterpret_cast(dynamic_data.data()), - dynamic_data.size()); + reinterpret_cast(compatible_data.data()), + compatible_data.size()); WireFormat::ParseAndMergePartial(&input, message); ExpectProto3PrimitiveRepeatedFieldsSet(*message); } + + const string packedTestAllTypes_; + const string packedTestUnpackedTypes_; + const string unpackedTestAllTypes_; + const string unpackedTestUnpackedTypes_; }; -INSTANTIATE_TEST_CASE_P(SetPacked, - Proto3PrimitiveRepeatedWireFormatTest, - ::testing::Values(false, true)); -TEST_P(Proto3PrimitiveRepeatedWireFormatTest, Proto3PrimitiveRepeated) { +TEST_F(Proto3PrimitiveRepeatedWireFormatTest, Proto3PrimitiveRepeated) { proto3_arena_unittest::TestAllTypes packed_message; proto3_arena_unittest::TestUnpackedTypes unpacked_message; - - const string packedExpected( - "\xFA\x01\x01\x01" - "\x82\x02\x01\x01" - "\x8A\x02\x01\x01" - "\x92\x02\x01\x01" - "\x9A\x02\x01\x02" - "\xA2\x02\x01\x02" - "\xAA\x02\x04\x01\x00\x00\x00" - "\xB2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00" - "\xBA\x02\x04\x01\x00\x00\x00" - "\xC2\x02\x08\x01\x00\x00\x00\x00\x00\x00\x00" - "\xCA\x02\x04\x00\x00\x80\x3f" - "\xD2\x02\x08\x00\x00\x00\x00\x00\x00\xf0\x3f" - "\xDA\x02\x01\x01" - "\x9A\x03\x01\x01", - 86); - - const string unpackedExpected( - "\x08\x01" - "\x10\x01" - "\x18\x01" - "\x20\x01" - "\x28\x02" - "\x30\x02" - "\x3D\x01\x00\x00\x00" - "\x41\x01\x00\x00\x00\x00\x00\x00\x00" - "\x4D\x01\x00\x00\x00" - "\x51\x01\x00\x00\x00\x00\x00\x00\x00" - "\x5D\x00\x00\x80\x3f" - "\x61\x00\x00\x00\x00\x00\x00\xf0\x3f" - "\x68\x01" - "\x70\x01", - 58); - - if (GetParam()) { - TestProto3PrimitiveRepeatedFields(&packed_message, packedExpected); - } else { - TestProto3PrimitiveRepeatedFields(&unpacked_message, unpackedExpected); - } + TestSerialization(&packed_message, packedTestAllTypes_); + TestParsing(&packed_message, packedTestAllTypes_); + TestParsing(&packed_message, unpackedTestAllTypes_); + TestSerialization(&unpacked_message, unpackedTestUnpackedTypes_); + TestParsing(&unpacked_message, packedTestUnpackedTypes_); + TestParsing(&unpacked_message, unpackedTestUnpackedTypes_); } class WireFormatInvalidInputTest : public testing::Test { -- cgit v1.2.3 From e96ff30120a3834f7d1e31e43e591bf7cfbd731f Mon Sep 17 00:00:00 2001 From: Feng Xiao Date: Mon, 15 Jun 2015 18:21:48 -0700 Subject: Down-integrate from internal code base. [ci skip] Change-Id: I9391c09640e0b0b2b21c45a97a1fc91814d95c5d --- Makefile.am | 27 +- README.md | 4 +- autogen.sh | 23 +- cmake/README.md | 10 +- cmake/extract_includes.bat.in | 6 + cmake/libprotobuf-lite.cmake | 5 + cmake/libprotobuf.cmake | 17 + cmake/tests.cmake | 44 +- configure.ac | 6 +- src/Makefile.am | 289 +- src/google/protobuf/compiler/cpp/cpp_message.cc | 6 +- src/google/protobuf/stubs/bytestream.cc | 196 ++ src/google/protobuf/stubs/bytestream.h | 348 +++ src/google/protobuf/stubs/bytestream_unittest.cc | 146 + src/google/protobuf/stubs/casts.h | 10 + src/google/protobuf/stubs/common.cc | 13 + src/google/protobuf/stubs/common.h | 303 +- src/google/protobuf/stubs/mathlimits.cc | 144 + src/google/protobuf/stubs/mathlimits.h | 277 ++ src/google/protobuf/stubs/mathutil.h | 149 + src/google/protobuf/stubs/status.cc | 133 + src/google/protobuf/stubs/status.h | 116 + src/google/protobuf/stubs/status_macros.h | 89 + src/google/protobuf/stubs/status_test.cc | 131 + src/google/protobuf/stubs/statusor.cc | 46 + src/google/protobuf/stubs/statusor.h | 259 ++ src/google/protobuf/stubs/statusor_test.cc | 274 ++ src/google/protobuf/stubs/stringpiece.cc | 268 ++ src/google/protobuf/stubs/stringpiece.h | 437 +++ src/google/protobuf/stubs/stringpiece_unittest.cc | 793 +++++ src/google/protobuf/stubs/strutil.cc | 768 ++++- src/google/protobuf/stubs/strutil.h | 214 +- src/google/protobuf/stubs/strutil_unittest.cc | 736 ++++- src/google/protobuf/stubs/time.cc | 364 +++ src/google/protobuf/stubs/time.h | 75 + src/google/protobuf/stubs/time_test.cc | 208 ++ src/google/protobuf/text_format.cc | 4 +- src/google/protobuf/util/field_comparator.cc | 187 ++ src/google/protobuf/util/field_comparator.h | 259 ++ src/google/protobuf/util/field_comparator_test.cc | 483 +++ src/google/protobuf/util/internal/constants.h | 93 + src/google/protobuf/util/internal/datapiece.cc | 285 ++ src/google/protobuf/util/internal/datapiece.h | 212 ++ .../util/internal/default_value_objectwriter.cc | 515 ++++ .../util/internal/default_value_objectwriter.h | 238 ++ .../internal/default_value_objectwriter_test.cc | 139 + .../protobuf/util/internal/error_listener.cc | 42 + src/google/protobuf/util/internal/error_listener.h | 99 + .../util/internal/expecting_objectwriter.h | 238 ++ .../protobuf/util/internal/field_mask_utility.cc | 228 ++ .../protobuf/util/internal/field_mask_utility.h | 72 + src/google/protobuf/util/internal/json_escaping.cc | 403 +++ src/google/protobuf/util/internal/json_escaping.h | 91 + .../protobuf/util/internal/json_objectwriter.cc | 175 ++ .../protobuf/util/internal/json_objectwriter.h | 206 ++ .../util/internal/json_objectwriter_test.cc | 284 ++ .../protobuf/util/internal/json_stream_parser.cc | 740 +++++ .../protobuf/util/internal/json_stream_parser.h | 256 ++ .../util/internal/json_stream_parser_test.cc | 697 +++++ .../protobuf/util/internal/location_tracker.h | 65 + .../protobuf/util/internal/mock_error_listener.h | 63 + .../util/internal/object_location_tracker.h | 64 + src/google/protobuf/util/internal/object_source.h | 79 + src/google/protobuf/util/internal/object_writer.cc | 92 + src/google/protobuf/util/internal/object_writer.h | 126 + .../util/internal/protostream_objectsource.cc | 1051 +++++++ .../util/internal/protostream_objectsource.h | 245 ++ .../util/internal/protostream_objectsource_test.cc | 824 +++++ .../util/internal/protostream_objectwriter.cc | 1557 ++++++++++ .../util/internal/protostream_objectwriter.h | 455 +++ .../util/internal/protostream_objectwriter_test.cc | 1513 ++++++++++ .../util/internal/snake2camel_objectwriter.h | 187 ++ .../util/internal/snake2camel_objectwriter_test.cc | 311 ++ .../util/internal/structured_objectwriter.h | 118 + .../protobuf/util/internal/testdata/anys.proto | 53 + .../protobuf/util/internal/testdata/books.proto | 171 ++ .../util/internal/testdata/default_value.proto | 162 + .../internal/testdata/default_value_test.proto | 46 + .../util/internal/testdata/field_mask.proto | 71 + .../protobuf/util/internal/testdata/maps.proto | 57 + .../protobuf/util/internal/testdata/struct.proto | 45 + .../internal/testdata/timestamp_duration.proto | 47 + .../protobuf/util/internal/testdata/wrappers.proto | 100 + src/google/protobuf/util/internal/type_info.cc | 171 ++ src/google/protobuf/util/internal/type_info.h | 87 + .../util/internal/type_info_test_helper.cc | 130 + .../protobuf/util/internal/type_info_test_helper.h | 98 + src/google/protobuf/util/internal/utility.cc | 332 +++ src/google/protobuf/util/internal/utility.h | 187 ++ src/google/protobuf/util/json_format_proto3.proto | 157 + src/google/protobuf/util/json_util.cc | 142 + src/google/protobuf/util/json_util.h | 132 + src/google/protobuf/util/json_util_test.cc | 277 ++ src/google/protobuf/util/message_differencer.cc | 1629 ++++++++++ src/google/protobuf/util/message_differencer.h | 817 +++++ .../protobuf/util/message_differencer_unittest.cc | 3132 ++++++++++++++++++++ .../util/message_differencer_unittest.proto | 74 + src/google/protobuf/util/type_resolver.h | 75 + src/google/protobuf/util/type_resolver_util.cc | 212 ++ src/google/protobuf/util/type_resolver_util.h | 52 + .../protobuf/util/type_resolver_util_test.cc | 338 +++ 101 files changed, 28226 insertions(+), 198 deletions(-) create mode 100644 src/google/protobuf/stubs/bytestream.cc create mode 100644 src/google/protobuf/stubs/bytestream.h create mode 100644 src/google/protobuf/stubs/bytestream_unittest.cc create mode 100644 src/google/protobuf/stubs/mathlimits.cc create mode 100644 src/google/protobuf/stubs/mathlimits.h create mode 100644 src/google/protobuf/stubs/mathutil.h create mode 100644 src/google/protobuf/stubs/status.cc create mode 100644 src/google/protobuf/stubs/status.h create mode 100644 src/google/protobuf/stubs/status_macros.h create mode 100644 src/google/protobuf/stubs/status_test.cc create mode 100644 src/google/protobuf/stubs/statusor.cc create mode 100644 src/google/protobuf/stubs/statusor.h create mode 100644 src/google/protobuf/stubs/statusor_test.cc create mode 100644 src/google/protobuf/stubs/stringpiece.cc create mode 100644 src/google/protobuf/stubs/stringpiece.h create mode 100644 src/google/protobuf/stubs/stringpiece_unittest.cc create mode 100644 src/google/protobuf/stubs/time.cc create mode 100644 src/google/protobuf/stubs/time.h create mode 100644 src/google/protobuf/stubs/time_test.cc create mode 100644 src/google/protobuf/util/field_comparator.cc create mode 100644 src/google/protobuf/util/field_comparator.h create mode 100644 src/google/protobuf/util/field_comparator_test.cc create mode 100644 src/google/protobuf/util/internal/constants.h create mode 100644 src/google/protobuf/util/internal/datapiece.cc create mode 100644 src/google/protobuf/util/internal/datapiece.h create mode 100644 src/google/protobuf/util/internal/default_value_objectwriter.cc create mode 100644 src/google/protobuf/util/internal/default_value_objectwriter.h create mode 100644 src/google/protobuf/util/internal/default_value_objectwriter_test.cc create mode 100644 src/google/protobuf/util/internal/error_listener.cc create mode 100644 src/google/protobuf/util/internal/error_listener.h create mode 100644 src/google/protobuf/util/internal/expecting_objectwriter.h create mode 100644 src/google/protobuf/util/internal/field_mask_utility.cc create mode 100644 src/google/protobuf/util/internal/field_mask_utility.h create mode 100644 src/google/protobuf/util/internal/json_escaping.cc create mode 100644 src/google/protobuf/util/internal/json_escaping.h create mode 100644 src/google/protobuf/util/internal/json_objectwriter.cc create mode 100644 src/google/protobuf/util/internal/json_objectwriter.h create mode 100644 src/google/protobuf/util/internal/json_objectwriter_test.cc create mode 100644 src/google/protobuf/util/internal/json_stream_parser.cc create mode 100644 src/google/protobuf/util/internal/json_stream_parser.h create mode 100644 src/google/protobuf/util/internal/json_stream_parser_test.cc create mode 100644 src/google/protobuf/util/internal/location_tracker.h create mode 100644 src/google/protobuf/util/internal/mock_error_listener.h create mode 100644 src/google/protobuf/util/internal/object_location_tracker.h create mode 100644 src/google/protobuf/util/internal/object_source.h create mode 100644 src/google/protobuf/util/internal/object_writer.cc create mode 100644 src/google/protobuf/util/internal/object_writer.h create mode 100644 src/google/protobuf/util/internal/protostream_objectsource.cc create mode 100644 src/google/protobuf/util/internal/protostream_objectsource.h create mode 100644 src/google/protobuf/util/internal/protostream_objectsource_test.cc create mode 100644 src/google/protobuf/util/internal/protostream_objectwriter.cc create mode 100644 src/google/protobuf/util/internal/protostream_objectwriter.h create mode 100644 src/google/protobuf/util/internal/protostream_objectwriter_test.cc create mode 100644 src/google/protobuf/util/internal/snake2camel_objectwriter.h create mode 100644 src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc create mode 100644 src/google/protobuf/util/internal/structured_objectwriter.h create mode 100644 src/google/protobuf/util/internal/testdata/anys.proto create mode 100644 src/google/protobuf/util/internal/testdata/books.proto create mode 100644 src/google/protobuf/util/internal/testdata/default_value.proto create mode 100644 src/google/protobuf/util/internal/testdata/default_value_test.proto create mode 100644 src/google/protobuf/util/internal/testdata/field_mask.proto create mode 100644 src/google/protobuf/util/internal/testdata/maps.proto create mode 100644 src/google/protobuf/util/internal/testdata/struct.proto create mode 100644 src/google/protobuf/util/internal/testdata/timestamp_duration.proto create mode 100644 src/google/protobuf/util/internal/testdata/wrappers.proto create mode 100644 src/google/protobuf/util/internal/type_info.cc create mode 100644 src/google/protobuf/util/internal/type_info.h create mode 100644 src/google/protobuf/util/internal/type_info_test_helper.cc create mode 100644 src/google/protobuf/util/internal/type_info_test_helper.h create mode 100644 src/google/protobuf/util/internal/utility.cc create mode 100644 src/google/protobuf/util/internal/utility.h create mode 100644 src/google/protobuf/util/json_format_proto3.proto create mode 100644 src/google/protobuf/util/json_util.cc create mode 100644 src/google/protobuf/util/json_util.h create mode 100644 src/google/protobuf/util/json_util_test.cc create mode 100644 src/google/protobuf/util/message_differencer.cc create mode 100644 src/google/protobuf/util/message_differencer.h create mode 100755 src/google/protobuf/util/message_differencer_unittest.cc create mode 100644 src/google/protobuf/util/message_differencer_unittest.proto create mode 100644 src/google/protobuf/util/type_resolver.h create mode 100644 src/google/protobuf/util/type_resolver_util.cc create mode 100644 src/google/protobuf/util/type_resolver_util.h create mode 100644 src/google/protobuf/util/type_resolver_util_test.cc (limited to 'src/google/protobuf/compiler') diff --git a/Makefile.am b/Makefile.am index 0eb80202..b506ef33 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,28 +8,29 @@ AUTOMAKE_OPTIONS = foreign # the right time. SUBDIRS = . src -# Always include gtest in distributions. +# Always include gmock in distributions. DIST_SUBDIRS = $(subdirs) src conformance -# Build gtest before we build protobuf tests. We don't add gtest to SUBDIRS -# because then "make check" would also build and run all of gtest's own tests, +# Build gmock before we build protobuf tests. We don't add gmock to SUBDIRS +# because then "make check" would also build and run all of gmock's own tests, # which takes a lot of time and is generally not useful to us. Also, we don't -# want "make install" to recurse into gtest since we don't want to overwrite -# the installed version of gtest if there is one. +# want "make install" to recurse into gmock since we don't want to overwrite +# the installed version of gmock if there is one. check-local: - @echo "Making lib/libgtest.a lib/libgtest_main.a in gtest" - @cd gtest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la + @echo "Making lib/libgmock.a lib/libgmock_main.a in gmock" + @cd gmock && $(MAKE) $(AM_MAKEFLAGS) lib/libgmock.la lib/libgmock_main.la + @cd gmock/gtest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la -# We would like to clean gtest when "make clean" is invoked. But we have to +# We would like to clean gmock when "make clean" is invoked. But we have to # be careful because clean-local is also invoked during "make distclean", but -# "make distclean" already recurses into gtest because it's listed among the -# DIST_SUBDIRS. distclean will delete gtest/Makefile, so if we then try to +# "make distclean" already recurses into gmock because it's listed among the +# DIST_SUBDIRS. distclean will delete gmock/Makefile, so if we then try to # cd to the directory again and "make clean" it will fail. So, check that the # Makefile exists before recursing. clean-local: - @if test -e gtest/Makefile; then \ - echo "Making clean in gtest"; \ - cd gtest && $(MAKE) $(AM_MAKEFLAGS) clean; \ + @if test -e gmock/Makefile; then \ + echo "Making clean in gmock"; \ + cd gmock && $(MAKE) $(AM_MAKEFLAGS) clean; \ fi; \ if test -e conformance/Makefile; then \ echo "Making clean in conformance"; \ diff --git a/README.md b/README.md index 51377ad7..a974d301 100644 --- a/README.md +++ b/README.md @@ -15,12 +15,12 @@ first: $ ./autogen.sh -This will download gtest source (which is used for C++ Protocol Buffer +This will download gmock source (which is used for C++ Protocol Buffer unit-tests) to the current directory and run automake, autoconf, etc. to generate the configure script and various template makefiles. You can skip this step if you are using a release package (which already -contains gtest and the configure script). +contains gmock and the configure script). To build and install the C++ Protocol Buffer runtime and the Protocol Buffer compiler (protoc) execute the following: diff --git a/autogen.sh b/autogen.sh index 08966c63..8160313e 100755 --- a/autogen.sh +++ b/autogen.sh @@ -15,27 +15,18 @@ __EOF__ exit 1 fi -# Check that gtest is present. Usually it is already there since the +# Check that gmock is present. Usually it is already there since the # directory is set up as an SVN external. -if test ! -e gtest; then - echo "Google Test not present. Fetching gtest-1.7.0 from the web..." - curl -O https://googletest.googlecode.com/files/gtest-1.7.0.zip - unzip -q gtest-1.7.0.zip - rm gtest-1.7.0.zip - mv gtest-1.7.0 gtest +if test ! -e gmock; then + echo "Google Mock not present. Fetching gmock-1.7.0 from the web..." + curl -O https://googlemock.googlecode.com/files/gmock-1.7.0.zip + unzip -q gmock-1.7.0.zip + rm gmock-1.7.0.zip + mv gmock-1.7.0 gmock fi set -ex -# Temporary hack: Must change C runtime library to "multi-threaded DLL", -# otherwise it will be set to "multi-threaded static" when MSVC upgrades -# the project file to MSVC 2005/2008. vladl of Google Test says gtest will -# probably change their default to match, then this will be unnecessary. -# One of these mappings converts the debug configuration and the other -# converts the release configuration. I don't know which is which. -sed -i -e 's/RuntimeLibrary="5"/RuntimeLibrary="3"/g; - s/RuntimeLibrary="4"/RuntimeLibrary="2"/g;' gtest/msvc/*.vcproj - # TODO(kenton): Remove the ",no-obsolete" part and fix the resulting warnings. autoreconf -f -i -Wall,no-obsolete diff --git a/cmake/README.md b/cmake/README.md index 1d5c8bc1..0abe078e 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -5,17 +5,17 @@ on your computer before proceeding. Compiling and Installing ======================== -1. Check whether a gtest directory exists in the upper level directory. If you - checkout the code from github via "git clone", this gtest directory won't +1. Check whether a gmock directory exists in the upper level directory. If you + checkout the code from github via "git clone", this gmock directory won't exist and you won't be able to build protobuf unit-tests. Consider using one of the release tar balls instead: https://github.com/google/protobuf/releases These release tar balls are more stable versions of protobuf and already - have the gtest directory included. + have the gmock directory included. - You can also download gtest by yourself and put it in the right place. + You can also download gmock by yourself and put it in the right place. If you absolutely don't want to build and run protobuf unit-tests, skip this step and use protobuf at your own risk. @@ -29,7 +29,7 @@ Compiling and Installing $ cd build $ cmake -G "Visual Studio 9 2008" .. - If you don't have gtest, skip the build of tests by turning off the + If you don't have gmock, skip the build of tests by turning off the BUILD_TESTING option: $ cmake -G "Visutal Studio 9 2008" -DBUILD_TESTING=OFF .. diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in index b2e9444d..d0c6dbfb 100644 --- a/cmake/extract_includes.bat.in +++ b/cmake/extract_includes.bat.in @@ -11,6 +11,7 @@ mkdir include\google\protobuf\compiler\python mkdir include\google\protobuf\compiler\ruby mkdir include\google\protobuf\io mkdir include\google\protobuf\stubs +mkdir include\google\protobuf\util copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.h include\google\protobuf\any.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.pb.h include\google\protobuf\any.pb.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.pb.h include\google\protobuf\api.pb.h @@ -98,6 +99,11 @@ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h include\ copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h include\google\protobuf\timestamp.pb.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h include\google\protobuf\type.pb.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\unknown_field_set.h include\google\protobuf\unknown_field_set.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_comparator.h include\google\protobuf\util\field_comparator.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\json_util.h include\google\protobuf\util\json_util.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\message_differencer.h include\google\protobuf\util\message_differencer.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h include\google\protobuf\util\type_resolver.h +copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h include\google\protobuf\util\type_resolver_util.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h include\google\protobuf\wire_format.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite.h include\google\protobuf\wire_format_lite.h copy ${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite_inl.h include\google\protobuf\wire_format_lite_inl.h diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake index 32c2d026..8d995df4 100644 --- a/cmake/libprotobuf-lite.cmake +++ b/cmake/libprotobuf-lite.cmake @@ -10,9 +10,14 @@ set(libprotobuf_lite_files ${protobuf_source_dir}/src/google/protobuf/repeated_field.cc ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_gcc.cc ${protobuf_source_dir}/src/google/protobuf/stubs/atomicops_internals_x86_msvc.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream.cc ${protobuf_source_dir}/src/google/protobuf/stubs/common.cc ${protobuf_source_dir}/src/google/protobuf/stubs/once.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/status.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/statusor.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece.cc ${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/time.cc ${protobuf_source_dir}/src/google/protobuf/wire_format_lite.cc ) diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake index b1f2dc3e..850d93a7 100644 --- a/cmake/libprotobuf.cmake +++ b/cmake/libprotobuf.cmake @@ -24,6 +24,7 @@ set(libprotobuf_files ${protobuf_source_dir}/src/google/protobuf/service.cc ${protobuf_source_dir}/src/google/protobuf/source_context.pb.cc ${protobuf_source_dir}/src/google/protobuf/struct.pb.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/mathlimits.cc ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid.cc ${protobuf_source_dir}/src/google/protobuf/stubs/strutil.cc ${protobuf_source_dir}/src/google/protobuf/stubs/substitute.cc @@ -31,6 +32,22 @@ set(libprotobuf_files ${protobuf_source_dir}/src/google/protobuf/timestamp.pb.cc ${protobuf_source_dir}/src/google/protobuf/type.pb.cc ${protobuf_source_dir}/src/google/protobuf/unknown_field_set.cc + ${protobuf_source_dir}/src/google/protobuf/util/field_comparator.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/datapiece.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/error_listener.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/field_mask_utility.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_escaping.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/object_writer.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectsource.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/utility.cc + ${protobuf_source_dir}/src/google/protobuf/util/json_util.cc + ${protobuf_source_dir}/src/google/protobuf/util/message_differencer.cc + ${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util.cc ${protobuf_source_dir}/src/google/protobuf/wire_format.cc ${protobuf_source_dir}/src/google/protobuf/wrappers.pb.cc ) diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 8fb5eef1..4396a657 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -1,10 +1,13 @@ -include_directories( - ${protobuf_source_dir}/gtest/include - ${protobuf_source_dir}/gtest) +if (NOT EXISTS "${PROJECT_SOURCE_DIR}/../gmock/CMakeLists.txt") + message(FATAL_ERROR "Cannot find gmock directory.") +endif() + +add_subdirectory(../gmock ${PROJECT_BINARY_DIR}/gmock) -add_library(gtest STATIC ${protobuf_source_dir}/gtest/src/gtest-all.cc) -add_library(gtest_main STATIC ${protobuf_source_dir}/gtest/src/gtest_main.cc) -target_link_libraries(gtest_main gtest) +include_directories( + ${protobuf_source_dir}/gmock/gtest/include + ${protobuf_source_dir}/gmock/include +) set(lite_test_protos google/protobuf/map_lite_unittest.proto @@ -39,6 +42,15 @@ set(tests_protos google/protobuf/unittest_preserve_unknown_enum2.proto google/protobuf/unittest_proto3_arena.proto google/protobuf/unittest_well_known_types.proto + google/protobuf/util/internal/testdata/anys.proto + google/protobuf/util/internal/testdata/books.proto + google/protobuf/util/internal/testdata/default_value.proto + google/protobuf/util/internal/testdata/default_value_test.proto + google/protobuf/util/internal/testdata/field_mask.proto + google/protobuf/util/internal/testdata/maps.proto + google/protobuf/util/internal/testdata/struct.proto + google/protobuf/util/internal/testdata/timestamp_duration.proto + google/protobuf/util/json_format_proto3.proto ) macro(compile_proto_file filename) @@ -46,10 +58,10 @@ macro(compile_proto_file filename) get_filename_component(basename ${filename} NAME_WE) add_custom_command( OUTPUT ${protobuf_source_dir}/src/${dirname}/${basename}.pb.cc + DEPENDS protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto COMMAND protoc ${protobuf_source_dir}/src/${dirname}/${basename}.proto --proto_path=${protobuf_source_dir}/src --cpp_out=${protobuf_source_dir}/src - DEPENDS protoc ) endmacro(compile_proto_file) @@ -113,21 +125,35 @@ set(tests_files ${protobuf_source_dir}/src/google/protobuf/reflection_ops_unittest.cc ${protobuf_source_dir}/src/google/protobuf/repeated_field_reflection_unittest.cc ${protobuf_source_dir}/src/google/protobuf/repeated_field_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/bytestream_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/common_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/once_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/status_test.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/statusor_test.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/stringpiece_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/stringprintf_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/structurally_valid_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/strutil_unittest.cc ${protobuf_source_dir}/src/google/protobuf/stubs/template_util_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/stubs/time_test.cc ${protobuf_source_dir}/src/google/protobuf/stubs/type_traits_unittest.cc ${protobuf_source_dir}/src/google/protobuf/text_format_unittest.cc ${protobuf_source_dir}/src/google/protobuf/unknown_field_set_unittest.cc + ${protobuf_source_dir}/src/google/protobuf/util/field_comparator_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/default_value_objectwriter_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_objectwriter_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/json_stream_parser_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectsource_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/protostream_objectwriter_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/internal/type_info_test_helper.cc + ${protobuf_source_dir}/src/google/protobuf/util/json_util_test.cc + ${protobuf_source_dir}/src/google/protobuf/util/type_resolver_util_test.cc ${protobuf_source_dir}/src/google/protobuf/well_known_types_unittest.cc ${protobuf_source_dir}/src/google/protobuf/wire_format_unittest.cc ) add_executable(tests ${tests_files} ${common_test_files} ${tests_proto_files} ${lite_test_proto_files}) -target_link_libraries(tests libprotoc libprotobuf gtest_main) +target_link_libraries(tests libprotoc libprotobuf gmock_main) set(test_plugin_files ${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc @@ -137,7 +163,7 @@ set(test_plugin_files ) add_executable(test_plugin ${test_plugin_files}) -target_link_libraries(test_plugin libprotoc libprotobuf gtest) +target_link_libraries(test_plugin libprotoc libprotobuf gmock) set(lite_test_files ${protobuf_source_dir}/src/google/protobuf/arena_test_util.cc diff --git a/configure.ac b/configure.ac index 8018cc75..764e5d43 100644 --- a/configure.ac +++ b/configure.ac @@ -157,12 +157,12 @@ case "$target_os" in ;; esac -# HACK: Make gtest's configure script pick up our copy of CFLAGS and CXXFLAGS, -# since the flags added by ACX_CHECK_SUNCC must be used when compiling gtest +# HACK: Make gmock's configure script pick up our copy of CFLAGS and CXXFLAGS, +# since the flags added by ACX_CHECK_SUNCC must be used when compiling gmock # too. export CFLAGS export CXXFLAGS -AC_CONFIG_SUBDIRS([gtest]) +AC_CONFIG_SUBDIRS([gmock]) AC_CONFIG_FILES([Makefile src/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc]) AC_OUTPUT diff --git a/src/Makefile.am b/src/Makefile.am index ac6ec6f4..de6a88e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -139,7 +139,12 @@ nobase_include_HEADERS = \ google/protobuf/compiler/objectivec/objectivec_helpers.h \ google/protobuf/compiler/python/python_generator.h \ google/protobuf/compiler/ruby/ruby_generator.h \ - google/protobuf/compiler/csharp/csharp_generator.h + google/protobuf/compiler/csharp/csharp_generator.h \ + google/protobuf/util/type_resolver.h \ + google/protobuf/util/type_resolver_util.h \ + google/protobuf/util/json_util.h \ + google/protobuf/util/field_comparator.h \ + google/protobuf/util/message_differencer.h lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la @@ -148,13 +153,25 @@ libprotobuf_lite_la_LDFLAGS = -version-info 10:0:0 -export-dynamic -no-undefined libprotobuf_lite_la_SOURCES = \ google/protobuf/stubs/atomicops_internals_x86_gcc.cc \ google/protobuf/stubs/atomicops_internals_x86_msvc.cc \ + google/protobuf/stubs/bytestream.cc \ + google/protobuf/stubs/bytestream.h \ google/protobuf/stubs/common.cc \ - google/protobuf/stubs/once.cc \ google/protobuf/stubs/hash.h \ google/protobuf/stubs/map_util.h \ + google/protobuf/stubs/mathutil.h \ + google/protobuf/stubs/once.cc \ google/protobuf/stubs/shared_ptr.h \ + google/protobuf/stubs/status.cc \ + google/protobuf/stubs/status.h \ + google/protobuf/stubs/status_macros.h \ + google/protobuf/stubs/statusor.cc \ + google/protobuf/stubs/statusor.h \ + google/protobuf/stubs/stringpiece.cc \ + google/protobuf/stubs/stringpiece.h \ google/protobuf/stubs/stringprintf.cc \ google/protobuf/stubs/stringprintf.h \ + google/protobuf/stubs/time.cc \ + google/protobuf/stubs/time.h \ google/protobuf/arena.cc \ google/protobuf/arenastring.cc \ google/protobuf/extension_set.cc \ @@ -173,6 +190,8 @@ libprotobuf_la_SOURCES = \ $(libprotobuf_lite_la_SOURCES) \ google/protobuf/any.pb.cc \ google/protobuf/api.pb.cc \ + google/protobuf/stubs/mathlimits.h \ + google/protobuf/stubs/mathlimits.cc \ google/protobuf/any.cc \ google/protobuf/descriptor.cc \ google/protobuf/descriptor_database.cc \ @@ -207,7 +226,39 @@ libprotobuf_la_SOURCES = \ google/protobuf/io/tokenizer.cc \ google/protobuf/io/zero_copy_stream_impl.cc \ google/protobuf/compiler/importer.cc \ - google/protobuf/compiler/parser.cc + google/protobuf/compiler/parser.cc \ + google/protobuf/util/field_comparator.cc \ + google/protobuf/util/internal/constants.h \ + google/protobuf/util/internal/datapiece.cc \ + google/protobuf/util/internal/datapiece.h \ + google/protobuf/util/internal/default_value_objectwriter.cc \ + google/protobuf/util/internal/default_value_objectwriter.h \ + google/protobuf/util/internal/error_listener.cc \ + google/protobuf/util/internal/error_listener.h \ + google/protobuf/util/internal/field_mask_utility.cc \ + google/protobuf/util/internal/field_mask_utility.h \ + google/protobuf/util/internal/json_escaping.cc \ + google/protobuf/util/internal/json_escaping.h \ + google/protobuf/util/internal/json_objectwriter.cc \ + google/protobuf/util/internal/json_objectwriter.h \ + google/protobuf/util/internal/json_stream_parser.cc \ + google/protobuf/util/internal/json_stream_parser.h \ + google/protobuf/util/internal/location_tracker.h \ + google/protobuf/util/internal/object_source.h \ + google/protobuf/util/internal/object_writer.cc \ + google/protobuf/util/internal/object_writer.h \ + google/protobuf/util/internal/object_writer.h \ + google/protobuf/util/internal/protostream_objectsource.cc \ + google/protobuf/util/internal/protostream_objectsource.h \ + google/protobuf/util/internal/protostream_objectwriter.cc \ + google/protobuf/util/internal/protostream_objectwriter.h \ + google/protobuf/util/internal/type_info.cc \ + google/protobuf/util/internal/type_info.h \ + google/protobuf/util/internal/utility.cc \ + google/protobuf/util/internal/utility.h \ + google/protobuf/util/json_util.cc \ + google/protobuf/util/type_resolver_util.cc \ + google/protobuf/util/message_differencer.cc nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES) libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la @@ -386,35 +437,44 @@ protoc_SOURCES = google/protobuf/compiler/main.cc # Tests ============================================================== -protoc_inputs = \ - google/protobuf/any_test.proto \ - google/protobuf/map_lite_unittest.proto \ - google/protobuf/map_proto2_unittest.proto \ - google/protobuf/map_unittest.proto \ - google/protobuf/unittest.proto \ - google/protobuf/unittest_arena.proto \ - google/protobuf/unittest_custom_options.proto \ - google/protobuf/unittest_drop_unknown_fields.proto \ - google/protobuf/unittest_embed_optimize_for.proto \ - google/protobuf/unittest_empty.proto \ - google/protobuf/unittest_enormous_descriptor.proto \ - google/protobuf/unittest_import_lite.proto \ - google/protobuf/unittest_import.proto \ - google/protobuf/unittest_import_public_lite.proto \ - google/protobuf/unittest_import_public.proto \ - google/protobuf/unittest_lite_imports_nonlite.proto \ - google/protobuf/unittest_lite.proto \ - google/protobuf/unittest_mset.proto \ - google/protobuf/unittest_no_arena_import.proto \ - google/protobuf/unittest_no_arena.proto \ - google/protobuf/unittest_no_field_presence.proto \ - google/protobuf/unittest_no_generic_services.proto \ - google/protobuf/unittest_optimize_for.proto \ - google/protobuf/unittest_preserve_unknown_enum.proto \ - google/protobuf/unittest_preserve_unknown_enum2.proto \ - google/protobuf/unittest_proto3_arena.proto \ - google/protobuf/unittest_well_known_types.proto \ - google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \ +protoc_inputs = \ + google/protobuf/any_test.proto \ + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto \ + google/protobuf/map_lite_unittest.proto \ + google/protobuf/map_proto2_unittest.proto \ + google/protobuf/map_unittest.proto \ + google/protobuf/unittest_arena.proto \ + google/protobuf/unittest_custom_options.proto \ + google/protobuf/unittest_drop_unknown_fields.proto \ + google/protobuf/unittest_embed_optimize_for.proto \ + google/protobuf/unittest_empty.proto \ + google/protobuf/unittest_enormous_descriptor.proto \ + google/protobuf/unittest_import_lite.proto \ + google/protobuf/unittest_import.proto \ + google/protobuf/unittest_import_public_lite.proto \ + google/protobuf/unittest_import_public.proto \ + google/protobuf/unittest_lite_imports_nonlite.proto \ + google/protobuf/unittest_lite.proto \ + google/protobuf/unittest_mset.proto \ + google/protobuf/unittest_no_arena_import.proto \ + google/protobuf/unittest_no_arena.proto \ + google/protobuf/unittest_no_field_presence.proto \ + google/protobuf/unittest_no_generic_services.proto \ + google/protobuf/unittest_optimize_for.proto \ + google/protobuf/unittest_preserve_unknown_enum2.proto \ + google/protobuf/unittest_preserve_unknown_enum.proto \ + google/protobuf/unittest.proto \ + google/protobuf/unittest_proto3_arena.proto \ + google/protobuf/unittest_well_known_types.proto \ + google/protobuf/util/internal/testdata/anys.proto \ + google/protobuf/util/internal/testdata/books.proto \ + google/protobuf/util/internal/testdata/default_value.proto \ + google/protobuf/util/internal/testdata/default_value_test.proto \ + google/protobuf/util/internal/testdata/field_mask.proto \ + google/protobuf/util/internal/testdata/maps.proto \ + google/protobuf/util/internal/testdata/struct.proto \ + google/protobuf/util/internal/testdata/timestamp_duration.proto \ + google/protobuf/util/json_format_proto3.proto \ google/protobuf/compiler/cpp/cpp_test_large_enum_value.proto EXTRA_DIST = \ @@ -451,58 +511,76 @@ protoc_lite_outputs = \ google/protobuf/unittest_import_public_lite.pb.cc \ google/protobuf/unittest_import_public_lite.pb.h -protoc_outputs = \ - $(protoc_lite_outputs) \ - google/protobuf/any_test.pb.cc \ - google/protobuf/any_test.pb.h \ - google/protobuf/map_proto2_unittest.pb.cc \ - google/protobuf/map_proto2_unittest.pb.h \ - google/protobuf/map_unittest.pb.cc \ - google/protobuf/map_unittest.pb.h \ - google/protobuf/unittest.pb.cc \ - google/protobuf/unittest.pb.h \ - google/protobuf/unittest_arena.pb.cc \ - google/protobuf/unittest_arena.pb.h \ - google/protobuf/unittest_custom_options.pb.cc \ - google/protobuf/unittest_custom_options.pb.h \ - google/protobuf/unittest_drop_unknown_fields.pb.cc \ - google/protobuf/unittest_drop_unknown_fields.pb.h \ - google/protobuf/unittest_embed_optimize_for.pb.cc \ - google/protobuf/unittest_embed_optimize_for.pb.h \ - google/protobuf/unittest_empty.pb.cc \ - google/protobuf/unittest_empty.pb.h \ - google/protobuf/unittest_enormous_descriptor.pb.cc \ - google/protobuf/unittest_enormous_descriptor.pb.h \ - google/protobuf/unittest_import.pb.cc \ - google/protobuf/unittest_import.pb.h \ - google/protobuf/unittest_import_public.pb.cc \ - google/protobuf/unittest_import_public.pb.h \ - google/protobuf/unittest_lite_imports_nonlite.pb.cc \ - google/protobuf/unittest_lite_imports_nonlite.pb.h \ - google/protobuf/unittest_mset.pb.cc \ - google/protobuf/unittest_mset.pb.h \ - google/protobuf/unittest_no_arena.pb.cc \ - google/protobuf/unittest_no_arena.pb.h \ - google/protobuf/unittest_no_arena_import.pb.cc \ - google/protobuf/unittest_no_arena_import.pb.h \ - google/protobuf/unittest_no_field_presence.pb.cc \ - google/protobuf/unittest_no_field_presence.pb.h \ - google/protobuf/unittest_no_generic_services.pb.cc \ - google/protobuf/unittest_no_generic_services.pb.h \ - google/protobuf/unittest_optimize_for.pb.cc \ - google/protobuf/unittest_optimize_for.pb.h \ - google/protobuf/unittest_preserve_unknown_enum.pb.cc \ - google/protobuf/unittest_preserve_unknown_enum.pb.h \ - google/protobuf/unittest_preserve_unknown_enum2.pb.cc \ - google/protobuf/unittest_preserve_unknown_enum2.pb.h \ - google/protobuf/unittest_proto3_arena.pb.cc \ - google/protobuf/unittest_proto3_arena.pb.h \ - google/protobuf/unittest_well_known_types.pb.cc \ - google/protobuf/unittest_well_known_types.pb.h \ - google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.cc \ - google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.h \ - google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ - google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h +protoc_outputs = \ + $(protoc_lite_outputs) \ + google/protobuf/any_test.pb.cc \ + google/protobuf/any_test.pb.h \ + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.cc \ + google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h \ + google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.cc \ + google/protobuf/compiler/cpp/cpp_test_large_enum_value.pb.h \ + google/protobuf/map_proto2_unittest.pb.cc \ + google/protobuf/map_proto2_unittest.pb.h \ + google/protobuf/map_unittest.pb.cc \ + google/protobuf/map_unittest.pb.h \ + google/protobuf/unittest_arena.pb.cc \ + google/protobuf/unittest_arena.pb.h \ + google/protobuf/unittest_custom_options.pb.cc \ + google/protobuf/unittest_custom_options.pb.h \ + google/protobuf/unittest_drop_unknown_fields.pb.cc \ + google/protobuf/unittest_drop_unknown_fields.pb.h \ + google/protobuf/unittest_embed_optimize_for.pb.cc \ + google/protobuf/unittest_embed_optimize_for.pb.h \ + google/protobuf/unittest_empty.pb.cc \ + google/protobuf/unittest_empty.pb.h \ + google/protobuf/unittest_enormous_descriptor.pb.cc \ + google/protobuf/unittest_enormous_descriptor.pb.h \ + google/protobuf/unittest_import.pb.cc \ + google/protobuf/unittest_import.pb.h \ + google/protobuf/unittest_import_public.pb.cc \ + google/protobuf/unittest_import_public.pb.h \ + google/protobuf/unittest_lite_imports_nonlite.pb.cc \ + google/protobuf/unittest_lite_imports_nonlite.pb.h \ + google/protobuf/unittest_mset.pb.cc \ + google/protobuf/unittest_mset.pb.h \ + google/protobuf/unittest_no_arena_import.pb.cc \ + google/protobuf/unittest_no_arena_import.pb.h \ + google/protobuf/unittest_no_arena.pb.cc \ + google/protobuf/unittest_no_arena.pb.h \ + google/protobuf/unittest_no_field_presence.pb.cc \ + google/protobuf/unittest_no_field_presence.pb.h \ + google/protobuf/unittest_no_generic_services.pb.cc \ + google/protobuf/unittest_no_generic_services.pb.h \ + google/protobuf/unittest_optimize_for.pb.cc \ + google/protobuf/unittest_optimize_for.pb.h \ + google/protobuf/unittest.pb.cc \ + google/protobuf/unittest.pb.h \ + google/protobuf/unittest_preserve_unknown_enum2.pb.cc \ + google/protobuf/unittest_preserve_unknown_enum2.pb.h \ + google/protobuf/unittest_preserve_unknown_enum.pb.cc \ + google/protobuf/unittest_preserve_unknown_enum.pb.h \ + google/protobuf/unittest_proto3_arena.pb.cc \ + google/protobuf/unittest_proto3_arena.pb.h \ + google/protobuf/unittest_well_known_types.pb.cc \ + google/protobuf/unittest_well_known_types.pb.h \ + google/protobuf/util/internal/testdata/anys.pb.cc \ + google/protobuf/util/internal/testdata/anys.pb.h \ + google/protobuf/util/internal/testdata/books.pb.cc \ + google/protobuf/util/internal/testdata/books.pb.h \ + google/protobuf/util/internal/testdata/default_value.pb.cc \ + google/protobuf/util/internal/testdata/default_value.pb.h \ + google/protobuf/util/internal/testdata/default_value_test.pb.cc \ + google/protobuf/util/internal/testdata/default_value_test.pb.h \ + google/protobuf/util/internal/testdata/field_mask.pb.cc \ + google/protobuf/util/internal/testdata/field_mask.pb.h \ + google/protobuf/util/internal/testdata/maps.pb.cc \ + google/protobuf/util/internal/testdata/maps.pb.h \ + google/protobuf/util/internal/testdata/struct.pb.cc \ + google/protobuf/util/internal/testdata/struct.pb.h \ + google/protobuf/util/internal/testdata/timestamp_duration.pb.cc \ + google/protobuf/util/internal/testdata/timestamp_duration.pb.h \ + google/protobuf/util/json_format_proto3.pb.cc \ + google/protobuf/util/json_format_proto3.pb.h BUILT_SOURCES = $(protoc_outputs) @@ -541,21 +619,27 @@ COMMON_TEST_SOURCES = \ check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \ protobuf-lite-test test_plugin $(GZCHECKPROGRAMS) protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \ - $(top_builddir)/gtest/lib/libgtest.la \ - $(top_builddir)/gtest/lib/libgtest_main.la -protobuf_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \ - -I$(top_builddir)/gtest/include + $(top_builddir)/gmock/gtest/lib/libgtest.la \ + $(top_builddir)/gmock/lib/libgmock.la \ + $(top_builddir)/gmock/lib/libgmock_main.la +protobuf_test_CPPFLAGS = -I$(top_builddir)/gmock/gtest/include \ + -I$(top_builddir)/gmock/include # Disable optimization for tests unless the user explicitly asked for it, # since test_util.cc takes forever to compile with optimization (with GCC). # See configure.ac for more info. protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_test_SOURCES = \ + google/protobuf/stubs/bytestream_unittest.cc \ google/protobuf/stubs/common_unittest.cc \ google/protobuf/stubs/once_unittest.cc \ - google/protobuf/stubs/strutil_unittest.cc \ - google/protobuf/stubs/structurally_valid_unittest.cc \ + google/protobuf/stubs/statusor_test.cc \ + google/protobuf/stubs/status_test.cc \ + google/protobuf/stubs/stringpiece_unittest.cc \ google/protobuf/stubs/stringprintf_unittest.cc \ + google/protobuf/stubs/structurally_valid_unittest.cc \ + google/protobuf/stubs/strutil_unittest.cc \ google/protobuf/stubs/template_util_unittest.cc \ + google/protobuf/stubs/time_test.cc \ google/protobuf/stubs/type_traits_unittest.cc \ google/protobuf/any_test.cc \ google/protobuf/arenastring_unittest.cc \ @@ -598,16 +682,28 @@ protobuf_test_SOURCES = \ google/protobuf/compiler/python/python_plugin_unittest.cc \ google/protobuf/compiler/ruby/ruby_generator_unittest.cc \ google/protobuf/compiler/csharp/csharp_generator_unittest.cc \ + google/protobuf/util/field_comparator_test.cc \ + google/protobuf/util/internal/default_value_objectwriter_test.cc \ + google/protobuf/util/internal/json_objectwriter_test.cc \ + google/protobuf/util/internal/json_stream_parser_test.cc \ + google/protobuf/util/internal/protostream_objectsource_test.cc \ + google/protobuf/util/internal/protostream_objectwriter_test.cc \ + google/protobuf/util/internal/type_info_test_helper.cc \ + google/protobuf/util/json_util_test.cc \ + google/protobuf/util/type_resolver_util_test.cc \ $(COMMON_TEST_SOURCES) + + nodist_protobuf_test_SOURCES = $(protoc_outputs) # Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined. protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \ libprotoc.la \ - $(top_builddir)/gtest/lib/libgtest.la \ - $(top_builddir)/gtest/lib/libgtest_main.la -protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \ - -I$(top_builddir)/gtest/include \ + $(top_builddir)/gmock/gtest/lib/libgtest.la \ + $(top_builddir)/gmock/lib/libgmock.la \ + $(top_builddir)/gmock/lib/libgmock_main.la +protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_builddir)/gmock/include \ + -I$(top_builddir)/gmock/gtest/include \ -DPROTOBUF_TEST_NO_DESCRIPTORS protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS) protobuf_lazy_descriptor_test_SOURCES = \ @@ -632,9 +728,8 @@ nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs) # Test plugin binary. test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \ - $(top_builddir)/gtest/lib/libgtest.la -test_plugin_CPPFLAGS = -I$(top_srcdir)/gtest/include \ - -I$(top_builddir)/gtest/include + $(top_builddir)/gmock/gtest/lib/libgtest.la +test_plugin_CPPFLAGS = -I$(top_builddir)/gmock/gtest/include test_plugin_SOURCES = \ google/protobuf/compiler/mock_code_generator.cc \ google/protobuf/testing/file.cc \ diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index af85919a..17f67a7b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -621,7 +621,7 @@ GenerateSingularFieldHasBits(const FieldDescriptor* field, // has_$name$() methods. vars["has_array_index"] = SimpleItoa(field->index() / 32); vars["has_mask"] = StrCat(strings::Hex(1u << (field->index() % 32), - strings::Hex::ZERO_PAD_8)); + strings::ZERO_PAD_8)); printer->Print(vars, "$inline$" "bool $classname$::has_$name$() const {\n" @@ -3364,7 +3364,7 @@ static string ConditionalToCheckBitmasks(const vector& masks) { vector parts; for (int i = 0; i < masks.size(); i++) { if (masks[i] == 0) continue; - string m = StrCat("0x", strings::Hex(masks[i], strings::Hex::ZERO_PAD_8)); + string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8)); // Each xor evaluates to 0 if the expected bits are present. parts.push_back(StrCat("((_has_bits_[", i, "] & ", m, ") ^ ", m, ")")); } @@ -3659,7 +3659,7 @@ GenerateIsInitialized(io::Printer* printer) { printer->Print( "if ((_has_bits_[$i$] & 0x$mask$) != 0x$mask$) return false;\n", "i", SimpleItoa(i), - "mask", StrCat(strings::Hex(mask, strings::Hex::ZERO_PAD_8))); + "mask", StrCat(strings::Hex(mask, strings::ZERO_PAD_8))); } } } diff --git a/src/google/protobuf/stubs/bytestream.cc b/src/google/protobuf/stubs/bytestream.cc new file mode 100644 index 00000000..f4af6a50 --- /dev/null +++ b/src/google/protobuf/stubs/bytestream.cc @@ -0,0 +1,196 @@ +// 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 + +#include +#include + +namespace google { +namespace protobuf { +namespace strings { + +void ByteSource::CopyTo(ByteSink* sink, size_t n) { + while (n > 0) { + StringPiece fragment = Peek(); + if (fragment.empty()) { + GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input."; + break; + } + std::size_t fragment_size = std::min(n, fragment.size()); + sink->Append(fragment.data(), fragment_size); + Skip(fragment_size); + n -= fragment_size; + } +} + +void ByteSink::Flush() {} + +void UncheckedArrayByteSink::Append(const char* data, size_t n) { + if (data != dest_) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n))) + << "Append() data[] overlaps with dest_[]"; + memcpy(dest_, data, n); + } + dest_ += n; +} + +CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity) + : outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) { +} + +void CheckedArrayByteSink::Append(const char* bytes, size_t n) { + size_t available = capacity_ - size_; + if (n > available) { + n = available; + overflowed_ = true; + } + if (n > 0 && bytes != (outbuf_ + size_)) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_))) + << "Append() bytes[] overlaps with outbuf_[]"; + memcpy(outbuf_ + size_, bytes, n); + } + size_ += n; +} + +GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size) + : capacity_(estimated_size), + buf_(new char[estimated_size]), + size_(0) { +} + +GrowingArrayByteSink::~GrowingArrayByteSink() { + delete[] buf_; // Just in case the user didn't call GetBuffer. +} + +void GrowingArrayByteSink::Append(const char* bytes, size_t n) { + size_t available = capacity_ - size_; + if (bytes != (buf_ + size_)) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + // We need to test for this before calling Expand() which may reallocate. + GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_))) + << "Append() bytes[] overlaps with buf_[]"; + } + if (n > available) { + Expand(n - available); + } + if (n > 0 && bytes != (buf_ + size_)) { + memcpy(buf_ + size_, bytes, n); + } + size_ += n; +} + +char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) { + ShrinkToFit(); + char* b = buf_; + *nbytes = size_; + buf_ = NULL; + size_ = capacity_ = 0; + return b; +} + +void GrowingArrayByteSink::Expand(size_t amount) { // Expand by at least 50%. + size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2); + char* bigger = new char[new_capacity]; + memcpy(bigger, buf_, size_); + delete[] buf_; + buf_ = bigger; + capacity_ = new_capacity; +} + +void GrowingArrayByteSink::ShrinkToFit() { + // Shrink only if the buffer is large and size_ is less than 3/4 + // of capacity_. + if (capacity_ > 256 && size_ < (3 * capacity_) / 4) { + char* just_enough = new char[size_]; + memcpy(just_enough, buf_, size_); + delete[] buf_; + buf_ = just_enough; + capacity_ = size_; + } +} + +void StringByteSink::Append(const char* data, size_t n) { + dest_->append(data, n); +} + +size_t ArrayByteSource::Available() const { + return input_.size(); +} + +StringPiece ArrayByteSource::Peek() { + return input_; +} + +void ArrayByteSource::Skip(size_t n) { + GOOGLE_DCHECK_LE(n, input_.size()); + input_.remove_prefix(n); +} + +LimitByteSource::LimitByteSource(ByteSource *source, size_t limit) + : source_(source), + limit_(limit) { +} + +size_t LimitByteSource::Available() const { + size_t available = source_->Available(); + if (available > limit_) { + available = limit_; + } + + return available; +} + +StringPiece LimitByteSource::Peek() { + StringPiece piece(source_->Peek()); + if (piece.size() > limit_) { + piece.set(piece.data(), limit_); + } + + return piece; +} + +void LimitByteSource::Skip(size_t n) { + GOOGLE_DCHECK_LE(n, limit_); + source_->Skip(n); + limit_ -= n; +} + +void LimitByteSource::CopyTo(ByteSink *sink, size_t n) { + GOOGLE_DCHECK_LE(n, limit_); + source_->CopyTo(sink, n); + limit_ -= n; +} + +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h new file mode 100644 index 00000000..c9c9a76e --- /dev/null +++ b/src/google/protobuf/stubs/bytestream.h @@ -0,0 +1,348 @@ +// 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. + +// This file declares the ByteSink and ByteSource abstract interfaces. These +// interfaces represent objects that consume (ByteSink) or produce (ByteSource) +// a sequence of bytes. Using these abstract interfaces in your APIs can help +// make your code work with a variety of input and output types. +// +// This file also declares the following commonly used implementations of these +// interfaces. +// +// ByteSink: +// UncheckedArrayByteSink Writes to an array, without bounds checking +// CheckedArrayByteSink Writes to an array, with bounds checking +// GrowingArrayByteSink Allocates and writes to a growable buffer +// StringByteSink Writes to an STL string +// NullByteSink Consumes a never-ending stream of bytes +// +// ByteSource: +// ArrayByteSource Reads from an array or string/StringPiece +// LimitedByteSource Limits the number of bytes read from an + +#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ +#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ + +#include +#include + +#include +#include + +class CordByteSink; +class MemBlock; + +namespace google { +namespace protobuf { +namespace strings { + +// An abstract interface for an object that consumes a sequence of bytes. This +// interface offers 3 different ways to append data, and a Flush() function. +// +// Example: +// +// string my_data; +// ... +// ByteSink* sink = ... +// sink->Append(my_data.data(), my_data.size()); +// sink->Flush(); +// +class ByteSink { + public: + ByteSink() {} + virtual ~ByteSink() {} + + // Appends the "n" bytes starting at "bytes". + virtual void Append(const char* bytes, size_t n) = 0; + + // Flushes internal buffers. The default implemenation does nothing. ByteSink + // subclasses may use internal buffers that require calling Flush() at the end + // of the stream. + virtual void Flush(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink); +}; + +// An abstract interface for an object that produces a fixed-size sequence of +// bytes. +// +// Example: +// +// ByteSource* source = ... +// while (source->Available() > 0) { +// StringPiece data = source->Peek(); +// ... do something with "data" ... +// source->Skip(data.length()); +// } +// +class ByteSource { + public: + ByteSource() {} + virtual ~ByteSource() {} + + // Returns the number of bytes left to read from the source. Available() + // should decrease by N each time Skip(N) is called. Available() may not + // increase. Available() returning 0 indicates that the ByteSource is + // exhausted. + // + // Note: Size() may have been a more appropriate name as it's more + // indicative of the fixed-size nature of a ByteSource. + virtual size_t Available() const = 0; + + // Returns a StringPiece of the next contiguous region of the source. Does not + // reposition the source. The returned region is empty iff Available() == 0. + // + // The returned region is valid until the next call to Skip() or until this + // object is destroyed, whichever occurs first. + // + // The length of the returned StringPiece will be <= Available(). + virtual StringPiece Peek() = 0; + + // Skips the next n bytes. Invalidates any StringPiece returned by a previous + // call to Peek(). + // + // REQUIRES: Available() >= n + virtual void Skip(size_t n) = 0; + + // Writes the next n bytes in this ByteSource to the given ByteSink, and + // advances this ByteSource past the copied bytes. The default implementation + // of this method just copies the bytes normally, but subclasses might + // override CopyTo to optimize certain cases. + // + // REQUIRES: Available() >= n + virtual void CopyTo(ByteSink* sink, size_t n); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource); +}; + +// +// Some commonly used implementations of ByteSink +// + +// Implementation of ByteSink that writes to an unsized byte array. No +// bounds-checking is performed--it is the caller's responsibility to ensure +// that the destination array is large enough. +// +// Example: +// +// char buf[10]; +// UncheckedArrayByteSink sink(buf); +// sink.Append("hi", 2); // OK +// sink.Append(data, 100); // WOOPS! Overflows buf[10]. +// +class UncheckedArrayByteSink : public ByteSink { + public: + explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n); + + // Returns the current output pointer so that a caller can see how many bytes + // were produced. + // + // Note: this method is not part of the ByteSink interface. + char* CurrentDestination() const { return dest_; } + + private: + char* dest_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink); +}; + +// Implementation of ByteSink that writes to a sized byte array. This sink will +// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are +// appended, subsequent bytes will be ignored and Overflowed() will return true. +// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail). +// +// Example: +// +// char buf[10]; +// CheckedArrayByteSink sink(buf, 10); +// sink.Append("hi", 2); // OK +// sink.Append(data, 100); // Will only write 8 more bytes +// +class CheckedArrayByteSink : public ByteSink { + public: + CheckedArrayByteSink(char* outbuf, size_t capacity); + virtual void Append(const char* bytes, size_t n); + + // Returns the number of bytes actually written to the sink. + size_t NumberOfBytesWritten() const { return size_; } + + // Returns true if any bytes were discarded, i.e., if there was an + // attempt to write more than 'capacity' bytes. + bool Overflowed() const { return overflowed_; } + + private: + char* outbuf_; + const size_t capacity_; + size_t size_; + bool overflowed_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink); +}; + +// Implementation of ByteSink that allocates an internal buffer (a char array) +// and expands it as needed to accomodate appended data (similar to a string), +// and allows the caller to take ownership of the internal buffer via the +// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by +// the caller with delete[]. GetBuffer() also sets the internal buffer to be +// empty, and subsequent appends to the sink will create a new buffer. The +// destructor will free the internal buffer if GetBuffer() was not called. +// +// Example: +// +// GrowingArrayByteSink sink(10); +// sink.Append("hi", 2); +// sink.Append(data, n); +// const char* buf = sink.GetBuffer(); // Ownership transferred +// delete[] buf; +// +class GrowingArrayByteSink : public strings::ByteSink { + public: + explicit GrowingArrayByteSink(size_t estimated_size); + virtual ~GrowingArrayByteSink(); + virtual void Append(const char* bytes, size_t n); + + // Returns the allocated buffer, and sets nbytes to its size. The caller takes + // ownership of the buffer and must delete it with delete[]. + char* GetBuffer(size_t* nbytes); + + private: + void Expand(size_t amount); + void ShrinkToFit(); + + size_t capacity_; + char* buf_; + size_t size_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink); +}; + +// Implementation of ByteSink that appends to the given string. +// Existing contents of "dest" are not modified; new data is appended. +// +// Example: +// +// string dest = "Hello "; +// StringByteSink sink(&dest); +// sink.Append("World", 5); +// assert(dest == "Hello World"); +// +class StringByteSink : public ByteSink { + public: + explicit StringByteSink(string* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n); + + private: + string* dest_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink); +}; + +// Implementation of ByteSink that discards all data. +// +// Example: +// +// NullByteSink sink; +// sink.Append(data, data.size()); // All data ignored. +// +class NullByteSink : public ByteSink { + public: + NullByteSink() {} + virtual void Append(const char *data, size_t n) {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink); +}; + +// +// Some commonly used implementations of ByteSource +// + +// Implementation of ByteSource that reads from a StringPiece. +// +// Example: +// +// string data = "Hello"; +// ArrayByteSource source(data); +// assert(source.Available() == 5); +// assert(source.Peek() == "Hello"); +// +class ArrayByteSource : public ByteSource { + public: + explicit ArrayByteSource(StringPiece s) : input_(s) {} + + virtual size_t Available() const; + virtual StringPiece Peek(); + virtual void Skip(size_t n); + + private: + StringPiece input_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource); +}; + +// Implementation of ByteSource that wraps another ByteSource, limiting the +// number of bytes returned. +// +// The caller maintains ownership of the underlying source, and may not use the +// underlying source while using the LimitByteSource object. The underlying +// source's pointer is advanced by n bytes every time this LimitByteSource +// object is advanced by n. +// +// Example: +// +// string data = "Hello World"; +// ArrayByteSource abs(data); +// assert(abs.Available() == data.size()); +// +// LimitByteSource limit(abs, 5); +// assert(limit.Available() == 5); +// assert(limit.Peek() == "Hello"); +// +class LimitByteSource : public ByteSource { + public: + // Returns at most "limit" bytes from "source". + LimitByteSource(ByteSource* source, size_t limit); + + virtual size_t Available() const; + virtual StringPiece Peek(); + virtual void Skip(size_t n); + + // We override CopyTo so that we can forward to the underlying source, in + // case it has an efficient implementation of CopyTo. + virtual void CopyTo(ByteSink* sink, size_t n); + + private: + ByteSource* source_; + size_t limit_; +}; + +} // namespace strings +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ diff --git a/src/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc new file mode 100644 index 00000000..06f114ab --- /dev/null +++ b/src/google/protobuf/stubs/bytestream_unittest.cc @@ -0,0 +1,146 @@ +// 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 + +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace strings { +namespace { + +// We use this class instead of ArrayByteSource to simulate a ByteSource that +// contains multiple fragments. ArrayByteSource returns the entire array in +// one fragment. +class MockByteSource : public ByteSource { + public: + MockByteSource(StringPiece data, int block_size) + : data_(data), block_size_(block_size) {} + + size_t Available() const { return data_.size(); } + StringPiece Peek() { + return data_.substr(0, block_size_); + } + void Skip(size_t n) { data_.remove_prefix(n); } + + private: + StringPiece data_; + int block_size_; +}; + +TEST(ByteSourceTest, CopyTo) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + string str; + StringByteSink sink(&str); + + source.CopyTo(&sink, data.size()); + EXPECT_EQ(data, str); +} + +TEST(ByteSourceTest, CopySubstringTo) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + source.Skip(1); + string str; + StringByteSink sink(&str); + + source.CopyTo(&sink, data.size() - 2); + EXPECT_EQ(data.substr(1, data.size() - 2), str); + EXPECT_EQ("!", source.Peek()); +} + +TEST(ByteSourceTest, LimitByteSource) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + LimitByteSource limit_source(&source, 6); + EXPECT_EQ(6, limit_source.Available()); + limit_source.Skip(1); + EXPECT_EQ(5, limit_source.Available()); + + { + string str; + StringByteSink sink(&str); + limit_source.CopyTo(&sink, limit_source.Available()); + EXPECT_EQ("ello ", str); + EXPECT_EQ(0, limit_source.Available()); + EXPECT_EQ(6, source.Available()); + } + + { + string str; + StringByteSink sink(&str); + source.CopyTo(&sink, source.Available()); + EXPECT_EQ("world!", str); + EXPECT_EQ(0, source.Available()); + } +} + +TEST(ByteSourceTest, CopyToStringByteSink) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + string str; + StringByteSink sink(&str); + source.CopyTo(&sink, data.size()); + EXPECT_EQ(data, str); +} + +// Verify that ByteSink is subclassable and Flush() overridable. +class FlushingByteSink : public StringByteSink { + public: + explicit FlushingByteSink(string* dest) : StringByteSink(dest) {} + virtual void Flush() { Append("z", 1); } + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink); +}; + +// Write and Flush via the ByteSink superclass interface. +void WriteAndFlush(ByteSink* s) { + s->Append("abc", 3); + s->Flush(); +} + +TEST(ByteSinkTest, Flush) { + string str; + FlushingByteSink f_sink(&str); + WriteAndFlush(&f_sink); + EXPECT_STREQ("abcz", str.c_str()); +} + +} // namespace +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h index cccf65a1..be652849 100644 --- a/src/google/protobuf/stubs/casts.h +++ b/src/google/protobuf/stubs/casts.h @@ -111,12 +111,22 @@ inline To down_cast(From& f) { return *static_cast(&f); } +template +inline To bit_cast(const From& from) { + GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To), + bit_cast_with_different_sizes); + To dest; + memcpy(&dest, &from, sizeof(dest)); + return dest; +} + } // namespace internal // We made these internal so that they would show up as such in the docs, // but we don't want to stick "internal::" in front of them everywhere. using internal::implicit_cast; using internal::down_cast; +using internal::bit_cast; } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc index 54e00ccb..b895d915 100644 --- a/src/google/protobuf/stubs/common.cc +++ b/src/google/protobuf/stubs/common.cc @@ -32,6 +32,8 @@ #include #include +#include +#include #include #include #include @@ -148,6 +150,17 @@ LogMessage& LogMessage::operator<<(const char* value) { return *this; } +LogMessage& LogMessage::operator<<(const StringPiece& value) { + message_ += value.ToString(); + return *this; +} + +LogMessage& LogMessage::operator<<( + const ::google::protobuf::util::Status& status) { + message_ += status.ToString(); + return *this; +} + // Since this is just for logging, we don't care if the current locale changes // the results -- in fact, we probably prefer that. So we use snprintf() // instead of Simple*toa(). diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index 49d16020..34d79f48 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -48,6 +48,26 @@ #include #endif +#undef PROTOBUF_LITTLE_ENDIAN +#ifdef _MSC_VER + #if defined(_M_IX86) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif + #if _MSC_VER >= 1300 + // If MSVC has "/RTCc" set, it will complain about truncating casts at + // runtime. This file contains some intentional truncating casts. + #pragma runtime_checks("c", off) + #endif +#else + #include // __BYTE_ORDER + #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN)) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif +#endif + #ifndef PROTOBUF_USE_EXCEPTIONS #if defined(_MSC_VER) && defined(_CPPUNWIND) #define PROTOBUF_USE_EXCEPTIONS 1 @@ -100,6 +120,12 @@ namespace protobuf { TypeName(const TypeName&); \ void operator=(const TypeName&) +#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS +#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + #if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS) #ifdef LIBPROTOBUF_EXPORTS #define LIBPROTOBUF_EXPORT __declspec(dllexport) @@ -660,6 +686,10 @@ enum LogLevel { #endif }; +class StringPiece; +namespace util { +class Status; +} namespace internal { class LogFinisher; @@ -678,6 +708,8 @@ class LIBPROTOBUF_EXPORT LogMessage { LogMessage& operator<<(unsigned long value); LogMessage& operator<<(double value); LogMessage& operator<<(void* value); + LogMessage& operator<<(const StringPiece& value); + LogMessage& operator<<(const ::google::protobuf::util::Status& status); private: friend class LogFinisher; @@ -696,6 +728,11 @@ class LIBPROTOBUF_EXPORT LogFinisher { void operator=(LogMessage& other); }; +template +bool IsOk(T status) { return status.ok(); } +template<> +inline bool IsOk(bool status) { return status; } + } // namespace internal // Undef everything in case we're being mixed with some other Google library @@ -717,6 +754,7 @@ class LIBPROTOBUF_EXPORT LogFinisher { #undef GOOGLE_DLOG #undef GOOGLE_DCHECK +#undef GOOGLE_DCHECK_OK #undef GOOGLE_DCHECK_EQ #undef GOOGLE_DCHECK_NE #undef GOOGLE_DCHECK_LT @@ -733,7 +771,7 @@ class LIBPROTOBUF_EXPORT LogFinisher { #define GOOGLE_CHECK(EXPRESSION) \ GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " -#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(A) +#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A)) #define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) #define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) #define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) @@ -760,6 +798,7 @@ T* CheckNotNull(const char* /* file */, int /* line */, #define GOOGLE_DLOG GOOGLE_LOG_IF(INFO, false) #define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) +#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E)) #define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B)) #define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B)) #define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B)) @@ -772,6 +811,7 @@ T* CheckNotNull(const char* /* file */, int /* line */, #define GOOGLE_DLOG GOOGLE_LOG #define GOOGLE_DCHECK GOOGLE_CHECK +#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK #define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ #define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE #define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT @@ -883,6 +923,30 @@ class LIBPROTOBUF_EXPORT Closure { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure); }; +template +class LIBPROTOBUF_EXPORT ResultCallback1 { + public: + ResultCallback1() {} + virtual ~ResultCallback1() {} + + virtual R Run(A1) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1); +}; + +template +class LIBPROTOBUF_EXPORT ResultCallback2 { + public: + ResultCallback2() {} + virtual ~ResultCallback2() {} + + virtual R Run(A1,A2) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2); +}; + namespace internal { class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure { @@ -1021,6 +1085,96 @@ class MethodClosure2 : public Closure { Arg2 arg2_; }; +template +class FunctionResultCallback_0_1 : public ResultCallback1 { + public: + typedef R (*FunctionType)(Arg1 arg1); + + FunctionResultCallback_0_1(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionResultCallback_0_1() {} + + R Run(Arg1 a1) { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template +class FunctionResultCallback_1_1 : public ResultCallback1 { + public: + typedef R (*FunctionType)(P1, A1); + + FunctionResultCallback_1_1(FunctionType function, bool self_deleting, + P1 p1) + : function_(function), self_deleting_(self_deleting), p1_(p1) {} + ~FunctionResultCallback_1_1() {} + + R Run(A1 a1) { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(p1_, a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; + P1 p1_; +}; + +// Duplicate this again in the type_traits.h, due to dependency problems. +template struct internal_remove_reference; +template struct internal_remove_reference { typedef T type; }; +template struct internal_remove_reference { typedef T type; }; + +template +struct InternalConstRef { + typedef typename internal_remove_reference::type base_type; + typedef const base_type& type; +}; + +template +class MethodResultCallback_5_2 : public ResultCallback2 { + public: + typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2); + MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting, + P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + method_(method), + self_deleting_(self_deleting), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5) {} + ~MethodResultCallback_5_2() {} + + R Run(A1 a1, A2 a2) { + bool needs_delete = self_deleting_; + R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2); + if (needs_delete) delete this; + return result; + } + + private: + T* object_; + MethodType method_; + bool self_deleting_; + typename internal_remove_reference::type p1_; + typename internal_remove_reference::type p2_; + typename internal_remove_reference::type p3_; + typename internal_remove_reference::type p4_; + typename internal_remove_reference::type p5_; +}; + } // namespace internal // See Closure. @@ -1106,6 +1260,48 @@ inline Closure* NewPermanentCallback( object, method, false, arg1, arg2); } +// See ResultCallback1 +template +inline ResultCallback1* NewCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1(function, true); +} + +// See ResultCallback1 +template +inline ResultCallback1* NewPermanentCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1(function, false); +} + +// See ResultCallback1 +template +inline ResultCallback1* NewCallback(R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1( + function, true, p1); +} + +// See ResultCallback1 +template +inline ResultCallback1* NewPermanentCallback( + R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1( + function, false, p1); +} + +// See MethodResultCallback_5_2 +template +inline ResultCallback2* NewPermanentCallback( + T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2), + typename internal::InternalConstRef::type p1, + typename internal::InternalConstRef::type p2, + typename internal::InternalConstRef::type p3, + typename internal::InternalConstRef::type p4, + typename internal::InternalConstRef::type p5) { + return new internal::MethodResultCallback_5_2(object, function, false, p1, + p2, p3, p4, p5); +} + // A function which does nothing. Useful for creating no-op callbacks, e.g.: // Closure* nothing = NewCallback(&DoNothing); void LIBPROTOBUF_EXPORT DoNothing(); @@ -1225,10 +1421,115 @@ LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); } // namespace internal +// =================================================================== +// from google3/base/port.h + +// The following guarantees declaration of the byte swap functions, and +// defines __BYTE_ORDER for MSVC +#ifdef _MSC_VER +#include // NOLINT(build/include) +#define __BYTE_ORDER __LITTLE_ENDIAN +#define bswap_16(x) _byteswap_ushort(x) +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) +// Mac OS X / Darwin features +#include +#define bswap_16(x) OSSwapInt16(x) +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#elif defined(__GLIBC__) || defined(__CYGWIN__) +#include // IWYU pragma: export + +#else + +static inline uint16 bswap_16(uint16 x) { + return static_cast(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); +} +#define bswap_16(x) bswap_16(x) +static inline uint32 bswap_32(uint32 x) { + return (((x & 0xFF) << 24) | + ((x & 0xFF00) << 8) | + ((x & 0xFF0000) >> 8) | + ((x & 0xFF000000) >> 24)); +} +#define bswap_32(x) bswap_32(x) +static inline uint64 bswap_64(uint64 x) { + return (((x & GG_ULONGLONG(0xFF)) << 56) | + ((x & GG_ULONGLONG(0xFF00)) << 40) | + ((x & GG_ULONGLONG(0xFF0000)) << 24) | + ((x & GG_ULONGLONG(0xFF000000)) << 8) | + ((x & GG_ULONGLONG(0xFF00000000)) >> 8) | + ((x & GG_ULONGLONG(0xFF0000000000)) >> 24) | + ((x & GG_ULONGLONG(0xFF000000000000)) >> 40) | + ((x & GG_ULONGLONG(0xFF00000000000000)) >> 56)); +} +#define bswap_64(x) bswap_64(x) + +#endif + // =================================================================== // from google3/util/endian/endian.h LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); +class BigEndian { + public: +#ifdef PROTOBUF_LITTLE_ENDIAN + + static uint16 FromHost16(uint16 x) { return bswap_16(x); } + static uint16 ToHost16(uint16 x) { return bswap_16(x); } + + static uint32 FromHost32(uint32 x) { return bswap_32(x); } + static uint32 ToHost32(uint32 x) { return bswap_32(x); } + + static uint64 FromHost64(uint64 x) { return bswap_64(x); } + static uint64 ToHost64(uint64 x) { return bswap_64(x); } + + static bool IsLittleEndian() { return true; } + +#else + + static uint16 FromHost16(uint16 x) { return x; } + static uint16 ToHost16(uint16 x) { return x; } + + static uint32 FromHost32(uint32 x) { return x; } + static uint32 ToHost32(uint32 x) { return x; } + + static uint64 FromHost64(uint64 x) { return x; } + static uint64 ToHost64(uint64 x) { return x; } + + static bool IsLittleEndian() { return false; } + +#endif /* ENDIAN */ + + // Functions to do unaligned loads and stores in big-endian order. + static uint16 Load16(const void *p) { + return ToHost16(GOOGLE_UNALIGNED_LOAD16(p)); + } + + static void Store16(void *p, uint16 v) { + GOOGLE_UNALIGNED_STORE16(p, FromHost16(v)); + } + + static uint32 Load32(const void *p) { + return ToHost32(GOOGLE_UNALIGNED_LOAD32(p)); + } + + static void Store32(void *p, uint32 v) { + GOOGLE_UNALIGNED_STORE32(p, FromHost32(v)); + } + + static uint64 Load64(const void *p) { + return ToHost64(GOOGLE_UNALIGNED_LOAD64(p)); + } + + static void Store64(void *p, uint64 v) { + GOOGLE_UNALIGNED_STORE64(p, FromHost64(v)); + } +}; + // =================================================================== // Shutdown support. diff --git a/src/google/protobuf/stubs/mathlimits.cc b/src/google/protobuf/stubs/mathlimits.cc new file mode 100644 index 00000000..0373b2bb --- /dev/null +++ b/src/google/protobuf/stubs/mathlimits.cc @@ -0,0 +1,144 @@ +// 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. + +// All Rights Reserved. +// +// Author: Maxim Lifantsev +// + +#include + +#include + +namespace google { +namespace protobuf { + +// MSVC++ 2005 and older compilers think the header declaration was a +// definition, and erroneously flag these as a duplicate definition. +#if defined(COMPILER_MSVC) || __cpluscplus < 201103L + +#define DEF_COMMON_LIMITS(Type) +#define DEF_UNSIGNED_INT_LIMITS(Type) +#define DEF_SIGNED_INT_LIMITS(Type) +#define DEF_PRECISION_LIMITS(Type) + +#else + +#define DEF_COMMON_LIMITS(Type) \ +const bool MathLimits::kIsSigned; \ +const bool MathLimits::kIsInteger; \ +const int MathLimits::kMin10Exp; \ +const int MathLimits::kMax10Exp; + +#define DEF_UNSIGNED_INT_LIMITS(Type) \ +DEF_COMMON_LIMITS(Type) \ +const Type MathLimits::kPosMin; \ +const Type MathLimits::kPosMax; \ +const Type MathLimits::kMin; \ +const Type MathLimits::kMax; \ +const Type MathLimits::kEpsilon; \ +const Type MathLimits::kStdError; + +#define DEF_SIGNED_INT_LIMITS(Type) \ +DEF_UNSIGNED_INT_LIMITS(Type) \ +const Type MathLimits::kNegMin; \ +const Type MathLimits::kNegMax; + +#define DEF_PRECISION_LIMITS(Type) \ +const int MathLimits::kPrecisionDigits; + +#endif // not COMPILER_MSVC + +// http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format#Double-double_arithmetic +// With some compilers (gcc 4.6.x) on some platforms (powerpc64), +// "long double" is implemented as a pair of double: "double double" format. +// This causes a problem with epsilon (eps). +// eps is the smallest positive number such that 1.0 + eps > 1.0 +// +// Normal format: 1.0 + e = 1.0...01 // N-1 zeros for N fraction bits +// D-D format: 1.0 + e = 1.000...0001 // epsilon can be very small +// +// In the normal format, 1.0 + e has to fit in one stretch of bits. +// The maximum rounding error is half of eps. +// +// In the double-double format, 1.0 + e splits across two doubles: +// 1.0 in the high double, e in the low double, and they do not have to +// be contiguous. The maximum rounding error on a value close to 1.0 is +// much larger than eps. +// +// Some code checks for errors by comparing a computed value to a golden +// value +/- some multiple of the maximum rounding error. The maximum +// rounding error is not available so we use eps as an approximation +// instead. That fails when long double is in the double-double format. +// Therefore, we define kStdError as a multiple of +// max(DBL_EPSILON * DBL_EPSILON, kEpsilon) rather than a multiple of kEpsilon. + +#define DEF_FP_LIMITS(Type, PREFIX) \ +DEF_COMMON_LIMITS(Type) \ +const Type MathLimits::kPosMin = PREFIX##_MIN; \ +const Type MathLimits::kPosMax = PREFIX##_MAX; \ +const Type MathLimits::kMin = -MathLimits::kPosMax; \ +const Type MathLimits::kMax = MathLimits::kPosMax; \ +const Type MathLimits::kNegMin = -MathLimits::kPosMin; \ +const Type MathLimits::kNegMax = -MathLimits::kPosMax; \ +const Type MathLimits::kEpsilon = PREFIX##_EPSILON; \ +/* 32 is 5 bits of mantissa error; should be adequate for common errors */ \ +const Type MathLimits::kStdError = \ + 32 * (DBL_EPSILON * DBL_EPSILON > MathLimits::kEpsilon \ + ? DBL_EPSILON * DBL_EPSILON : MathLimits::kEpsilon); \ +DEF_PRECISION_LIMITS(Type) \ +const Type MathLimits::kNaN = HUGE_VAL - HUGE_VAL; \ +const Type MathLimits::kPosInf = HUGE_VAL; \ +const Type MathLimits::kNegInf = -HUGE_VAL; + +// The following are *not* casts! +DEF_SIGNED_INT_LIMITS(int8) +DEF_SIGNED_INT_LIMITS(int16) // NOLINT(readability/casting) +DEF_SIGNED_INT_LIMITS(int32) // NOLINT(readability/casting) +DEF_SIGNED_INT_LIMITS(int64) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint8) +DEF_UNSIGNED_INT_LIMITS(uint16) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint32) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint64) // NOLINT(readability/casting) + +DEF_SIGNED_INT_LIMITS(long int) +DEF_UNSIGNED_INT_LIMITS(unsigned long int) + +DEF_FP_LIMITS(float, FLT) +DEF_FP_LIMITS(double, DBL) +DEF_FP_LIMITS(long double, LDBL); + +#undef DEF_COMMON_LIMITS +#undef DEF_SIGNED_INT_LIMITS +#undef DEF_UNSIGNED_INT_LIMITS +#undef DEF_FP_LIMITS +#undef DEF_PRECISION_LIMITS +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/mathlimits.h b/src/google/protobuf/stubs/mathlimits.h new file mode 100644 index 00000000..39957d69 --- /dev/null +++ b/src/google/protobuf/stubs/mathlimits.h @@ -0,0 +1,277 @@ +// 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. + +// All Rights Reserved. +// +// Author: Maxim Lifantsev +// +// Useful integer and floating point limits and type traits. +// +// This partially replaces/duplictes numeric_limits<> from . +// We get a Google-style class that we have a greater control over +// and thus can add new features to it or fix whatever happens to be broken in +// numeric_limits for the compilers we use. +// + +#ifndef UTIL_MATH_MATHLIMITS_H__ +#define UTIL_MATH_MATHLIMITS_H__ + +// lacks a lot of prototypes. However, this file needs to +// access old-fashioned isinf et al. Even worse more: this file must not +// include because that breaks the definition of isinf with gcc 4.9. +// +// TODO(mec): after C++11 everywhere, use and std::isinf in this file. +#include +#include + +#include + +// ========================================================================= // + +// Useful integer and floating point limits and type traits. +// This is just for the documentation; +// real members are defined in our specializations below. +namespace google { +namespace protobuf { +template struct MathLimits { + // Type name. + typedef T Type; + // Unsigned version of the Type with the same byte size. + // Same as Type for floating point and unsigned types. + typedef T UnsignedType; + // If the type supports negative values. + static const bool kIsSigned; + // If the type supports only integer values. + static const bool kIsInteger; + // Magnitude-wise smallest representable positive value. + static const Type kPosMin; + // Magnitude-wise largest representable positive value. + static const Type kPosMax; + // Smallest representable value. + static const Type kMin; + // Largest representable value. + static const Type kMax; + // Magnitude-wise smallest representable negative value. + // Present only if kIsSigned. + static const Type kNegMin; + // Magnitude-wise largest representable negative value. + // Present only if kIsSigned. + static const Type kNegMax; + // Smallest integer x such that 10^x is representable. + static const int kMin10Exp; + // Largest integer x such that 10^x is representable. + static const int kMax10Exp; + // Smallest positive value such that Type(1) + kEpsilon != Type(1) + static const Type kEpsilon; + // Typical rounding error that is enough to cover + // a few simple floating-point operations. + // Slightly larger than kEpsilon to account for a few rounding errors. + // Is zero if kIsInteger. + static const Type kStdError; + // Number of decimal digits of mantissa precision. + // Present only if !kIsInteger. + static const int kPrecisionDigits; + // Not a number, i.e. result of 0/0. + // Present only if !kIsInteger. + static const Type kNaN; + // Positive infinity, i.e. result of 1/0. + // Present only if !kIsInteger. + static const Type kPosInf; + // Negative infinity, i.e. result of -1/0. + // Present only if !kIsInteger. + static const Type kNegInf; + + // NOTE: Special floating point values behave + // in a special (but mathematically-logical) way + // in terms of (in)equalty comparison and mathematical operations + // -- see out unittest for examples. + + // Special floating point value testers. + // Present in integer types for convenience. + static bool IsFinite(const Type x); + static bool IsNaN(const Type x); + static bool IsInf(const Type x); + static bool IsPosInf(const Type x); + static bool IsNegInf(const Type x); +}; + +// ========================================================================= // + +// All #define-s below are simply to refactor the declarations of +// MathLimits template specializations. +// They are all #undef-ined below. + +// The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not +// get an overflow while computing the constants. + +#define SIGNED_INT_MAX(Type) \ + (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2))) + +#define SIGNED_INT_MIN(Type) \ + (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2))) + +#define UNSIGNED_INT_MAX(Type) \ + (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1))) + +// Compile-time selected log10-related constants for integer types. +#define SIGNED_MAX_10_EXP(Type) \ + (sizeof(Type) == 1 ? 2 : ( \ + sizeof(Type) == 2 ? 4 : ( \ + sizeof(Type) == 4 ? 9 : ( \ + sizeof(Type) == 8 ? 18 : -1)))) + +#define UNSIGNED_MAX_10_EXP(Type) \ + (sizeof(Type) == 1 ? 2 : ( \ + sizeof(Type) == 2 ? 4 : ( \ + sizeof(Type) == 4 ? 9 : ( \ + sizeof(Type) == 8 ? 19 : -1)))) + +#define DECL_INT_LIMIT_FUNCS \ + static bool IsFinite(const Type /*x*/) { return true; } \ + static bool IsNaN(const Type /*x*/) { return false; } \ + static bool IsInf(const Type /*x*/) { return false; } \ + static bool IsPosInf(const Type /*x*/) { return false; } \ + static bool IsNegInf(const Type /*x*/) { return false; } + +#define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \ +template<> \ +struct MathLimits { \ + typedef IntType Type; \ + typedef UnsignedIntType UnsignedType; \ + static const bool kIsSigned = true; \ + static const bool kIsInteger = true; \ + static const Type kPosMin = 1; \ + static const Type kPosMax = SIGNED_INT_MAX(Type); \ + static const Type kMin = SIGNED_INT_MIN(Type); \ + static const Type kMax = kPosMax; \ + static const Type kNegMin = -1; \ + static const Type kNegMax = kMin; \ + static const int kMin10Exp = 0; \ + static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \ + static const Type kEpsilon = 1; \ + static const Type kStdError = 0; \ + DECL_INT_LIMIT_FUNCS \ +}; + +#define DECL_UNSIGNED_INT_LIMITS(IntType) \ +template<> \ +struct MathLimits { \ + typedef IntType Type; \ + typedef IntType UnsignedType; \ + static const bool kIsSigned = false; \ + static const bool kIsInteger = true; \ + static const Type kPosMin = 1; \ + static const Type kPosMax = UNSIGNED_INT_MAX(Type); \ + static const Type kMin = 0; \ + static const Type kMax = kPosMax; \ + static const int kMin10Exp = 0; \ + static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \ + static const Type kEpsilon = 1; \ + static const Type kStdError = 0; \ + DECL_INT_LIMIT_FUNCS \ +}; + +DECL_SIGNED_INT_LIMITS(signed char, unsigned char) +DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int) +DECL_SIGNED_INT_LIMITS(signed int, unsigned int) +DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int) +DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int) +DECL_UNSIGNED_INT_LIMITS(unsigned char) +DECL_UNSIGNED_INT_LIMITS(unsigned short int) +DECL_UNSIGNED_INT_LIMITS(unsigned int) +DECL_UNSIGNED_INT_LIMITS(unsigned long int) +DECL_UNSIGNED_INT_LIMITS(unsigned long long int) + +#undef DECL_SIGNED_INT_LIMITS +#undef DECL_UNSIGNED_INT_LIMITS +#undef SIGNED_INT_MAX +#undef SIGNED_INT_MIN +#undef UNSIGNED_INT_MAX +#undef SIGNED_MAX_10_EXP +#undef UNSIGNED_MAX_10_EXP +#undef DECL_INT_LIMIT_FUNCS + +// ========================================================================= // +#ifdef WIN32 // Lacks built-in isnan() and isinf() +#define DECL_FP_LIMIT_FUNCS \ + static bool IsFinite(const Type x) { return _finite(x); } \ + static bool IsNaN(const Type x) { return _isnan(x); } \ + static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \ + static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \ + static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; } +#else +#define DECL_FP_LIMIT_FUNCS \ + static bool IsFinite(const Type x) { return !isinf(x) && !isnan(x); } \ + static bool IsNaN(const Type x) { return isnan(x); } \ + static bool IsInf(const Type x) { return isinf(x); } \ + static bool IsPosInf(const Type x) { return isinf(x) && x > 0; } \ + static bool IsNegInf(const Type x) { return isinf(x) && x < 0; } +#endif + +// We can't put floating-point constant values in the header here because +// such constants are not considered to be primitive-type constants by gcc. +// CAVEAT: Hence, they are going to be initialized only during +// the global objects construction time. +#define DECL_FP_LIMITS(FP_Type, PREFIX) \ +template<> \ +struct MathLimits { \ + typedef FP_Type Type; \ + typedef FP_Type UnsignedType; \ + static const bool kIsSigned = true; \ + static const bool kIsInteger = false; \ + static const Type kPosMin; \ + static const Type kPosMax; \ + static const Type kMin; \ + static const Type kMax; \ + static const Type kNegMin; \ + static const Type kNegMax; \ + static const int kMin10Exp = PREFIX##_MIN_10_EXP; \ + static const int kMax10Exp = PREFIX##_MAX_10_EXP; \ + static const Type kEpsilon; \ + static const Type kStdError; \ + static const int kPrecisionDigits = PREFIX##_DIG; \ + static const Type kNaN; \ + static const Type kPosInf; \ + static const Type kNegInf; \ + DECL_FP_LIMIT_FUNCS \ +}; + +DECL_FP_LIMITS(float, FLT) +DECL_FP_LIMITS(double, DBL) +DECL_FP_LIMITS(long double, LDBL) + +#undef DECL_FP_LIMITS +#undef DECL_FP_LIMIT_FUNCS + +// ========================================================================= // +} // namespace protobuf +} // namespace google + +#endif // UTIL_MATH_MATHLIMITS_H__ diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h new file mode 100644 index 00000000..87ca5e91 --- /dev/null +++ b/src/google/protobuf/stubs/mathutil.h @@ -0,0 +1,149 @@ +// 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. +#ifndef GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ +#define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +template +bool IsNan(T value) { + return false; +} +template<> +inline bool IsNan(float value) { return isnan(value); } +template<> +inline bool IsNan(double value) { return isnan(value); } + +template +bool AlmostEquals(T a, T b) { + return a == b; +} +template<> +inline bool AlmostEquals(float a, float b) { + return fabs(a - b) < 32 * FLT_EPSILON; +} + +template<> +inline bool AlmostEquals(double a, double b) { + return fabs(a - b) < 32 * DBL_EPSILON; +} +} // namespace internal + +class MathUtil { + public: + template + static T Sign(T value) { + if (value == T(0) || ::google::protobuf::internal::IsNan(value)) { + return value; + } + return value > T(0) ? value : -value; + } + + template + static bool AlmostEquals(T a, T b) { + return ::google::protobuf::internal::AlmostEquals(a, b); + } + + // Largest of two values. + // Works correctly for special floating point values. + // Note: 0.0 and -0.0 are not differentiated by Max (Max(0.0, -0.0) is -0.0), + // which should be OK because, although they (can) have different + // bit representation, they are observably the same when examined + // with arithmetic and (in)equality operators. + template + static T Max(const T x, const T y) { + return MathLimits::IsNaN(x) || x > y ? x : y; + } + + // Absolute value of x + // Works correctly for unsigned types and + // for special floating point values. + // Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0), + // which should be OK: see the comment for Max above. + template + static T Abs(const T x) { + return x > T(0) ? x : -x; + } + + // Absolute value of the difference between two numbers. + // Works correctly for signed types and special floating point values. + template + static typename MathLimits::UnsignedType AbsDiff(const T x, const T y) { + // Carries out arithmetic as unsigned to avoid overflow. + typedef typename MathLimits::UnsignedType R; + return x > y ? R(x) - R(y) : R(y) - R(x); + } + + // If two (usually floating point) numbers are within a certain + // fraction of their magnitude or within a certain absolute margin of error. + // This is the same as the following but faster: + // WithinFraction(x, y, fraction) || WithinMargin(x, y, margin) + // E.g. WithinFraction(0.0, 1e-10, 1e-5) is false but + // WithinFractionOrMargin(0.0, 1e-10, 1e-5, 1e-5) is true. + template + static bool WithinFractionOrMargin(const T x, const T y, + const T fraction, const T margin); +}; + +template +bool MathUtil::WithinFractionOrMargin(const T x, const T y, + const T fraction, const T margin) { + // Not just "0 <= fraction" to fool the compiler for unsigned types. + GOOGLE_DCHECK((T(0) < fraction || T(0) == fraction) && + fraction < T(1) && + margin >= T(0)); + + // Template specialization will convert the if() condition to a constant, + // which will cause the compiler to generate code for either the "if" part + // or the "then" part. In this way we avoid a compiler warning + // about a potential integer overflow in crosstool v12 (gcc 4.3.1). + if (MathLimits::kIsInteger) { + return x == y; + } else { + // IsFinite checks are to make kPosInf and kNegInf not within fraction + if (!MathLimits::IsFinite(x) && !MathLimits::IsFinite(y)) { + return false; + } + T relative_margin = static_cast(fraction * Max(Abs(x), Abs(y))); + return AbsDiff(x, y) <= Max(margin, relative_margin); + } +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc new file mode 100644 index 00000000..9a68fad4 --- /dev/null +++ b/src/google/protobuf/stubs/status.cc @@ -0,0 +1,133 @@ +// 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 + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace error { +inline string CodeEnumToString(error::Code code) { + switch (code) { + case OK: + return "OK"; + case CANCELLED: + return "CANCELLED"; + case UNKNOWN: + return "UNKNOWN"; + case INVALID_ARGUMENT: + return "INVALID_ARGUMENT"; + case DEADLINE_EXCEEDED: + return "DEADLINE_EXCEEDED"; + case NOT_FOUND: + return "NOT_FOUND"; + case ALREADY_EXISTS: + return "ALREADY_EXISTS"; + case PERMISSION_DENIED: + return "PERMISSION_DENIED"; + case UNAUTHENTICATED: + return "UNAUTHENTICATED"; + case RESOURCE_EXHAUSTED: + return "RESOURCE_EXHAUSTED"; + case FAILED_PRECONDITION: + return "FAILED_PRECONDITION"; + case ABORTED: + return "ABORTED"; + case OUT_OF_RANGE: + return "OUT_OF_RANGE"; + case UNIMPLEMENTED: + return "UNIMPLEMENTED"; + case INTERNAL: + return "INTERNAL"; + case UNAVAILABLE: + return "UNAVAILABLE"; + case DATA_LOSS: + return "DATA_LOSS"; + } + + // No default clause, clang will abort if a code is missing from + // above switch. + return "UNKNOWN"; +} +} // namespace error. + +const Status Status::OK = Status(); +const Status Status::CANCELLED = Status(error::CANCELLED, ""); +const Status Status::UNKNOWN = Status(error::UNKNOWN, ""); + +Status::Status() : error_code_(error::OK) { +} + +Status::Status(error::Code error_code, StringPiece error_message) + : error_code_(error_code) { + if (error_code != error::OK) { + error_message_ = error_message.ToString(); + } +} + +Status::Status(const Status& other) + : error_code_(other.error_code_), error_message_(other.error_message_) { +} + +Status& Status::operator=(const Status& other) { + error_code_ = other.error_code_; + error_message_ = other.error_message_; + return *this; +} + +bool Status::operator==(const Status& x) const { + return error_code_ == x.error_code_ && + error_message_ == x.error_message_; +} + +string Status::ToString() const { + if (error_code_ == error::OK) { + return "OK"; + } else { + if (error_message_.empty()) { + return error::CodeEnumToString(error_code_); + } else { + return error::CodeEnumToString(error_code_) + ":" + + error_message_; + } + } +} + +ostream& operator<<(ostream& os, const Status& x) { + os << x.ToString(); + return os; +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/status.h b/src/google/protobuf/stubs/status.h new file mode 100644 index 00000000..34d6cf12 --- /dev/null +++ b/src/google/protobuf/stubs/status.h @@ -0,0 +1,116 @@ +// 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. +#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUS_H_ + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace error { +// These values must match error codes defined in google/rpc/code.proto. +enum Code { + OK = 0, + CANCELLED = 1, + UNKNOWN = 2, + INVALID_ARGUMENT = 3, + DEADLINE_EXCEEDED = 4, + NOT_FOUND = 5, + ALREADY_EXISTS = 6, + PERMISSION_DENIED = 7, + UNAUTHENTICATED = 16, + RESOURCE_EXHAUSTED = 8, + FAILED_PRECONDITION = 9, + ABORTED = 10, + OUT_OF_RANGE = 11, + UNIMPLEMENTED = 12, + INTERNAL = 13, + UNAVAILABLE = 14, + DATA_LOSS = 15, +}; +} // namespace error + +class Status { + public: + // Creates a "successful" status. + Status(); + + // Create a status in the canonical error space with the specified + // code, and error message. If "code == 0", error_message is + // ignored and a Status object identical to Status::OK is + // constructed. + Status(error::Code error_code, StringPiece error_message); + Status(const Status&); + Status& operator=(const Status& x); + ~Status() {} + + // Some pre-defined Status objects + static const Status OK; // Identical to 0-arg constructor + static const Status CANCELLED; + static const Status UNKNOWN; + + // Accessor + bool ok() const { + return error_code_ == error::OK; + } + int error_code() const { + return error_code_; + } + StringPiece error_message() const { + return error_message_; + } + + bool operator==(const Status& x) const; + bool operator!=(const Status& x) const { + return !operator==(x); + } + + // Return a combination of the error code name and message. + string ToString() const; + + private: + error::Code error_code_; + string error_message_; +}; + +// Prints a human-readable representation of 'x' to 'os'. +ostream& operator<<(ostream& os, const Status& x); + +#define EXPECT_OK(value) EXPECT_TRUE((value).ok()) + +} // namespace util +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/src/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h new file mode 100644 index 00000000..743e79a7 --- /dev/null +++ b/src/google/protobuf/stubs/status_macros.h @@ -0,0 +1,89 @@ +// 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. + +// From: util/task/contrib/status_macros/status_macros.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { + +// Run a command that returns a util::Status. If the called code returns an +// error status, return that status up out of this method too. +// +// Example: +// RETURN_IF_ERROR(DoThings(4)); +#define RETURN_IF_ERROR(expr) \ + do { \ + /* Using _status below to avoid capture problems if expr is "status". */ \ + const ::google::protobuf::util::Status _status = (expr); \ + if (GOOGLE_PREDICT_FALSE(!_status.ok())) return _status; \ + } while (0) + +// Internal helper for concatenating macro values. +#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y +#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y) + +template +Status DoAssignOrReturn(T& lhs, StatusOr result) { + if (result.ok()) { + lhs = result.ValueOrDie(); + } + return result.status(); +} + +#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \ + Status status = DoAssignOrReturn(lhs, (rexpr)); \ + if (GOOGLE_PREDICT_FALSE(!status.ok())) return status; + +// Executes an expression that returns a util::StatusOr, extracting its value +// into the variable defined by lhs (or returning on error). +// +// Example: Assigning to an existing value +// ValueType value; +// ASSIGN_OR_RETURN(value, MaybeGetValue(arg)); +// +// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used +// in a single statement (e.g. as the body of an if statement without {})! +#define ASSIGN_OR_RETURN(lhs, rexpr) \ + ASSIGN_OR_RETURN_IMPL( \ + STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr); + +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc new file mode 100644 index 00000000..c70c33c4 --- /dev/null +++ b/src/google/protobuf/stubs/status_test.cc @@ -0,0 +1,131 @@ +// 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 + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace { +TEST(Status, Empty) { + util::Status status; + EXPECT_EQ(util::error::OK, util::Status::OK.error_code()); + EXPECT_EQ("OK", util::Status::OK.ToString()); +} + +TEST(Status, GenericCodes) { + EXPECT_EQ(util::error::OK, util::Status::OK.error_code()); + EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.error_code()); + EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.error_code()); +} + +TEST(Status, ConstructorZero) { + util::Status status(util::error::OK, "msg"); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("OK", status.ToString()); +} + +TEST(Status, CheckOK) { + util::Status status; + GOOGLE_CHECK_OK(status); + GOOGLE_CHECK_OK(status) << "Failed"; + GOOGLE_DCHECK_OK(status) << "Failed"; +} + +TEST(Status, ErrorMessage) { + util::Status status(util::error::INVALID_ARGUMENT, ""); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("", status.error_message().ToString()); + EXPECT_EQ("INVALID_ARGUMENT", status.ToString()); + status = util::Status(util::error::INVALID_ARGUMENT, "msg"); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("msg", status.error_message().ToString()); + EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString()); + status = util::Status(util::error::OK, "msg"); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("", status.error_message().ToString()); + EXPECT_EQ("OK", status.ToString()); +} + +TEST(Status, Copy) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b(a); + ASSERT_EQ(a.ToString(), b.ToString()); +} + +TEST(Status, Assign) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b; + b = a; + ASSERT_EQ(a.ToString(), b.ToString()); +} + +TEST(Status, AssignEmpty) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b; + a = b; + ASSERT_EQ(string("OK"), a.ToString()); + ASSERT_TRUE(b.ok()); + ASSERT_TRUE(a.ok()); +} + +TEST(Status, EqualsOK) { + ASSERT_EQ(util::Status::OK, util::Status()); +} + +TEST(Status, EqualsSame) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::CANCELLED, "message"); + ASSERT_EQ(a, b); +} + +TEST(Status, EqualsCopy) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = a; + ASSERT_EQ(a, b); +} + +TEST(Status, EqualsDifferentCode) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::UNKNOWN, "message"); + ASSERT_NE(a, b); +} + +TEST(Status, EqualsDifferentMessage) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::CANCELLED, "another"); + ASSERT_NE(a, b); +} +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/statusor.cc b/src/google/protobuf/stubs/statusor.cc new file mode 100644 index 00000000..48d1402a --- /dev/null +++ b/src/google/protobuf/stubs/statusor.cc @@ -0,0 +1,46 @@ +// 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 + +namespace google { +namespace protobuf { +namespace util { +namespace internal { + +void StatusOrHelper::Crash(const Status& status) { + GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error " + << status.ToString(); +} + +} // namespace internal +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/statusor.h b/src/google/protobuf/stubs/statusor.h new file mode 100644 index 00000000..9495107e --- /dev/null +++ b/src/google/protobuf/stubs/statusor.h @@ -0,0 +1,259 @@ +// 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. + +// StatusOr is the union of a Status object and a T +// object. StatusOr models the concept of an object that is either a +// usable value, or an error Status explaining why such a value is +// not present. To this end, StatusOr does not allow its Status +// value to be Status::OK. Further, StatusOr does not allow the +// contained pointer to be NULL. +// +// The primary use-case for StatusOr is as the return value of a +// function which may fail. +// +// Example client usage for a StatusOr, where T is not a pointer: +// +// StatusOr result = DoBigCalculationThatCouldFail(); +// if (result.ok()) { +// float answer = result.ValueOrDie(); +// printf("Big calculation yielded: %f", answer); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr: +// +// StatusOr result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr foo(result.ValueOrDie()); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr>: +// +// StatusOr> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr foo = result.ConsumeValueOrDie(); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example factory implementation returning StatusOr: +// +// StatusOr FooFactory::MakeNewFoo(int arg) { +// if (arg <= 0) { +// return ::util::Status(::util::error::INVALID_ARGUMENT, +// "Arg must be positive"); +// } else { +// return new Foo(arg); +// } +// } +// + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace util { + +template +class StatusOr { + template friend class StatusOr; + + public: + // Construct a new StatusOr with Status::UNKNOWN status + StatusOr(); + + // Construct a new StatusOr with the given non-ok status. After calling + // this constructor, calls to ValueOrDie() will CHECK-fail. + // + // NOTE: Not explicit - we want to use StatusOr as a return + // value, so it is convenient and sensible to be able to do 'return + // Status()' when the return type is StatusOr. + // + // REQUIRES: status != Status::OK. This requirement is DCHECKed. + // In optimized builds, passing Status::OK here will have the effect + // of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const Status& status); // NOLINT + + // Construct a new StatusOr with the given value. If T is a plain pointer, + // value must not be NULL. After calling this constructor, calls to + // ValueOrDie() will succeed, and calls to status() will return OK. + // + // NOTE: Not explicit - we want to use StatusOr as a return type + // so it is convenient and sensible to be able to do 'return T()' + // when when the return type is StatusOr. + // + // REQUIRES: if T is a plain pointer, value != NULL. This requirement is + // DCHECKed. In optimized builds, passing a NULL pointer here will have + // the effect of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const T& value); // NOLINT + + // Copy constructor. + StatusOr(const StatusOr& other); + + // Conversion copy constructor, T must be copy constructible from U + template + StatusOr(const StatusOr& other); + + // Assignment operator. + StatusOr& operator=(const StatusOr& other); + + // Conversion assignment operator, T must be assignable from U + template + StatusOr& operator=(const StatusOr& other); + + // Returns a reference to our status. If this contains a T, then + // returns Status::OK. + const Status& status() const; + + // Returns this->status().ok() + bool ok() const; + + // Returns a reference to our current value, or CHECK-fails if !this->ok(). + // If you need to initialize a T object from the stored value, + // ConsumeValueOrDie() may be more efficient. + const T& ValueOrDie() const; + + private: + Status status_; + T value_; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Implementation details for StatusOr + +namespace internal { + +class StatusOrHelper { + public: + // Move type-agnostic error handling to the .cc. + static void Crash(const util::Status& status); + + // Customized behavior for StatusOr vs. StatusOr + template + struct Specialize; +}; + +template +struct StatusOrHelper::Specialize { + // For non-pointer T, a reference can never be NULL. + static inline bool IsValueNull(const T& t) { return false; } +}; + +template +struct StatusOrHelper::Specialize { + static inline bool IsValueNull(const T* t) { return t == NULL; } +}; + +} // namespace internal + +template +inline StatusOr::StatusOr() + : status_(util::Status::UNKNOWN) { +} + +template +inline StatusOr::StatusOr(const Status& status) { + if (status.ok()) { + status_ = Status(error::INTERNAL, "Status::OK is not a valid argument."); + } else { + status_ = status; + } +} + +template +inline StatusOr::StatusOr(const T& value) { + if (internal::StatusOrHelper::Specialize::IsValueNull(value)) { + status_ = Status(error::INTERNAL, "NULL is not a vaild argument."); + } else { + status_ = Status::OK; + value_ = value; + } +} + +template +inline StatusOr::StatusOr(const StatusOr& other) + : status_(other.status_), value_(other.value_) { +} + +template +inline StatusOr& StatusOr::operator=(const StatusOr& other) { + status_ = other.status_; + value_ = other.value_; + return *this; +} + +template +template +inline StatusOr::StatusOr(const StatusOr& other) + : status_(other.status_), value_(other.value_) { +} + +template +template +inline StatusOr& StatusOr::operator=(const StatusOr& other) { + status_ = other.status_; + value_ = other.value_; + return *this; +} + +template +inline const Status& StatusOr::status() const { + return status_; +} + +template +inline bool StatusOr::ok() const { + return status().ok(); +} + +template +inline const T& StatusOr::ValueOrDie() const { + if (!status_.ok()) { + internal::StatusOrHelper::Crash(status_); + } + return value_; +} +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc new file mode 100644 index 00000000..6e2a9e55 --- /dev/null +++ b/src/google/protobuf/stubs/statusor_test.cc @@ -0,0 +1,274 @@ +// 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 + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace { + +class Base1 { + public: + virtual ~Base1() {} + int pad; +}; + +class Base2 { + public: + virtual ~Base2() {} + int yetotherpad; +}; + +class Derived : public Base1, public Base2 { + public: + virtual ~Derived() {} + int evenmorepad; +}; + +class CopyNoAssign { + public: + explicit CopyNoAssign(int value) : foo(value) {} + CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {} + int foo; + private: + const CopyNoAssign& operator=(const CopyNoAssign&); +}; + +TEST(StatusOr, TestDefaultCtor) { + StatusOr thing; + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::UNKNOWN, thing.status()); +} + +TEST(StatusOr, TestStatusCtor) { + StatusOr thing(Status::CANCELLED); + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::CANCELLED, thing.status()); +} + +TEST(StatusOr, TestValueCtor) { + const int kI = 4; + StatusOr thing(kI); + EXPECT_TRUE(thing.ok()); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusOk) { + const int kI = 4; + StatusOr original(kI); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusNotOk) { + StatusOr original(Status::CANCELLED); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestCopyCtorStatusOKConverting) { + const int kI = 4; + StatusOr original(kI); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusNotOkConverting) { + StatusOr original(Status::CANCELLED); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestAssignmentStatusOk) { + const int kI = 4; + StatusOr source(kI); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestAssignmentStatusNotOk) { + StatusOr source(Status::CANCELLED); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestAssignmentStatusOKConverting) { + const int kI = 4; + StatusOr source(kI); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_DOUBLE_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestAssignmentStatusNotOkConverting) { + StatusOr source(Status::CANCELLED); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestStatus) { + StatusOr good(4); + EXPECT_TRUE(good.ok()); + StatusOr bad(Status::CANCELLED); + EXPECT_FALSE(bad.ok()); + EXPECT_EQ(Status::CANCELLED, bad.status()); +} + +TEST(StatusOr, TestValue) { + const int kI = 4; + StatusOr thing(kI); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestValueConst) { + const int kI = 4; + const StatusOr thing(kI); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerDefaultCtor) { + StatusOr thing; + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::UNKNOWN, thing.status()); +} + +TEST(StatusOr, TestPointerStatusCtor) { + StatusOr thing(Status::CANCELLED); + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::CANCELLED, thing.status()); +} + +TEST(StatusOr, TestPointerValueCtor) { + const int kI = 4; + StatusOr thing(&kI); + EXPECT_TRUE(thing.ok()); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusOk) { + const int kI = 0; + StatusOr original(&kI); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusNotOk) { + StatusOr original(Status::CANCELLED); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) { + Derived derived; + StatusOr original(&derived); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(static_cast(original.ValueOrDie()), + copy.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) { + StatusOr original(Status::CANCELLED); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestPointerAssignmentStatusOk) { + const int kI = 0; + StatusOr source(&kI); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestPointerAssignmentStatusNotOk) { + StatusOr source(Status::CANCELLED); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestPointerAssignmentStatusOKConverting) { + Derived derived; + StatusOr source(&derived); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(static_cast(source.ValueOrDie()), + target.ValueOrDie()); +} + +TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) { + StatusOr source(Status::CANCELLED); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestPointerStatus) { + const int kI = 0; + StatusOr good(&kI); + EXPECT_TRUE(good.ok()); + StatusOr bad(Status::CANCELLED); + EXPECT_EQ(Status::CANCELLED, bad.status()); +} + +TEST(StatusOr, TestPointerValue) { + const int kI = 0; + StatusOr thing(&kI); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerValueConst) { + const int kI = 0; + const StatusOr thing(&kI); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +} // namespace +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/stringpiece.cc b/src/google/protobuf/stubs/stringpiece.cc new file mode 100644 index 00000000..989474b7 --- /dev/null +++ b/src/google/protobuf/stubs/stringpiece.cc @@ -0,0 +1,268 @@ +// 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 + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +std::ostream& operator<<(std::ostream& o, StringPiece piece) { + o.write(piece.data(), piece.size()); + return o; +} + +// Out-of-line error path. +void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) { + GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details; +} + +StringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos) + : ptr_(x.ptr_ + pos), length_(x.length_ - pos) { + GOOGLE_DCHECK_LE(0, pos); + GOOGLE_DCHECK_LE(pos, x.length_); +} + +StringPiece::StringPiece(StringPiece x, + stringpiece_ssize_type pos, + stringpiece_ssize_type len) + : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) { + GOOGLE_DCHECK_LE(0, pos); + GOOGLE_DCHECK_LE(pos, x.length_); + GOOGLE_DCHECK_GE(len, 0); +} + +void StringPiece::CopyToString(string* target) const { + target->assign(ptr_, length_); +} + +void StringPiece::AppendToString(string* target) const { + target->append(ptr_, length_); +} + +bool StringPiece::Consume(StringPiece x) { + if (starts_with(x)) { + ptr_ += x.length_; + length_ -= x.length_; + return true; + } + return false; +} + +bool StringPiece::ConsumeFromEnd(StringPiece x) { + if (ends_with(x)) { + length_ -= x.length_; + return true; + } + return false; +} + +stringpiece_ssize_type StringPiece::copy(char* buf, + size_type n, + size_type pos) const { + stringpiece_ssize_type ret = std::min(length_ - pos, n); + memcpy(buf, ptr_ + pos, ret); + return ret; +} + +bool StringPiece::contains(StringPiece s) const { + return find(s, 0) != npos; +} + +stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const { + if (length_ <= 0 || pos > static_cast(length_)) { + if (length_ == 0 && pos == 0 && s.length_ == 0) return 0; + return npos; + } + const char *result = std::search(ptr_ + pos, ptr_ + length_, + s.ptr_, s.ptr_ + s.length_); + return result == ptr_ + length_ ? npos : result - ptr_; +} + +stringpiece_ssize_type StringPiece::find(char c, size_type pos) const { + if (length_ <= 0 || pos >= static_cast(length_)) { + return npos; + } + const char* result = static_cast( + memchr(ptr_ + pos, c, length_ - pos)); + return result != NULL ? result - ptr_ : npos; +} + +stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const { + if (length_ < s.length_) return npos; + const size_t ulen = length_; + if (s.length_ == 0) return std::min(ulen, pos); + + const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_; + const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); + return result != last ? result - ptr_ : npos; +} + +// Search range is [0..pos] inclusive. If pos == npos, search everything. +stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const { + // Note: memrchr() is not available on Windows. + if (length_ <= 0) return npos; + for (stringpiece_ssize_type i = + std::min(pos, static_cast(length_ - 1)); + i >= 0; --i) { + if (ptr_[i] == c) { + return i; + } + } + return npos; +} + +// For each character in characters_wanted, sets the index corresponding +// to the ASCII code of that character to 1 in table. This is used by +// the find_.*_of methods below to tell whether or not a character is in +// the lookup table in constant time. +// The argument `table' must be an array that is large enough to hold all +// the possible values of an unsigned char. Thus it should be be declared +// as follows: +// bool table[UCHAR_MAX + 1] +static inline void BuildLookupTable(StringPiece characters_wanted, + bool* table) { + const stringpiece_ssize_type length = characters_wanted.length(); + const char* const data = characters_wanted.data(); + for (stringpiece_ssize_type i = 0; i < length; ++i) { + table[static_cast(data[i])] = true; + } +} + +stringpiece_ssize_type StringPiece::find_first_of(StringPiece s, + size_type pos) const { + if (length_ <= 0 || s.length_ <= 0) { + return npos; + } + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_first_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = pos; i < length_; ++i) { + if (lookup[static_cast(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s, + size_type pos) const { + if (length_ <= 0) return npos; + if (s.length_ <= 0) return 0; + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = pos; i < length_; ++i) { + if (!lookup[static_cast(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_first_not_of(char c, + size_type pos) const { + if (length_ <= 0) return npos; + + for (; pos < static_cast(length_); ++pos) { + if (ptr_[pos] != c) { + return pos; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_of(StringPiece s, + size_type pos) const { + if (length_ <= 0 || s.length_ <= 0) return npos; + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_last_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = + std::min(pos, static_cast(length_ - 1)); i >= 0; --i) { + if (lookup[static_cast(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s, + size_type pos) const { + if (length_ <= 0) return npos; + + stringpiece_ssize_type i = std::min(pos, static_cast(length_ - 1)); + if (s.length_ <= 0) return i; + + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (; i >= 0; --i) { + if (!lookup[static_cast(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_not_of(char c, + size_type pos) const { + if (length_ <= 0) return npos; + + for (stringpiece_ssize_type i = + std::min(pos, static_cast(length_ - 1)); i >= 0; --i) { + if (ptr_[i] != c) { + return i; + } + } + return npos; +} + +StringPiece StringPiece::substr(size_type pos, size_type n) const { + if (pos > length_) pos = length_; + if (n > length_ - pos) n = length_ - pos; + return StringPiece(ptr_ + pos, n); +} + +const StringPiece::size_type StringPiece::npos = size_type(-1); + +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/stringpiece.h b/src/google/protobuf/stubs/stringpiece.h new file mode 100644 index 00000000..5d4d5fe4 --- /dev/null +++ b/src/google/protobuf/stubs/stringpiece.h @@ -0,0 +1,437 @@ +// 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. + +// A StringPiece points to part or all of a string, Cord, double-quoted string +// literal, or other string-like object. A StringPiece does *not* own the +// string to which it points. A StringPiece is not null-terminated. +// +// You can use StringPiece as a function or method parameter. A StringPiece +// parameter can receive a double-quoted string literal argument, a "const +// char*" argument, a string argument, or a StringPiece argument with no data +// copying. Systematic use of StringPiece for arguments reduces data +// copies and strlen() calls. +// +// Prefer passing StringPieces by value: +// void MyFunction(StringPiece arg); +// If circumstances require, you may also pass by const reference: +// void MyFunction(const StringPiece& arg); // not preferred +// Both of these have the same lifetime semantics. Passing by value +// generates slightly smaller code. For more discussion, see the thread +// go/stringpiecebyvalue on c-users. +// +// StringPiece is also suitable for local variables if you know that +// the lifetime of the underlying object is longer than the lifetime +// of your StringPiece variable. +// +// Beware of binding a StringPiece to a temporary: +// StringPiece sp = obj.MethodReturningString(); // BAD: lifetime problem +// +// This code is okay: +// string str = obj.MethodReturningString(); // str owns its contents +// StringPiece sp(str); // GOOD, because str outlives sp +// +// StringPiece is sometimes a poor choice for a return value and usually a poor +// choice for a data member. If you do use a StringPiece this way, it is your +// responsibility to ensure that the object pointed to by the StringPiece +// outlives the StringPiece. +// +// A StringPiece may represent just part of a string; thus the name "Piece". +// For example, when splitting a string, vector is a natural data +// type for the output. For another example, a Cord is a non-contiguous, +// potentially very long string-like object. The Cord class has an interface +// that iteratively provides StringPiece objects that point to the +// successive pieces of a Cord object. +// +// A StringPiece is not null-terminated. If you write code that scans a +// StringPiece, you must check its length before reading any characters. +// Common idioms that work on null-terminated strings do not work on +// StringPiece objects. +// +// There are several ways to create a null StringPiece: +// StringPiece() +// StringPiece(NULL) +// StringPiece(NULL, 0) +// For all of the above, sp.data() == NULL, sp.length() == 0, +// and sp.empty() == true. Also, if you create a StringPiece with +// a non-NULL pointer then sp.data() != NULL. Once created, +// sp.data() will stay either NULL or not-NULL, except if you call +// sp.clear() or sp.set(). +// +// Thus, you can use StringPiece(NULL) to signal an out-of-band value +// that is different from other StringPiece values. This is similar +// to the way that const char* p1 = NULL; is different from +// const char* p2 = "";. +// +// There are many ways to create an empty StringPiece: +// StringPiece() +// StringPiece(NULL) +// StringPiece(NULL, 0) +// StringPiece("") +// StringPiece("", 0) +// StringPiece("abcdef", 0) +// StringPiece("abcdef"+6, 0) +// For all of the above, sp.length() will be 0 and sp.empty() will be true. +// For some empty StringPiece values, sp.data() will be NULL. +// For some empty StringPiece values, sp.data() will not be NULL. +// +// Be careful not to confuse: null StringPiece and empty StringPiece. +// The set of empty StringPieces properly includes the set of null StringPieces. +// That is, every null StringPiece is an empty StringPiece, +// but some non-null StringPieces are empty Stringpieces too. +// +// All empty StringPiece values compare equal to each other. +// Even a null StringPieces compares equal to a non-null empty StringPiece: +// StringPiece() == StringPiece("", 0) +// StringPiece(NULL) == StringPiece("abc", 0) +// StringPiece(NULL, 0) == StringPiece("abcdef"+6, 0) +// +// Look carefully at this example: +// StringPiece("") == NULL +// True or false? TRUE, because StringPiece::operator== converts +// the right-hand side from NULL to StringPiece(NULL), +// and then compares two zero-length spans of characters. +// However, we are working to make this example produce a compile error. +// +// Suppose you want to write: +// bool TestWhat?(StringPiece sp) { return sp == NULL; } // BAD +// Do not do that. Write one of these instead: +// bool TestNull(StringPiece sp) { return sp.data() == NULL; } +// bool TestEmpty(StringPiece sp) { return sp.empty(); } +// The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty? +// Right now, TestWhat? behaves likes TestEmpty. +// We are working to make TestWhat? produce a compile error. +// TestNull is good to test for an out-of-band signal. +// TestEmpty is good to test for an empty StringPiece. +// +// Caveats (again): +// (1) The lifetime of the pointed-to string (or piece of a string) +// must be longer than the lifetime of the StringPiece. +// (2) There may or may not be a '\0' character after the end of +// StringPiece data. +// (3) A null StringPiece is empty. +// An empty StringPiece may or may not be a null StringPiece. + +#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ +#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ + +#include +#include +#include +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +// StringPiece has *two* size types. +// StringPiece::size_type +// is unsigned +// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 +// no future changes intended +// stringpiece_ssize_type +// is signed +// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 +// future changes intended: http://go/64BitStringPiece +// +typedef string::difference_type stringpiece_ssize_type; + +// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows. +// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit. +#if !defined(NDEBUG) +#define STRINGPIECE_CHECK_SIZE 1 +#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#define STRINGPIECE_CHECK_SIZE 1 +#else +#define STRINGPIECE_CHECK_SIZE 0 +#endif + +class StringPiece { + private: + const char* ptr_; + stringpiece_ssize_type length_; + + // Prevent overflow in debug mode or fortified mode. + // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t). + static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) { +#if STRINGPIECE_CHECK_SIZE > 0 + if (size > static_cast( + std::numeric_limits::max())) { + // Some people grep for this message in logs + // so take care if you ever change it. + LogFatalSizeTooBig(size, "size_t to int conversion"); + } +#endif + return static_cast(size); + } + + // Out-of-line error path. + static void LogFatalSizeTooBig(size_t size, const char* details); + + public: + // We provide non-explicit singleton constructors so users can pass + // in a "const char*" or a "string" wherever a "StringPiece" is + // expected. + // + // Style guide exception granted: + // http://goto/style-guide-exception-20978288 + StringPiece() : ptr_(NULL), length_(0) {} + + StringPiece(const char* str) // NOLINT(runtime/explicit) + : ptr_(str), length_(0) { + if (str != NULL) { + length_ = CheckedSsizeTFromSizeT(strlen(str)); + } + } + + template + StringPiece( // NOLINT(runtime/explicit) + const std::basic_string, Allocator>& str) + : ptr_(str.data()), length_(0) { + length_ = CheckedSsizeTFromSizeT(str.size()); + } +#if defined(HAS_GLOBAL_STRING) + template + StringPiece( // NOLINT(runtime/explicit) + const basic_string, Allocator>& str) + : ptr_(str.data()), length_(0) { + length_ = CheckedSsizeTFromSizeT(str.size()); + } +#endif + + StringPiece(const char* offset, stringpiece_ssize_type len) + : ptr_(offset), length_(len) { + assert(len >= 0); + } + + // Substring of another StringPiece. + // pos must be non-negative and <= x.length(). + StringPiece(StringPiece x, stringpiece_ssize_type pos); + // Substring of another StringPiece. + // pos must be non-negative and <= x.length(). + // len must be non-negative and will be pinned to at most x.length() - pos. + StringPiece(StringPiece x, + stringpiece_ssize_type pos, + stringpiece_ssize_type len); + + // data() may return a pointer to a buffer with embedded NULs, and the + // returned buffer may or may not be null terminated. Therefore it is + // typically a mistake to pass data() to a routine that expects a NUL + // terminated string. + const char* data() const { return ptr_; } + stringpiece_ssize_type size() const { return length_; } + stringpiece_ssize_type length() const { return length_; } + bool empty() const { return length_ == 0; } + + void clear() { + ptr_ = NULL; + length_ = 0; + } + + void set(const char* data, stringpiece_ssize_type len) { + assert(len >= 0); + ptr_ = data; + length_ = len; + } + + void set(const char* str) { + ptr_ = str; + if (str != NULL) + length_ = CheckedSsizeTFromSizeT(strlen(str)); + else + length_ = 0; + } + + void set(const void* data, stringpiece_ssize_type len) { + ptr_ = reinterpret_cast(data); + length_ = len; + } + + char operator[](stringpiece_ssize_type i) const { + assert(0 <= i); + assert(i < length_); + return ptr_[i]; + } + + void remove_prefix(stringpiece_ssize_type n) { + assert(length_ >= n); + ptr_ += n; + length_ -= n; + } + + void remove_suffix(stringpiece_ssize_type n) { + assert(length_ >= n); + length_ -= n; + } + + // returns {-1, 0, 1} + int compare(StringPiece x) const { + const stringpiece_ssize_type min_size = + length_ < x.length_ ? length_ : x.length_; + int r = memcmp(ptr_, x.ptr_, min_size); + if (r < 0) return -1; + if (r > 0) return 1; + if (length_ < x.length_) return -1; + if (length_ > x.length_) return 1; + return 0; + } + + string as_string() const { + return ToString(); + } + // We also define ToString() here, since many other string-like + // interfaces name the routine that converts to a C++ string + // "ToString", and it's confusing to have the method that does that + // for a StringPiece be called "as_string()". We also leave the + // "as_string()" method defined here for existing code. + string ToString() const { + if (ptr_ == NULL) return string(); + return string(data(), size()); + } + + operator string() const { + return ToString(); + } + + void CopyToString(string* target) const; + void AppendToString(string* target) const; + + bool starts_with(StringPiece x) const { + return (length_ >= x.length_) && (memcmp(ptr_, x.ptr_, x.length_) == 0); + } + + bool ends_with(StringPiece x) const { + return ((length_ >= x.length_) && + (memcmp(ptr_ + (length_-x.length_), x.ptr_, x.length_) == 0)); + } + + // Checks whether StringPiece starts with x and if so advances the beginning + // of it to past the match. It's basically a shortcut for starts_with + // followed by remove_prefix. + bool Consume(StringPiece x); + // Like above but for the end of the string. + bool ConsumeFromEnd(StringPiece x); + + // standard STL container boilerplate + typedef char value_type; + typedef const char* pointer; + typedef const char& reference; + typedef const char& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + static const size_type npos; + typedef const char* const_iterator; + typedef const char* iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + iterator begin() const { return ptr_; } + iterator end() const { return ptr_ + length_; } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(ptr_ + length_); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(ptr_); + } + stringpiece_ssize_type max_size() const { return length_; } + stringpiece_ssize_type capacity() const { return length_; } + + // cpplint.py emits a false positive [build/include_what_you_use] + stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT + + bool contains(StringPiece s) const; + + stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const; + stringpiece_ssize_type find(char c, size_type pos = 0) const; + stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const; + stringpiece_ssize_type rfind(char c, size_type pos = npos) const; + + stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const; + stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const { + return find(c, pos); + } + stringpiece_ssize_type find_first_not_of(StringPiece s, + size_type pos = 0) const; + stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const; + stringpiece_ssize_type find_last_of(StringPiece s, + size_type pos = npos) const; + stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const { + return rfind(c, pos); + } + stringpiece_ssize_type find_last_not_of(StringPiece s, + size_type pos = npos) const; + stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const; + + StringPiece substr(size_type pos, size_type n = npos) const; +}; + +// This large function is defined inline so that in a fairly common case where +// one of the arguments is a literal, the compiler can elide a lot of the +// following comparisons. +inline bool operator==(StringPiece x, StringPiece y) { + stringpiece_ssize_type len = x.size(); + if (len != y.size()) { + return false; + } + + return x.data() == y.data() || len <= 0 || + memcmp(x.data(), y.data(), len) == 0; +} + +inline bool operator!=(StringPiece x, StringPiece y) { + return !(x == y); +} + +inline bool operator<(StringPiece x, StringPiece y) { + const stringpiece_ssize_type min_size = + x.size() < y.size() ? x.size() : y.size(); + const int r = memcmp(x.data(), y.data(), min_size); + return (r < 0) || (r == 0 && x.size() < y.size()); +} + +inline bool operator>(StringPiece x, StringPiece y) { + return y < x; +} + +inline bool operator<=(StringPiece x, StringPiece y) { + return !(x > y); +} + +inline bool operator>=(StringPiece x, StringPiece y) { + return !(x < y); +} + +// allow StringPiece to be logged +extern std::ostream& operator<<(std::ostream& o, StringPiece piece); + +} // namespace protobuf +} // namespace google + +#endif // STRINGS_STRINGPIECE_H_ diff --git a/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc new file mode 100644 index 00000000..9b5dae13 --- /dev/null +++ b/src/google/protobuf/stubs/stringpiece_unittest.cc @@ -0,0 +1,793 @@ +// 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 + +#include +#include +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace { +TEST(StringPiece, Ctor) { + { + // Null. + StringPiece s10; + EXPECT_TRUE(s10.data() == NULL); + EXPECT_EQ(0, s10.length()); + } + + { + // const char* without length. + const char* hello = "hello"; + StringPiece s20(hello); + EXPECT_TRUE(s20.data() == hello); + EXPECT_EQ(5, s20.length()); + + // const char* with length. + StringPiece s21(hello, 4); + EXPECT_TRUE(s21.data() == hello); + EXPECT_EQ(4, s21.length()); + + // Not recommended, but valid C++ + StringPiece s22(hello, 6); + EXPECT_TRUE(s22.data() == hello); + EXPECT_EQ(6, s22.length()); + } + + { + // std::string. + std::string hola = "hola"; + StringPiece s30(hola); + EXPECT_TRUE(s30.data() == hola.data()); + EXPECT_EQ(4, s30.length()); + + // std::string with embedded '\0'. + hola.push_back('\0'); + hola.append("h2"); + hola.push_back('\0'); + StringPiece s31(hola); + EXPECT_TRUE(s31.data() == hola.data()); + EXPECT_EQ(8, s31.length()); + } + +#if defined(HAS_GLOBAL_STRING) + { + // ::string + string bonjour = "bonjour"; + StringPiece s40(bonjour); + EXPECT_TRUE(s40.data() == bonjour.data()); + EXPECT_EQ(7, s40.length()); + } +#endif + + // TODO(mec): StringPiece(StringPiece x, int pos); + // TODO(mec): StringPiece(StringPiece x, int pos, int len); + // TODO(mec): StringPiece(const StringPiece&); +} + +TEST(StringPiece, STLComparator) { + string s1("foo"); + string s2("bar"); + string s3("baz"); + + StringPiece p1(s1); + StringPiece p2(s2); + StringPiece p3(s3); + + typedef std::map TestMap; + TestMap map; + + map.insert(std::make_pair(p1, 0)); + map.insert(std::make_pair(p2, 1)); + map.insert(std::make_pair(p3, 2)); + EXPECT_EQ(map.size(), 3); + + TestMap::const_iterator iter = map.begin(); + EXPECT_EQ(iter->second, 1); + ++iter; + EXPECT_EQ(iter->second, 2); + ++iter; + EXPECT_EQ(iter->second, 0); + ++iter; + EXPECT_TRUE(iter == map.end()); + + TestMap::iterator new_iter = map.find("zot"); + EXPECT_TRUE(new_iter == map.end()); + + new_iter = map.find("bar"); + EXPECT_TRUE(new_iter != map.end()); + + map.erase(new_iter); + EXPECT_EQ(map.size(), 2); + + iter = map.begin(); + EXPECT_EQ(iter->second, 2); + ++iter; + EXPECT_EQ(iter->second, 0); + ++iter; + EXPECT_TRUE(iter == map.end()); +} + +TEST(StringPiece, ComparisonOperators) { +#define COMPARE(result, op, x, y) \ + EXPECT_EQ(result, StringPiece((x)) op StringPiece((y))); \ + EXPECT_EQ(result, StringPiece((x)).compare(StringPiece((y))) op 0) + + COMPARE(true, ==, "", ""); + COMPARE(true, ==, "", NULL); + COMPARE(true, ==, NULL, ""); + COMPARE(true, ==, "a", "a"); + COMPARE(true, ==, "aa", "aa"); + COMPARE(false, ==, "a", ""); + COMPARE(false, ==, "", "a"); + COMPARE(false, ==, "a", "b"); + COMPARE(false, ==, "a", "aa"); + COMPARE(false, ==, "aa", "a"); + + COMPARE(false, !=, "", ""); + COMPARE(false, !=, "a", "a"); + COMPARE(false, !=, "aa", "aa"); + COMPARE(true, !=, "a", ""); + COMPARE(true, !=, "", "a"); + COMPARE(true, !=, "a", "b"); + COMPARE(true, !=, "a", "aa"); + COMPARE(true, !=, "aa", "a"); + + COMPARE(true, <, "a", "b"); + COMPARE(true, <, "a", "aa"); + COMPARE(true, <, "aa", "b"); + COMPARE(true, <, "aa", "bb"); + COMPARE(false, <, "a", "a"); + COMPARE(false, <, "b", "a"); + COMPARE(false, <, "aa", "a"); + COMPARE(false, <, "b", "aa"); + COMPARE(false, <, "bb", "aa"); + + COMPARE(true, <=, "a", "a"); + COMPARE(true, <=, "a", "b"); + COMPARE(true, <=, "a", "aa"); + COMPARE(true, <=, "aa", "b"); + COMPARE(true, <=, "aa", "bb"); + COMPARE(false, <=, "b", "a"); + COMPARE(false, <=, "aa", "a"); + COMPARE(false, <=, "b", "aa"); + COMPARE(false, <=, "bb", "aa"); + + COMPARE(false, >=, "a", "b"); + COMPARE(false, >=, "a", "aa"); + COMPARE(false, >=, "aa", "b"); + COMPARE(false, >=, "aa", "bb"); + COMPARE(true, >=, "a", "a"); + COMPARE(true, >=, "b", "a"); + COMPARE(true, >=, "aa", "a"); + COMPARE(true, >=, "b", "aa"); + COMPARE(true, >=, "bb", "aa"); + + COMPARE(false, >, "a", "a"); + COMPARE(false, >, "a", "b"); + COMPARE(false, >, "a", "aa"); + COMPARE(false, >, "aa", "b"); + COMPARE(false, >, "aa", "bb"); + COMPARE(true, >, "b", "a"); + COMPARE(true, >, "aa", "a"); + COMPARE(true, >, "b", "aa"); + COMPARE(true, >, "bb", "aa"); + + string x; + for (int i = 0; i < 256; i++) { + x += 'a'; + string y = x; + COMPARE(true, ==, x, y); + for (int j = 0; j < i; j++) { + string z = x; + z[j] = 'b'; // Differs in position 'j' + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + if (j + 1 < i) { + z[j + 1] = 'A'; // Differs in position 'j+1' as well + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + z[j + 1] = 'z'; // Differs in position 'j+1' as well + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + } + } + } + +#undef COMPARE +} + +TEST(StringPiece, STL1) { + const StringPiece a("abcdefghijklmnopqrstuvwxyz"); + const StringPiece b("abc"); + const StringPiece c("xyz"); + const StringPiece d("foobar"); + const StringPiece e; + string temp("123"); + temp += '\0'; + temp += "456"; + const StringPiece f(temp); + + EXPECT_EQ(a[6], 'g'); + EXPECT_EQ(b[0], 'a'); + EXPECT_EQ(c[2], 'z'); + EXPECT_EQ(f[3], '\0'); + EXPECT_EQ(f[5], '5'); + + EXPECT_EQ(*d.data(), 'f'); + EXPECT_EQ(d.data()[5], 'r'); + EXPECT_TRUE(e.data() == NULL); + + EXPECT_EQ(*a.begin(), 'a'); + EXPECT_EQ(*(b.begin() + 2), 'c'); + EXPECT_EQ(*(c.end() - 1), 'z'); + + EXPECT_EQ(*a.rbegin(), 'z'); + EXPECT_EQ(*(b.rbegin() + 2), 'a'); + EXPECT_EQ(*(c.rend() - 1), 'x'); + EXPECT_TRUE(a.rbegin() + 26 == a.rend()); + + EXPECT_EQ(a.size(), 26); + EXPECT_EQ(b.size(), 3); + EXPECT_EQ(c.size(), 3); + EXPECT_EQ(d.size(), 6); + EXPECT_EQ(e.size(), 0); + EXPECT_EQ(f.size(), 7); + + EXPECT_TRUE(!d.empty()); + EXPECT_TRUE(d.begin() != d.end()); + EXPECT_TRUE(d.begin() + 6 == d.end()); + + EXPECT_TRUE(e.empty()); + EXPECT_TRUE(e.begin() == e.end()); + + EXPECT_GE(a.max_size(), a.capacity()); + EXPECT_GE(a.capacity(), a.size()); + + char buf[4] = { '%', '%', '%', '%' }; + EXPECT_EQ(a.copy(buf, 4), 4); + EXPECT_EQ(buf[0], a[0]); + EXPECT_EQ(buf[1], a[1]); + EXPECT_EQ(buf[2], a[2]); + EXPECT_EQ(buf[3], a[3]); + EXPECT_EQ(a.copy(buf, 3, 7), 3); + EXPECT_EQ(buf[0], a[7]); + EXPECT_EQ(buf[1], a[8]); + EXPECT_EQ(buf[2], a[9]); + EXPECT_EQ(buf[3], a[3]); + EXPECT_EQ(c.copy(buf, 99), 3); + EXPECT_EQ(buf[0], c[0]); + EXPECT_EQ(buf[1], c[1]); + EXPECT_EQ(buf[2], c[2]); + EXPECT_EQ(buf[3], a[3]); +} + +// Separated from STL1() because some compilers produce an overly +// large stack frame for the combined function. +TEST(StringPiece, STL2) { + const StringPiece a("abcdefghijklmnopqrstuvwxyz"); + const StringPiece b("abc"); + const StringPiece c("xyz"); + StringPiece d("foobar"); + const StringPiece e; + const StringPiece f("123" "\0" "456", 7); + + d.clear(); + EXPECT_EQ(d.size(), 0); + EXPECT_TRUE(d.empty()); + EXPECT_TRUE(d.data() == NULL); + EXPECT_TRUE(d.begin() == d.end()); + + EXPECT_EQ(StringPiece::npos, string::npos); + + EXPECT_EQ(a.find(b), 0); + EXPECT_EQ(a.find(b, 1), StringPiece::npos); + EXPECT_EQ(a.find(c), 23); + EXPECT_EQ(a.find(c, 9), 23); + EXPECT_EQ(a.find(c, StringPiece::npos), StringPiece::npos); + EXPECT_EQ(b.find(c), StringPiece::npos); + EXPECT_EQ(b.find(c, StringPiece::npos), StringPiece::npos); + EXPECT_EQ(a.find(d), 0); + EXPECT_EQ(a.find(e), 0); + EXPECT_EQ(a.find(d, 12), 12); + EXPECT_EQ(a.find(e, 17), 17); + StringPiece g("xx not found bb"); + EXPECT_EQ(a.find(g), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.find(b), StringPiece::npos); + EXPECT_EQ(e.find(b), StringPiece::npos); + EXPECT_EQ(d.find(b, 4), StringPiece::npos); + EXPECT_EQ(e.find(b, 7), StringPiece::npos); + + size_t empty_search_pos = string().find(string()); + EXPECT_EQ(d.find(d), empty_search_pos); + EXPECT_EQ(d.find(e), empty_search_pos); + EXPECT_EQ(e.find(d), empty_search_pos); + EXPECT_EQ(e.find(e), empty_search_pos); + EXPECT_EQ(d.find(d, 4), string().find(string(), 4)); + EXPECT_EQ(d.find(e, 4), string().find(string(), 4)); + EXPECT_EQ(e.find(d, 4), string().find(string(), 4)); + EXPECT_EQ(e.find(e, 4), string().find(string(), 4)); + + EXPECT_EQ(a.find('a'), 0); + EXPECT_EQ(a.find('c'), 2); + EXPECT_EQ(a.find('z'), 25); + EXPECT_EQ(a.find('$'), StringPiece::npos); + EXPECT_EQ(a.find('\0'), StringPiece::npos); + EXPECT_EQ(f.find('\0'), 3); + EXPECT_EQ(f.find('3'), 2); + EXPECT_EQ(f.find('5'), 5); + EXPECT_EQ(g.find('o'), 4); + EXPECT_EQ(g.find('o', 4), 4); + EXPECT_EQ(g.find('o', 5), 8); + EXPECT_EQ(a.find('b', 5), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.find('\0'), StringPiece::npos); + EXPECT_EQ(e.find('\0'), StringPiece::npos); + EXPECT_EQ(d.find('\0', 4), StringPiece::npos); + EXPECT_EQ(e.find('\0', 7), StringPiece::npos); + EXPECT_EQ(d.find('x'), StringPiece::npos); + EXPECT_EQ(e.find('x'), StringPiece::npos); + EXPECT_EQ(d.find('x', 4), StringPiece::npos); + EXPECT_EQ(e.find('x', 7), StringPiece::npos); + + EXPECT_EQ(a.rfind(b), 0); + EXPECT_EQ(a.rfind(b, 1), 0); + EXPECT_EQ(a.rfind(c), 23); + EXPECT_EQ(a.rfind(c, 22), StringPiece::npos); + EXPECT_EQ(a.rfind(c, 1), StringPiece::npos); + EXPECT_EQ(a.rfind(c, 0), StringPiece::npos); + EXPECT_EQ(b.rfind(c), StringPiece::npos); + EXPECT_EQ(b.rfind(c, 0), StringPiece::npos); + EXPECT_EQ(a.rfind(d), a.as_string().rfind(string())); + EXPECT_EQ(a.rfind(e), a.as_string().rfind(string())); + EXPECT_EQ(a.rfind(d, 12), 12); + EXPECT_EQ(a.rfind(e, 17), 17); + EXPECT_EQ(a.rfind(g), StringPiece::npos); + EXPECT_EQ(d.rfind(b), StringPiece::npos); + EXPECT_EQ(e.rfind(b), StringPiece::npos); + EXPECT_EQ(d.rfind(b, 4), StringPiece::npos); + EXPECT_EQ(e.rfind(b, 7), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.rfind(d, 4), string().rfind(string())); + EXPECT_EQ(e.rfind(d, 7), string().rfind(string())); + EXPECT_EQ(d.rfind(e, 4), string().rfind(string())); + EXPECT_EQ(e.rfind(e, 7), string().rfind(string())); + EXPECT_EQ(d.rfind(d), string().rfind(string())); + EXPECT_EQ(e.rfind(d), string().rfind(string())); + EXPECT_EQ(d.rfind(e), string().rfind(string())); + EXPECT_EQ(e.rfind(e), string().rfind(string())); + + EXPECT_EQ(g.rfind('o'), 8); + EXPECT_EQ(g.rfind('q'), StringPiece::npos); + EXPECT_EQ(g.rfind('o', 8), 8); + EXPECT_EQ(g.rfind('o', 7), 4); + EXPECT_EQ(g.rfind('o', 3), StringPiece::npos); + EXPECT_EQ(f.rfind('\0'), 3); + EXPECT_EQ(f.rfind('\0', 12), 3); + EXPECT_EQ(f.rfind('3'), 2); + EXPECT_EQ(f.rfind('5'), 5); + // empty string nonsense + EXPECT_EQ(d.rfind('o'), StringPiece::npos); + EXPECT_EQ(e.rfind('o'), StringPiece::npos); + EXPECT_EQ(d.rfind('o', 4), StringPiece::npos); + EXPECT_EQ(e.rfind('o', 7), StringPiece::npos); + + EXPECT_EQ(a.find_first_of(b), 0); + EXPECT_EQ(a.find_first_of(b, 0), 0); + EXPECT_EQ(a.find_first_of(b, 1), 1); + EXPECT_EQ(a.find_first_of(b, 2), 2); + EXPECT_EQ(a.find_first_of(b, 3), StringPiece::npos); + EXPECT_EQ(a.find_first_of(c), 23); + EXPECT_EQ(a.find_first_of(c, 23), 23); + EXPECT_EQ(a.find_first_of(c, 24), 24); + EXPECT_EQ(a.find_first_of(c, 25), 25); + EXPECT_EQ(a.find_first_of(c, 26), StringPiece::npos); + EXPECT_EQ(g.find_first_of(b), 13); + EXPECT_EQ(g.find_first_of(c), 0); + EXPECT_EQ(a.find_first_of(f), StringPiece::npos); + EXPECT_EQ(f.find_first_of(a), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(a.find_first_of(d), StringPiece::npos); + EXPECT_EQ(a.find_first_of(e), StringPiece::npos); + EXPECT_EQ(d.find_first_of(b), StringPiece::npos); + EXPECT_EQ(e.find_first_of(b), StringPiece::npos); + EXPECT_EQ(d.find_first_of(d), StringPiece::npos); + EXPECT_EQ(e.find_first_of(d), StringPiece::npos); + EXPECT_EQ(d.find_first_of(e), StringPiece::npos); + EXPECT_EQ(e.find_first_of(e), StringPiece::npos); + + EXPECT_EQ(a.find_first_not_of(b), 3); + EXPECT_EQ(a.find_first_not_of(c), 0); + EXPECT_EQ(b.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(c.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(f.find_first_not_of(a), 0); + EXPECT_EQ(a.find_first_not_of(f), 0); + EXPECT_EQ(a.find_first_not_of(d), 0); + EXPECT_EQ(a.find_first_not_of(e), 0); + // empty string nonsense + EXPECT_EQ(d.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of(d), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(d), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of(e), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos); + + StringPiece h("===="); + EXPECT_EQ(h.find_first_not_of('='), StringPiece::npos); + EXPECT_EQ(h.find_first_not_of('=', 3), StringPiece::npos); + EXPECT_EQ(h.find_first_not_of('\0'), 0); + EXPECT_EQ(g.find_first_not_of('x'), 2); + EXPECT_EQ(f.find_first_not_of('\0'), 0); + EXPECT_EQ(f.find_first_not_of('\0', 3), 4); + EXPECT_EQ(f.find_first_not_of('\0', 2), 2); + // empty string nonsense + EXPECT_EQ(d.find_first_not_of('x'), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of('x'), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of('\0'), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos); + + // StringPiece g("xx not found bb"); + StringPiece i("56"); + EXPECT_EQ(h.find_last_of(a), StringPiece::npos); + EXPECT_EQ(g.find_last_of(a), g.size()-1); + EXPECT_EQ(a.find_last_of(b), 2); + EXPECT_EQ(a.find_last_of(c), a.size()-1); + EXPECT_EQ(f.find_last_of(i), 6); + EXPECT_EQ(a.find_last_of('a'), 0); + EXPECT_EQ(a.find_last_of('b'), 1); + EXPECT_EQ(a.find_last_of('z'), 25); + EXPECT_EQ(a.find_last_of('a', 5), 0); + EXPECT_EQ(a.find_last_of('b', 5), 1); + EXPECT_EQ(a.find_last_of('b', 0), StringPiece::npos); + EXPECT_EQ(a.find_last_of('z', 25), 25); + EXPECT_EQ(a.find_last_of('z', 24), StringPiece::npos); + EXPECT_EQ(f.find_last_of(i, 5), 5); + EXPECT_EQ(f.find_last_of(i, 6), 6); + EXPECT_EQ(f.find_last_of(a, 4), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(f.find_last_of(d), StringPiece::npos); + EXPECT_EQ(f.find_last_of(e), StringPiece::npos); + EXPECT_EQ(f.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(d), StringPiece::npos); + EXPECT_EQ(d.find_last_of(e), StringPiece::npos); + EXPECT_EQ(e.find_last_of(d), StringPiece::npos); + EXPECT_EQ(e.find_last_of(e), StringPiece::npos); + EXPECT_EQ(d.find_last_of(f), StringPiece::npos); + EXPECT_EQ(e.find_last_of(f), StringPiece::npos); + EXPECT_EQ(d.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(f, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos); + + EXPECT_EQ(a.find_last_not_of(b), a.size()-1); + EXPECT_EQ(a.find_last_not_of(c), 22); + EXPECT_EQ(b.find_last_not_of(a), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of(b), StringPiece::npos); + EXPECT_EQ(f.find_last_not_of(i), 4); + EXPECT_EQ(a.find_last_not_of(c, 24), 22); + EXPECT_EQ(a.find_last_not_of(b, 3), 3); + EXPECT_EQ(a.find_last_not_of(b, 2), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(f.find_last_not_of(d), f.size()-1); + EXPECT_EQ(f.find_last_not_of(e), f.size()-1); + EXPECT_EQ(f.find_last_not_of(d, 4), 4); + EXPECT_EQ(f.find_last_not_of(e, 4), 4); + EXPECT_EQ(d.find_last_not_of(d), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(e), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(d), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(f), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(d, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(e, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(d, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(f, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(f, 4), StringPiece::npos); + + EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1); + EXPECT_EQ(h.find_last_not_of('='), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of('c'), 1); + EXPECT_EQ(h.find_last_not_of('x', 2), 2); + EXPECT_EQ(h.find_last_not_of('=', 2), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of('b', 1), 0); + // empty string nonsense + EXPECT_EQ(d.find_last_not_of('x'), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of('x'), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of('\0'), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos); + + EXPECT_EQ(a.substr(0, 3), b); + EXPECT_EQ(a.substr(23), c); + EXPECT_EQ(a.substr(23, 3), c); + EXPECT_EQ(a.substr(23, 99), c); + EXPECT_EQ(a.substr(0), a); + EXPECT_EQ(a.substr(3, 2), "de"); + // empty string nonsense + EXPECT_EQ(a.substr(99, 2), e); + EXPECT_EQ(d.substr(99), e); + EXPECT_EQ(d.substr(0, 99), e); + EXPECT_EQ(d.substr(99, 99), e); + // use of npos + EXPECT_EQ(a.substr(0, StringPiece::npos), a); + EXPECT_EQ(a.substr(23, StringPiece::npos), c); + EXPECT_EQ(a.substr(StringPiece::npos, 0), e); + EXPECT_EQ(a.substr(StringPiece::npos, 1), e); + EXPECT_EQ(a.substr(StringPiece::npos, StringPiece::npos), e); + + // Substring constructors. + EXPECT_EQ(StringPiece(a, 0, 3), b); + EXPECT_EQ(StringPiece(a, 23), c); + EXPECT_EQ(StringPiece(a, 23, 3), c); + EXPECT_EQ(StringPiece(a, 23, 99), c); + EXPECT_EQ(StringPiece(a, 0), a); + EXPECT_EQ(StringPiece(a, 3, 2), "de"); + // empty string nonsense + EXPECT_EQ(StringPiece(d, 0, 99), e); + // Verify that they work taking an actual string, not just a StringPiece. + string a2 = a.as_string(); + EXPECT_EQ(StringPiece(a2, 0, 3), b); + EXPECT_EQ(StringPiece(a2, 23), c); + EXPECT_EQ(StringPiece(a2, 23, 3), c); + EXPECT_EQ(StringPiece(a2, 23, 99), c); + EXPECT_EQ(StringPiece(a2, 0), a); + EXPECT_EQ(StringPiece(a2, 3, 2), "de"); +} + +TEST(StringPiece, Custom) { + StringPiece a("foobar"); + string s1("123"); + s1 += '\0'; + s1 += "456"; + StringPiece b(s1); + StringPiece e; + string s2; + + // CopyToString + a.CopyToString(&s2); + EXPECT_EQ(s2.size(), 6); + EXPECT_EQ(s2, "foobar"); + b.CopyToString(&s2); + EXPECT_EQ(s2.size(), 7); + EXPECT_EQ(s1, s2); + e.CopyToString(&s2); + EXPECT_TRUE(s2.empty()); + + // AppendToString + s2.erase(); + a.AppendToString(&s2); + EXPECT_EQ(s2.size(), 6); + EXPECT_EQ(s2, "foobar"); + a.AppendToString(&s2); + EXPECT_EQ(s2.size(), 12); + EXPECT_EQ(s2, "foobarfoobar"); + + // starts_with + EXPECT_TRUE(a.starts_with(a)); + EXPECT_TRUE(a.starts_with("foo")); + EXPECT_TRUE(a.starts_with(e)); + EXPECT_TRUE(b.starts_with(s1)); + EXPECT_TRUE(b.starts_with(b)); + EXPECT_TRUE(b.starts_with(e)); + EXPECT_TRUE(e.starts_with("")); + EXPECT_TRUE(!a.starts_with(b)); + EXPECT_TRUE(!b.starts_with(a)); + EXPECT_TRUE(!e.starts_with(a)); + + // ends with + EXPECT_TRUE(a.ends_with(a)); + EXPECT_TRUE(a.ends_with("bar")); + EXPECT_TRUE(a.ends_with(e)); + EXPECT_TRUE(b.ends_with(s1)); + EXPECT_TRUE(b.ends_with(b)); + EXPECT_TRUE(b.ends_with(e)); + EXPECT_TRUE(e.ends_with("")); + EXPECT_TRUE(!a.ends_with(b)); + EXPECT_TRUE(!b.ends_with(a)); + EXPECT_TRUE(!e.ends_with(a)); + + // remove_prefix + StringPiece c(a); + c.remove_prefix(3); + EXPECT_EQ(c, "bar"); + c = a; + c.remove_prefix(0); + EXPECT_EQ(c, a); + c.remove_prefix(c.size()); + EXPECT_EQ(c, e); + + // remove_suffix + c = a; + c.remove_suffix(3); + EXPECT_EQ(c, "foo"); + c = a; + c.remove_suffix(0); + EXPECT_EQ(c, a); + c.remove_suffix(c.size()); + EXPECT_EQ(c, e); + + // set + c.set("foobar", 6); + EXPECT_EQ(c, a); + c.set("foobar", 0); + EXPECT_EQ(c, e); + c.set("foobar", 7); + EXPECT_NE(c, a); + + c.set("foobar"); + EXPECT_EQ(c, a); + + c.set(static_cast("foobar"), 6); + EXPECT_EQ(c, a); + c.set(static_cast("foobar"), 0); + EXPECT_EQ(c, e); + c.set(static_cast("foobar"), 7); + EXPECT_NE(c, a); + + // as_string + string s3(a.as_string().c_str(), 7); + EXPECT_EQ(c, s3); + string s4(e.as_string()); + EXPECT_TRUE(s4.empty()); + + // ToString + { + string s5(a.ToString().c_str(), 7); + EXPECT_EQ(c, s5); + string s6(e.ToString()); + EXPECT_TRUE(s6.empty()); + } + + // Consume + a.set("foobar"); + EXPECT_TRUE(a.Consume("foo")); + EXPECT_EQ(a, "bar"); + EXPECT_FALSE(a.Consume("foo")); + EXPECT_FALSE(a.Consume("barbar")); + EXPECT_FALSE(a.Consume("ar")); + EXPECT_EQ(a, "bar"); + + a.set("foobar"); + EXPECT_TRUE(a.ConsumeFromEnd("bar")); + EXPECT_EQ(a, "foo"); + EXPECT_FALSE(a.ConsumeFromEnd("bar")); + EXPECT_FALSE(a.ConsumeFromEnd("foofoo")); + EXPECT_FALSE(a.ConsumeFromEnd("fo")); + EXPECT_EQ(a, "foo"); +} + +TEST(StringPiece, Contains) { + StringPiece a("abcdefg"); + StringPiece b("abcd"); + StringPiece c("efg"); + StringPiece d("gh"); + EXPECT_TRUE(a.contains(b)); + EXPECT_TRUE(a.contains(c)); + EXPECT_TRUE(!a.contains(d)); +} + +TEST(StringPiece, NULLInput) { + // we used to crash here, but now we don't. + StringPiece s(NULL); + EXPECT_EQ(s.data(), (const char*)NULL); + EXPECT_EQ(s.size(), 0); + + s.set(NULL); + EXPECT_EQ(s.data(), (const char*)NULL); + EXPECT_EQ(s.size(), 0); + + // .ToString() on a StringPiece with NULL should produce the empty string. + EXPECT_EQ("", s.ToString()); + EXPECT_EQ("", s.as_string()); +} + +TEST(StringPiece, Comparisons2) { + StringPiece abc("abcdefghijklmnopqrstuvwxyz"); + + // check comparison operations on strings longer than 4 bytes. + EXPECT_EQ(abc, StringPiece("abcdefghijklmnopqrstuvwxyz")); + EXPECT_EQ(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyz")), 0); + + EXPECT_LT(abc, StringPiece("abcdefghijklmnopqrstuvwxzz")); + EXPECT_LT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxzz")), 0); + + EXPECT_GT(abc, StringPiece("abcdefghijklmnopqrstuvwxyy")); + EXPECT_GT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyy")), 0); + + // starts_with + EXPECT_TRUE(abc.starts_with(abc)); + EXPECT_TRUE(abc.starts_with("abcdefghijklm")); + EXPECT_TRUE(!abc.starts_with("abcdefguvwxyz")); + + // ends_with + EXPECT_TRUE(abc.ends_with(abc)); + EXPECT_TRUE(!abc.ends_with("abcdefguvwxyz")); + EXPECT_TRUE(abc.ends_with("nopqrstuvwxyz")); +} + +TEST(ComparisonOpsTest, StringCompareNotAmbiguous) { + EXPECT_EQ("hello", string("hello")); + EXPECT_LT("hello", string("world")); +} + +TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) { + EXPECT_EQ(StringPiece("hello"), string("hello")); + EXPECT_EQ("hello", StringPiece("hello")); +} + +TEST(FindOneCharTest, EdgeCases) { + StringPiece a("xxyyyxx"); + + // Set a = "xyyyx". + a.remove_prefix(1); + a.remove_suffix(1); + + EXPECT_EQ(0, a.find('x')); + EXPECT_EQ(0, a.find('x', 0)); + EXPECT_EQ(4, a.find('x', 1)); + EXPECT_EQ(4, a.find('x', 4)); + EXPECT_EQ(StringPiece::npos, a.find('x', 5)); + + EXPECT_EQ(4, a.rfind('x')); + EXPECT_EQ(4, a.rfind('x', 5)); + EXPECT_EQ(4, a.rfind('x', 4)); + EXPECT_EQ(0, a.rfind('x', 3)); + EXPECT_EQ(0, a.rfind('x', 0)); + + // Set a = "yyy". + a.remove_prefix(1); + a.remove_suffix(1); + + EXPECT_EQ(StringPiece::npos, a.find('x')); + EXPECT_EQ(StringPiece::npos, a.rfind('x')); +} + +#ifndef NDEBUG +TEST(NonNegativeLenTest, NonNegativeLen) { + EXPECT_DEATH(StringPiece("xyz", -1), "len >= 0"); +} +#endif // ndef DEBUG + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 7ecc17ee..99e8bf1d 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -31,6 +31,7 @@ // from google3/strings/strutil.cc #include + #include #include // FLT_DIG and DBL_DIG #include @@ -38,6 +39,8 @@ #include #include +#include + #ifdef _WIN32 // MSVC has only _snprintf, not snprintf. // @@ -309,17 +312,6 @@ void JoinStrings(const vector& components, #define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7')) -inline int hex_digit_to_int(char c) { - /* Assume ASCII. */ - assert('0' == 0x30 && 'A' == 0x41 && 'a' == 0x61); - assert(isxdigit(c)); - int x = static_cast(c); - if (x > '9') { - x += 9; - } - return x & 0xf; -} - // Protocol buffers doesn't ever care about errors, but I don't want to remove // the code. #define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false) @@ -652,14 +644,15 @@ inline bool safe_parse_sign(string* text /*inout*/, return true; } -inline bool safe_parse_positive_int( - string text, int32* value_p) { +template +bool safe_parse_positive_int( + string text, IntType* value_p) { int base = 10; - int32 value = 0; - const int32 vmax = std::numeric_limits::max(); + IntType value = 0; + const IntType vmax = std::numeric_limits::max(); assert(vmax > 0); assert(vmax >= base); - const int32 vmax_over_base = vmax / base; + const IntType vmax_over_base = vmax / base; const char* start = text.data(); const char* end = start + text.size(); // loop over digits @@ -685,14 +678,15 @@ inline bool safe_parse_positive_int( return true; } -inline bool safe_parse_negative_int( - string text, int32* value_p) { +template +bool safe_parse_negative_int( + const string& text, IntType* value_p) { int base = 10; - int32 value = 0; - const int32 vmin = std::numeric_limits::min(); + IntType value = 0; + const IntType vmin = std::numeric_limits::min(); assert(vmin < 0); assert(vmin <= 0 - base); - int32 vmin_over_base = vmin / base; + IntType vmin_over_base = vmin / base; // 2003 c++ standard [expr.mul] // "... the sign of the remainder is implementation-defined." // Although (vmin/base)*base + vmin%base is always vmin. @@ -725,7 +719,8 @@ inline bool safe_parse_negative_int( return true; } -bool safe_int(string text, int32* value_p) { +template +bool safe_int_internal(string text, IntType* value_p) { *value_p = 0; bool negative; if (!safe_parse_sign(&text, &negative)) { @@ -738,6 +733,16 @@ bool safe_int(string text, int32* value_p) { } } +template +bool safe_uint_internal(string text, IntType* value_p) { + *value_p = 0; + bool negative; + if (!safe_parse_sign(&text, &negative) || negative) { + return false; + } + return safe_parse_positive_int(text, value_p); +} + // ---------------------------------------------------------------------- // FastIntToBuffer() // FastInt64ToBuffer() @@ -1236,6 +1241,41 @@ char* DoubleToBuffer(double value, char* buffer) { return buffer; } +static int memcasecmp(const char *s1, const char *s2, size_t len) { + const unsigned char *us1 = reinterpret_cast(s1); + const unsigned char *us2 = reinterpret_cast(s2); + + for ( int i = 0; i < len; i++ ) { + const int diff = + static_cast(static_cast(ascii_tolower(us1[i]))) - + static_cast(static_cast(ascii_tolower(us2[i]))); + if (diff != 0) return diff; + } + return 0; +} + +inline bool CaseEqual(StringPiece s1, StringPiece s2) { + if (s1.size() != s2.size()) return false; + return memcasecmp(s1.data(), s2.data(), s1.size()) == 0; +} + +bool safe_strtob(StringPiece str, bool* value) { + GOOGLE_CHECK(value != NULL) << "NULL output boolean given."; + if (CaseEqual(str, "true") || CaseEqual(str, "t") || + CaseEqual(str, "yes") || CaseEqual(str, "y") || + CaseEqual(str, "1")) { + *value = true; + return true; + } + if (CaseEqual(str, "false") || CaseEqual(str, "f") || + CaseEqual(str, "no") || CaseEqual(str, "n") || + CaseEqual(str, "0")) { + *value = false; + return true; + } + return false; +} + bool safe_strtof(const char* str, float* value) { char* endptr; errno = 0; // errno only gets set on errors @@ -1247,6 +1287,34 @@ bool safe_strtof(const char* str, float* value) { return *str != 0 && *endptr == 0 && errno == 0; } +bool safe_strtod(const char* str, double* value) { + char* endptr; + *value = strtod(str, &endptr); + if (endptr != str) { + while (ascii_isspace(*endptr)) ++endptr; + } + // Ignore range errors from strtod. The values it + // returns on underflow and overflow are the right + // fallback in a robust setting. + return *str != '\0' && *endptr == '\0'; +} + +bool safe_strto32(const string& str, int32* value) { + return safe_int_internal(str, value); +} + +bool safe_strtou32(const string& str, uint32* value) { + return safe_uint_internal(str, value); +} + +bool safe_strto64(const string& str, int64* value) { + return safe_int_internal(str, value); +} + +bool safe_strtou64(const string& str, uint64* value) { + return safe_uint_internal(str, value); +} + char* FloatToBuffer(float value, char* buffer) { // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all // platforms these days. Just in case some system exists where FLT_DIG @@ -1518,5 +1586,661 @@ int GlobalReplaceSubstring(const string& substring, return num_replacements; } +int CalculateBase64EscapedLen(int input_len, bool do_padding) { + // Base64 encodes three bytes of input at a time. If the input is not + // divisible by three, we pad as appropriate. + // + // (from http://tools.ietf.org/html/rfc3548) + // Special processing is performed if fewer than 24 bits are available + // at the end of the data being encoded. A full encoding quantum is + // always completed at the end of a quantity. When fewer than 24 input + // bits are available in an input group, zero bits are added (on the + // right) to form an integral number of 6-bit groups. Padding at the + // end of the data is performed using the '=' character. Since all base + // 64 input is an integral number of octets, only the following cases + // can arise: + + + // Base64 encodes each three bytes of input into four bytes of output. + int len = (input_len / 3) * 4; + + if (input_len % 3 == 0) { + // (from http://tools.ietf.org/html/rfc3548) + // (1) the final quantum of encoding input is an integral multiple of 24 + // bits; here, the final unit of encoded output will be an integral + // multiple of 4 characters with no "=" padding, + } else if (input_len % 3 == 1) { + // (from http://tools.ietf.org/html/rfc3548) + // (2) the final quantum of encoding input is exactly 8 bits; here, the + // final unit of encoded output will be two characters followed by two + // "=" padding characters, or + len += 2; + if (do_padding) { + len += 2; + } + } else { // (input_len % 3 == 2) + // (from http://tools.ietf.org/html/rfc3548) + // (3) the final quantum of encoding input is exactly 16 bits; here, the + // final unit of encoded output will be three characters followed by one + // "=" padding character. + len += 3; + if (do_padding) { + len += 1; + } + } + + assert(len >= input_len); // make sure we didn't overflow + return len; +} + +// Base64Escape does padding, so this calculation includes padding. +int CalculateBase64EscapedLen(int input_len) { + return CalculateBase64EscapedLen(input_len, true); +} + +// ---------------------------------------------------------------------- +// int Base64Unescape() - base64 decoder +// int Base64Escape() - base64 encoder +// int WebSafeBase64Unescape() - Google's variation of base64 decoder +// int WebSafeBase64Escape() - Google's variation of base64 encoder +// +// Check out +// http://tools.ietf.org/html/rfc2045 for formal description, but what we +// care about is that... +// Take the encoded stuff in groups of 4 characters and turn each +// character into a code 0 to 63 thus: +// A-Z map to 0 to 25 +// a-z map to 26 to 51 +// 0-9 map to 52 to 61 +// +(- for WebSafe) maps to 62 +// /(_ for WebSafe) maps to 63 +// There will be four numbers, all less than 64 which can be represented +// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively). +// Arrange the 6 digit binary numbers into three bytes as such: +// aaaaaabb bbbbcccc ccdddddd +// Equals signs (one or two) are used at the end of the encoded block to +// indicate that the text was not an integer multiple of three bytes long. +// ---------------------------------------------------------------------- + +int Base64UnescapeInternal(const char *src_param, int szsrc, + char *dest, int szdest, + const signed char* unbase64) { + static const char kPad64Equals = '='; + static const char kPad64Dot = '.'; + + int decode = 0; + int destidx = 0; + int state = 0; + unsigned int ch = 0; + unsigned int temp = 0; + + // If "char" is signed by default, using *src as an array index results in + // accessing negative array elements. Treat the input as a pointer to + // unsigned char to avoid this. + const unsigned char *src = reinterpret_cast(src_param); + + // The GET_INPUT macro gets the next input character, skipping + // over any whitespace, and stopping when we reach the end of the + // string or when we read any non-data character. The arguments are + // an arbitrary identifier (used as a label for goto) and the number + // of data bytes that must remain in the input to avoid aborting the + // loop. +#define GET_INPUT(label, remain) \ + label: \ + --szsrc; \ + ch = *src++; \ + decode = unbase64[ch]; \ + if (decode < 0) { \ + if (ascii_isspace(ch) && szsrc >= remain) \ + goto label; \ + state = 4 - remain; \ + break; \ + } + + // if dest is null, we're just checking to see if it's legal input + // rather than producing output. (I suspect this could just be done + // with a regexp...). We duplicate the loop so this test can be + // outside it instead of in every iteration. + + if (dest) { + // This loop consumes 4 input bytes and produces 3 output bytes + // per iteration. We can't know at the start that there is enough + // data left in the string for a full iteration, so the loop may + // break out in the middle; if so 'state' will be set to the + // number of input bytes read. + + while (szsrc >= 4) { + // We'll start by optimistically assuming that the next four + // bytes of the string (src[0..3]) are four good data bytes + // (that is, no nulls, whitespace, padding chars, or illegal + // chars). We need to test src[0..2] for nulls individually + // before constructing temp to preserve the property that we + // never read past a null in the string (no matter how long + // szsrc claims the string is). + + if (!src[0] || !src[1] || !src[2] || + (temp = ((unsigned(unbase64[src[0]]) << 18) | + (unsigned(unbase64[src[1]]) << 12) | + (unsigned(unbase64[src[2]]) << 6) | + (unsigned(unbase64[src[3]])))) & 0x80000000) { + // Iff any of those four characters was bad (null, illegal, + // whitespace, padding), then temp's high bit will be set + // (because unbase64[] is -1 for all bad characters). + // + // We'll back up and resort to the slower decoder, which knows + // how to handle those cases. + + GET_INPUT(first, 4); + temp = decode; + GET_INPUT(second, 3); + temp = (temp << 6) | decode; + GET_INPUT(third, 2); + temp = (temp << 6) | decode; + GET_INPUT(fourth, 1); + temp = (temp << 6) | decode; + } else { + // We really did have four good data bytes, so advance four + // characters in the string. + + szsrc -= 4; + src += 4; + decode = -1; + ch = '\0'; + } + + // temp has 24 bits of input, so write that out as three bytes. + + if (destidx+3 > szdest) return -1; + dest[destidx+2] = temp; + temp >>= 8; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + destidx += 3; + } + } else { + while (szsrc >= 4) { + if (!src[0] || !src[1] || !src[2] || + (temp = ((unsigned(unbase64[src[0]]) << 18) | + (unsigned(unbase64[src[1]]) << 12) | + (unsigned(unbase64[src[2]]) << 6) | + (unsigned(unbase64[src[3]])))) & 0x80000000) { + GET_INPUT(first_no_dest, 4); + GET_INPUT(second_no_dest, 3); + GET_INPUT(third_no_dest, 2); + GET_INPUT(fourth_no_dest, 1); + } else { + szsrc -= 4; + src += 4; + decode = -1; + ch = '\0'; + } + destidx += 3; + } + } + +#undef GET_INPUT + + // if the loop terminated because we read a bad character, return + // now. + if (decode < 0 && ch != '\0' && + ch != kPad64Equals && ch != kPad64Dot && !ascii_isspace(ch)) + return -1; + + if (ch == kPad64Equals || ch == kPad64Dot) { + // if we stopped by hitting an '=' or '.', un-read that character -- we'll + // look at it again when we count to check for the proper number of + // equals signs at the end. + ++szsrc; + --src; + } else { + // This loop consumes 1 input byte per iteration. It's used to + // clean up the 0-3 input bytes remaining when the first, faster + // loop finishes. 'temp' contains the data from 'state' input + // characters read by the first loop. + while (szsrc > 0) { + --szsrc; + ch = *src++; + decode = unbase64[ch]; + if (decode < 0) { + if (ascii_isspace(ch)) { + continue; + } else if (ch == '\0') { + break; + } else if (ch == kPad64Equals || ch == kPad64Dot) { + // back up one character; we'll read it again when we check + // for the correct number of pad characters at the end. + ++szsrc; + --src; + break; + } else { + return -1; + } + } + + // Each input character gives us six bits of output. + temp = (temp << 6) | decode; + ++state; + if (state == 4) { + // If we've accumulated 24 bits of output, write that out as + // three bytes. + if (dest) { + if (destidx+3 > szdest) return -1; + dest[destidx+2] = temp; + temp >>= 8; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + } + destidx += 3; + state = 0; + temp = 0; + } + } + } + + // Process the leftover data contained in 'temp' at the end of the input. + int expected_equals = 0; + switch (state) { + case 0: + // Nothing left over; output is a multiple of 3 bytes. + break; + + case 1: + // Bad input; we have 6 bits left over. + return -1; + + case 2: + // Produce one more output byte from the 12 input bits we have left. + if (dest) { + if (destidx+1 > szdest) return -1; + temp >>= 4; + dest[destidx] = temp; + } + ++destidx; + expected_equals = 2; + break; + + case 3: + // Produce two more output bytes from the 18 input bits we have left. + if (dest) { + if (destidx+2 > szdest) return -1; + temp >>= 2; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + } + destidx += 2; + expected_equals = 1; + break; + + default: + // state should have no other values at this point. + GOOGLE_LOG(FATAL) << "This can't happen; base64 decoder state = " << state; + } + + // The remainder of the string should be all whitespace, mixed with + // exactly 0 equals signs, or exactly 'expected_equals' equals + // signs. (Always accepting 0 equals signs is a google extension + // not covered in the RFC, as is accepting dot as the pad character.) + + int equals = 0; + while (szsrc > 0 && *src) { + if (*src == kPad64Equals || *src == kPad64Dot) + ++equals; + else if (!ascii_isspace(*src)) + return -1; + --szsrc; + ++src; + } + + return (equals == 0 || equals == expected_equals) ? destidx : -1; +} + +// The arrays below were generated by the following code +// #include +// #include +// #include +// main() +// { +// static const char Base64[] = +// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +// char *pos; +// int idx, i, j; +// printf(" "); +// for (i = 0; i < 255; i += 8) { +// for (j = i; j < i + 8; j++) { +// pos = strchr(Base64, j); +// if ((pos == NULL) || (j == 0)) +// idx = -1; +// else +// idx = pos - Base64; +// if (idx == -1) +// printf(" %2d, ", idx); +// else +// printf(" %2d/*%c*/,", idx, j); +// } +// printf("\n "); +// } +// } +// +// where the value of "Base64[]" was replaced by one of the base-64 conversion +// tables from the functions below. +static const signed char kUnBase64[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, + -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1, + -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; +static const signed char kUnWebSafeBase64[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 62/*-*/, -1, -1, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, + -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/, + -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) { + return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64); +} + +static bool Base64UnescapeInternal(const char* src, int slen, string* dest, + const signed char* unbase64) { + // Determine the size of the output string. Base64 encodes every 3 bytes into + // 4 characters. any leftover chars are added directly for good measure. + // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548 + const int dest_len = 3 * (slen / 4) + (slen % 4); + + dest->resize(dest_len); + + // We are getting the destination buffer by getting the beginning of the + // string and converting it into a char *. + const int len = Base64UnescapeInternal(src, slen, string_as_array(dest), + dest_len, unbase64); + if (len < 0) { + dest->clear(); + return false; + } + + // could be shorter if there was padding + GOOGLE_DCHECK_LE(len, dest_len); + dest->erase(len); + + return true; +} + +bool Base64Unescape(StringPiece src, string* dest) { + return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64); +} + +bool WebSafeBase64Unescape(StringPiece src, string* dest) { + return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64); +} + +int Base64EscapeInternal(const unsigned char *src, int szsrc, + char *dest, int szdest, const char *base64, + bool do_padding) { + static const char kPad64 = '='; + + if (szsrc <= 0) return 0; + + if (szsrc * 4 > szdest * 3) return 0; + + char *cur_dest = dest; + const unsigned char *cur_src = src; + + char *limit_dest = dest + szdest; + const unsigned char *limit_src = src + szsrc; + + // Three bytes of data encodes to four characters of cyphertext. + // So we can pump through three-byte chunks atomically. + while (cur_src < limit_src - 3) { // keep going as long as we have >= 32 bits + uint32 in = BigEndian::Load32(cur_src) >> 8; + + cur_dest[0] = base64[in >> 18]; + in &= 0x3FFFF; + cur_dest[1] = base64[in >> 12]; + in &= 0xFFF; + cur_dest[2] = base64[in >> 6]; + in &= 0x3F; + cur_dest[3] = base64[in]; + + cur_dest += 4; + cur_src += 3; + } + // To save time, we didn't update szdest or szsrc in the loop. So do it now. + szdest = limit_dest - cur_dest; + szsrc = limit_src - cur_src; + + /* now deal with the tail (<=3 bytes) */ + switch (szsrc) { + case 0: + // Nothing left; nothing more to do. + break; + case 1: { + // One byte left: this encodes to two characters, and (optionally) + // two pad characters to round out the four-character cypherblock. + if ((szdest -= 2) < 0) return 0; + uint32 in = cur_src[0]; + cur_dest[0] = base64[in >> 2]; + in &= 0x3; + cur_dest[1] = base64[in << 4]; + cur_dest += 2; + if (do_padding) { + if ((szdest -= 2) < 0) return 0; + cur_dest[0] = kPad64; + cur_dest[1] = kPad64; + cur_dest += 2; + } + break; + } + case 2: { + // Two bytes left: this encodes to three characters, and (optionally) + // one pad character to round out the four-character cypherblock. + if ((szdest -= 3) < 0) return 0; + uint32 in = BigEndian::Load16(cur_src); + cur_dest[0] = base64[in >> 10]; + in &= 0x3FF; + cur_dest[1] = base64[in >> 4]; + in &= 0x00F; + cur_dest[2] = base64[in << 2]; + cur_dest += 3; + if (do_padding) { + if ((szdest -= 1) < 0) return 0; + cur_dest[0] = kPad64; + cur_dest += 1; + } + break; + } + case 3: { + // Three bytes left: same as in the big loop above. We can't do this in + // the loop because the loop above always reads 4 bytes, and the fourth + // byte is past the end of the input. + if ((szdest -= 4) < 0) return 0; + uint32 in = (cur_src[0] << 16) + BigEndian::Load16(cur_src + 1); + cur_dest[0] = base64[in >> 18]; + in &= 0x3FFFF; + cur_dest[1] = base64[in >> 12]; + in &= 0xFFF; + cur_dest[2] = base64[in >> 6]; + in &= 0x3F; + cur_dest[3] = base64[in]; + cur_dest += 4; + break; + } + default: + // Should not be reached: blocks of 4 bytes are handled + // in the while loop before this switch statement. + GOOGLE_LOG(FATAL) << "Logic problem? szsrc = " << szsrc; + break; + } + return (cur_dest - dest); +} + +static const char kBase64Chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const char kWebSafeBase64Chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) { + return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true); +} +int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest, + int szdest, bool do_padding) { + return Base64EscapeInternal(src, szsrc, dest, szdest, + kWebSafeBase64Chars, do_padding); +} + +void Base64EscapeInternal(const unsigned char* src, int szsrc, + string* dest, bool do_padding, + const char* base64_chars) { + const int calc_escaped_size = + CalculateBase64EscapedLen(szsrc, do_padding); + dest->resize(calc_escaped_size); + const int escaped_len = Base64EscapeInternal(src, szsrc, + string_as_array(dest), + dest->size(), + base64_chars, + do_padding); + GOOGLE_DCHECK_EQ(calc_escaped_size, escaped_len); + dest->erase(escaped_len); +} + +void Base64Escape(const unsigned char *src, int szsrc, + string* dest, bool do_padding) { + Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars); +} + +void WebSafeBase64Escape(const unsigned char *src, int szsrc, + string *dest, bool do_padding) { + Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars); +} + +void Base64Escape(StringPiece src, string* dest) { + Base64Escape(reinterpret_cast(src.data()), + src.size(), dest, true); +} + +void WebSafeBase64Escape(StringPiece src, string* dest) { + WebSafeBase64Escape(reinterpret_cast(src.data()), + src.size(), dest, false); +} + +void WebSafeBase64EscapeWithPadding(StringPiece src, string* dest) { + WebSafeBase64Escape(reinterpret_cast(src.data()), + src.size(), dest, true); +} + +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. +int EncodeAsUTF8Char(uint32 code_point, char* output) { + uint32 tmp = 0; + int len = 0; + if (code_point <= 0x7f) { + tmp = code_point; + len = 1; + } else if (code_point <= 0x07ff) { + tmp = 0x0000c080 | + ((code_point & 0x07c0) << 2) | + (code_point & 0x003f); + len = 2; + } else if (code_point <= 0xffff) { + tmp = 0x00e08080 | + ((code_point & 0xf000) << 4) | + ((code_point & 0x0fc0) << 2) | + (code_point & 0x003f); + len = 3; + } else { + // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is + // normally only defined up to there as well. + tmp = 0xf0808080 | + ((code_point & 0x1c0000) << 6) | + ((code_point & 0x03f000) << 4) | + ((code_point & 0x000fc0) << 2) | + (code_point & 0x003f); + len = 4; + } + tmp = ghtonl(tmp); + memcpy(output, reinterpret_cast(&tmp) + sizeof(tmp) - len, len); + return len; +} + +// Table of UTF-8 character lengths, based on first byte +static const unsigned char kUTF8LenTbl[256] = { + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4 +}; + +// Return length of a single UTF-8 source character +int UTF8FirstLetterNumBytes(const char* src, int len) { + if (len == 0) { + return 0; + } + return kUTF8LenTbl[*reinterpret_cast(src)]; +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index 397122ef..b22066b6 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace google { namespace protobuf { @@ -72,7 +73,33 @@ inline bool ascii_isdigit(char c) { } inline bool ascii_isspace(char c) { - return c == ' '; + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || + c == '\r'; +} + +inline bool ascii_isupper(char c) { + return c >= 'A' && c <= 'Z'; +} + +inline bool ascii_islower(char c) { + return c >= 'a' && c <= 'z'; +} + +inline char ascii_toupper(char c) { + return ascii_islower(c) ? c - ('a' - 'A') : c; +} + +inline char ascii_tolower(char c) { + return ascii_isupper(c) ? c + ('a' - 'A') : c; +} + +inline int hex_digit_to_int(char c) { + /* Assume ASCII. */ + int x = static_cast(c); + if (x > '9') { + x += 9; + } + return x & 0xf; } // ---------------------------------------------------------------------- @@ -360,12 +387,59 @@ inline uint64 strtou64(const char *nptr, char **endptr, int base) { } // ---------------------------------------------------------------------- +// safe_strtob() // safe_strto32() -// ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT bool safe_int(string text, int32* value_p); +// safe_strtou32() +// safe_strto64() +// safe_strtou64() +// safe_strtof() +// safe_strtod() +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value); + +LIBPROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value); +LIBPROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value); +inline bool safe_strto32(const char* str, int32* value) { + return safe_strto32(string(str), value); +} +inline bool safe_strto32(StringPiece str, int32* value) { + return safe_strto32(str.ToString(), value); +} +inline bool safe_strtou32(const char* str, uint32* value) { + return safe_strtou32(string(str), value); +} +inline bool safe_strtou32(StringPiece str, uint32* value) { + return safe_strtou32(str.ToString(), value); +} -inline bool safe_strto32(string text, int32* value) { - return safe_int(text, value); +LIBPROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value); +LIBPROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value); +inline bool safe_strto64(const char* str, int64* value) { + return safe_strto64(string(str), value); +} +inline bool safe_strto64(StringPiece str, int64* value) { + return safe_strto64(str.ToString(), value); +} +inline bool safe_strtou64(const char* str, uint64* value) { + return safe_strtou64(string(str), value); +} +inline bool safe_strtou64(StringPiece str, uint64* value) { + return safe_strtou64(str.ToString(), value); +} + +LIBPROTOBUF_EXPORT bool safe_strtof(const char* str, float* value); +LIBPROTOBUF_EXPORT bool safe_strtod(const char* str, double* value); +inline bool safe_strtof(const string& str, float* value) { + return safe_strtof(str.c_str(), value); +} +inline bool safe_strtod(const string& str, double* value) { + return safe_strtod(str.c_str(), value); +} +inline bool safe_strtof(StringPiece str, float* value) { + return safe_strtof(str.ToString(), value); +} +inline bool safe_strtod(StringPiece str, double* value) { + return safe_strtod(str.ToString(), value); } // ---------------------------------------------------------------------- @@ -451,6 +525,10 @@ inline char* FastUInt64ToBuffer(uint64 i, char* buffer) { return buffer; } +inline string SimpleBtoa(bool value) { + return value ? "true" : "false"; +} + // ---------------------------------------------------------------------- // SimpleItoa() // Description: converts an integer to a string. @@ -497,28 +575,30 @@ static const int kFloatToBufferSize = 24; namespace strings { +enum PadSpec { + NO_PAD = 1, + ZERO_PAD_2, + ZERO_PAD_3, + ZERO_PAD_4, + ZERO_PAD_5, + ZERO_PAD_6, + ZERO_PAD_7, + ZERO_PAD_8, + ZERO_PAD_9, + ZERO_PAD_10, + ZERO_PAD_11, + ZERO_PAD_12, + ZERO_PAD_13, + ZERO_PAD_14, + ZERO_PAD_15, + ZERO_PAD_16, +}; + struct Hex { uint64 value; - enum PadSpec { - NONE = 1, - ZERO_PAD_2, - ZERO_PAD_3, - ZERO_PAD_4, - ZERO_PAD_5, - ZERO_PAD_6, - ZERO_PAD_7, - ZERO_PAD_8, - ZERO_PAD_9, - ZERO_PAD_10, - ZERO_PAD_11, - ZERO_PAD_12, - ZERO_PAD_13, - ZERO_PAD_14, - ZERO_PAD_15, - ZERO_PAD_16, - } spec; + enum PadSpec spec; template - explicit Hex(Int v, PadSpec s = NONE) + explicit Hex(Int v, PadSpec s = NO_PAD) : spec(s) { // Prevent sign-extension by casting integers to // their unsigned counterparts. @@ -571,6 +651,9 @@ struct LIBPROTOBUF_EXPORT AlphaNum { AlphaNum(const string& str) : piece_data_(str.data()), piece_size_(str.size()) {} + AlphaNum(StringPiece str) + : piece_data_(str.data()), piece_size_(str.size()) {} + size_t size() const { return piece_size_; } const char *data() const { return piece_data_; } @@ -691,6 +774,12 @@ string Join(const Range& components, return result; } +// ---------------------------------------------------------------------- +// ToHex() +// Return a lower-case hex string representation of the given integer. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT string ToHex(uint64 num); + // ---------------------------------------------------------------------- // GlobalReplaceSubstring() // Replaces all instances of a substring in a string. Does nothing @@ -702,6 +791,83 @@ LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring, const string& replacement, string* s); +// ---------------------------------------------------------------------- +// Base64Unescape() +// Converts "src" which is encoded in Base64 to its binary equivalent and +// writes it to "dest". If src contains invalid characters, dest is cleared +// and the function returns false. Returns true on success. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest); + +// ---------------------------------------------------------------------- +// WebSafeBase64Unescape() +// This is a variation of Base64Unescape which uses '-' instead of '+', and +// '_' instead of '/'. src is not null terminated, instead specify len. I +// recommend that slen(base64_tests[i].plaintext); + + StringPiece plaintext(base64_tests[i].plaintext, + base64_tests[i].plain_length); + + cypher_length = strlen(base64_tests[i].cyphertext); + + // The basic escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = Base64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer)); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + // Would it have been okay to allocate only CalculateBase64EscapeLen()? + EXPECT_EQ(CalculateBase64EscapedLen(base64_tests[i].plain_length), + encode_length); + + // Is it the expected encoded value? + EXPECT_STREQ(encode_buffer, base64_tests[i].cyphertext); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = Base64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, base64_tests[i].cyphertext); + + // If we decode it back: + decode_str.clear(); + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, cypher_length), &decode_str)); + + // Is it of the expected length? + EXPECT_EQ(base64_tests[i].plain_length, decode_str.length()); + + // Is it the expected decoded value? + EXPECT_EQ(plaintext, decode_str); + + // Let's try with a pre-populated string. + string encoded("this junk should be ignored"); + Base64Escape(string(base64_tests[i].plaintext, + base64_tests[i].plain_length), + &encoded); + EXPECT_EQ(encoded, string(encode_buffer, cypher_length)); + + string decoded("this junk should be ignored"); + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Our decoder treats the padding '=' characters at the end as + // optional (but if there are any, there must be the correct + // number of them.) If encode_buffer has any, run some additional + // tests that fiddle with them. + char* first_equals = strchr(encode_buffer, '='); + if (first_equals) { + // How many equals signs does the string start with? + int equals = (*(first_equals+1) == '=') ? 2 : 1; + + // Try chopping off the equals sign(s) entirely. The decoder + // should still be okay with this. + string decoded2("this junk should also be ignored"); + *first_equals = '\0'; + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Now test chopping off the equals sign(s) and adding + // whitespace. Our decoder should still accept this. + decoded2.assign("this junk should be ignored"); + *first_equals = ' '; + *(first_equals+1) = '\0'; + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer + 1), + &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Now stick a bad character at the end of the string. The decoder + // should refuse this string. + decoded2.assign("this junk should be ignored"); + *first_equals = '?'; + *(first_equals+1) = '\0'; + EXPECT_TRUE( + !Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer + 1), + &decoded2)); + + int len; + + // Test whitespace mixed with the padding. (eg "AA = = ") The + // decoder should accept this. + if (equals == 2) { + snprintf(first_equals, 6, " = = "); + len = first_equals - encode_buffer + 5; + } else { + snprintf(first_equals, 6, " = "); + len = first_equals - encode_buffer + 3; + } + decoded2.assign("this junk should be ignored"); + EXPECT_TRUE( + Base64Unescape(StringPiece(encode_buffer, len), &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Test whitespace mixed with the padding, but with the wrong + // number of equals signs (eg "AA = "). The decoder should + // refuse these strings. + if (equals == 1) { + snprintf(first_equals, 6, " = = "); + len = first_equals - encode_buffer + 5; + } else { + snprintf(first_equals, 6, " = "); + len = first_equals - encode_buffer + 3; + } + EXPECT_TRUE( + !Base64Unescape(StringPiece(encode_buffer, len), &decoded2)); + } + + // Cool! the basic Base64 encoder/decoder works. + // Let's try the alternate alphabet: tr -- '+/' '-_' + + char websafe[100]; + memset(websafe, 0, sizeof(websafe)); + strncpy(websafe, base64_tests[i].cyphertext, cypher_length); + for (int c = 0; c < sizeof(websafe); ++c) { + if ('+' == websafe[c]) { websafe[c] = '-'; } + if ('/' == websafe[c]) { websafe[c] = '_'; } + } + + // The websafe escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer), + true); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + EXPECT_EQ( + CalculateBase64EscapedLen(base64_tests[i].plain_length, true), + encode_length); + + // Is it the expected encoded value? + EXPECT_STREQ(encode_buffer, websafe); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length, + true); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, websafe); + + // Let's try the string version of the encoder + encoded = "this junk should be ignored"; + WebSafeBase64Escape( + unsigned_plaintext, base64_tests[i].plain_length, + &encoded, true); + EXPECT_EQ(encoded.size(), cypher_length); + EXPECT_STREQ(encoded.c_str(), websafe); + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // Try using '.' for the pad character. + for (int c = cypher_length - 1; c >= 0 && '=' == encode_buffer[c]; --c) { + encode_buffer[c] = '.'; + } + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // Let's try the string version of the decoder + decoded = "this junk should be ignored"; + EXPECT_TRUE(WebSafeBase64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Okay! the websafe Base64 encoder/decoder works. + // Let's try the unpadded version + + for (int c = 0; c < sizeof(websafe); ++c) { + if ('=' == websafe[c]) { + websafe[c] = '\0'; + cypher_length = c; + break; + } + } + + // The websafe escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer), + false); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + EXPECT_EQ( + CalculateBase64EscapedLen(base64_tests[i].plain_length, false), + encode_length); + + // Is it the expected encoded value? + EXPECT_STREQ(encode_buffer, websafe); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length, + false); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, websafe); + + // Let's try the (other) string version of the encoder + string plain(base64_tests[i].plaintext, base64_tests[i].plain_length); + encoded = "this junk should be ignored"; + WebSafeBase64Escape(plain, &encoded); + EXPECT_EQ(encoded.size(), cypher_length); + EXPECT_STREQ(encoded.c_str(), websafe); + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + + // Let's try the string version of the decoder + decoded = "this junk should be ignored"; + EXPECT_TRUE(WebSafeBase64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // This value works. Try the next. + } + + // Now try the long strings, this tests the streaming + for (int i = 0; i < sizeof(base64_strings) / sizeof(base64_strings[0]); + ++i) { + + const unsigned char* unsigned_plaintext = + reinterpret_cast(base64_strings[i].plaintext); + int plain_length = strlen(base64_strings[i].plaintext); + int cypher_length = strlen(base64_strings[i].cyphertext); + vector buffer(cypher_length+1); + int encode_length = WebSafeBase64Escape(unsigned_plaintext, + plain_length, + &buffer[0], + buffer.size(), + false); + EXPECT_EQ(cypher_length, encode_length); + EXPECT_EQ( + CalculateBase64EscapedLen(plain_length, false), encode_length); + buffer[ encode_length ] = '\0'; + EXPECT_STREQ(base64_strings[i].cyphertext, &buffer[0]); + } + + // Verify the behavior when decoding bad data + { + const char* bad_data = "ab-/"; + string buf; + EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf)); + EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf)); + EXPECT_TRUE(buf.empty()); + } +} + } // anonymous namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc new file mode 100644 index 00000000..73b99af6 --- /dev/null +++ b/src/google/protobuf/stubs/time.cc @@ -0,0 +1,364 @@ +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +namespace { +static const int64 kSecondsPerMinute = 60; +static const int64 kSecondsPerHour = 3600; +static const int64 kSecondsPerDay = kSecondsPerHour * 24; +static const int64 kSecondsPer400Years = + kSecondsPerDay * (400 * 365 + 400 / 4 - 3); +// Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00 +static const int64 kSecondsFromEraToEpoch = 62135596800LL; +// The range of timestamp values we support. +static const int64 kMinTime = -62135596800LL; // 0001-01-01T00:00:00 +static const int64 kMaxTime = 253402300799LL; // 9999-12-31T23:59:59 + +static const int kNanosPerSecond = 1000000000; +static const int kNanosPerMillisecond = 1000000; +static const int kNanosPerMicrosecond = 1000; + +// Count the seconds from the given year (start at Jan 1, 00:00) to 100 years +// after. +int64 SecondsPer100Years(int year) { + if (year % 400 == 0 || year % 400 > 300) { + return kSecondsPerDay * (100 * 365 + 100 / 4); + } else { + return kSecondsPerDay * (100 * 365 + 100 / 4 - 1); + } +} + +// Count the seconds from the given year (start at Jan 1, 00:00) to 4 years +// after. +int64 SecondsPer4Years(int year) { + if ((year % 100 == 0 || year % 100 > 96) && + !(year % 400 == 0 || year % 400 > 396)) { + // No leap years. + return kSecondsPerDay * (4 * 365); + } else { + // One leap years. + return kSecondsPerDay * (4 * 365 + 1); + } +} + +bool IsLeapYear(int year) { + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); +} + +int64 SecondsPerYear(int year) { + return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365); +} + +static const int kDaysInMonth[13] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +int64 SecondsPerMonth(int month, bool leap) { + if (month == 2 && leap) { + return kSecondsPerDay * (kDaysInMonth[month] + 1); + } + return kSecondsPerDay * kDaysInMonth[month]; +} + +static const int kDaysSinceJan[13] = { + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, +}; + +bool ValidateDateTime(const DateTime& time) { + if (time.year < 1 || time.year > 9999 || + time.month < 1 || time.month > 12 || + time.day < 1 || time.day > 31 || + time.hour < 0 || time.hour > 23 || + time.minute < 0 || time.minute > 59 || + time.second < 0 || time.second > 59) { + return false; + } + if (time.month == 2 && IsLeapYear(time.year)) { + return time.month <= kDaysInMonth[time.month] + 1; + } else { + return time.month <= kDaysInMonth[time.month]; + } +} + +// Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given +// time. +int64 SecondsSinceCommonEra(const DateTime& time) { + int64 result = 0; + // Years should be between 1 and 9999. + assert(time.year >= 1 && time.year <= 9999); + int year = 1; + if ((time.year - year) >= 400) { + int count_400years = (time.year - year) / 400; + result += kSecondsPer400Years * count_400years; + year += count_400years * 400; + } + while ((time.year - year) >= 100) { + result += SecondsPer100Years(year); + year += 100; + } + while ((time.year - year) >= 4) { + result += SecondsPer4Years(year); + year += 4; + } + while (time.year > year) { + result += SecondsPerYear(year); + ++year; + } + // Months should be between 1 and 12. + assert(time.month >= 1 && time.month <= 12); + int month = time.month; + result += kSecondsPerDay * kDaysSinceJan[month]; + if (month > 2 && IsLeapYear(year)) { + result += kSecondsPerDay; + } + assert(time.day >= 1 && + time.day <= (month == 2 && IsLeapYear(year) + ? kDaysInMonth[month] + 1 + : kDaysInMonth[month])); + result += kSecondsPerDay * (time.day - 1); + result += kSecondsPerHour * time.hour + + kSecondsPerMinute * time.minute + + time.second; + return result; +} + +// Format nanoseconds with either 3, 6, or 9 digits depending on the required +// precision to represent the exact value. +string FormatNanos(int32 nanos) { + if (nanos % kNanosPerMillisecond == 0) { + return StringPrintf("%03d", nanos / kNanosPerMillisecond); + } else if (nanos % kNanosPerMicrosecond == 0) { + return StringPrintf("%06d", nanos / kNanosPerMicrosecond); + } else { + return StringPrintf("%09d", nanos); + } +} + +// Parses an integer from a null-terminated char sequence. The method +// consumes at most "width" chars. Returns a pointer after the consumed +// integer, or NULL if the data does not start with an integer or the +// integer value does not fall in the range of [min_value, max_value]. +const char* ParseInt(const char* data, int width, int min_value, + int max_value, int* result) { + if (!ascii_isdigit(*data)) { + return NULL; + } + int value = 0; + for (int i = 0; i < width; ++i, ++data) { + if (ascii_isdigit(*data)) { + value = value * 10 + (*data - '0'); + } else { + break; + } + } + if (value >= min_value && value <= max_value) { + *result = value; + return data; + } else { + return NULL; + } +} + +// Consumes the fractional parts of a second into nanos. For example, +// "010" will be parsed to 10000000 nanos. +const char* ParseNanos(const char* data, int32* nanos) { + if (!ascii_isdigit(*data)) { + return NULL; + } + int value = 0; + int len = 0; + // Consume as many digits as there are but only take the first 9 into + // account. + while (ascii_isdigit(*data)) { + if (len < 9) { + value = value * 10 + *data - '0'; + } + ++len; + ++data; + } + while (len < 9) { + value = value * 10; + ++len; + } + *nanos = value; + return data; +} + +const char* ParseTimezoneOffset(const char* data, int64* offset) { + // Accept format "HH:MM". E.g., "08:00" + int hour; + if ((data = ParseInt(data, 2, 0, 23, &hour)) == NULL) { + return NULL; + } + if (*data++ != ':') { + return NULL; + } + int minute; + if ((data = ParseInt(data, 2, 0, 59, &minute)) == NULL) { + return NULL; + } + *offset = (hour * 60 + minute) * 60; + return data; +} +} // namespace + +bool SecondsToDateTime(int64 seconds, DateTime* time) { + if (seconds < kMinTime || seconds > kMaxTime) { + return false; + } + // It's easier to calcuate the DateTime starting from 0001-01-01T00:00:00 + seconds = seconds + kSecondsFromEraToEpoch; + int year = 1; + if (seconds >= kSecondsPer400Years) { + int count_400years = seconds / kSecondsPer400Years; + year += 400 * count_400years; + seconds %= kSecondsPer400Years; + } + while (seconds >= SecondsPer100Years(year)) { + seconds -= SecondsPer100Years(year); + year += 100; + } + while (seconds >= SecondsPer4Years(year)) { + seconds -= SecondsPer4Years(year); + year += 4; + } + while (seconds >= SecondsPerYear(year)) { + seconds -= SecondsPerYear(year); + year += 1; + } + bool leap = IsLeapYear(year); + int month = 1; + while (seconds >= SecondsPerMonth(month, leap)) { + seconds -= SecondsPerMonth(month, leap); + ++month; + } + int day = 1 + seconds / kSecondsPerDay; + seconds %= kSecondsPerDay; + int hour = seconds / kSecondsPerHour; + seconds %= kSecondsPerHour; + int minute = seconds / kSecondsPerMinute; + seconds %= kSecondsPerMinute; + time->year = year; + time->month = month; + time->day = day; + time->hour = hour; + time->minute = minute; + time->second = static_cast(seconds); + return true; +} + +bool DateTimeToSeconds(const DateTime& time, int64* seconds) { + if (!ValidateDateTime(time)) { + return false; + } + *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch; + return true; +} + +void GetCurrentTime(int64* seconds, int32* nanos) { + // TODO(xiaofeng): Improve the accuracy of this implementation (or just + // remove this method from protobuf). + *seconds = time(NULL); + *nanos = 0; +} + +string FormatTime(int64 seconds, int32 nanos) { + DateTime time; + if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) { + return "InvalidTime"; + } + string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", + time.year, time.month, time.day, + time.hour, time.minute, time.second); + if (nanos != 0) { + result += "." + FormatNanos(nanos); + } + return result + "Z"; +} + +bool ParseTime(const string& value, int64* seconds, int32* nanos) { + DateTime time; + const char* data = value.c_str(); + // We only accept: + // Z-normalized: 2015-05-20T13:29:35.120Z + // With UTC offset: 2015-05-20T13:29:35.120-08:00 + + // Parse year + if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == NULL) { + return false; + } + // Expect '-' + if (*data++ != '-') return false; + // Parse month + if ((data = ParseInt(data, 2, 1, 12, &time.month)) == NULL) { + return false; + } + // Expect '-' + if (*data++ != '-') return false; + // Parse day + if ((data = ParseInt(data, 2, 1, 31, &time.day)) == NULL) { + return false; + } + // Expect 'T' + if (*data++ != 'T') return false; + // Parse hour + if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == NULL) { + return false; + } + // Expect ':' + if (*data++ != ':') return false; + // Parse minute + if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == NULL) { + return false; + } + // Expect ':' + if (*data++ != ':') return false; + // Parse second + if ((data = ParseInt(data, 2, 0, 59, &time.second)) == NULL) { + return false; + } + if (!DateTimeToSeconds(time, seconds)) { + return false; + } + // Parse nanoseconds. + if (*data == '.') { + ++data; + // Parse nanoseconds. + if ((data = ParseNanos(data, nanos)) == NULL) { + return false; + } + } else { + *nanos = 0; + } + // Parse UTC offsets. + if (*data == 'Z') { + ++data; + } else if (*data == '+') { + ++data; + int64 offset; + if ((data = ParseTimezoneOffset(data, &offset)) == NULL) { + return false; + } + *seconds -= offset; + } else if (*data == '-') { + ++data; + int64 offset; + if ((data = ParseTimezoneOffset(data, &offset)) == NULL) { + return false; + } + *seconds += offset; + } else { + return false; + } + // Done with parsing. + return *data == 0; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/stubs/time.h b/src/google/protobuf/stubs/time.h new file mode 100644 index 00000000..0f641dc9 --- /dev/null +++ b/src/google/protobuf/stubs/time.h @@ -0,0 +1,75 @@ +// 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. +#ifndef GOOGLE_PROTOBUF_STUBS_TIME_H_ +#define GOOGLE_PROTOBUF_STUBS_TIME_H_ + +#include + +namespace google { +namespace protobuf { +namespace internal { + +struct DateTime { + int year; + int month; + int day; + int hour; + int minute; + int second; +}; + +// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be +// negative to represent time before 1970-01-01) to DateTime. Returns false +// if the timestamp is not in the range between 0001-01-01T00:00:00 and +// 9999-12-31T23:59:59. +bool SecondsToDateTime(int64 seconds, DateTime* time); +// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00). +// Returns false if the DateTime is not valid or is not in the valid range. +bool DateTimeToSeconds(const DateTime& time, int64* seconds); + +void GetCurrentTime(int64* seconds, int32* nanos); + +// Formats a time string in RFC3339 fromat. +// +// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional +// digits will be used depending on how many are required to represent the exact +// value. +// +// Note that "nanos" must in the range of [0, 999999999]. +string FormatTime(int64 seconds, int32 nanos); +// Parses a time string. This method accepts RFC3339 date/time string with UTC +// offset. For example, "2015-05-20T13:29:35.120-08:00". +bool ParseTime(const string& vaule, int64* seconds, int32* nanos); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_TIME_H_ diff --git a/src/google/protobuf/stubs/time_test.cc b/src/google/protobuf/stubs/time_test.cc new file mode 100644 index 00000000..59e9d1c7 --- /dev/null +++ b/src/google/protobuf/stubs/time_test.cc @@ -0,0 +1,208 @@ +// 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 + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +namespace { +static const int64 kSecondsPerDay = 3600 * 24; + +// For DateTime, tests will mostly focuse on the date part because that's +// the tricky one. +int64 CreateTimestamp(int year, int month, int day) { + DateTime time; + time.year = year; + time.month = month; + time.day = day; + time.hour = time.minute = time.second = 0; + int64 result; + GOOGLE_CHECK(DateTimeToSeconds(time, &result)); + // Check that a roundtrip produces the same result. + GOOGLE_CHECK(SecondsToDateTime(result, &time)); + GOOGLE_CHECK(time.year == year); + GOOGLE_CHECK(time.month == month); + GOOGLE_CHECK(time.day == day); + return result; +} + +TEST(DateTimeTest, SimpleTime) { + DateTime time; + ASSERT_TRUE(SecondsToDateTime(1, &time)); + EXPECT_EQ(1970, time.year); + EXPECT_EQ(1, time.month); + EXPECT_EQ(1, time.day); + EXPECT_EQ(0, time.hour); + EXPECT_EQ(0, time.minute); + EXPECT_EQ(1, time.second); + int64 seconds; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(1, seconds); + + ASSERT_TRUE(SecondsToDateTime(-1, &time)); + EXPECT_EQ(1969, time.year); + EXPECT_EQ(12, time.month); + EXPECT_EQ(31, time.day); + EXPECT_EQ(23, time.hour); + EXPECT_EQ(59, time.minute); + EXPECT_EQ(59, time.second); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(-1, seconds); + + DateTime start, end; + start.year = 1; + start.month = 1; + start.day = 1; + start.hour = 0; + start.minute = 0; + start.second = 0; + end.year = 9999; + end.month = 12; + end.day = 31; + end.hour = 23; + end.minute = 59; + end.second = 59; + int64 start_time, end_time; + ASSERT_TRUE(DateTimeToSeconds(start, &start_time)); + ASSERT_TRUE(DateTimeToSeconds(end, &end_time)); + EXPECT_EQ(315537897599LL, end_time - start_time); + ASSERT_TRUE(SecondsToDateTime(start_time, &time)); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(start_time, seconds); + ASSERT_TRUE(SecondsToDateTime(end_time, &time)); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(end_time, seconds); +} + +TEST(DateTimeTest, DayInMonths) { + // Check that month boundaries are handled correctly. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 1, 1) - CreateTimestamp(2014, 12, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 2, 1) - CreateTimestamp(2015, 1, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 4, 1) - CreateTimestamp(2015, 3, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 5, 1) - CreateTimestamp(2015, 4, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 6, 1) - CreateTimestamp(2015, 5, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 7, 1) - CreateTimestamp(2015, 6, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 8, 1) - CreateTimestamp(2015, 7, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 9, 1) - CreateTimestamp(2015, 8, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 10, 1) - CreateTimestamp(2015, 9, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 11, 1) - CreateTimestamp(2015, 10, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 12, 1) - CreateTimestamp(2015, 11, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2016, 1, 1) - CreateTimestamp(2015, 12, 31)); +} + +TEST(DateTimeTest, LeapYear) { + // Non-leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28)); + // Leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2016, 3, 1) - CreateTimestamp(2016, 2, 29)); + // Non-leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2100, 3, 1) - CreateTimestamp(2100, 2, 28)); + // Leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2400, 3, 1) - CreateTimestamp(2400, 2, 29)); +} + +TEST(DateTimeTest, StringFormat) { + DateTime start, end; + start.year = 1; + start.month = 1; + start.day = 1; + start.hour = 0; + start.minute = 0; + start.second = 0; + end.year = 9999; + end.month = 12; + end.day = 31; + end.hour = 23; + end.minute = 59; + end.second = 59; + int64 start_time, end_time; + ASSERT_TRUE(DateTimeToSeconds(start, &start_time)); + ASSERT_TRUE(DateTimeToSeconds(end, &end_time)); + + EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(start_time, 0)); + EXPECT_EQ("9999-12-31T23:59:59Z", FormatTime(end_time, 0)); + + // Make sure the nanoseconds part is formated correctly. + EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(0, 10000000)); + EXPECT_EQ("1970-01-01T00:00:00.000010Z", FormatTime(0, 10000)); + EXPECT_EQ("1970-01-01T00:00:00.000000010Z", FormatTime(0, 10)); +} + +TEST(DateTimeTest, ParseString) { + int64 seconds; + int32 nanos; + ASSERT_TRUE(ParseTime("0001-01-01T00:00:00Z", &seconds, &nanos)); + EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("9999-12-31T23:59:59.999999999Z", &seconds, &nanos)); + EXPECT_EQ("9999-12-31T23:59:59.999999999Z", FormatTime(seconds, nanos)); + + // Test time zone offsets. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00-08:00", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T08:00:00Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00+08:00", &seconds, &nanos)); + EXPECT_EQ("1969-12-31T16:00:00Z", FormatTime(seconds, nanos)); + + // Test nanoseconds. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.01Z", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00001-08:00", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T08:00:00.000010Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00000001+08:00", &seconds, &nanos)); + EXPECT_EQ("1969-12-31T16:00:00.000000010Z", FormatTime(seconds, nanos)); + // Fractional parts less than 1 nanosecond will be ignored. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.0123456789Z", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T00:00:00.012345678Z", FormatTime(seconds, nanos)); +} + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index 61dfa5d6..4d8c1f91 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -1880,7 +1880,7 @@ void TextFormat::Printer::PrintUnknownFields( generator.Print(field_number); generator.Print(": 0x"); generator.Print( - StrCat(strings::Hex(field.fixed32(), strings::Hex::ZERO_PAD_8))); + StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8))); if (single_line_mode_) { generator.Print(" "); } else { @@ -1892,7 +1892,7 @@ void TextFormat::Printer::PrintUnknownFields( generator.Print(field_number); generator.Print(": 0x"); generator.Print( - StrCat(strings::Hex(field.fixed64(), strings::Hex::ZERO_PAD_16))); + StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16))); if (single_line_mode_) { generator.Print(" "); } else { diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc new file mode 100644 index 00000000..b7676a88 --- /dev/null +++ b/src/google/protobuf/util/field_comparator.cc @@ -0,0 +1,187 @@ +// 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. + +// Author: ksroka@google.com (Krzysztof Sroka) + +#include + +#include + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { + +FieldComparator::FieldComparator() {} +FieldComparator::~FieldComparator() {} + +DefaultFieldComparator::DefaultFieldComparator() + : float_comparison_(EXACT), + treat_nan_as_equal_(false), + has_default_tolerance_(false) { +} + +DefaultFieldComparator::~DefaultFieldComparator() {} + +FieldComparator::ComparisonResult DefaultFieldComparator::Compare( + const google::protobuf::Message& message_1, + const google::protobuf::Message& message_2, + const google::protobuf::FieldDescriptor* field, + int index_1, int index_2, + const google::protobuf::util::FieldContext* field_context) { + const Reflection* reflection_1 = message_1.GetReflection(); + const Reflection* reflection_2 = message_2.GetReflection(); + + switch (field->cpp_type()) { +#define COMPARE_FIELD(METHOD) \ + if (field->is_repeated()) { \ + return ResultFromBoolean(Compare##METHOD( \ + *field, \ + reflection_1->GetRepeated##METHOD(message_1, field, index_1), \ + reflection_2->GetRepeated##METHOD(message_2, field, index_2))); \ + } else { \ + return ResultFromBoolean(Compare##METHOD( \ + *field, \ + reflection_1->Get##METHOD(message_1, field), \ + reflection_2->Get##METHOD(message_2, field))); \ + } \ + break; // Make sure no fall-through is introduced. + + case FieldDescriptor::CPPTYPE_BOOL: + COMPARE_FIELD(Bool); + case FieldDescriptor::CPPTYPE_DOUBLE: + COMPARE_FIELD(Double); + case FieldDescriptor::CPPTYPE_ENUM: + COMPARE_FIELD(Enum); + case FieldDescriptor::CPPTYPE_FLOAT: + COMPARE_FIELD(Float); + case FieldDescriptor::CPPTYPE_INT32: + COMPARE_FIELD(Int32); + case FieldDescriptor::CPPTYPE_INT64: + COMPARE_FIELD(Int64); + case FieldDescriptor::CPPTYPE_STRING: + COMPARE_FIELD(String); + case FieldDescriptor::CPPTYPE_UINT32: + COMPARE_FIELD(UInt32); + case FieldDescriptor::CPPTYPE_UINT64: + COMPARE_FIELD(UInt64); + +#undef COMPARE_FIELD + + case FieldDescriptor::CPPTYPE_MESSAGE: + return RECURSE; + + default: + GOOGLE_LOG(FATAL) << "No comparison code for field " << field->full_name() + << " of CppType = " << field->cpp_type(); + } +} + +void DefaultFieldComparator::SetDefaultFractionAndMargin(double fraction, + double margin) { + default_tolerance_ = Tolerance(fraction, margin); + has_default_tolerance_ = true; +} + +void DefaultFieldComparator::SetFractionAndMargin(const FieldDescriptor* field, + double fraction, + double margin) { + GOOGLE_CHECK(FieldDescriptor::CPPTYPE_FLOAT == field->cpp_type() || + FieldDescriptor::CPPTYPE_DOUBLE == field->cpp_type()) + << "Field has to be float or double type. Field name is: " + << field->full_name(); + map_tolerance_[field] = Tolerance(fraction, margin); +} + +bool DefaultFieldComparator::CompareDouble(const FieldDescriptor& field, + double value_1, double value_2) { + return CompareDoubleOrFloat(field, value_1, value_2); +} + +bool DefaultFieldComparator::CompareEnum(const FieldDescriptor& field, + const EnumValueDescriptor* value_1, + const EnumValueDescriptor* value_2) { + return value_1->number() == value_2->number(); +} + +bool DefaultFieldComparator::CompareFloat(const FieldDescriptor& field, + float value_1, float value_2) { + return CompareDoubleOrFloat(field, value_1, value_2); +} + +template +bool DefaultFieldComparator::CompareDoubleOrFloat(const FieldDescriptor& field, + T value_1, T value_2) { + if (value_1 == value_2) { + // Covers +inf and -inf (which are not within margin or fraction of + // themselves), and is a shortcut for finite values. + return true; + } else if (float_comparison_ == EXACT) { + if (treat_nan_as_equal_ && + MathLimits::IsNaN(value_1) && MathLimits::IsNaN(value_2)) { + return true; + } + return false; + } else { + if (treat_nan_as_equal_ && + MathLimits::IsNaN(value_1) && MathLimits::IsNaN(value_2)) { + return true; + } + // float_comparison_ == APPROXIMATE covers two use cases. + Tolerance* tolerance = FindOrNull(map_tolerance_, &field); + if (tolerance == NULL && has_default_tolerance_) { + tolerance = &default_tolerance_; + } + if (tolerance == NULL) { + return MathUtil::AlmostEquals(value_1, value_2); + } else { + // Use user-provided fraction and margin. Since they are stored as + // doubles, we explicitely cast them to types of values provided. This + // is very likely to fail if provided values are not numeric. + return MathUtil::WithinFractionOrMargin( + value_1, value_2, static_cast(tolerance->fraction), + static_cast(tolerance->margin)); + } + } +} + +FieldComparator::ComparisonResult DefaultFieldComparator::ResultFromBoolean( + bool boolean_result) const { + return boolean_result ? FieldComparator::SAME : FieldComparator::DIFFERENT; +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h new file mode 100644 index 00000000..5e893f9c --- /dev/null +++ b/src/google/protobuf/util/field_comparator.h @@ -0,0 +1,259 @@ +// 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. + +// Author: ksroka@google.com (Krzysztof Sroka) + +#ifndef GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ +#define GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ + +#include +#include + +#include + +namespace google { +namespace protobuf { + +class Message; +class EnumValueDescriptor; +class FieldDescriptor; + +namespace util { + +struct FieldContext; + +// Base class specifying the interface for comparing protocol buffer fields. +// Regular users should consider using or subclassing DefaultFieldComparator +// rather than this interface. +// Currently, this does not support comparing unknown fields. +class LIBPROTOBUF_EXPORT FieldComparator { + public: + FieldComparator(); + virtual ~FieldComparator(); + + enum ComparisonResult { + SAME, // Compared fields are equal. In case of comparing submessages, + // user should not recursively compare their contents. + DIFFERENT, // Compared fields are different. In case of comparing + // submessages, user should not recursively compare their + // contents. + RECURSE, // Compared submessages need to be compared recursively. + // FieldComparator does not specify the semantics of recursive + // comparison. This value should not be returned for simple + // values. + }; + + // Compares the values of a field in two protocol buffer messages. + // Returns SAME or DIFFERENT for simple values, and SAME, DIFFERENT or RECURSE + // for submessages. Returning RECURSE for fields not being submessages is + // illegal. + // In case the given FieldDescriptor points to a repeated field, the indices + // need to be valid. Otherwise they should be ignored. + // + // FieldContext contains information about the specific instances of the + // fields being compared, versus FieldDescriptor which only contains general + // type information about the fields. + virtual ComparisonResult Compare( + const google::protobuf::Message& message_1, + const google::protobuf::Message& message_2, + const google::protobuf::FieldDescriptor* field, + int index_1, int index_2, + const google::protobuf::util::FieldContext* field_context) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator); +}; + +// Basic implementation of FieldComparator. Supports four modes of floating +// point value comparison: exact, approximate using MathUtil::AlmostEqual +// method, and arbitrarilly precise using MathUtil::WithinFracionOrMargin. +class LIBPROTOBUF_EXPORT DefaultFieldComparator : public FieldComparator { + public: + enum FloatComparison { + EXACT, // Floats and doubles are compared exactly. + APPROXIMATE, // Floats and doubles are compared using the + // MathUtil::AlmostEqual method or + // MathUtil::WithinFractionOrMargin method. + // TODO(ksroka): Introduce third value to differenciate uses of AlmostEqual + // and WithinFractionOrMargin. + }; + + // Creates new comparator with float comparison set to EXACT. + DefaultFieldComparator(); + + virtual ~DefaultFieldComparator(); + + virtual ComparisonResult Compare( + const google::protobuf::Message& message_1, + const google::protobuf::Message& message_2, + const google::protobuf::FieldDescriptor* field, + int index_1, int index_2, + const google::protobuf::util::FieldContext* field_context); + + void set_float_comparison(FloatComparison float_comparison) { + float_comparison_ = float_comparison; + } + + FloatComparison float_comparison() const { + return float_comparison_; + } + + // Set whether the FieldComparator shall treat floats or doubles that are both + // NaN as equal (treat_nan_as_equal = true) or as different + // (treat_nan_as_equal = false). Default is treating NaNs always as different. + void set_treat_nan_as_equal(bool treat_nan_as_equal) { + treat_nan_as_equal_ = treat_nan_as_equal; + } + + bool treat_nan_as_equal() const { + return treat_nan_as_equal_; + } + + // Sets the fraction and margin for the float comparison of a given field. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // + // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or + // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT + // REQUIRES: float_comparison_ == APPROXIMATE + void SetFractionAndMargin(const FieldDescriptor* field, double fraction, + double margin); + + // Sets the fraction and margin for the float comparison of all float and + // double fields, unless a field has been given a specific setting via + // SetFractionAndMargin() above. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // + // REQUIRES: float_comparison_ == APPROXIMATE + void SetDefaultFractionAndMargin(double fraction, double margin); + + private: + // Defines the tolerance for floating point comparison (fraction and margin). + struct Tolerance { + double fraction; + double margin; + Tolerance() + : fraction(0.0), + margin(0.0) {} + Tolerance(double f, double m) + : fraction(f), + margin(m) {} + }; + + // Defines the map to store the tolerances for floating point comparison. + typedef map ToleranceMap; + + // The following methods get executed when CompareFields is called for the + // basic types (instead of submessages). They return true on success. One + // can use ResultFromBoolean() to convert that boolean to a ComparisonResult + // value. + bool CompareBool(const google::protobuf::FieldDescriptor& field, + bool value_1, bool value_2) { + return value_1 == value_2; + } + + // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and + // CompareFloat. + bool CompareDouble(const google::protobuf::FieldDescriptor& field, + double value_1, double value_2); + + bool CompareEnum(const google::protobuf::FieldDescriptor& field, + const EnumValueDescriptor* value_1, + const EnumValueDescriptor* value_2); + + // Uses CompareDoubleOrFloat, a helper function used by both CompareDouble and + // CompareFloat. + bool CompareFloat(const google::protobuf::FieldDescriptor& field, + float value_1, float value_2); + + bool CompareInt32(const google::protobuf::FieldDescriptor& field, + int32 value_1, int32 value_2) { + return value_1 == value_2; + } + + bool CompareInt64(const google::protobuf::FieldDescriptor& field, + int64 value_1, int64 value_2) { + return value_1 == value_2; + } + + bool CompareString(const google::protobuf::FieldDescriptor& field, + const string& value_1, const string& value_2) { + return value_1 == value_2; + } + + bool CompareUInt32(const google::protobuf::FieldDescriptor& field, + uint32 value_1, uint32 value_2) { + return value_1 == value_2; + } + + bool CompareUInt64(const google::protobuf::FieldDescriptor& field, + uint64 value_1, uint64 value_2) { + return value_1 == value_2; + } + + // This function is used by CompareDouble and CompareFloat to avoid code + // duplication. There are no checks done against types of the values passed, + // but it's likely to fail if passed non-numeric arguments. + template + bool CompareDoubleOrFloat(const google::protobuf::FieldDescriptor& field, + T value_1, T value_2); + + // Returns FieldComparator::SAME if boolean_result is true and + // FieldComparator::DIFFERENT otherwise. + ComparisonResult ResultFromBoolean(bool boolean_result) const; + + FloatComparison float_comparison_; + + // If true, floats and doubles that are both NaN are considered to be + // equal. Otherwise, two floats or doubles that are NaN are considered to be + // different. + bool treat_nan_as_equal_; + + // True iff default_tolerance_ has been explicitly set. + // + // If false, then the default tolerance for flaots and doubles is that which + // is used by MathUtil::AlmostEquals(). + bool has_default_tolerance_; + + // Default float/double tolerance. Only meaningful if + // has_default_tolerance_ == true. + Tolerance default_tolerance_; + + // Field-specific float/double tolerances, which override any default for + // those particular fields. + ToleranceMap map_tolerance_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultFieldComparator); +}; + +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__ diff --git a/src/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc new file mode 100644 index 00000000..748c7d11 --- /dev/null +++ b/src/google/protobuf/util/field_comparator_test.cc @@ -0,0 +1,483 @@ +// 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. + +// Author: ksroka@google.com (Krzysztof Sroka) + +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace { + +using protobuf_unittest::TestAllTypes; + +class DefaultFieldComparatorTest : public ::testing::Test { + protected: + void SetUp() { + descriptor_ = TestAllTypes::descriptor(); + } + + const Descriptor* descriptor_; + DefaultFieldComparator comparator_; + TestAllTypes message_1_; + TestAllTypes message_2_; +}; + +TEST_F(DefaultFieldComparatorTest, RecursesIntoGroup) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optionalgroup"); + EXPECT_EQ(FieldComparator::RECURSE, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, RecursesIntoNestedMessage) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_nested_message"); + EXPECT_EQ(FieldComparator::RECURSE, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, RecursesIntoForeignMessage) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_foreign_message"); + EXPECT_EQ(FieldComparator::RECURSE, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, Int32Comparison) { + const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int32"); + message_1_.set_optional_int32(1); + message_2_.set_optional_int32(1); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_int32(-1); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, Int64Comparison) { + const FieldDescriptor* field = descriptor_->FindFieldByName("optional_int64"); + message_1_.set_optional_int64(1L); + message_2_.set_optional_int64(1L); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_int64(-1L); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, UInt32Comparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_uint32"); + message_1_.set_optional_uint32(1); + message_2_.set_optional_uint32(1); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_uint32(2); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, UInt64Comparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_uint64"); + message_1_.set_optional_uint64(1L); + message_2_.set_optional_uint64(1L); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_uint64(2L); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, BooleanComparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_bool"); + message_1_.set_optional_bool(true); + message_2_.set_optional_bool(true); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_bool(false); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, EnumComparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_nested_enum"); + message_1_.set_optional_nested_enum(TestAllTypes::BAR); + message_2_.set_optional_nested_enum(TestAllTypes::BAR); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_nested_enum(TestAllTypes::BAZ); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, StringComparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("optional_string"); + message_1_.set_optional_string("foo"); + message_2_.set_optional_string("foo"); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); + + message_2_.set_optional_string("bar"); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonExact) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(0.1f); + message_2_.set_optional_float(0.1f); + message_1_.set_optional_double(0.1); + message_2_.set_optional_double(0.1); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + message_2_.set_optional_float(0.2f); + message_2_.set_optional_double(0.2); + + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonApproximate) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(2.300005f); + message_2_.set_optional_float(2.300006f); + message_1_.set_optional_double(2.3000000000000003); + message_2_.set_optional_double(2.3000000000000007); + + // Approximate comparison depends on MathUtil, so we assert on MathUtil + // results first to check if that's where the failure was introduced. + ASSERT_NE(message_1_.optional_float(), message_2_.optional_float()); + ASSERT_NE(message_1_.optional_double(), message_2_.optional_double()); + ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_float(), + message_2_.optional_float())); + ASSERT_TRUE(MathUtil::AlmostEquals(message_1_.optional_double(), + message_2_.optional_double())); + + // DefaultFieldComparator's default float comparison mode is EXACT. + ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison()); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, FloatingPointComparisonTreatNaNsAsEqual) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(MathLimits::kNaN); + message_2_.set_optional_float(MathLimits::kNaN); + message_1_.set_optional_double(MathLimits::kNaN); + message_2_.set_optional_double(MathLimits::kNaN); + + // DefaultFieldComparator's default float comparison mode is EXACT with + // treating NaNs as different. + ASSERT_EQ(DefaultFieldComparator::EXACT, comparator_.float_comparison()); + ASSERT_EQ(false, comparator_.treat_nan_as_equal()); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + comparator_.set_treat_nan_as_equal(true); + ASSERT_EQ(true, comparator_.treat_nan_as_equal()); + comparator_.set_float_comparison(DefaultFieldComparator::EXACT); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, + FloatingPointComparisonWithinFractionOrMargin) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(100.0f); + message_2_.set_optional_float(109.9f); + message_1_.set_optional_double(100.0); + message_2_.set_optional_double(109.9); + + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Should fail since the fraction is too low. + comparator_.SetFractionAndMargin(field_float, 0.01, 0.0); + comparator_.SetFractionAndMargin(field_double, 0.01, 0.0); + + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Should fail since the margin is too low. + comparator_.SetFractionAndMargin(field_float, 0.0, 9.0); + comparator_.SetFractionAndMargin(field_double, 0.0, 9.0); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Should succeed since the fraction is high enough. + comparator_.SetFractionAndMargin(field_float, 0.2, 0.0); + comparator_.SetFractionAndMargin(field_double, 0.2, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Should succeed since the margin is high enough. + comparator_.SetFractionAndMargin(field_float, 0.0, 10.0); + comparator_.SetFractionAndMargin(field_double, 0.0, 10.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Setting values for one of the fields should not affect the other. + comparator_.SetFractionAndMargin(field_double, 0.0, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // +inf should be equal even though they are not technically within margin or + // fraction. + message_1_.set_optional_float(numeric_limits::infinity()); + message_2_.set_optional_float(numeric_limits::infinity()); + message_1_.set_optional_double(numeric_limits::infinity()); + message_2_.set_optional_double(numeric_limits::infinity()); + comparator_.SetFractionAndMargin(field_float, 0.0, 0.0); + comparator_.SetFractionAndMargin(field_double, 0.0, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // -inf should be equal even though they are not technically within margin or + // fraction. + message_1_.set_optional_float(-numeric_limits::infinity()); + message_2_.set_optional_float(-numeric_limits::infinity()); + message_1_.set_optional_double(-numeric_limits::infinity()); + message_2_.set_optional_double(-numeric_limits::infinity()); + comparator_.SetFractionAndMargin(field_float, 0.0, 0.0); + comparator_.SetFractionAndMargin(field_double, 0.0, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +TEST_F(DefaultFieldComparatorTest, + FloatingPointComparisonWithinDefaultFractionOrMargin) { + const FieldDescriptor* field_float = + descriptor_->FindFieldByName("optional_float"); + const FieldDescriptor* field_double = + descriptor_->FindFieldByName("optional_double"); + + message_1_.set_optional_float(100.0f); + message_2_.set_optional_float(109.9f); + message_1_.set_optional_double(100.0); + message_2_.set_optional_double(109.9); + + comparator_.set_float_comparison(DefaultFieldComparator::APPROXIMATE); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Set default fraction and margin. + comparator_.SetDefaultFractionAndMargin(0.01, 0.0); + + // Float comparisons should fail since the fraction is too low. + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Set field-specific fraction and margin for one field (field_float) but not + // the other (field_double) + comparator_.SetFractionAndMargin(field_float, 0.2, 0.0); + + // The field with the override should succeed, since its field-specific + // fraction is high enough. + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + // The field with no override should fail, since the default fraction is too + // low + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // Set the default fraction and margin high enough so that fields that use + // the default should succeed + comparator_.SetDefaultFractionAndMargin(0.2, 0.0); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); + + // The field with an override should still be OK + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + + // Set fraction and margin for the field with an override to be too low + comparator_.SetFractionAndMargin(field_float, 0.01, 0.0); + + // Now our default is high enough but field_float's override is too low. + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, + field_float, -1, -1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, + field_double, -1, -1, NULL)); +} + +// Simple test checking whether we compare values at correct indices. +TEST_F(DefaultFieldComparatorTest, RepeatedFieldComparison) { + const FieldDescriptor* field = + descriptor_->FindFieldByName("repeated_string"); + + message_1_.add_repeated_string("foo"); + message_1_.add_repeated_string("bar"); + message_2_.add_repeated_string("bar"); + message_2_.add_repeated_string("baz"); + + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, 0, 0, NULL)); + EXPECT_EQ(FieldComparator::DIFFERENT, + comparator_.Compare(message_1_, message_2_, field, 1, 1, NULL)); + EXPECT_EQ(FieldComparator::SAME, + comparator_.Compare(message_1_, message_2_, field, 1, 0, NULL)); +} + +} // namespace util +} // namespace protobuf +} // namespace +} // namespace google diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h new file mode 100644 index 00000000..0cb8f6e1 --- /dev/null +++ b/src/google/protobuf/util/internal/constants.h @@ -0,0 +1,93 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__ + +#include + +// This file contains constants used by //net/proto2/util/converter. + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +// Prefix for type URLs. +const char kTypeServiceBaseUrl[] = "type.googleapis.com"; + +// Format string for RFC3339 timestamp formatting. +const char kRfc3339TimeFormat[] = "%Y-%m-%dT%H:%M:%S"; + +// Minimum seconds allowed in a google.protobuf.TimeStamp or Duration value. +const int64 kMinSeconds = -315576000000; + +// Maximum seconds allowed in a google.protobuf.TimeStamp or Duration value. +const int64 kMaxSeconds = 315576000000; + +// Nano seconds in a second. +const int32 kNanosPerSecond = 1000000000; + +// Type url representing NULL values in google.protobuf.Struct type. +const char kStructNullValueTypeUrl[] = + "type.googleapis.com/google.protobuf.NullValue"; + +// Type string for google.protobuf.Struct +const char kStructType[] = "google.protobuf.Struct"; + +// Type string for struct.proto's google.protobuf.Value value type. +const char kStructValueType[] = "google.protobuf.Value"; + +// Type string for struct.proto's google.protobuf.ListValue value type. +const char kStructListValueType[] = "google.protobuf.ListValue"; + +// Type string for google.protobuf.Timestamp +const char kTimestampType[] = "google.protobuf.Timestamp"; + +// Type string for google.protobuf.Duration +const char kDurationType[] = "google.protobuf.Duration"; + +// Type URL for struct value type google.protobuf.Value +const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value"; + +// Type URL for struct value type google.protobuf.Value +const char kStructTypeUrl[] = "type.googleapis.com/google.protobuf.Struct"; + +// Type string for google.protobuf.Any +const char kAnyType[] = "google.protobuf.Any"; + +// The type URL of google.protobuf.FieldMask; +const char kFieldMaskTypeUrl[] = + "type.googleapis.com/google.protobuf.FieldMask"; + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_CONSTANTS_H__ diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc new file mode 100644 index 00000000..72b737e9 --- /dev/null +++ b/src/google/protobuf/util/internal/datapiece.cc @@ -0,0 +1,285 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::EnumDescriptor; +using google::protobuf::EnumValueDescriptor; +; +; +using util::error::Code; +using util::Status; +using util::StatusOr; + +namespace { + +inline Status InvalidArgument(StringPiece value_str) { + return Status(util::error::INVALID_ARGUMENT, value_str); +} + +// For general conversion between +// int32, int64, uint32, uint64, double and float +// except conversion between double and float. +template +StatusOr NumberConvertAndCheck(From before) { + if (::google::protobuf::internal::is_same::value) return before; + To after = static_cast(before); + if (after == before && + MathUtil::Sign(before) == MathUtil::Sign(after)) { + return after; + } else { + return InvalidArgument(::google::protobuf::internal::is_integral::value + ? ValueAsString(before) + : ::google::protobuf::internal::is_same::value + ? DoubleAsString(before) + : FloatAsString(before)); + } +} + +// For conversion between double and float only. +template +StatusOr FloatingPointConvertAndCheck(From before) { + if (isnan(before)) return std::numeric_limits::quiet_NaN(); + + To after = static_cast(before); + if (MathUtil::AlmostEquals(after, before)) { + return after; + } else { + return InvalidArgument(::google::protobuf::internal::is_same::value + ? DoubleAsString(before) + : FloatAsString(before)); + } +} + +} // namespace + +StatusOr DataPiece::ToInt32() const { + if (type_ == TYPE_STRING) { + return StringToNumber(safe_strto32); + } + return GenericConvert(); +} + +StatusOr DataPiece::ToUint32() const { + if (type_ == TYPE_STRING) { + return StringToNumber(safe_strtou32); + } + return GenericConvert(); +} + +StatusOr DataPiece::ToInt64() const { + if (type_ == TYPE_STRING) { + return StringToNumber(safe_strto64); + } + return GenericConvert(); +} + +StatusOr DataPiece::ToUint64() const { + if (type_ == TYPE_STRING) { + return StringToNumber(safe_strtou64); + } + return GenericConvert(); +} + +StatusOr DataPiece::ToDouble() const { + if (type_ == TYPE_FLOAT) { + return FloatingPointConvertAndCheck(float_); + } + if (type_ == TYPE_STRING) { + if (str_ == "Infinity") return std::numeric_limits::infinity(); + if (str_ == "-Infinity") return -std::numeric_limits::infinity(); + if (str_ == "NaN") return std::numeric_limits::quiet_NaN(); + return StringToNumber(safe_strtod); + } + return GenericConvert(); +} + +StatusOr DataPiece::ToFloat() const { + if (type_ == TYPE_DOUBLE) { + return FloatingPointConvertAndCheck(double_); + } + if (type_ == TYPE_STRING) { + if (str_ == "Infinity") return std::numeric_limits::infinity(); + if (str_ == "-Infinity") return -std::numeric_limits::infinity(); + if (str_ == "NaN") return std::numeric_limits::quiet_NaN(); + // SafeStrToFloat() is used instead of safe_strtof() because the later + // does not fail on inputs like SimpleDtoa(DBL_MAX). + return StringToNumber(SafeStrToFloat); + } + return GenericConvert(); +} + +StatusOr DataPiece::ToBool() const { + switch (type_) { + case TYPE_BOOL: + return bool_; + case TYPE_STRING: + return StringToNumber(safe_strtob); + default: + return InvalidArgument( + ValueAsStringOrDefault("Wrong type. Cannot convert to Bool.")); + } +} + +StatusOr DataPiece::ToString() const { + switch (type_) { + case TYPE_STRING: + return str_.ToString(); + case TYPE_BYTES: { + string base64; + WebSafeBase64Escape(str_, &base64); + return base64; + } + default: + return InvalidArgument( + ValueAsStringOrDefault("Cannot convert to string.")); + } +} + +string DataPiece::ValueAsStringOrDefault(StringPiece default_string) const { + switch (type_) { + case TYPE_INT32: + return SimpleItoa(i32_); + case TYPE_INT64: + return SimpleItoa(i64_); + case TYPE_UINT32: + return SimpleItoa(u32_); + case TYPE_UINT64: + return SimpleItoa(u64_); + case TYPE_DOUBLE: + return DoubleAsString(double_); + case TYPE_FLOAT: + return FloatAsString(float_); + case TYPE_BOOL: + return SimpleBtoa(bool_); + case TYPE_STRING: + return StrCat("\"", str_.ToString(), "\""); + case TYPE_BYTES: { + string base64; + WebSafeBase64Escape(str_, &base64); + return StrCat("\"", base64, "\""); + } + case TYPE_NULL: + return "null"; + default: + return default_string.ToString(); + } +} + +StatusOr DataPiece::ToBytes() const { + if (type_ == TYPE_BYTES) return str_.ToString(); + if (type_ == TYPE_STRING) { + string decoded; + if (!WebSafeBase64Unescape(str_, &decoded)) { + if (!Base64Unescape(str_, &decoded)) { + return InvalidArgument( + ValueAsStringOrDefault("Invalid data in input.")); + } + } + return decoded; + } else { + return InvalidArgument(ValueAsStringOrDefault( + "Wrong type. Only String or Bytes can be converted to Bytes.")); + } +} + +StatusOr DataPiece::ToEnum(const google::protobuf::Enum* enum_type) const { + if (type_ == TYPE_NULL) return google::protobuf::NULL_VALUE; + + if (type_ == TYPE_STRING) { + // First try the given value as a name. + string enum_name = str_.ToString(); + const google::protobuf::EnumValue* value = + FindEnumValueByNameOrNull(enum_type, enum_name); + if (value != NULL) return value->number(); + // Next try a normalized name. + for (string::iterator it = enum_name.begin(); it != enum_name.end(); ++it) { + *it = *it == '-' ? '_' : ascii_toupper(*it); + } + value = FindEnumValueByNameOrNull(enum_type, enum_name); + if (value != NULL) return value->number(); + } else { + StatusOr value = ToInt32(); + if (value.ok()) { + if (const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumberOrNull(enum_type, value.ValueOrDie())) { + return enum_value->number(); + } + } + } + return InvalidArgument( + ValueAsStringOrDefault("Cannot find enum with given value.")); +} + +template +StatusOr DataPiece::GenericConvert() const { + switch (type_) { + case TYPE_INT32: + return NumberConvertAndCheck(i32_); + case TYPE_INT64: + return NumberConvertAndCheck(i64_); + case TYPE_UINT32: + return NumberConvertAndCheck(u32_); + case TYPE_UINT64: + return NumberConvertAndCheck(u64_); + case TYPE_DOUBLE: + return NumberConvertAndCheck(double_); + case TYPE_FLOAT: + return NumberConvertAndCheck(float_); + default: // TYPE_ENUM, TYPE_STRING, TYPE_CORD, TYPE_BOOL + return InvalidArgument(ValueAsStringOrDefault( + "Wrong type. Bool, Enum, String and Cord not supported in " + "GenericConvert.")); + } +} + +template +StatusOr DataPiece::StringToNumber(bool (*func)(StringPiece, To*)) const { + To result; + if (func(str_, &result)) return result; + return InvalidArgument(StrCat("\"", str_.ToString(), "\"")); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h new file mode 100644 index 00000000..30947252 --- /dev/null +++ b/src/google/protobuf/util/internal/datapiece.h @@ -0,0 +1,212 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ + +#include + +#include +#include +#include + + +namespace google { +namespace protobuf { +class Enum; +} // namespace protobuf + + +namespace protobuf { +namespace util { +namespace converter { + +// Container for a single piece of data together with its data type. +// +// For primitive types (int32, int64, uint32, uint64, double, float, bool), +// the data is stored by value. +// +// For string, a StringPiece is stored. For Cord, a pointer to Cord is stored. +// Just like StringPiece, the DataPiece class does not own the storage for +// the actual string or Cord, so it is the user's responsiblity to guarantee +// that the underlying storage is still valid when the DataPiece is accessed. +class LIBPROTOBUF_EXPORT DataPiece { + public: + // Identifies data type of the value. + // These are the types supported by DataPiece. + enum Type { + TYPE_INT32 = 1, + TYPE_INT64 = 2, + TYPE_UINT32 = 3, + TYPE_UINT64 = 4, + TYPE_DOUBLE = 5, + TYPE_FLOAT = 6, + TYPE_BOOL = 7, + TYPE_ENUM = 8, + TYPE_STRING = 9, + TYPE_BYTES = 10, + TYPE_NULL = 11, // explicit NULL type + }; + + // Constructors and Destructor + explicit DataPiece(const int32 value) : type_(TYPE_INT32), i32_(value) {} + explicit DataPiece(const int64 value) : type_(TYPE_INT64), i64_(value) {} + explicit DataPiece(const uint32 value) : type_(TYPE_UINT32), u32_(value) {} + explicit DataPiece(const uint64 value) : type_(TYPE_UINT64), u64_(value) {} + explicit DataPiece(const double value) : type_(TYPE_DOUBLE), double_(value) {} + explicit DataPiece(const float value) : type_(TYPE_FLOAT), float_(value) {} + explicit DataPiece(const bool value) : type_(TYPE_BOOL), bool_(value) {} + explicit DataPiece(StringPiece value) + : type_(TYPE_STRING), + str_(StringPiecePod::CreateFromStringPiece(value)) {} + // Constructor for bytes. The second parameter is not used. + explicit DataPiece(StringPiece value, bool dummy) + : type_(TYPE_BYTES), str_(StringPiecePod::CreateFromStringPiece(value)) {} + DataPiece(const DataPiece& r) : type_(r.type_), str_(r.str_) {} + DataPiece& operator=(const DataPiece& x) { + type_ = x.type_; + str_ = x.str_; + return *this; + } + + static DataPiece NullData() { return DataPiece(TYPE_NULL, 0); } + + virtual ~DataPiece() {} + + // Accessors + Type type() const { return type_; } + + StringPiece str() const { + GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type."; + return str_; + } + + + // Parses, casts or converts the value stored in the DataPiece into an int32. + util::StatusOr ToInt32() const; + + // Parses, casts or converts the value stored in the DataPiece into a uint32. + util::StatusOr ToUint32() const; + + // Parses, casts or converts the value stored in the DataPiece into an int64. + util::StatusOr ToInt64() const; + + // Parses, casts or converts the value stored in the DataPiece into a uint64. + util::StatusOr ToUint64() const; + + // Parses, casts or converts the value stored in the DataPiece into a double. + util::StatusOr ToDouble() const; + + // Parses, casts or converts the value stored in the DataPiece into a float. + util::StatusOr ToFloat() const; + + // Parses, casts or converts the value stored in the DataPiece into a bool. + util::StatusOr ToBool() const; + + // Parses, casts or converts the value stored in the DataPiece into a string. + util::StatusOr ToString() const; + + // Tries to convert the value contained in this datapiece to string. If the + // conversion fails, it returns the default_string. + string ValueAsStringOrDefault(StringPiece default_string) const; + + util::StatusOr ToBytes() const; + + // Converts a value into protocol buffer enum number. If the value is a + // string, first attempts conversion by name, trying names as follows: + // 1) the directly provided string value. + // 2) the value upper-cased and replacing '-' by '_' + // If the value is not a string, attempts to convert to a 32-bit integer. + // If none of these succeeds, returns a conversion error status. + util::StatusOr ToEnum(const google::protobuf::Enum* enum_type) const; + + private: + // Disallow implicit constructor. + DataPiece(); + + // Helper to create NULL or ENUM types. + DataPiece(Type type, int32 val) : type_(type), i32_(val) {} + + // For numeric conversion between + // int32, int64, uint32, uint64, double, float and bool + template + util::StatusOr GenericConvert() const; + + // For conversion from string to + // int32, int64, uint32, uint64, double, float and bool + template + util::StatusOr StringToNumber(bool (*func)(StringPiece, To*)) const; + + // Data type for this piece of data. + Type type_; + + // StringPiece is not a POD and can not be used in an union (pre C++11). We + // need a POD version of it. + struct StringPiecePod { + const char* data; + int size; + + // Create from a StringPiece. + static StringPiecePod CreateFromStringPiece(StringPiece str) { + StringPiecePod pod; + pod.data = str.data(); + pod.size = str.size(); + return pod; + } + + // Cast to StringPiece. + operator StringPiece() const { return StringPiece(data, size); } + + bool operator==(const char* value) const { + return StringPiece(data, size) == StringPiece(value); + } + + string ToString() const { return string(data, size); } + }; + + // Stored piece of data. + union { + const int32 i32_; + const int64 i64_; + const uint32 u32_; + const uint64 u64_; + const double double_; + const float float_; + const bool bool_; + StringPiecePod str_; + }; +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DATAPIECE_H__ diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc new file mode 100644 index 00000000..267e2cd3 --- /dev/null +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -0,0 +1,515 @@ +// 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 + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +using util::Status; +using util::StatusOr; +namespace converter { + +DefaultValueObjectWriter::DefaultValueObjectWriter( + TypeResolver* type_resolver, const google::protobuf::Type& type, + ObjectWriter* ow) + : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + type_(type), + disable_normalize_(false), + current_(NULL), + root_(NULL), + ow_(ow) {} + +DefaultValueObjectWriter::~DefaultValueObjectWriter() { + for (int i = 0; i < string_values_.size(); ++i) { + delete string_values_[i]; + } +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(StringPiece name, + bool value) { + if (current_ == NULL) { + ow_->RenderBool(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32( + StringPiece name, int32 value) { + if (current_ == NULL) { + ow_->RenderInt32(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32( + StringPiece name, uint32 value) { + if (current_ == NULL) { + ow_->RenderUint32(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64( + StringPiece name, int64 value) { + if (current_ == NULL) { + ow_->RenderInt64(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64( + StringPiece name, uint64 value) { + if (current_ == NULL) { + ow_->RenderUint64(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble( + StringPiece name, double value) { + if (current_ == NULL) { + ow_->RenderDouble(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat( + StringPiece name, float value) { + if (current_ == NULL) { + ow_->RenderBool(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString( + StringPiece name, StringPiece value) { + if (current_ == NULL) { + ow_->RenderString(name, value); + } else { + // Since StringPiece is essentially a pointer, takes a copy of "value" to + // avoid ownership issues. + string_values_.push_back(new string(value.ToString())); + RenderDataPiece(name, DataPiece(*string_values_.back())); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes( + StringPiece name, StringPiece value) { + if (current_ == NULL) { + ow_->RenderBytes(name, value); + } else { + RenderDataPiece(name, DataPiece(value)); + } + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull( + StringPiece name) { + if (current_ == NULL) { + ow_->RenderNull(name); + } else { + RenderDataPiece(name, DataPiece::NullData()); + } + return this; +} + +DefaultValueObjectWriter* +DefaultValueObjectWriter::DisableCaseNormalizationForNextKey() { + disable_normalize_ = true; + return this; +} + +DefaultValueObjectWriter::Node::Node(const string& name, + const google::protobuf::Type* type, + NodeKind kind, const DataPiece& data, + bool is_placeholder) + : name_(name), + type_(type), + kind_(kind), + disable_normalize_(false), + is_any_(false), + data_(data), + is_placeholder_(is_placeholder) {} + +DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild( + StringPiece name) { + if (name.empty() || kind_ != OBJECT) { + return NULL; + } + for (int i = 0; i < children_.size(); ++i) { + Node* child = children_[i]; + if (child->name() == name) { + return child; + } + } + return NULL; +} + +void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) { + if (disable_normalize_) { + ow->DisableCaseNormalizationForNextKey(); + } + if (kind_ == PRIMITIVE) { + ObjectWriter::RenderDataPieceTo(data_, name_, ow); + return; + } + if (is_placeholder_) { + // If is_placeholder_ = true, we didn't see this node in the response, so + // skip output. + return; + } + if (kind_ == LIST) { + ow->StartList(name_); + } else { + ow->StartObject(name_); + } + for (int i = 0; i < children_.size(); ++i) { + Node* child = children_[i]; + child->WriteTo(ow); + } + if (kind_ == LIST) { + ow->EndList(); + } else { + ow->EndObject(); + } +} + +const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType( + const google::protobuf::Type& found_type, TypeInfo* typeinfo) { + // If this field is a map, we should use the type of its "Value" as + // the type of the child node. + for (int i = 0; i < found_type.fields_size(); ++i) { + const google::protobuf::Field& sub_field = found_type.fields(i); + if (sub_field.number() != 2) { + continue; + } + if (sub_field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE) { + // This map's value type is not a message type. We don't need to + // get the field_type in this case. + break; + } + util::StatusOr sub_type = + typeinfo->ResolveTypeUrl(sub_field.type_url()); + if (!sub_type.ok()) { + GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'."; + } else { + return sub_type.ValueOrDie(); + } + break; + } + return NULL; +} + +void DefaultValueObjectWriter::Node::PopulateChildren(TypeInfo* typeinfo) { + // Ignores well known types that don't require automatically populating their + // primitive children. For type "Any", we only populate its children when the + // "@type" field is set. + // TODO(tsun): remove "kStructValueType" from the list. It's being checked + // now because of a bug in the tool-chain that causes the "oneof_index" + // of kStructValueType to not be set correctly. + if (type_ == NULL || type_->name() == kAnyType || + type_->name() == kStructType || type_->name() == kTimestampType || + type_->name() == kDurationType || type_->name() == kStructValueType) { + return; + } + std::vector new_children; + hash_map orig_children_map; + + // Creates a map of child nodes to speed up lookup. + for (int i = 0; i < children_.size(); ++i) { + InsertIfNotPresent(&orig_children_map, children_[i]->name_, i); + } + + for (int i = 0; i < type_->fields_size(); ++i) { + const google::protobuf::Field& field = type_->fields(i); + hash_map::iterator found = + orig_children_map.find(field.name()); + // If the child field has already been set, we just add it to the new list + // of children. + if (found != orig_children_map.end()) { + new_children.push_back(children_[found->second]); + children_[found->second] = NULL; + continue; + } + + const google::protobuf::Type* field_type = NULL; + bool is_map = false; + NodeKind kind = PRIMITIVE; + + if (field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { + kind = OBJECT; + util::StatusOr found_result = + typeinfo->ResolveTypeUrl(field.type_url()); + if (!found_result.ok()) { + // "field" is of an unknown type. + GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'."; + } else { + const google::protobuf::Type* found_type = found_result.ValueOrDie(); + is_map = IsMap(field, *found_type); + + if (!is_map) { + field_type = found_type; + } else { + // If this field is a map, we should use the type of its "Value" as + // the type of the child node. + field_type = GetMapValueType(*found_type, typeinfo); + kind = MAP; + } + } + } + if (!is_map && + field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + kind = LIST; + } + // If the child field is of primitive type, sets its data to the default + // value of its type. + // If oneof_index() != 0, the child field is part of a "oneof", which means + // the child field is optional and we shouldn't populate its default value. + google::protobuf::scoped_ptr child( + new Node(field.name(), field_type, kind, + ((kind == PRIMITIVE && field.oneof_index() == 0) + ? CreateDefaultDataPieceForField(field) + : DataPiece::NullData()), + true)); + new_children.push_back(child.release()); + } + // Adds all leftover nodes in children_ to the beginning of new_child. + for (int i = 0; i < children_.size(); ++i) { + if (children_[i] == NULL) { + continue; + } + new_children.insert(new_children.begin(), children_[i]); + children_[i] = NULL; + } + children_.swap(new_children); +} + +void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) { + // If this is an "Any" node with "@type" already given and no other children + // have been added, populates its children. + if (node != NULL && node->is_any() && node->type() != NULL && + node->type()->name() != kAnyType && node->number_of_children() == 1) { + node->PopulateChildren(typeinfo_.get()); + } +} + +DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField( + const google::protobuf::Field& field) { + switch (field.kind()) { + case google::protobuf::Field_Kind_TYPE_DOUBLE: { + return DataPiece(static_cast(0)); + } + case google::protobuf::Field_Kind_TYPE_FLOAT: { + return DataPiece(static_cast(0)); + } + case google::protobuf::Field_Kind_TYPE_INT64: + case google::protobuf::Field_Kind_TYPE_SINT64: + case google::protobuf::Field_Kind_TYPE_SFIXED64: { + return DataPiece(static_cast(0)); + } + case google::protobuf::Field_Kind_TYPE_UINT64: + case google::protobuf::Field_Kind_TYPE_FIXED64: { + return DataPiece(static_cast(0)); + } + case google::protobuf::Field_Kind_TYPE_INT32: + case google::protobuf::Field_Kind_TYPE_SINT32: + case google::protobuf::Field_Kind_TYPE_SFIXED32: { + return DataPiece(static_cast(0)); + } + case google::protobuf::Field_Kind_TYPE_BOOL: { + return DataPiece(false); + } + case google::protobuf::Field_Kind_TYPE_STRING: { + return DataPiece(string()); + } + case google::protobuf::Field_Kind_TYPE_BYTES: { + return DataPiece("", false); + } + case google::protobuf::Field_Kind_TYPE_UINT32: + case google::protobuf::Field_Kind_TYPE_FIXED32: { + return DataPiece(static_cast(0)); + } + default: { return DataPiece::NullData(); } + } +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( + StringPiece name) { + if (current_ == NULL) { + root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(), + false)); + root_->set_disable_normalize(GetAndResetDisableNormalize()); + root_->PopulateChildren(typeinfo_.get()); + current_ = root_.get(); + return this; + } + MaybePopulateChildrenOfAny(current_); + Node* child = current_->FindChild(name); + if (current_->kind() == LIST || current_->kind() == MAP || child == NULL) { + // If current_ is a list or a map node, we should create a new child and use + // the type of current_ as the type of the new child. + google::protobuf::scoped_ptr node(new Node( + name.ToString(), ((current_->kind() == LIST || current_->kind() == MAP) + ? current_->type() + : NULL), + OBJECT, DataPiece::NullData(), false)); + child = node.get(); + current_->AddChild(node.release()); + } + + child->set_is_placeholder(false); + child->set_disable_normalize(GetAndResetDisableNormalize()); + if (child->kind() == OBJECT && child->number_of_children() == 0) { + child->PopulateChildren(typeinfo_.get()); + } + + stack_.push(current_); + current_ = child; + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() { + if (stack_.empty()) { + // The root object ends here. Writes out the tree. + WriteRoot(); + return this; + } + current_ = stack_.top(); + stack_.pop(); + return this; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( + StringPiece name) { + if (current_ == NULL) { + root_.reset( + new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), false)); + root_->set_disable_normalize(GetAndResetDisableNormalize()); + current_ = root_.get(); + return this; + } + MaybePopulateChildrenOfAny(current_); + Node* child = current_->FindChild(name); + if (child == NULL || child->kind() != LIST) { + GOOGLE_LOG(WARNING) << "Cannot find field '" << name << "'."; + google::protobuf::scoped_ptr node( + new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false)); + child = node.get(); + current_->AddChild(node.release()); + } + child->set_is_placeholder(false); + child->set_disable_normalize(GetAndResetDisableNormalize()); + + stack_.push(current_); + current_ = child; + return this; +} + +void DefaultValueObjectWriter::WriteRoot() { + root_->WriteTo(ow_); + root_.reset(NULL); + current_ = NULL; +} + +DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() { + if (stack_.empty()) { + WriteRoot(); + return this; + } + current_ = stack_.top(); + stack_.pop(); + return this; +} + +void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, + const DataPiece& data) { + MaybePopulateChildrenOfAny(current_); + util::StatusOr data_string = data.ToString(); + if (current_->type() != NULL && current_->type()->name() == kAnyType && + name == "@type" && data_string.ok()) { + const string& string_value = data_string.ValueOrDie(); + // If the type of current_ is "Any" and its "@type" field is being set here, + // sets the type of current_ to be the type specified by the "@type". + util::StatusOr found_type = + typeinfo_->ResolveTypeUrl(string_value); + if (!found_type.ok()) { + GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'."; + } else { + current_->set_type(found_type.ValueOrDie()); + } + current_->set_is_any(true); + // If the "@type" field is placed after other fields, we should populate + // other children of primitive type now. Otherwise, we should wait until the + // first value field is rendered before we populate the children, because + // the "value" field of a Any message could be omitted. + if (current_->number_of_children() > 1 && current_->type() != NULL) { + current_->PopulateChildren(typeinfo_.get()); + } + } + Node* child = current_->FindChild(name); + if (child == NULL || child->kind() != PRIMITIVE) { + GOOGLE_LOG(WARNING) << "Cannot find primitive field '" << name << "'."; + // No children are found, creates a new child. + google::protobuf::scoped_ptr node( + new Node(name.ToString(), NULL, PRIMITIVE, data, false)); + child = node.get(); + current_->AddChild(node.release()); + } else { + child->set_data(data); + } + child->set_disable_normalize(GetAndResetDisableNormalize()); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h new file mode 100644 index 00000000..ae013aa4 --- /dev/null +++ b/src/google/protobuf/util/internal/default_value_objectwriter.h @@ -0,0 +1,238 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An ObjectWriter that renders non-repeated primitive fields of proto messages +// with their default values. DefaultValueObjectWriter holds objects, lists and +// fields it receives in a tree structure and writes them out to another +// ObjectWriter when EndObject() is called on the root object. It also writes +// out all non-repeated primitive fields that haven't been explicitly rendered +// with their default values (0 for numbers, "" for strings, etc). +class DefaultValueObjectWriter : public ObjectWriter { + public: + DefaultValueObjectWriter(TypeResolver* type_resolver, + const google::protobuf::Type& type, + ObjectWriter* ow); + + virtual ~DefaultValueObjectWriter(); + + // ObjectWriter methods. + virtual DefaultValueObjectWriter* StartObject(StringPiece name); + + virtual DefaultValueObjectWriter* EndObject(); + + virtual DefaultValueObjectWriter* StartList(StringPiece name); + + virtual DefaultValueObjectWriter* EndList(); + + virtual DefaultValueObjectWriter* RenderBool(StringPiece name, bool value); + + virtual DefaultValueObjectWriter* RenderInt32(StringPiece name, int32 value); + + virtual DefaultValueObjectWriter* RenderUint32(StringPiece name, + uint32 value); + + virtual DefaultValueObjectWriter* RenderInt64(StringPiece name, int64 value); + + virtual DefaultValueObjectWriter* RenderUint64(StringPiece name, + uint64 value); + + virtual DefaultValueObjectWriter* RenderDouble(StringPiece name, + double value); + + virtual DefaultValueObjectWriter* RenderFloat(StringPiece name, float value); + + virtual DefaultValueObjectWriter* RenderString(StringPiece name, + StringPiece value); + virtual DefaultValueObjectWriter* RenderBytes(StringPiece name, + StringPiece value); + + virtual DefaultValueObjectWriter* RenderNull(StringPiece name); + + virtual DefaultValueObjectWriter* DisableCaseNormalizationForNextKey(); + + private: + enum NodeKind { + PRIMITIVE = 0, + OBJECT = 1, + LIST = 2, + MAP = 3, + }; + + // "Node" represents a node in the tree that holds the input of + // DefaultValueObjectWriter. + class Node { + public: + Node(const string& name, const google::protobuf::Type* type, NodeKind kind, + const DataPiece& data, bool is_placeholder); + virtual ~Node() { + for (int i = 0; i < children_.size(); ++i) { + delete children_[i]; + } + } + + // Adds a child to this node. Takes ownership of this child. + void AddChild(Node* child) { children_.push_back(child); } + + // Finds the child given its name. + Node* FindChild(StringPiece name); + + // Populates children of this Node based on its type. If there are already + // children created, they will be merged to the result. Caller should pass + // in TypeInfo for looking up types of the children. + void PopulateChildren(TypeInfo* typeinfo); + + // If this node is a leaf (has data), writes the current node to the + // ObjectWriter; if not, then recursively writes the children to the + // ObjectWriter. + void WriteTo(ObjectWriter* ow); + + // Accessors + const string& name() const { return name_; } + + const google::protobuf::Type* type() { return type_; } + + void set_type(const google::protobuf::Type* type) { type_ = type; } + + NodeKind kind() { return kind_; } + + int number_of_children() { return children_.size(); } + + void set_data(const DataPiece& data) { data_ = data; } + + void set_disable_normalize(bool disable_normalize) { + disable_normalize_ = disable_normalize; + } + + bool is_any() { return is_any_; } + + void set_is_any(bool is_any) { is_any_ = is_any; } + + void set_is_placeholder(bool is_placeholder) { + is_placeholder_ = is_placeholder; + } + + private: + // Returns the Value Type of a map given the Type of the map entry and a + // TypeInfo instance. + const google::protobuf::Type* GetMapValueType( + const google::protobuf::Type& entry_type, TypeInfo* typeinfo); + + // The name of this node. + string name_; + // google::protobuf::Type of this node. Owned by TypeInfo. + const google::protobuf::Type* type_; + // The kind of this node. + NodeKind kind_; + // Whether to disable case normalization of the name. + bool disable_normalize_; + // Whether this is a node for "Any". + bool is_any_; + // The data of this node when it is a leaf node. + DataPiece data_; + // Children of this node. + std::vector children_; + // Whether this node is a placeholder for an object or list automatically + // generated when creating the parent node. Should be set to false after + // the parent node's StartObject()/StartList() method is called with this + // node's name. + bool is_placeholder_; + }; + + // Populates children of "node" if it is an "any" Node and its real type has + // been given. + void MaybePopulateChildrenOfAny(Node* node); + + // Writes the root_ node to ow_ and resets the root_ and current_ pointer to + // NULL. + void WriteRoot(); + + // Creates a DataPiece containing the default value of the type of the field. + static DataPiece CreateDefaultDataPieceForField( + const google::protobuf::Field& field); + + // Returns disable_normalize_ and reset it to false. + bool GetAndResetDisableNormalize() { + return disable_normalize_ ? (disable_normalize_ = false, true) : false; + } + + // Adds or replaces the data_ of a primitive child node. + void RenderDataPiece(StringPiece name, const DataPiece& data); + + // Type information for all the types used in the descriptor. Used to find + // google::protobuf::Type of nested messages/enums. + google::protobuf::scoped_ptr typeinfo_; + // google::protobuf::Type of the root message type. + const google::protobuf::Type& type_; + // Holds copies of strings passed to RenderString. + vector string_values_; + + // Whether to disable case normalization of the next node. + bool disable_normalize_; + // The current Node. Owned by its parents. + Node* current_; + // The root Node. + google::protobuf::scoped_ptr root_; + // The stack to hold the path of Nodes from current_ to root_; + std::stack stack_; + + ObjectWriter* ow_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_DEFAULT_VALUE_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc new file mode 100644 index 00000000..593c7105 --- /dev/null +++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc @@ -0,0 +1,139 @@ +// 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 +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +namespace testing { + +using google::protobuf::testing::DefaultValueTest; + +// Tests to cover some basic DefaultValueObjectWriter use cases. More tests are +// in the marshalling_test.cc and translator_integration_test.cc. +class DefaultValueObjectWriterTest + : public ::testing::TestWithParam { + protected: + DefaultValueObjectWriterTest() + : helper_(GetParam()), mock_(), expects_(&mock_) { + helper_.ResetTypeInfo(DefaultValueTest::descriptor()); + testing_.reset(helper_.NewDefaultValueWriter( + string(kTypeServiceBaseUrl) + "/" + + DefaultValueTest::descriptor()->full_name(), + &mock_)); + } + + virtual ~DefaultValueObjectWriterTest() {} + + TypeInfoTestHelper helper_; + MockObjectWriter mock_; + ExpectingObjectWriter expects_; + google::protobuf::scoped_ptr testing_; +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + DefaultValueObjectWriterTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(DefaultValueObjectWriterTest, Empty) { + // Set expectation + expects_.StartObject("") + ->RenderDouble("double_value", 0.0) + ->RenderFloat("float_value", 0.0) + ->RenderInt64("int64_value", 0) + ->RenderUint64("uint64_value", 0) + ->RenderInt32("int32_value", 0) + ->RenderUint32("uint32_value", 0) + ->RenderBool("bool_value", false) + ->RenderString("string_value", "") + ->RenderBytes("bytes_value", "") + ->EndObject(); + + // Actual testing + testing_->StartObject("")->EndObject(); +} + +TEST_P(DefaultValueObjectWriterTest, NonDefaultDouble) { + // Set expectation + expects_.StartObject("") + ->RenderDouble("double_value", 1.0) + ->RenderFloat("float_value", 0.0) + ->RenderInt64("int64_value", 0) + ->RenderUint64("uint64_value", 0) + ->RenderInt32("int32_value", 0) + ->RenderUint32("uint32_value", 0) + ->RenderBool("bool_value", false) + ->RenderString("string_value", "") + ->EndObject(); + + // Actual testing + testing_->StartObject("")->RenderDouble("double_value", 1.0)->EndObject(); +} + +TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) { + // Set expectation + expects_.StartObject("") + ->RenderDouble("double_value", 1.0) + ->RenderFloat("float_value", 0.0) + ->RenderInt64("int64_value", 0) + ->RenderUint64("uint64_value", 0) + ->RenderInt32("int32_value", 0) + ->RenderUint32("uint32_value", 0) + ->RenderBool("bool_value", false) + ->RenderString("string_value", "") + ->RenderString("unknown", "abc") + ->StartObject("unknown_object") + ->RenderString("unknown", "def") + ->EndObject() + ->EndObject(); + + // Actual testing + testing_->StartObject("") + ->RenderDouble("double_value", 1.0) + ->RenderString("unknown", "abc") + ->StartObject("unknown_object") + ->RenderString("unknown", "def") + ->EndObject() + ->EndObject(); +} + +} // namespace testing +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/error_listener.cc b/src/google/protobuf/util/internal/error_listener.cc new file mode 100644 index 00000000..538307ba --- /dev/null +++ b/src/google/protobuf/util/internal/error_listener.cc @@ -0,0 +1,42 @@ +// 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 + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h new file mode 100644 index 00000000..9b907df5 --- /dev/null +++ b/src/google/protobuf/util/internal/error_listener.h @@ -0,0 +1,99 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__ + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// Interface for error listener. +class LIBPROTOBUF_EXPORT ErrorListener { + public: + virtual ~ErrorListener() {} + + // Reports an invalid name at the given location. + virtual void InvalidName(const LocationTrackerInterface& loc, + StringPiece unknown_name, StringPiece message) = 0; + + // Reports an invalid value for a field. + virtual void InvalidValue(const LocationTrackerInterface& loc, + StringPiece type_name, StringPiece value) = 0; + + // Reports a missing required field. + virtual void MissingField(const LocationTrackerInterface& loc, + StringPiece missing_name) = 0; + + protected: + ErrorListener() {} + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorListener); +}; + +// An error listener that ignores all errors. +class LIBPROTOBUF_EXPORT NoopErrorListener : public ErrorListener { + public: + NoopErrorListener() {} + virtual ~NoopErrorListener() {} + + virtual void InvalidName(const LocationTrackerInterface& loc, + StringPiece unknown_name, StringPiece message) {} + + virtual void InvalidValue(const LocationTrackerInterface& loc, + StringPiece type_name, StringPiece value) {} + + virtual void MissingField(const LocationTrackerInterface& loc, + StringPiece missing_name) {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener); +}; + + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_ERROR_LISTENER_H__ diff --git a/src/google/protobuf/util/internal/expecting_objectwriter.h b/src/google/protobuf/util/internal/expecting_objectwriter.h new file mode 100644 index 00000000..75096221 --- /dev/null +++ b/src/google/protobuf/util/internal/expecting_objectwriter.h @@ -0,0 +1,238 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__ + +// An implementation of ObjectWriter that automatically sets the +// gmock expectations for the response to a method. Every method +// returns the object itself for chaining. +// +// Usage: +// // Setup +// MockObjectWriter mock; +// ExpectingObjectWriter ow(&mock); +// +// // Set expectation +// ow.StartObject("") +// ->RenderString("key", "value") +// ->EndObject(); +// +// // Actual testing +// mock.StartObject(StringPiece()) +// ->RenderString("key", "value") +// ->EndObject(); + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using testing::IsEmpty; +using testing::NanSensitiveDoubleEq; +using testing::NanSensitiveFloatEq; +using testing::Return; +using testing::StrEq; +using testing::TypedEq; + +class MockObjectWriter : public ObjectWriter { + public: + MockObjectWriter() {} + + MOCK_METHOD1(StartObject, ObjectWriter*(StringPiece)); + MOCK_METHOD0(EndObject, ObjectWriter*()); + MOCK_METHOD1(StartList, ObjectWriter*(StringPiece)); + MOCK_METHOD0(EndList, ObjectWriter*()); + MOCK_METHOD2(RenderBool, ObjectWriter*(StringPiece, const bool)); + MOCK_METHOD2(RenderInt32, ObjectWriter*(StringPiece, const int32)); + MOCK_METHOD2(RenderUint32, ObjectWriter*(StringPiece, const uint32)); + MOCK_METHOD2(RenderInt64, ObjectWriter*(StringPiece, const int64)); + MOCK_METHOD2(RenderUint64, ObjectWriter*(StringPiece, const uint64)); + MOCK_METHOD2(RenderDouble, ObjectWriter*(StringPiece, const double)); + MOCK_METHOD2(RenderFloat, ObjectWriter*(StringPiece, const float)); + MOCK_METHOD2(RenderString, ObjectWriter*(StringPiece, StringPiece)); + MOCK_METHOD2(RenderBytes, ObjectWriter*(StringPiece, StringPiece)); + MOCK_METHOD1(RenderNull, ObjectWriter*(StringPiece)); +}; + +class ExpectingObjectWriter : public ObjectWriter { + public: + explicit ExpectingObjectWriter(MockObjectWriter* mock) : mock_(mock) {} + + virtual ObjectWriter* StartObject(StringPiece name) { + (name.empty() + ? EXPECT_CALL(*mock_, StartObject(IsEmpty())) + : EXPECT_CALL(*mock_, StartObject(StrEq(name.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* EndObject() { + EXPECT_CALL(*mock_, EndObject()) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* StartList(StringPiece name) { + (name.empty() + ? EXPECT_CALL(*mock_, StartList(IsEmpty())) + : EXPECT_CALL(*mock_, StartList(StrEq(name.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* EndList() { + EXPECT_CALL(*mock_, EndList()) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderBool(StringPiece name, const bool value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq(value))) + : EXPECT_CALL(*mock_, RenderBool(StrEq(name.ToString()), + TypedEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderInt32(StringPiece name, const int32 value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderInt32(IsEmpty(), TypedEq(value))) + : EXPECT_CALL(*mock_, RenderInt32(StrEq(name.ToString()), + TypedEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderUint32(StringPiece name, const uint32 value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderUint32(IsEmpty(), TypedEq(value))) + : EXPECT_CALL(*mock_, RenderUint32(StrEq(name.ToString()), + TypedEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderInt64(StringPiece name, const int64 value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderInt64(IsEmpty(), TypedEq(value))) + : EXPECT_CALL(*mock_, RenderInt64(StrEq(name.ToString()), + TypedEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderUint64(StringPiece name, const uint64 value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderUint64(IsEmpty(), TypedEq(value))) + : EXPECT_CALL(*mock_, RenderUint64(StrEq(name.ToString()), + TypedEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderDouble(StringPiece name, const double value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderDouble(IsEmpty(), + NanSensitiveDoubleEq(value))) + : EXPECT_CALL(*mock_, RenderDouble(StrEq(name.ToString()), + NanSensitiveDoubleEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderFloat(StringPiece name, const float value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderFloat(IsEmpty(), + NanSensitiveFloatEq(value))) + : EXPECT_CALL(*mock_, RenderFloat(StrEq(name.ToString()), + NanSensitiveFloatEq(value)))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderString(IsEmpty(), + TypedEq(value.ToString()))) + : EXPECT_CALL(*mock_, RenderString(StrEq(name.ToString()), + TypedEq(value.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) { + (name.empty() + ? EXPECT_CALL(*mock_, RenderBytes(IsEmpty(), TypedEq( + value.ToString()))) + : EXPECT_CALL(*mock_, + RenderBytes(StrEq(name.ToString()), + TypedEq(value.ToString())))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation(); + return this; + } + + virtual ObjectWriter* RenderNull(StringPiece name) { + (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty())) + : EXPECT_CALL(*mock_, RenderNull(StrEq(name.ToString()))) + .WillOnce(Return(mock_)) + .RetiresOnSaturation()); + return this; + } + + private: + MockObjectWriter* mock_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ExpectingObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_EXPECTING_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc new file mode 100644 index 00000000..92468959 --- /dev/null +++ b/src/google/protobuf/util/internal/field_mask_utility.cc @@ -0,0 +1,228 @@ +// 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 + +#include +#include + +namespace google { + +namespace protobuf { +namespace util { +namespace converter { + +namespace { +inline util::Status CallPathSink(PathSinkCallback path_sink, + StringPiece arg) { + return path_sink->Run(arg); +} + +util::Status CreatePublicError(util::error::Code code, + const string& message) { + return util::Status(code, message); +} + +// Appends a FieldMask path segment to a prefix. +string AppendPathSegmentToPrefix(StringPiece prefix, StringPiece segment) { + if (prefix.empty()) { + return segment.ToString(); + } + if (segment.empty()) { + return prefix.ToString(); + } + // If the segment is a map key, appends it to the prefix without the ".". + if (segment.starts_with("[\"")) { + return StrCat(prefix, segment); + } + return StrCat(prefix, ".", segment); +} + +} // namespace + +string ConvertFieldMaskPath(const StringPiece path, + ConverterCallback converter) { + string result; + result.reserve(path.size() << 1); + + bool is_quoted = false; + bool is_escaping = false; + int current_segment_start = 0; + + // Loops until 1 passed the end of the input to make handling the last + // segment easier. + for (size_t i = 0; i <= path.size(); ++i) { + // Outputs quoted string as-is. + if (is_quoted) { + if (i == path.size()) { + break; + } + result.push_back(path[i]); + if (is_escaping) { + is_escaping = false; + } else if (path[i] == '\\') { + is_escaping = true; + } else if (path[i] == '\"') { + current_segment_start = i + 1; + is_quoted = false; + } + continue; + } + if (i == path.size() || path[i] == '.' || path[i] == '(' || + path[i] == ')' || path[i] == '\"') { + result += converter( + path.substr(current_segment_start, i - current_segment_start)); + if (i < path.size()) { + result.push_back(path[i]); + } + current_segment_start = i + 1; + } + if (i < path.size() && path[i] == '\"') { + is_quoted = true; + } + } + return result; +} + +util::Status DecodeCompactFieldMaskPaths(StringPiece paths, + PathSinkCallback path_sink) { + stack prefix; + int length = paths.length(); + int previous_position = 0; + bool in_map_key = false; + bool is_escaping = false; + // Loops until 1 passed the end of the input to make the handle of the last + // segment easier. + for (int i = 0; i <= length; ++i) { + if (i != length) { + // Skips everything in a map key until we hit the end of it, which is + // marked by an un-escaped '"' immediately followed by a ']'. + if (in_map_key) { + if (is_escaping) { + is_escaping = false; + continue; + } + if (paths[i] == '\\') { + is_escaping = true; + continue; + } + if (paths[i] != '\"') { + continue; + } + // Un-escaped '"' must be followed with a ']'. + if (i >= length - 1 || paths[i + 1] != ']') { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Map keys should be represented as [\"some_key\"].")); + } + // The end of the map key ("\"]") has been found. + in_map_key = false; + // Skips ']'. + i++; + // Checks whether the key ends at the end of a path segment. + if (i < length - 1 && paths[i + 1] != '.' && paths[i + 1] != ',' && + paths[i + 1] != ')' && paths[i + 1] != '(') { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Map keys should be at the end of a path segment.")); + } + is_escaping = false; + continue; + } + + // We are not in a map key, look for the start of one. + if (paths[i] == '[') { + if (i >= length - 1 || paths[i + 1] != '\"') { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Map keys should be represented as [\"some_key\"].")); + } + // "[\"" starts a map key. + in_map_key = true; + i++; // Skips the '\"'. + continue; + } + // If the current character is not a special character (',', '(' or ')'), + // continue to the next. + if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') { + continue; + } + } + // Gets the current segment - sub-string between previous position (after + // '(', ')', ',', or the beginning of the input) and the current position. + StringPiece segment = + paths.substr(previous_position, i - previous_position); + string current_prefix = prefix.empty() ? "" : prefix.top(); + + if (i < length && paths[i] == '(') { + // Builds a prefix and save it into the stack. + prefix.push(AppendPathSegmentToPrefix(current_prefix, segment)); + } else if (!segment.empty()) { + // When the current charactor is ')', ',' or the current position has + // passed the end of the input, builds and outputs a new paths by + // concatenating the last prefix with the current segment. + RETURN_IF_ERROR(CallPathSink( + path_sink, AppendPathSegmentToPrefix(current_prefix, segment))); + } + + // Removes the last prefix after seeing a ')'. + if (i < length && paths[i] == ')') { + if (prefix.empty()) { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching '(' for all ')'.")); + } + prefix.pop(); + } + previous_position = i + 1; + } + if (in_map_key) { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ']' for all '['.")); + } + if (!prefix.empty()) { + return CreatePublicError( + util::error::INVALID_ARGUMENT, + StrCat("Invalid FieldMask '", paths, + "'. Cannot find matching ')' for all '('.")); + } + return util::Status::OK; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h new file mode 100644 index 00000000..59f36f75 --- /dev/null +++ b/src/google/protobuf/util/internal/field_mask_utility.h @@ -0,0 +1,72 @@ +// 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. + +// FieldMask related utility methods. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ + +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +typedef string (*ConverterCallback)(StringPiece); +typedef ResultCallback1* PathSinkCallback; + +// Applies a 'converter' to each segment of a FieldMask path and returns the +// result. Quoted strings in the 'path' are copied to the output as-is without +// converting their content. Escaping is supported within quoted strings. +// For example, "ab\"_c" will be returned as "ab\"_c" without any changes. +string ConvertFieldMaskPath(const StringPiece path, + ConverterCallback converter); + +// Decodes a compact list of FieldMasks. For example, "a.b,a.c.d,a.c.e" will be +// decoded into a list of field paths - "a.b", "a.c.d", "a.c.e". And the results +// will be sent to 'path_sink', i.e. 'path_sink' will be called once per +// resulting path. +// Note that we also support Apiary style FieldMask form. The above example in +// the Apiary style will look like "a.b,a.c(d,e)". +util::Status DecodeCompactFieldMaskPaths(StringPiece paths, + PathSinkCallback path_sink); + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_FIELD_MASK_UTILITY_H__ diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc new file mode 100644 index 00000000..5ac23421 --- /dev/null +++ b/src/google/protobuf/util/internal/json_escaping.cc @@ -0,0 +1,403 @@ +// 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 + +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { + +// Array of hex characters for conversion to hex. +static const char kHex[] = "0123456789abcdef"; + +// Characters 0x00 to 0x9f are very commonly used, so we provide a special +// table lookup. +// +// For unicode code point ch < 0xa0: +// kCommonEscapes[ch] is the escaped string of ch, if escaping is needed; +// or an empty string, if escaping is not needed. +static const char kCommonEscapes[160][7] = { + // C0 (ASCII and derivatives) control characters + "\\u0000", "\\u0001", "\\u0002", "\\u0003", // 0x00 + "\\u0004", "\\u0005", "\\u0006", "\\u0007", + "\\b", "\\t", "\\n", "\\u000b", + "\\f", "\\r", "\\u000e", "\\u000f", + "\\u0010", "\\u0011", "\\u0012", "\\u0013", // 0x10 + "\\u0014", "\\u0015", "\\u0016", "\\u0017", + "\\u0018", "\\u0019", "\\u001a", "\\u001b", + "\\u001c", "\\u001d", "\\u001e", "\\u001f", + // Escaping of " and \ are required by www.json.org string definition. + // Escaping of < and > are required for HTML security. + "", "", "\\\"", "", "", "", "", "", // 0x20 + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", // 0x30 + "", "", "", "", "\\u003c", "", "\\u003e", "", + "", "", "", "", "", "", "", "", // 0x40 + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", // 0x50 + "", "", "", "", "\\\\", "", "", "", + "", "", "", "", "", "", "", "", // 0x60 + "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", // 0x70 + "", "", "", "", "", "", "", "\\u007f", + // C1 (ISO 8859 and Unicode) extended control characters + "\\u0080", "\\u0081", "\\u0082", "\\u0083", // 0x80 + "\\u0084", "\\u0085", "\\u0086", "\\u0087", + "\\u0088", "\\u0089", "\\u008a", "\\u008b", + "\\u008c", "\\u008d", "\\u008e", "\\u008f", + "\\u0090", "\\u0091", "\\u0092", "\\u0093", // 0x90 + "\\u0094", "\\u0095", "\\u0096", "\\u0097", + "\\u0098", "\\u0099", "\\u009a", "\\u009b", + "\\u009c", "\\u009d", "\\u009e", "\\u009f" +}; + +// Determines if the given char value is a unicode high-surrogate code unit. +// Such values do not represent characters by themselves, but are used in the +// representation of supplementary characters in the utf-16 encoding. +inline bool IsHighSurrogate(uint16 c) { + // Optimized form of: + // return c >= kMinHighSurrogate && c <= kMaxHighSurrogate; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (c & ~(JsonEscaping::kMaxHighSurrogate - + JsonEscaping::kMinHighSurrogate)) + == JsonEscaping::kMinHighSurrogate; +} + +// Determines if the given char value is a unicode low-surrogate code unit. +// Such values do not represent characters by themselves, but are used in the +// representation of supplementary characters in the utf-16 encoding. +inline bool IsLowSurrogate(uint16 c) { + // Optimized form of: + // return c >= kMinLowSurrogate && c <= kMaxLowSurrogate; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (c & ~(JsonEscaping::kMaxLowSurrogate - + JsonEscaping::kMinLowSurrogate)) + == JsonEscaping::kMinLowSurrogate; +} + +// Determines if the given char value is a unicode surrogate code unit (either +// high-surrogate or low-surrogate). +inline bool IsSurrogate(uint32 c) { + // Optimized form of: + // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (c & 0xfffff800) == JsonEscaping::kMinHighSurrogate; +} + +// Returns true if the given unicode code point cp is +// in the supplementary character range. +inline bool IsSupplementalCodePoint(uint32 cp) { + // Optimized form of: + // return kMinSupplementaryCodePoint <= cp && cp <= kMaxCodePoint; + // (Reduced from 3 ALU instructions to 2 ALU instructions) + return (cp & ~(JsonEscaping::kMinSupplementaryCodePoint - 1)) + < JsonEscaping::kMaxCodePoint; +} + +// Returns true if the given unicode code point cp is a valid +// unicode code point (i.e. in the range 0 <= cp <= kMaxCodePoint). +inline bool IsValidCodePoint(uint32 cp) { + return cp <= JsonEscaping::kMaxCodePoint; +} + +// Converts the specified surrogate pair to its supplementary code point value. +// It is the callers' responsibility to validate the specified surrogate pair. +inline uint32 ToCodePoint(uint16 high, uint16 low) { + // Optimized form of: + // return ((high - kMinHighSurrogate) << 10) + // + (low - kMinLowSurrogate) + // + kMinSupplementaryCodePoint; + // (Reduced from 5 ALU instructions to 3 ALU instructions) + return (high << 10) + low + + (JsonEscaping::kMinSupplementaryCodePoint + - (static_cast(JsonEscaping::kMinHighSurrogate) << 10) + - JsonEscaping::kMinLowSurrogate); +} + +// Returns the low surrogate for the given unicode code point. The result is +// meaningless if the given code point is not a supplementary character. +inline uint16 ToLowSurrogate(uint32 cp) { + return (cp & (JsonEscaping::kMaxLowSurrogate + - JsonEscaping::kMinLowSurrogate)) + + JsonEscaping::kMinLowSurrogate; +} + +// Returns the high surrogate for the given unicode code point. The result is +// meaningless if the given code point is not a supplementary character. +inline uint16 ToHighSurrogate(uint32 cp) { + return (cp >> 10) + (JsonEscaping::kMinHighSurrogate - + (JsonEscaping::kMinSupplementaryCodePoint >> 10)); +} + +// Input str is encoded in UTF-8. A unicode code point could be encoded in +// UTF-8 using anywhere from 1 to 4 characters, and it could span multiple +// reads of the ByteSource. +// +// This function reads the next unicode code point from the input (str) at +// the given position (index), taking into account any left-over partial +// code point from the previous iteration (cp), together with the number +// of characters left to read to complete this code point (num_left). +// +// This function assumes that the input (str) is valid at the given position +// (index). In order words, at least one character could be read successfully. +// +// The code point read (partial or complete) is stored in (cp). Upon return, +// (num_left) stores the number of characters that has yet to be read in +// order to complete the current unicode code point. If the read is complete, +// then (num_left) is 0. Also, (num_read) is the number of characters read. +// +// Returns false if we encounter an invalid UTF-8 string. Returns true +// otherwise, including the case when we reach the end of the input (str) +// before a complete unicode code point is read. +bool ReadCodePoint(StringPiece str, int index, + uint32 *cp, int* num_left, int *num_read) { + if (*num_left == 0) { + // Last read was complete. Start reading a new unicode code point. + *cp = str[index++]; + *num_read = 1; + // The length of the code point is determined from reading the first byte. + // + // If the first byte is between: + // 0..0x7f: that's the value of the code point. + // 0x80..0xbf: + // 0xc0..0xdf: 11-bit code point encoded in 2 bytes. + // bit 10-6, bit 5-0 + // 0xe0..0xef: 16-bit code point encoded in 3 bytes. + // bit 15-12, bit 11-6, bit 5-0 + // 0xf0..0xf7: 21-bit code point encoded in 4 bytes. + // bit 20-18, bit 17-12, bit 11-6, bit 5-0 + // 0xf8..0xff: + // + // Meaning of each bit: + // bit 7: 0 - single byte code point: bits 6-0 are values. + // 1 - multibyte code point + // bit 6: 0 - subsequent bytes of multibyte code point: + // bits 5-0 are values. + // 1 - first byte of multibyte code point + // bit 5: 0 - first byte of 2-byte code point: bits 4-0 are values. + // 1 - first byte of code point with >= 3 bytes. + // bit 4: 0 - first byte of 3-byte code point: bits 3-0 are values. + // 1 - first byte of code point with >= 4 bytes. + // bit 3: 0 - first byte of 4-byte code point: bits 2-0 are values. + // 1 - reserved for future expansion. + if (*cp <= 0x7f) { + return true; + } else if (*cp <= 0xbf) { + return false; + } else if (*cp <= 0xdf) { + *cp &= 0x1f; + *num_left = 1; + } else if (*cp <= 0xef) { + *cp &= 0x0f; + *num_left = 2; + } else if (*cp <= 0xf7) { + *cp &= 0x07; + *num_left = 3; + } else { + return false; + } + } else { + // Last read was partial. Initialize num_read to 0 and continue reading + // the last unicode code point. + *num_read = 0; + } + while (*num_left > 0 && index < str.size()) { + uint32 ch = str[index++]; + --(*num_left); + ++(*num_read); + *cp = (*cp << 6) | (ch & 0x3f); + if (ch < 0x80 || ch > 0xbf) return false; + } + return *num_left > 0 || (!IsSurrogate(*cp) && IsValidCodePoint(*cp)); +} + +// Stores the 16-bit unicode code point as its hexadecimal digits in buffer +// and returns a StringPiece that points to this buffer. The input buffer needs +// to be at least 6 bytes long. +StringPiece ToHex(uint16 cp, char* buffer) { + buffer[5] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[4] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[3] = kHex[cp & 0x0f]; + cp >>= 4; + buffer[2] = kHex[cp & 0x0f]; + return StringPiece(buffer, 0, 6); +} + +// Stores the 32-bit unicode code point as its hexadecimal digits in buffer +// and returns a StringPiece that points to this buffer. The input buffer needs +// to be at least 12 bytes long. +StringPiece ToSurrogateHex(uint32 cp, char* buffer) { + uint16 low = ToLowSurrogate(cp); + uint16 high = ToHighSurrogate(cp); + + buffer[11] = kHex[low & 0x0f]; + low >>= 4; + buffer[10] = kHex[low & 0x0f]; + low >>= 4; + buffer[9] = kHex[low & 0x0f]; + low >>= 4; + buffer[8] = kHex[low & 0x0f]; + + buffer[5] = kHex[high & 0x0f]; + high >>= 4; + buffer[4] = kHex[high & 0x0f]; + high >>= 4; + buffer[3] = kHex[high & 0x0f]; + high >>= 4; + buffer[2] = kHex[high & 0x0f]; + + return StringPiece(buffer, 12); +} + +// If the given unicode code point needs escaping, then returns the +// escaped form. The returned StringPiece either points to statically +// pre-allocated char[] or to the given buffer. The input buffer needs +// to be at least 12 bytes long. +// +// If the given unicode code point does not need escaping, an empty +// StringPiece is returned. +StringPiece EscapeCodePoint(uint32 cp, char* buffer) { + if (cp < 0xa0) return kCommonEscapes[cp]; + switch (cp) { + // These are not required by json spec + // but used to prevent security bugs in javascript. + case 0xfeff: // Zero width no-break space + case 0xfff9: // Interlinear annotation anchor + case 0xfffa: // Interlinear annotation separator + case 0xfffb: // Interlinear annotation terminator + + case 0x00ad: // Soft-hyphen + case 0x06dd: // Arabic end of ayah + case 0x070f: // Syriac abbreviation mark + case 0x17b4: // Khmer vowel inherent Aq + case 0x17b5: // Khmer vowel inherent Aa + return ToHex(cp, buffer); + + default: + if ((cp >= 0x0600 && cp <= 0x0603) || // Arabic signs + (cp >= 0x200b && cp <= 0x200f) || // Zero width etc. + (cp >= 0x2028 && cp <= 0x202e) || // Separators etc. + (cp >= 0x2060 && cp <= 0x2064) || // Invisible etc. + (cp >= 0x206a && cp <= 0x206f)) { // Shaping etc. + return ToHex(cp, buffer); + } + + if (cp == 0x000e0001 || // Language tag + (cp >= 0x0001d173 && cp <= 0x0001d17a) || // Music formatting + (cp >= 0x000e0020 && cp <= 0x000e007f)) { // TAG symbols + return ToSurrogateHex(cp, buffer); + } + } + return StringPiece(); +} + +// Tries to escape the given code point first. If the given code point +// does not need to be escaped, but force_output is true, then render +// the given multi-byte code point in UTF8 in the buffer and returns it. +StringPiece EscapeCodePoint(uint32 cp, char* buffer, bool force_output) { + StringPiece sp = EscapeCodePoint(cp, buffer); + if (force_output && sp.empty()) { + buffer[5] = (cp & 0x3f) | 0x80; + cp >>= 6; + if (cp <= 0x1f) { + buffer[4] = cp | 0xc0; + sp.set(buffer + 4, 2); + return sp; + } + buffer[4] = (cp & 0x3f) | 0x80; + cp >>= 6; + if (cp <= 0x0f) { + buffer[3] = cp | 0xe0; + sp.set(buffer + 3, 3); + return sp; + } + buffer[3] = (cp & 0x3f) | 0x80; + buffer[2] = ((cp >> 6) & 0x07) | 0xf0; + sp.set(buffer + 2, 4); + } + return sp; +} + +} // namespace + +void JsonEscaping::Escape(strings::ByteSource* input, + strings::ByteSink* output) { + char buffer[12] = "\\udead\\ubee"; + uint32 cp = 0; // Current unicode code point. + int num_left = 0; // Num of chars to read to complete the code point. + while (input->Available() > 0) { + StringPiece str = input->Peek(); + StringPiece escaped; + int i = 0; + int num_read; + bool ok; + bool cp_was_split = num_left > 0; + // Loop until we encounter either + // i) a code point that needs to be escaped; or + // ii) a split code point is completely read; or + // iii) a character that is not a valid utf8; or + // iv) end of the StringPiece str is reached. + do { + ok = ReadCodePoint(str, i, &cp, &num_left, &num_read); + if (num_left > 0 || !ok) break; // case iii or iv + escaped = EscapeCodePoint(cp, buffer, cp_was_split); + if (!escaped.empty()) break; // case i or ii + i += num_read; + num_read = 0; + } while (i < str.length()); // case iv + // First copy the un-escaped prefix, if any, to the output ByteSink. + if (i > 0) input->CopyTo(output, i); + if (num_read > 0) input->Skip(num_read); + if (!ok) { + // Case iii: Report error. + // TODO(wpoon): Add error reporting. + num_left = 0; + } else if (num_left == 0 && !escaped.empty()) { + // Case i or ii: Append the escaped code point to the output ByteSink. + output->Append(escaped.data(), escaped.size()); + } + } + if (num_left > 0) { + // Treat as case iii: report error. + // TODO(wpoon): Add error reporting. + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h new file mode 100644 index 00000000..e3e329fc --- /dev/null +++ b/src/google/protobuf/util/internal/json_escaping.h @@ -0,0 +1,91 @@ +// 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. + +#ifndef NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_ +#define NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_ + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class JsonEscaping { + public: + // The minimum value of a unicode high-surrogate code unit in the utf-16 + // encoding. A high-surrogate is also known as a leading-surrogate. + // See http://www.unicode.org/glossary/#high_surrogate_code_unit + static const uint16 kMinHighSurrogate = 0xd800; + + // The maximum value of a unicide high-surrogate code unit in the utf-16 + // encoding. A high-surrogate is also known as a leading-surrogate. + // See http://www.unicode.org/glossary/#high_surrogate_code_unit + static const uint16 kMaxHighSurrogate = 0xdbff; + + // The minimum value of a unicode low-surrogate code unit in the utf-16 + // encoding. A low-surrogate is also known as a trailing-surrogate. + // See http://www.unicode.org/glossary/#low_surrogate_code_unit + static const uint16 kMinLowSurrogate = 0xdc00; + + // The maximum value of a unicode low-surrogate code unit in the utf-16 + // encoding. A low-surrogate is also known as a trailing surrogate. + // See http://www.unicode.org/glossary/#low_surrogate_code_unit + static const uint16 kMaxLowSurrogate = 0xdfff; + + // The minimum value of a unicode supplementary code point. + // See http://www.unicode.org/glossary/#supplementary_code_point + static const uint32 kMinSupplementaryCodePoint = 0x010000; + + // The minimum value of a unicode code point. + // See http://www.unicode.org/glossary/#code_point + static const uint32 kMinCodePoint = 0x000000; + + // The maximum value of a unicode code point. + // See http://www.unicode.org/glossary/#code_point + static const uint32 kMaxCodePoint = 0x10ffff; + + JsonEscaping() {} + virtual ~JsonEscaping() {} + + // Escape the given ByteSource to the given ByteSink. + static void Escape(strings::ByteSource* input, strings::ByteSink* output); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JsonEscaping); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +#endif // NET_PROTO2_UTIL_CONVERTER_STRINGS_JSON_ESCAPING_H_ +} // namespace google diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc new file mode 100644 index 00000000..d14ae10a --- /dev/null +++ b/src/google/protobuf/util/internal/json_objectwriter.cc @@ -0,0 +1,175 @@ +// 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 + +#include + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using strings::ArrayByteSource; + +JsonObjectWriter::~JsonObjectWriter() { + if (!element_->is_root()) { + GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed."; + } +} + +JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) { + WritePrefix(name); + WriteChar('{'); + Push(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::EndObject() { + Pop(); + WriteChar('}'); + if (element()->is_root()) NewLine(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) { + WritePrefix(name); + WriteChar('['); + Push(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::EndList() { + Pop(); + WriteChar(']'); + if (element()->is_root()) NewLine(); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name, + const bool value) { + return RenderSimple(name, value ? "true" : "false"); +} + +JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name, + const int32 value) { + return RenderSimple(name, SimpleItoa(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name, + const uint32 value) { + return RenderSimple(name, SimpleItoa(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name, + const int64 value) { + WritePrefix(name); + WriteChar('"'); + stream_->WriteString(SimpleItoa(value)); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name, + const uint64 value) { + WritePrefix(name); + WriteChar('"'); + stream_->WriteString(SimpleItoa(value)); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name, + const double value) { + if (isfinite(value)) return RenderSimple(name, SimpleDtoa(value)); + + // Render quoted with NaN/Infinity-aware DoubleAsString. + return RenderString(name, DoubleAsString(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name, + const float value) { + if (isfinite(value)) return RenderSimple(name, SimpleFtoa(value)); + + // Render quoted with NaN/Infinity-aware FloatAsString. + return RenderString(name, FloatAsString(value)); +} + +JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name, + StringPiece value) { + WritePrefix(name); + WriteChar('"'); + ArrayByteSource source(value); + JsonEscaping::Escape(&source, &sink_); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name, + StringPiece value) { + WritePrefix(name); + string base64; + WebSafeBase64EscapeWithPadding(value, &base64); + WriteChar('"'); + // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes + // directly to the stream, rather than first putting them + // into a string and then writing them to the stream. + stream_->WriteRaw(base64.data(), base64.size()); + WriteChar('"'); + return this; +} + +JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) { + return RenderSimple(name, "null"); +} + +void JsonObjectWriter::WritePrefix(StringPiece name) { + bool not_first = !element()->is_first(); + if (not_first) WriteChar(','); + if (not_first || !element()->is_root()) NewLine(); + if (!name.empty()) { + WriteChar('"'); + ArrayByteSource source(name); + JsonEscaping::Escape(&source, &sink_); + stream_->WriteString("\":"); + if (!indent_string_.empty()) WriteChar(' '); + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h new file mode 100644 index 00000000..761a0a10 --- /dev/null +++ b/src/google/protobuf/util/internal/json_objectwriter.h @@ -0,0 +1,206 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An ObjectWriter implementation that outputs JSON. This ObjectWriter +// supports writing a compact form or a pretty printed form. +// +// Sample usage: +// string output; +// StringOutputStream* str_stream = new StringOutputStream(&output); +// CodedOutputStream* out_stream = new CodedOutputStream(str_stream); +// JsonObjectWriter* ow = new JsonObjectWriter(" ", out_stream); +// ow->StartObject("") +// ->RenderString("name", "value") +// ->RenderString("emptystring", string()) +// ->StartObject("nested") +// ->RenderInt64("light", 299792458); +// ->RenderDouble("pi", 3.141592653589793); +// ->EndObject() +// ->StartList("empty") +// ->EndList() +// ->EndObject(); +// +// And then the output string would become: +// { +// "name": "value", +// "emptystring": "", +// "nested": { +// "light": "299792458", +// "pi": 3.141592653589793 +// }, +// "empty": [] +// } +// +// JsonObjectWriter does not validate if calls actually result in valid JSON. +// For example, passing an empty name when one would be required won't result +// in an error, just an invalid output. +// +// Note that all int64 and uint64 are rendered as strings instead of numbers. +// This is because JavaScript parses numbers as 64-bit float thus int64 and +// uint64 would lose precision if rendered as numbers. +// +// JsonObjectWriter is thread-unsafe. +class LIBPROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter { + public: + JsonObjectWriter(StringPiece indent_string, + google::protobuf::io::CodedOutputStream* out) + : element_(new Element(NULL)), + stream_(out), sink_(out), + indent_string_(indent_string.ToString()) { + } + virtual ~JsonObjectWriter(); + + // ObjectWriter methods. + virtual JsonObjectWriter* StartObject(StringPiece name); + virtual JsonObjectWriter* EndObject(); + virtual JsonObjectWriter* StartList(StringPiece name); + virtual JsonObjectWriter* EndList(); + virtual JsonObjectWriter* RenderBool(StringPiece name, bool value); + virtual JsonObjectWriter* RenderInt32(StringPiece name, int32 value); + virtual JsonObjectWriter* RenderUint32(StringPiece name, uint32 value); + virtual JsonObjectWriter* RenderInt64(StringPiece name, int64 value); + virtual JsonObjectWriter* RenderUint64(StringPiece name, uint64 value); + virtual JsonObjectWriter* RenderDouble(StringPiece name, double value); + virtual JsonObjectWriter* RenderFloat(StringPiece name, float value); + virtual JsonObjectWriter* RenderString(StringPiece name, StringPiece value); + virtual JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value); + virtual JsonObjectWriter* RenderNull(StringPiece name); + + protected: + class LIBPROTOBUF_EXPORT Element : public BaseElement { + public: + explicit Element(Element* parent) : BaseElement(parent), is_first_(true) {} + + // Called before each field of the Element is to be processed. + // Returns true if this is the first call (processing the first field). + bool is_first() { + if (is_first_) { + is_first_ = false; + return true; + } + return false; + } + + private: + bool is_first_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Element); + }; + + virtual Element* element() { return element_.get(); } + + private: + class LIBPROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink { + public: + explicit ByteSinkWrapper(google::protobuf::io::CodedOutputStream* stream) + : stream_(stream) {} + virtual ~ByteSinkWrapper() {} + + // ByteSink methods. + virtual void Append(const char* bytes, size_t n) { + stream_->WriteRaw(bytes, n); + } + + private: + google::protobuf::io::CodedOutputStream* stream_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSinkWrapper); + }; + + // Renders a simple value as a string. By default all non-string Render + // methods convert their argument to a string and call this method. This + // method can then be used to render the simple value without escaping it. + JsonObjectWriter* RenderSimple(StringPiece name, const string& value) { + WritePrefix(name); + stream_->WriteString(value); + return this; + } + + // Pushes a new element to the stack. + void Push() { element_.reset(new Element(element_.release())); } + + // Pops an element off of the stack and deletes the popped element. + void Pop() { + bool needs_newline = !element_->is_first(); + element_.reset(element_->pop()); + if (needs_newline) NewLine(); + } + + // If pretty printing is enabled, this will write a newline to the output, + // followed by optional indentation. Otherwise this method is a noop. + void NewLine() { + if (!indent_string_.empty()) { + WriteChar('\n'); + for (int i = 0; i < element()->level(); i++) { + stream_->WriteString(indent_string_); + } + } + } + + // Writes a prefix. This will write out any pretty printing and + // commas that are required, followed by the name and a ':' if + // the name is not null. + void WritePrefix(StringPiece name); + + // Writes an individual character to the output. + void WriteChar(const char c) { stream_->WriteRaw(&c, sizeof(c)); } + + google::protobuf::scoped_ptr element_; + google::protobuf::io::CodedOutputStream* stream_; + ByteSinkWrapper sink_; + const string indent_string_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc new file mode 100644 index 00000000..c8fff8b3 --- /dev/null +++ b/src/google/protobuf/util/internal/json_objectwriter_test.cc @@ -0,0 +1,284 @@ +// 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 + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::io::CodedOutputStream; +using google::protobuf::io::StringOutputStream; + +class JsonObjectWriterTest : public ::testing::Test { + protected: + JsonObjectWriterTest() + : str_stream_(new StringOutputStream(&output_)), + out_stream_(new CodedOutputStream(str_stream_)), + ow_(NULL) {} + + virtual ~JsonObjectWriterTest() { + delete ow_; + delete out_stream_; + delete str_stream_; + } + + string output_; + StringOutputStream* const str_stream_; + CodedOutputStream* const out_stream_; + ObjectWriter* ow_; +}; + +TEST_F(JsonObjectWriterTest, EmptyRootObject) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("")->EndObject(); + EXPECT_EQ("{}", output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, EmptyObject) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->RenderString("test", "value") + ->StartObject("empty") + ->EndObject() + ->EndObject(); + EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, EmptyRootList) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartList("")->EndList(); + EXPECT_EQ("[]", output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, EmptyList) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->RenderString("test", "value") + ->StartList("empty") + ->EndList() + ->EndObject(); + EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, ObjectInObject) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->StartObject("nested") + ->RenderString("field", "value") + ->EndObject() + ->EndObject(); + EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, ListInObject) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->StartList("nested") + ->RenderString("", "value") + ->EndList() + ->EndObject(); + EXPECT_EQ("{\"nested\":[\"value\"]}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, ObjectInList) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartList("") + ->StartObject("") + ->RenderString("field", "value") + ->EndObject() + ->EndList(); + EXPECT_EQ("[{\"field\":\"value\"}]", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, ListInList) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartList("") + ->StartList("") + ->RenderString("", "value") + ->EndList() + ->EndList(); + EXPECT_EQ("[[\"value\"]]", output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, RenderPrimitives) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->RenderBool("bool", true) + ->RenderDouble("double", std::numeric_limits::max()) + ->RenderFloat("float", std::numeric_limits::max()) + ->RenderInt32("int", std::numeric_limits::min()) + ->RenderInt64("long", std::numeric_limits::min()) + ->RenderBytes("bytes", "abracadabra") + ->RenderString("string", "string") + ->RenderBytes("emptybytes", "") + ->RenderString("emptystring", string()) + ->EndObject(); + EXPECT_EQ( + "{\"bool\":true," + "\"double\":1.7976931348623157e+308," + "\"float\":3.4028235e+38," + "\"int\":-2147483648," + "\"long\":\"-9223372036854775808\"," + "\"bytes\":\"YWJyYWNhZGFicmE=\"," + "\"string\":\"string\"," + "\"emptybytes\":\"\"," + "\"emptystring\":\"\"}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, BytesEncodesAsWebSafeBase64) { + string s; + s.push_back('\377'); + s.push_back('\357'); + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("")->RenderBytes("bytes", s)->EndObject(); + // Non-web-safe would encode this as "/+8=" + EXPECT_EQ("{\"bytes\":\"_-8=\"}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, PrettyPrintList) { + ow_ = new JsonObjectWriter(" ", out_stream_); + ow_->StartObject("") + ->StartList("items") + ->RenderString("", "item1") + ->RenderString("", "item2") + ->RenderString("", "item3") + ->EndList() + ->StartList("empty") + ->EndList() + ->EndObject(); + EXPECT_EQ( + "{\n" + " \"items\": [\n" + " \"item1\",\n" + " \"item2\",\n" + " \"item3\"\n" + " ],\n" + " \"empty\": []\n" + "}\n", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, PrettyPrintObject) { + ow_ = new JsonObjectWriter(" ", out_stream_); + ow_->StartObject("") + ->StartObject("items") + ->RenderString("key1", "item1") + ->RenderString("key2", "item2") + ->RenderString("key3", "item3") + ->EndObject() + ->StartObject("empty") + ->EndObject() + ->EndObject(); + EXPECT_EQ( + "{\n" + " \"items\": {\n" + " \"key1\": \"item1\",\n" + " \"key2\": \"item2\",\n" + " \"key3\": \"item3\"\n" + " },\n" + " \"empty\": {}\n" + "}\n", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) { + ow_ = new JsonObjectWriter(" ", out_stream_); + ow_->StartObject("") + ->StartList("list") + ->StartObject("") + ->EndObject() + ->EndList() + ->EndObject(); + EXPECT_EQ( + "{\n" + " \"list\": [\n" + " {}\n" + " ]\n" + "}\n", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) { + ow_ = new JsonObjectWriter(" ", out_stream_); + ow_->StartObject("") + ->RenderBool("bool", true) + ->RenderInt32("int", 42) + ->EndObject(); + EXPECT_EQ( + "{\n" + " \"bool\": true,\n" + " \"int\": 42\n" + "}\n", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("")->RenderString("string", "'<>&\\\"\r\n")->EndObject(); + EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&\\\\\\\"\\r\\n\"}", + output_.substr(0, out_stream_->ByteCount())); +} + +TEST_F(JsonObjectWriterTest, Stringification) { + ow_ = new JsonObjectWriter("", out_stream_); + ow_->StartObject("") + ->RenderDouble("double_nan", std::numeric_limits::quiet_NaN()) + ->RenderFloat("float_nan", std::numeric_limits::quiet_NaN()) + ->RenderDouble("double_pos", std::numeric_limits::infinity()) + ->RenderFloat("float_pos", std::numeric_limits::infinity()) + ->RenderDouble("double_neg", -std::numeric_limits::infinity()) + ->RenderFloat("float_neg", -std::numeric_limits::infinity()) + ->EndObject(); + EXPECT_EQ( + "{\"double_nan\":\"NaN\"," + "\"float_nan\":\"NaN\"," + "\"double_pos\":\"Infinity\"," + "\"float_pos\":\"Infinity\"," + "\"double_neg\":\"-Infinity\"," + "\"float_neg\":\"-Infinity\"}", + output_.substr(0, out_stream_->ByteCount())); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc new file mode 100644 index 00000000..d439a221 --- /dev/null +++ b/src/google/protobuf/util/internal/json_stream_parser.cc @@ -0,0 +1,740 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#ifndef _SHARED_PTR_H +#include +#endif + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { + +// Allow these symbols to be referenced as util::Status, util::error::* in +// this file. +using util::Status; +namespace error { +using util::error::INTERNAL; +using util::error::INVALID_ARGUMENT; +} // namespace error + +namespace converter { + +// Number of digits in a unicode escape sequence (/uXXXX) +static const int kUnicodeEscapedLength = 6; + +// Length of the true, false, and null literals. +static const int true_len = strlen("true"); +static const int false_len = strlen("false"); +static const int null_len = strlen("null"); + +inline bool IsLetter(char c) { + return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') || + (c == '$'); +} + +inline bool IsAlphanumeric(char c) { + return IsLetter(c) || ('0' <= c && c <= '9'); +} + +static bool ConsumeKey(StringPiece* input, StringPiece* key) { + if (input->empty() || !IsLetter((*input)[0])) return false; + int len = 1; + for (; len < input->size(); ++len) { + if (!IsAlphanumeric((*input)[len])) { + break; + } + } + *key = StringPiece(input->data(), len); + *input = StringPiece(input->data() + len, input->size() - len); + return true; +} + +static bool MatchKey(StringPiece input) { + return !input.empty() && IsLetter(input[0]); +} + +JsonStreamParser::JsonStreamParser(ObjectWriter* ow) + : ow_(ow), + stack_(), + leftover_(), + json_(), + p_(), + key_(), + key_storage_(), + finishing_(false), + parsed_(), + parsed_storage_(), + string_open_(0), + utf8_storage_(), + utf8_length_(0) { + // Initialize the stack with a single value to be parsed. + stack_.push(VALUE); +} + +JsonStreamParser::~JsonStreamParser() {} + +util::Status JsonStreamParser::Parse(StringPiece json) { + return ParseChunk(json); +} + +util::Status JsonStreamParser::FinishParse() { + // If we do not expect anything and there is nothing left to parse we're all + // done. + if (stack_.empty() && leftover_.empty()) { + return util::Status::OK; + } + // Parse the remainder in finishing mode, which reports errors for things like + // unterminated strings or unknown tokens that would normally be retried. + p_ = json_ = StringPiece(leftover_); + finishing_ = true; + util::Status result = RunParser(); + if (result.ok()) { + SkipWhitespace(); + if (!p_.empty()) { + result = ReportFailure("Parsing terminated before end of input."); + } + } + return result; +} + +util::Status JsonStreamParser::ParseChunk(StringPiece chunk) { + // If we have leftovers from a previous chunk, append the new chunk to it and + // create a new StringPiece pointing at the string's data. This could be + // large but we rely on the chunks to be small, assuming they are fragments + // of a Cord. + if (!leftover_.empty()) { + chunk.AppendToString(&leftover_); + p_ = json_ = StringPiece(leftover_); + } else { + p_ = json_ = chunk; + } + + finishing_ = false; + util::Status result = RunParser(); + if (!result.ok()) return result; + + SkipWhitespace(); + if (p_.empty()) { + // If we parsed everything we had, clear the leftover. + leftover_.clear(); + } else { + // If we do not expect anything i.e. stack is empty, and we have non-empty + // string left to parse, we report an error. + if (stack_.empty()) { + return ReportFailure("Parsing terminated before end of input."); + } + // If we expect future data i.e. stack is non-empty, and we have some + // unparsed data left, we save it for later parse. + leftover_ = p_.ToString(); + } + return util::Status::OK; +} + +util::Status JsonStreamParser::RunParser() { + while (!stack_.empty()) { + ParseType type = stack_.top(); + TokenType t = (string_open_ == 0) ? GetNextTokenType() : BEGIN_STRING; + stack_.pop(); + util::Status result; + switch (type) { + case VALUE: + result = ParseValue(t); + break; + + case OBJ_MID: + result = ParseObjectMid(t); + break; + + case ENTRY: + result = ParseEntry(t); + break; + + case ENTRY_MID: + result = ParseEntryMid(t); + break; + + case ARRAY_VALUE: + result = ParseArrayValue(t); + break; + + case ARRAY_MID: + result = ParseArrayMid(t); + break; + + default: + result = util::Status(util::error::INTERNAL, + StrCat("Unknown parse type: ", type)); + break; + } + if (!result.ok()) { + // If we were cancelled, save our state and try again later. + if (!finishing_ && result == util::Status::CANCELLED) { + stack_.push(type); + // If we have a key we still need to render, make sure to save off the + // contents in our own storage. + if (!key_.empty() && key_storage_.empty()) { + key_.AppendToString(&key_storage_); + key_ = StringPiece(key_storage_); + } + result = util::Status::OK; + } + return result; + } + } + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseValue(TokenType type) { + switch (type) { + case BEGIN_OBJECT: + return HandleBeginObject(); + case BEGIN_ARRAY: + return HandleBeginArray(); + case BEGIN_STRING: + return ParseString(); + case BEGIN_NUMBER: + return ParseNumber(); + case BEGIN_TRUE: + return ParseTrue(); + case BEGIN_FALSE: + return ParseFalse(); + case BEGIN_NULL: + return ParseNull(); + case UNKNOWN: + return ReportUnknown("Expected a value."); + default: { + // Special case for having been cut off while parsing, wait for more data. + // This handles things like 'fals' being at the end of the string, we + // don't know if the next char would be e, completing it, or something + // else, making it invalid. + if (!finishing_ && p_.length() < false_len) { + return util::Status::CANCELLED; + } + return ReportFailure("Unexpected token."); + } + } +} + +util::Status JsonStreamParser::ParseString() { + util::Status result = ParseStringHelper(); + if (result.ok()) { + ow_->RenderString(key_, parsed_); + key_.clear(); + parsed_.clear(); + parsed_storage_.clear(); + } + return result; +} + +util::Status JsonStreamParser::ParseStringHelper() { + // If we haven't seen the start quote, grab it and remember it for later. + if (string_open_ == 0) { + string_open_ = *p_.data(); + GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\''); + Advance(); + } + // Track where we last copied data from so we can minimize copying. + const char* last = p_.data(); + while (!p_.empty()) { + const char* data = p_.data(); + if (*data == '\\') { + // We're about to handle an escape, copy all bytes from last to data. + if (last < data) { + parsed_storage_.append(last, data - last); + last = data; + } + // If we ran out of string after the \, cancel or report an error + // depending on if we expect more data later. + if (p_.length() == 1) { + if (!finishing_) { + return util::Status::CANCELLED; + } + return ReportFailure("Closing quote expected in string."); + } + // Parse a unicode escape if we found \u in the string. + if (data[1] == 'u') { + util::Status result = ParseUnicodeEscape(); + if (!result.ok()) { + return result; + } + // Move last pointer past the unicode escape and continue. + last = p_.data(); + continue; + } + // Handle the standard set of backslash-escaped characters. + switch (data[1]) { + case 'b': + parsed_storage_.push_back('\b'); + break; + case 'f': + parsed_storage_.push_back('\f'); + break; + case 'n': + parsed_storage_.push_back('\n'); + break; + case 'r': + parsed_storage_.push_back('\r'); + break; + case 't': + parsed_storage_.push_back('\t'); + break; + case 'v': + parsed_storage_.push_back('\v'); + break; + default: + parsed_storage_.push_back(data[1]); + } + // We handled two characters, so advance past them and continue. + p_.remove_prefix(2); + last = p_.data(); + continue; + } + // If we found the closing quote note it, advance past it, and return. + if (*data == string_open_) { + // If we didn't copy anything, reuse the input buffer. + if (parsed_storage_.empty()) { + parsed_ = StringPiece(last, data - last); + } else { + if (last < data) { + parsed_storage_.append(last, data - last); + last = data; + } + parsed_ = StringPiece(parsed_storage_); + } + // Clear the quote char so next time we try to parse a string we'll + // start fresh. + string_open_ = 0; + Advance(); + return util::Status::OK; + } + // Normal character, just advance past it. + Advance(); + } + // If we ran out of characters, copy over what we have so far. + if (last < p_.data()) { + parsed_storage_.append(last, p_.data() - last); + } + // If we didn't find the closing quote but we expect more data, cancel for now + if (!finishing_) { + return util::Status::CANCELLED; + } + // End of string reached without a closing quote, report an error. + string_open_ = 0; + return ReportFailure("Closing quote expected in string."); +} + +// Converts a unicode escaped character to a decimal value stored in a char32 +// for use in UTF8 encoding utility. We assume that str begins with \uhhhh and +// convert that from the hex number to a decimal value. +// +// There are some security exploits with UTF-8 that we should be careful of: +// - http://www.unicode.org/reports/tr36/#UTF-8_Exploit +// - http://sites/intl-eng/design-guide/core-application +util::Status JsonStreamParser::ParseUnicodeEscape() { + if (p_.length() < kUnicodeEscapedLength) { + if (!finishing_) { + return util::Status::CANCELLED; + } + return ReportFailure("Illegal hex string."); + } + GOOGLE_DCHECK_EQ('\\', p_.data()[0]); + GOOGLE_DCHECK_EQ('u', p_.data()[1]); + uint32 code = 0; + for (int i = 2; i < kUnicodeEscapedLength; ++i) { + if (!isxdigit(p_.data()[i])) { + return ReportFailure("Invalid escape sequence."); + } + code = (code << 4) + hex_digit_to_int(p_.data()[i]); + } + char buf[UTFmax]; + int len = EncodeAsUTF8Char(code, buf); + // Advance past the unicode escape. + p_.remove_prefix(kUnicodeEscapedLength); + parsed_storage_.append(buf, len); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseNumber() { + NumberResult number; + util::Status result = ParseNumberHelper(&number); + if (result.ok()) { + switch (number.type) { + case NumberResult::DOUBLE: + ow_->RenderDouble(key_, number.double_val); + key_.clear(); + break; + + case NumberResult::INT: + ow_->RenderInt64(key_, number.int_val); + key_.clear(); + break; + + case NumberResult::UINT: + ow_->RenderUint64(key_, number.uint_val); + key_.clear(); + break; + + default: + return ReportFailure("Unable to parse number."); + } + } + return result; +} + +util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) { + const char* data = p_.data(); + int length = p_.length(); + + // Look for the first non-numeric character, or the end of the string. + int index = 0; + bool floating = false; + bool negative = data[index] == '-'; + // Find the first character that cannot be part of the number. Along the way + // detect if the number needs to be parsed as a double. + // Note that this restricts numbers to the JSON specification, so for example + // we do not support hex or octal notations. + for (; index < length; ++index) { + char c = data[index]; + if (isdigit(c)) continue; + if (c == '.' || c == 'e' || c == 'E') { + floating = true; + continue; + } + if (c == '+' || c == '-') continue; + // Not a valid number character, break out. + break; + } + + // If the entire input is a valid number, and we may have more content in the + // future, we abort for now and resume when we know more. + if (index == length && !finishing_) { + return util::Status::CANCELLED; + } + + // Create a string containing just the number, so we can use safe_strtoX + string number = p_.substr(0, index).ToString(); + + // Floating point number, parse as a double. + if (floating) { + if (!safe_strtod(number, &result->double_val)) { + return ReportFailure("Unable to parse number."); + } + result->type = NumberResult::DOUBLE; + p_.remove_prefix(index); + return util::Status::OK; + } + + // Positive non-floating point number, parse as a uint64. + if (!negative) { + if (!safe_strtou64(number, &result->uint_val)) { + return ReportFailure("Unable to parse number."); + } + result->type = NumberResult::UINT; + p_.remove_prefix(index); + return util::Status::OK; + } + + // Negative non-floating point number, parse as an int64. + if (!safe_strto64(number, &result->int_val)) { + return ReportFailure("Unable to parse number."); + } + result->type = NumberResult::INT; + p_.remove_prefix(index); + return util::Status::OK; +} + +util::Status JsonStreamParser::HandleBeginObject() { + GOOGLE_DCHECK_EQ('{', *p_.data()); + Advance(); + ow_->StartObject(key_); + key_.clear(); + stack_.push(ENTRY); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseObjectMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected , or } after key:value pair."); + } + + // Object is complete, advance past the comma and render the EndObject. + if (type == END_OBJECT) { + Advance(); + ow_->EndObject(); + return util::Status::OK; + } + // Found a comma, advance past it and get ready for an entry. + if (type == VALUE_SEPARATOR) { + Advance(); + stack_.push(ENTRY); + return util::Status::OK; + } + // Illegal token after key:value pair. + return ReportFailure("Expected , or } after key:value pair."); +} + +util::Status JsonStreamParser::ParseEntry(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected an object key or }."); + } + + // Close the object and return. This allows for trailing commas. + if (type == END_OBJECT) { + ow_->EndObject(); + Advance(); + return util::Status::OK; + } + + util::Status result; + if (type == BEGIN_STRING) { + // Key is a string (standard JSON), parse it and store the string. + result = ParseStringHelper(); + if (result.ok()) { + key_storage_.clear(); + if (!parsed_storage_.empty()) { + parsed_storage_.swap(key_storage_); + key_ = StringPiece(key_storage_); + } else { + key_ = parsed_; + } + parsed_.clear(); + } + } else if (type == BEGIN_KEY) { + // Key is a bare key (back compat), create a StringPiece pointing to it. + result = ParseKey(); + } else { + // Unknown key type, report an error. + result = ReportFailure("Expected an object key or }."); + } + // On success we next expect an entry mid ':' then an object mid ',' or '}' + if (result.ok()) { + stack_.push(OBJ_MID); + stack_.push(ENTRY_MID); + } + return result; +} + +util::Status JsonStreamParser::ParseEntryMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected : between key:value pair."); + } + if (type == ENTRY_SEPARATOR) { + Advance(); + stack_.push(VALUE); + return util::Status::OK; + } + return ReportFailure("Expected : between key:value pair."); +} + +util::Status JsonStreamParser::HandleBeginArray() { + GOOGLE_DCHECK_EQ('[', *p_.data()); + Advance(); + ow_->StartList(key_); + key_.clear(); + stack_.push(ARRAY_VALUE); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseArrayValue(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected a value or ] within an array."); + } + + if (type == END_ARRAY) { + ow_->EndList(); + Advance(); + return util::Status::OK; + } + + // The ParseValue call may push something onto the stack so we need to make + // sure an ARRAY_MID is after it, so we push it on now. + stack_.push(ARRAY_MID); + util::Status result = ParseValue(type); + if (result == util::Status::CANCELLED) { + // If we were cancelled, pop back off the ARRAY_MID so we don't try to + // push it on again when we try over. + stack_.pop(); + } + return result; +} + +util::Status JsonStreamParser::ParseArrayMid(TokenType type) { + if (type == UNKNOWN) { + return ReportUnknown("Expected , or ] after array value."); + } + + if (type == END_ARRAY) { + ow_->EndList(); + Advance(); + return util::Status::OK; + } + + // Found a comma, advance past it and expect an array value next. + if (type == VALUE_SEPARATOR) { + Advance(); + stack_.push(ARRAY_VALUE); + return util::Status::OK; + } + // Illegal token after array value. + return ReportFailure("Expected , or ] after array value."); +} + +util::Status JsonStreamParser::ParseTrue() { + ow_->RenderBool(key_, true); + key_.clear(); + p_.remove_prefix(true_len); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseFalse() { + ow_->RenderBool(key_, false); + key_.clear(); + p_.remove_prefix(false_len); + return util::Status::OK; +} + +util::Status JsonStreamParser::ParseNull() { + ow_->RenderNull(key_); + key_.clear(); + p_.remove_prefix(null_len); + return util::Status::OK; +} + +util::Status JsonStreamParser::ReportFailure(StringPiece message) { + static const int kContextLength = 20; + const char* p_start = p_.data(); + const char* json_start = json_.data(); + const char* begin = max(p_start - kContextLength, json_start); + const char* end = min(p_start + kContextLength, json_start + json_.size()); + StringPiece segment(begin, end - begin); + string location(p_start - begin, ' '); + location.push_back('^'); + return util::Status(util::error::INVALID_ARGUMENT, + StrCat(message, "\n", segment, "\n", location)); +} + +util::Status JsonStreamParser::ReportUnknown(StringPiece message) { + // If we aren't finishing the parse, cancel parsing and try later. + if (!finishing_) { + return util::Status::CANCELLED; + } + if (p_.empty()) { + return ReportFailure(StrCat("Unexpected end of string. ", message)); + } + return ReportFailure(message); +} + +void JsonStreamParser::SkipWhitespace() { + while (!p_.empty() && ascii_isspace(*p_.data())) { + Advance(); + } +} + +void JsonStreamParser::Advance() { + // Advance by moving one UTF8 character while making sure we don't go beyond + // the length of StringPiece. + p_.remove_prefix( + min(p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length()))); +} + +util::Status JsonStreamParser::ParseKey() { + StringPiece original = p_; + if (!ConsumeKey(&p_, &key_)) { + return ReportFailure("Invalid key or variable name."); + } + // If we consumed everything but expect more data, reset p_ and cancel since + // we can't know if the key was complete or not. + if (!finishing_ && p_.empty()) { + p_ = original; + return util::Status::CANCELLED; + } + // Since we aren't using the key storage, clear it out. + key_storage_.clear(); + return util::Status::OK; +} + +JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() { + SkipWhitespace(); + + int size = p_.size(); + if (size == 0) { + // If we ran out of data, report unknown and we'll place the previous parse + // type onto the stack and try again when we have more data. + return UNKNOWN; + } + // TODO(sven): Split this method based on context since different contexts + // support different tokens. Would slightly speed up processing? + const char* data = p_.data(); + if (*data == '\"' || *data == '\'') return BEGIN_STRING; + if (*data == '-' || ('0' <= *data && *data <= '9')) { + return BEGIN_NUMBER; + } + if (size >= true_len && !strncmp(data, "true", true_len)) { + return BEGIN_TRUE; + } + if (size >= false_len && !strncmp(data, "false", false_len)) { + return BEGIN_FALSE; + } + if (size >= null_len && !strncmp(data, "null", null_len)) { + return BEGIN_NULL; + } + if (*data == '{') return BEGIN_OBJECT; + if (*data == '}') return END_OBJECT; + if (*data == '[') return BEGIN_ARRAY; + if (*data == ']') return END_ARRAY; + if (*data == ':') return ENTRY_SEPARATOR; + if (*data == ',') return VALUE_SEPARATOR; + if (MatchKey(p_)) { + return BEGIN_KEY; + } + + // We don't know that we necessarily have an invalid token here, just that we + // can't parse what we have so far. So we don't report an error and just + // return UNKNOWN so we can try again later when we have more data, or if we + // finish and we have leftovers. + return UNKNOWN; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h new file mode 100644 index 00000000..17b094ae --- /dev/null +++ b/src/google/protobuf/util/internal/json_stream_parser.h @@ -0,0 +1,256 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ + +#include +#include + +#include +#include +#include + +namespace google { +namespace util { +class Status; +} // namespace util + +namespace protobuf { +namespace util { +namespace converter { + +class ObjectWriter; + +// A JSON parser that can parse a stream of JSON chunks rather than needing the +// entire JSON string up front. It is a modified version of the parser in +// //net/proto/json/json-parser.h that has been changed in the following ways: +// - Changed from recursion to an explicit stack to allow resumption +// - Added support for int64 and uint64 numbers +// - Removed support for octal and decimal escapes +// - Removed support for numeric keys +// - Removed support for functions (javascript) +// - Removed some lax-comma support (but kept trailing comma support) +// - Writes directly to an ObjectWriter rather than using subclassing +// +// Here is an example usage: +// JsonStreamParser parser(ow_.get()); +// util::Status result = parser.Parse(chunk1); +// result.Update(parser.Parse(chunk2)); +// result.Update(parser.FinishParse()); +// GOOGLE_DCHECK(result.ok()) << "Failed to parse JSON"; +// +// This parser is thread-compatible as long as only one thread is calling a +// Parse() method at a time. +class LIBPROTOBUF_EXPORT JsonStreamParser { + public: + // Creates a JsonStreamParser that will write to the given ObjectWriter. + explicit JsonStreamParser(ObjectWriter* ow); + virtual ~JsonStreamParser(); + + // Parse a JSON string (UTF-8 encoded). + util::Status Parse(StringPiece json); + + // Finish parsing the JSON string. + util::Status FinishParse(); + + private: + enum TokenType { + BEGIN_STRING, // " or ' + BEGIN_NUMBER, // - or digit + BEGIN_TRUE, // true + BEGIN_FALSE, // false + BEGIN_NULL, // null + BEGIN_OBJECT, // { + END_OBJECT, // } + BEGIN_ARRAY, // [ + END_ARRAY, // ] + ENTRY_SEPARATOR, // : + VALUE_SEPARATOR, // , + BEGIN_KEY, // letter, _, $ or digit. Must begin with non-digit + UNKNOWN // Unknown token or we ran out of the stream. + }; + + enum ParseType { + VALUE, // Expects a {, [, true, false, null, string or number + OBJ_MID, // Expects a ',' or } + ENTRY, // Expects a key or } + ENTRY_MID, // Expects a : + ARRAY_VALUE, // Expects a value or ] + ARRAY_MID // Expects a ',' or ] + }; + + // Holds the result of parsing a number + struct NumberResult { + enum Type { DOUBLE, INT, UINT }; + Type type; + union { + double double_val; + int64 int_val; + uint64 uint_val; + }; + }; + + // Parses a single chunk of JSON, returning an error if the JSON was invalid. + util::Status ParseChunk(StringPiece json); + + // Runs the parser based on stack_ and p_, until the stack is empty or p_ runs + // out of data. If we unexpectedly run out of p_ we push the latest back onto + // the stack and return. + util::Status RunParser(); + + // Parses a value from p_ and writes it to ow_. + // A value may be an object, array, true, false, null, string or number. + util::Status ParseValue(TokenType type); + + // Parses a string and writes it out to the ow_. + util::Status ParseString(); + + // Parses a string, storing the result in parsed_. + util::Status ParseStringHelper(); + + // This function parses unicode escape sequences in strings. It returns an + // error when there's a parsing error, either the size is not the expected + // size or a character is not a hex digit. When it returns str will contain + // what has been successfully parsed so far. + util::Status ParseUnicodeEscape(); + + // Expects p_ to point to a JSON number, writes the number to the writer using + // the appropriate Render method based on the type of number. + util::Status ParseNumber(); + + // Parse a number into a NumberResult, reporting an error if no number could + // be parsed. This method will try to parse into a uint64, int64, or double + // based on whether the number was positive or negative or had a decimal + // component. + util::Status ParseNumberHelper(NumberResult* result); + + // Handles a { during parsing of a value. + util::Status HandleBeginObject(); + + // Parses from the ENTRY state. + util::Status ParseEntry(TokenType type); + + // Parses from the ENTRY_MID state. + util::Status ParseEntryMid(TokenType type); + + // Parses from the OBJ_MID state. + util::Status ParseObjectMid(TokenType type); + + // Handles a [ during parsing of a value. + util::Status HandleBeginArray(); + + // Parses from the ARRAY_VALUE state. + util::Status ParseArrayValue(TokenType type); + + // Parses from the ARRAY_MID state. + util::Status ParseArrayMid(TokenType type); + + // Expects p_ to point to an unquoted literal + util::Status ParseTrue(); + util::Status ParseFalse(); + util::Status ParseNull(); + + // Report a failure as a util::Status. + util::Status ReportFailure(StringPiece message); + + // Report a failure due to an UNKNOWN token type. We check if we hit the + // end of the stream and if we're finishing or not to detect what type of + // status to return in this case. + util::Status ReportUnknown(StringPiece message); + + // Advance p_ past all whitespace or until the end of the string. + void SkipWhitespace(); + + // Advance p_ one UTF-8 character + void Advance(); + + // Expects p_ to point to the beginning of a key. + util::Status ParseKey(); + + // Return the type of the next token at p_. + TokenType GetNextTokenType(); + + // The object writer to write parse events to. + ObjectWriter* ow_; + + // The stack of parsing we still need to do. When the stack runs empty we will + // have parsed a single value from the root (e.g. an object or list). + std::stack stack_; + + // Contains any leftover text from a previous chunk that we weren't able to + // fully parse, for example the start of a key or number. + string leftover_; + + // The current chunk of JSON being parsed. Primarily used for providing + // context during error reporting. + StringPiece json_; + + // A pointer within the current JSON being parsed, used to track location. + StringPiece p_; + + // Stores the last key read, as we separate parsing of keys and values. + StringPiece key_; + + // Storage for key_ if we need to keep ownership, for example between chunks + // or if the key was unescaped from a JSON string. + string key_storage_; + + // True during the FinishParse() call, so we know that any errors are fatal. + // For example an unterminated string will normally result in cancelling and + // trying during the next chunk, but during FinishParse() it is an error. + bool finishing_; + + // String we parsed during a call to ParseStringHelper(). + StringPiece parsed_; + + // Storage for the string we parsed. This may be empty if the string was able + // to be parsed directly from the input. + string parsed_storage_; + + // The character that opened the string, either ' or ". + // A value of 0 indicates that string parsing is not in process. + char string_open_; + + // Storage for utf8-coerced bytes. + google::protobuf::scoped_array utf8_storage_; + + // Length of the storage for utf8-coerced bytes. + int utf8_length_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_JSON_STREAM_PARSER_H__ diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc new file mode 100644 index 00000000..bd8ed135 --- /dev/null +++ b/src/google/protobuf/util/internal/json_stream_parser_test.cc @@ -0,0 +1,697 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace util { +using util::Status; +namespace error { +using util::error::INVALID_ARGUMENT; +} // namespace error +namespace converter { + +using util::Status; + +// Tests for the JSON Stream Parser. These tests are intended to be +// comprehensive and cover the following: +// +// Positive tests: +// - true, false, null +// - empty object or array. +// - negative and positive double and int, unsigned int +// - single and double quoted strings +// - string key, unquoted key, numeric key +// - array containing array, object, value +// - object containing array, object, value +// - unicode handling in strings +// - ascii escaping (\b, \f, \n, \r, \t, \v) +// - trailing commas +// +// Negative tests: +// - illegal literals +// - mismatched quotes failure on strings +// - unterminated string failure +// - unexpected end of string failure +// - mismatched object and array closing +// - Failure to close array or object +// - numbers too large +// - invalid unicode escapes. +// - invalid unicode sequences. +// - numbers as keys +// +// For each test we split the input string on every possible character to ensure +// the parser is able to handle arbitrarily split input for all cases. We also +// do a final test of the entire test case one character at a time. +class JsonStreamParserTest : public ::testing::Test { + protected: + JsonStreamParserTest() : mock_(), ow_(&mock_) {} + virtual ~JsonStreamParserTest() {} + + util::Status RunTest(StringPiece json, int split) { + JsonStreamParser parser(&mock_); + + // Special case for split == length, test parsing one character at a time. + if (split == json.length()) { + GOOGLE_LOG(INFO) << "Testing split every char: " << json; + for (int i = 0; i < json.length(); ++i) { + StringPiece single = json.substr(i, 1); + util::Status result = parser.Parse(single); + if (!result.ok()) { + return result; + } + } + return parser.FinishParse(); + } + + // Normal case, split at the split point and parse two substrings. + StringPiece first = json.substr(0, split); + StringPiece rest = json.substr(split); + GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest; + util::Status result = parser.Parse(first); + if (result.ok()) { + result = parser.Parse(rest); + if (result.ok()) { + result = parser.FinishParse(); + } + } + return result; + } + + void DoTest(StringPiece json, int split) { + util::Status result = RunTest(json, split); + if (!result.ok()) { + GOOGLE_LOG(WARNING) << result; + } + EXPECT_OK(result); + } + + void DoErrorTest(StringPiece json, int split, StringPiece error_prefix) { + util::Status result = RunTest(json, split); + EXPECT_EQ(util::error::INVALID_ARGUMENT, result.error_code()); + StringPiece error_message(result.error_message()); + EXPECT_EQ(error_prefix, error_message.substr(0, error_prefix.size())); + } + + + MockObjectWriter mock_; + ExpectingObjectWriter ow_; +}; + + +// Positive tests + +// - true, false, null +TEST_F(JsonStreamParserTest, SimpleTrue) { + StringPiece str = "true"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderBool("", true); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleFalse) { + StringPiece str = "false"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderBool("", false); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleNull) { + StringPiece str = "null"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderNull(""); + DoTest(str, i); + } +} + +// - empty object and array. +TEST_F(JsonStreamParserTest, EmptyObject) { + StringPiece str = "{}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->EndObject(); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, EmptyList) { + StringPiece str = "[]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->EndList(); + DoTest(str, i); + } +} + +// - negative and positive double and int, unsigned int +TEST_F(JsonStreamParserTest, SimpleDouble) { + StringPiece str = "42.5"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderDouble("", 42.5); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, ScientificDouble) { + StringPiece str = "1.2345e-10"; + for (int i = 0; i < str.length(); ++i) { + ow_.RenderDouble("", 1.2345e-10); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleNegativeDouble) { + StringPiece str = "-1045.235"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderDouble("", -1045.235); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleInt) { + StringPiece str = "123456"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderUint64("", 123456); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleNegativeInt) { + StringPiece str = "-79497823553162765"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderInt64("", -79497823553162765LL); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleUnsignedInt) { + StringPiece str = "11779497823553162765"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderUint64("", 11779497823553162765ULL); + DoTest(str, i); + } +} + +// - single and double quoted strings +TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) { + StringPiece str = "\"\""; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", ""); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, EmptySingleQuotedString) { + StringPiece str = "''"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", ""); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleDoubleQuotedString) { + StringPiece str = "\"Some String\""; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", "Some String"); + DoTest(str, i); + } +} + +TEST_F(JsonStreamParserTest, SimpleSingleQuotedString) { + StringPiece str = "'Another String'"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", "Another String"); + DoTest(str, i); + } +} + +// - string key, unquoted key, numeric key +TEST_F(JsonStreamParserTest, ObjectKeyTypes) { + StringPiece str = + "{'s': true, \"d\": false, key: null, snake_key: [], camelKey: {}}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("") + ->RenderBool("s", true) + ->RenderBool("d", false) + ->RenderNull("key") + ->StartList("snake_key") + ->EndList() + ->StartObject("camelKey") + ->EndObject() + ->EndObject(); + DoTest(str, i); + } +} + +// - array containing array, object, values (true, false, null, num, string) +TEST_F(JsonStreamParserTest, ArrayValues) { + StringPiece str = + "[true, false, null, 'a string', \"another string\", [22, -127, 45.3, " + "-1056.4, 11779497823553162765], {'key': true}]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("") + ->RenderBool("", true) + ->RenderBool("", false) + ->RenderNull("") + ->RenderString("", "a string") + ->RenderString("", "another string") + ->StartList("") + ->RenderUint64("", 22) + ->RenderInt64("", -127) + ->RenderDouble("", 45.3) + ->RenderDouble("", -1056.4) + ->RenderUint64("", 11779497823553162765ULL) + ->EndList() + ->StartObject("") + ->RenderBool("key", true) + ->EndObject() + ->EndList(); + DoTest(str, i); + } +} + +// - object containing array, object, value (true, false, null, num, string) +TEST_F(JsonStreamParserTest, ObjectValues) { + StringPiece str = + "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: " + "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], " + "o: {'key': true}}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("") + ->RenderBool("t", true) + ->RenderBool("f", false) + ->RenderNull("n") + ->RenderString("s", "a string") + ->RenderString("d", "another string") + ->RenderUint64("pi", 22) + ->RenderInt64("ni", -127) + ->RenderDouble("pd", 45.3) + ->RenderDouble("nd", -1056.4) + ->RenderUint64("pl", 11779497823553162765ULL) + ->StartList("l") + ->StartList("") + ->EndList() + ->EndList() + ->StartObject("o") + ->RenderBool("key", true) + ->EndObject() + ->EndObject(); + DoTest(str, i); + } +} + +// - unicode handling in strings +TEST_F(JsonStreamParserTest, UnicodeEscaping) { + StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->RenderString("", "\u0639\u0631\u0628\u0649")->EndList(); + DoTest(str, i); + } +} + +// - ascii escaping (\b, \f, \n, \r, \t, \v) +TEST_F(JsonStreamParserTest, AsciiEscaping) { + StringPiece str = + "[\"\\b\", \"\\ning\", \"test\\f\", \"\\r\\t\", \"test\\\\\\ving\"]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("") + ->RenderString("", "\b") + ->RenderString("", "\ning") + ->RenderString("", "test\f") + ->RenderString("", "\r\t") + ->RenderString("", "test\\\ving") + ->EndList(); + DoTest(str, i); + } +} + +// - trailing commas, we support a single trailing comma but no internal commas. +TEST_F(JsonStreamParserTest, TrailingCommas) { + StringPiece str = "[['a',true,], {b: null,},]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("") + ->StartList("") + ->RenderString("", "a") + ->RenderBool("", true) + ->EndList() + ->StartObject("") + ->RenderNull("b") + ->EndObject() + ->EndList(); + DoTest(str, i); + } +} + +// Negative tests + +// illegal literals +TEST_F(JsonStreamParserTest, ExtraTextAfterTrue) { + StringPiece str = "truee"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderBool("", true); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +TEST_F(JsonStreamParserTest, InvalidNumberDashOnly) { + StringPiece str = "-"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Unable to parse number."); + } +} + +TEST_F(JsonStreamParserTest, InvalidNumberDashName) { + StringPiece str = "-foo"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Unable to parse number."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralInArray) { + StringPiece str = "[nule]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Unexpected token."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralInObject) { + StringPiece str = "{123false}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +// mismatched quotes failure on strings +TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) { + StringPiece str = "'Some str\""; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, MismatchedDoubleQuotedLiteral) { + StringPiece str = "\"Another string that ends poorly!'"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +// unterminated strings +TEST_F(JsonStreamParserTest, UnterminatedLiteralString) { + StringPiece str = "\"Forgot the rest of i"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, UnterminatedStringEscape) { + StringPiece str = "\"Forgot the rest of \\"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, UnterminatedStringInArray) { + StringPiece str = "[\"Forgot to close the string]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, UnterminatedStringInObject) { + StringPiece str = "{f: \"Forgot to close the string}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Closing quote expected in string."); + } +} + +TEST_F(JsonStreamParserTest, UnterminatedObject) { + StringPiece str = "{"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Unexpected end of string."); + } +} + + +// mismatched object and array closing +TEST_F(JsonStreamParserTest, MismatchedCloseObject) { + StringPiece str = "{'key': true]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->RenderBool("key", true); + DoErrorTest(str, i, "Expected , or } after key:value pair."); + } +} + +TEST_F(JsonStreamParserTest, MismatchedCloseArray) { + StringPiece str = "[true, null}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->RenderBool("", true)->RenderNull(""); + DoErrorTest(str, i, "Expected , or ] after array value."); + } +} + +// Invalid object keys. +TEST_F(JsonStreamParserTest, InvalidNumericObjectKey) { + StringPiece str = "{42: true}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralObjectInObject) { + StringPiece str = "{{bob: true}}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralArrayInObject) { + StringPiece str = "{[null]}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralValueInObject) { + StringPiece str = "{false}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, MissingColonAfterStringInObject) { + StringPiece str = "{\"key\"}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected : between key:value pair."); + } +} + +TEST_F(JsonStreamParserTest, MissingColonAfterKeyInObject) { + StringPiece str = "{key}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected : between key:value pair."); + } +} + +TEST_F(JsonStreamParserTest, EndOfTextAfterKeyInObject) { + StringPiece str = "{key"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Unexpected end of string."); + } +} + +TEST_F(JsonStreamParserTest, MissingValueAfterColonInObject) { + StringPiece str = "{key:}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Unexpected token."); + } +} + +TEST_F(JsonStreamParserTest, MissingCommaBetweenObjectEntries) { + StringPiece str = "{key:20 'hello': true}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->RenderUint64("key", 20); + DoErrorTest(str, i, "Expected , or } after key:value pair."); + } +} + +TEST_F(JsonStreamParserTest, InvalidLiteralAsObjectKey) { + StringPiece str = "{false: 20}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, ExtraCharactersAfterObject) { + StringPiece str = "{}}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->EndObject(); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +// numbers too large +TEST_F(JsonStreamParserTest, PositiveNumberTooBig) { + StringPiece str = "[18446744073709551616]"; // 2^64 + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Unable to parse number."); + } +} + +TEST_F(JsonStreamParserTest, NegativeNumberTooBig) { + StringPiece str = "[-18446744073709551616]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Unable to parse number."); + } +} + +/* +TODO(sven): Fail parsing when parsing a double that is too large. + +TEST_F(JsonStreamParserTest, DoubleTooBig) { + StringPiece str = "[184464073709551232321616.45]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Unable to parse number"); + } +} +*/ + +// invalid unicode sequence. +TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) { + StringPiece str = "\"\\u12"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Illegal hex string."); + } +} + +TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) { + StringPiece str = "\"\\u12$4hello"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Invalid escape sequence."); + } +} + +// Extra commas with an object or array. +TEST_F(JsonStreamParserTest, ExtraCommaInObject) { + StringPiece str = "{'k1': true,,'k2': false}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->RenderBool("k1", true); + DoErrorTest(str, i, "Expected an object key or }."); + } +} + +TEST_F(JsonStreamParserTest, ExtraCommaInArray) { + StringPiece str = "[true,,false}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->RenderBool("", true); + DoErrorTest(str, i, "Unexpected token."); + } +} + +// Extra text beyond end of value. +TEST_F(JsonStreamParserTest, ExtraTextAfterLiteral) { + StringPiece str = "'hello', 'world'"; + for (int i = 0; i <= str.length(); ++i) { + ow_.RenderString("", "hello"); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +TEST_F(JsonStreamParserTest, ExtraTextAfterObject) { + StringPiece str = "{'key': true} 'oops'"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject("")->RenderBool("key", true)->EndObject(); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +TEST_F(JsonStreamParserTest, ExtraTextAfterArray) { + StringPiece str = "[null] 'oops'"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList("")->RenderNull("")->EndList(); + DoErrorTest(str, i, "Parsing terminated before end of input."); + } +} + +// Random unknown text in the value. +TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) { + StringPiece str = "*"; + for (int i = 0; i <= str.length(); ++i) { + DoErrorTest(str, i, "Expected a value."); + } +} + +TEST_F(JsonStreamParserTest, UnknownCharactersInArray) { + StringPiece str = "[*]"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartList(""); + DoErrorTest(str, i, "Expected a value or ] within an array."); + } +} + +TEST_F(JsonStreamParserTest, UnknownCharactersInObject) { + StringPiece str = "{'key': *}"; + for (int i = 0; i <= str.length(); ++i) { + ow_.StartObject(""); + DoErrorTest(str, i, "Expected a value."); + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/util/internal/location_tracker.h new file mode 100644 index 00000000..0864b057 --- /dev/null +++ b/src/google/protobuf/util/internal/location_tracker.h @@ -0,0 +1,65 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__ + +#include + +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// LocationTrackerInterface is an interface for classes that track +// the location information for the purpose of error reporting. +class LIBPROTOBUF_EXPORT LocationTrackerInterface { + public: + virtual ~LocationTrackerInterface() {} + + // Returns the object location as human readable string. + virtual string ToString() const = 0; + + protected: + LocationTrackerInterface() {} + + private: + // Please do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_LOCATION_TRACKER_H__ diff --git a/src/google/protobuf/util/internal/mock_error_listener.h b/src/google/protobuf/util/internal/mock_error_listener.h new file mode 100644 index 00000000..591c35db --- /dev/null +++ b/src/google/protobuf/util/internal/mock_error_listener.h @@ -0,0 +1,63 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class MockErrorListener : public ErrorListener { + public: + MockErrorListener() {} + virtual ~MockErrorListener() {} + + MOCK_METHOD3(InvalidName, void(const LocationTrackerInterface& loc, + StringPiece unknown_name, + StringPiece message)); + MOCK_METHOD3(InvalidValue, void(const LocationTrackerInterface& loc, + StringPiece type_name, StringPiece value)); + MOCK_METHOD2(MissingField, void(const LocationTrackerInterface& loc, + StringPiece missing_name)); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_MOCK_ERROR_LISTENER_H__ diff --git a/src/google/protobuf/util/internal/object_location_tracker.h b/src/google/protobuf/util/internal/object_location_tracker.h new file mode 100644 index 00000000..8586cecc --- /dev/null +++ b/src/google/protobuf/util/internal/object_location_tracker.h @@ -0,0 +1,64 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An empty concrete implementation of LocationTrackerInterface. +class ObjectLocationTracker : public LocationTrackerInterface { + public: + // Creates an empty location tracker. + ObjectLocationTracker() {} + + virtual ~ObjectLocationTracker() {} + + // Returns empty because nothing is tracked. + virtual string ToString() const { return ""; } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_LOCATION_TRACKER_H__ diff --git a/src/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h new file mode 100644 index 00000000..2c31cfb0 --- /dev/null +++ b/src/google/protobuf/util/internal/object_source.h @@ -0,0 +1,79 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class ObjectWriter; + +// An ObjectSource is anything that can write to an ObjectWriter. +// Implementation of this interface typically provide constructors or +// factory methods to create an instance based on some source data, for +// example, a character stream, or protobuf. +// +// Derived classes could be thread-unsafe. +class LIBPROTOBUF_EXPORT ObjectSource { + public: + virtual ~ObjectSource() {} + + // Writes to the ObjectWriter + virtual util::Status WriteTo(ObjectWriter* ow) const { + return NamedWriteTo("", ow); + } + + // Writes to the ObjectWriter with a custom name for the message. + // This is useful when you chain ObjectSource together by embedding one + // within another. + virtual util::Status NamedWriteTo(StringPiece name, + ObjectWriter* ow) const = 0; + + protected: + ObjectSource() {} + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_SOURCE_H__ diff --git a/src/google/protobuf/util/internal/object_writer.cc b/src/google/protobuf/util/internal/object_writer.cc new file mode 100644 index 00000000..57cc08a1 --- /dev/null +++ b/src/google/protobuf/util/internal/object_writer.cc @@ -0,0 +1,92 @@ +// 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 + +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// static +void ObjectWriter::RenderDataPieceTo(const DataPiece& data, StringPiece name, + ObjectWriter* ow) { + switch (data.type()) { + case DataPiece::TYPE_INT32: { + ow->RenderInt32(name, data.ToInt32().ValueOrDie()); + break; + } + case DataPiece::TYPE_INT64: { + ow->RenderInt64(name, data.ToInt64().ValueOrDie()); + break; + } + case DataPiece::TYPE_UINT32: { + ow->RenderUint32(name, data.ToUint32().ValueOrDie()); + break; + } + case DataPiece::TYPE_UINT64: { + ow->RenderUint64(name, data.ToUint64().ValueOrDie()); + break; + } + case DataPiece::TYPE_DOUBLE: { + ow->RenderDouble(name, data.ToDouble().ValueOrDie()); + break; + } + case DataPiece::TYPE_FLOAT: { + ow->RenderFloat(name, data.ToFloat().ValueOrDie()); + break; + } + case DataPiece::TYPE_BOOL: { + ow->RenderBool(name, data.ToBool().ValueOrDie()); + break; + } + case DataPiece::TYPE_STRING: { + ow->RenderString(name, data.ToString().ValueOrDie()); + break; + } + case DataPiece::TYPE_BYTES: { + ow->RenderBytes(name, data.ToBytes().ValueOrDie()); + break; + } + case DataPiece::TYPE_NULL: { + ow->RenderNull(name); + break; + } + default: + break; + } +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h new file mode 100644 index 00000000..20bd3627 --- /dev/null +++ b/src/google/protobuf/util/internal/object_writer.h @@ -0,0 +1,126 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__ + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class DataPiece; + +// An ObjectWriter is an interface for writing a stream of events +// representing objects and collections. Implementation of this +// interface can be used to write an object stream to an in-memory +// structure, protobufs, JSON, XML, or any other output format +// desired. The ObjectSource interface is typically used as the +// source of an object stream. +// +// See JsonObjectWriter for a sample implementation of ObjectWriter +// and its use. +// +// Derived classes could be thread-unsafe. +// +// TODO(xinb): seems like a prime candidate to apply the RAII paradigm +// and get rid the need to call EndXXX(). +class LIBPROTOBUF_EXPORT ObjectWriter { + public: + virtual ~ObjectWriter() {} + + // Starts an object. If the name is empty, the object will not be named. + virtual ObjectWriter* StartObject(StringPiece name) = 0; + + // Ends an object. + virtual ObjectWriter* EndObject() = 0; + + // Starts a list. If the name is empty, the list will not be named. + virtual ObjectWriter* StartList(StringPiece name) = 0; + + // Ends a list. + virtual ObjectWriter* EndList() = 0; + + // Renders a boolean value. + virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0; + + // Renders an 32-bit integer value. + virtual ObjectWriter* RenderInt32(StringPiece name, int32 value) = 0; + + // Renders an 32-bit unsigned integer value. + virtual ObjectWriter* RenderUint32(StringPiece name, uint32 value) = 0; + + // Renders a 64-bit integer value. + virtual ObjectWriter* RenderInt64(StringPiece name, int64 value) = 0; + + // Renders an 64-bit unsigned integer value. + virtual ObjectWriter* RenderUint64(StringPiece name, uint64 value) = 0; + + // Renders a double value. + virtual ObjectWriter* RenderDouble(StringPiece name, double value) = 0; + + // Renders a float value. + virtual ObjectWriter* RenderFloat(StringPiece name, float value) = 0; + + // Renders a StringPiece value. This is for rendering strings. + virtual ObjectWriter* RenderString(StringPiece name, StringPiece value) = 0; + + // Renders a bytes value. + virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0; + + // Renders a Null value. + virtual ObjectWriter* RenderNull(StringPiece name) = 0; + + // Disables case normalization. Any RenderTYPE call after calling this + // function will output the name field as-is. No normalization is attempted on + // it. This setting is reset immediately after the next RenderTYPE is called. + virtual ObjectWriter* DisableCaseNormalizationForNextKey() { return this; } + + // Renders a DataPiece object to a ObjectWriter. + static void RenderDataPieceTo(const DataPiece& data, StringPiece name, + ObjectWriter* ow); + + protected: + ObjectWriter() {} + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_OBJECT_WRITER_H__ diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc new file mode 100644 index 00000000..53a0e47a --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectsource.cc @@ -0,0 +1,1051 @@ +// 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace util { +using util::Status; +using util::StatusOr; +namespace error { +using util::error::Code; +using util::error::INTERNAL; +} +namespace converter { + +using google::protobuf::Descriptor; +using google::protobuf::EnumValueDescriptor; +using google::protobuf::FieldDescriptor; +using google::protobuf::internal::WireFormat; +using google::protobuf::internal::WireFormatLite; +using util::Status; +using util::StatusOr; + +namespace { +// Finds a field with the given number. NULL if none found. +const google::protobuf::Field* FindFieldByNumber( + const google::protobuf::Type& type, int number); + +// Returns true if the field is packable. +bool IsPackable(const google::protobuf::Field& field); + +// Finds an enum value with the given number. NULL if none found. +const google::protobuf::EnumValue* FindEnumValueByNumber( + const google::protobuf::Enum& tech_enum, int number); + +// Utility function to format nanos. +const string FormatNanos(uint32 nanos); +} // namespace + + +ProtoStreamObjectSource::ProtoStreamObjectSource( + google::protobuf::io::CodedInputStream* stream, TypeResolver* type_resolver, + const google::protobuf::Type& type) + : stream_(stream), + typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + own_typeinfo_(true), + type_(type) { + GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; +} + +ProtoStreamObjectSource::ProtoStreamObjectSource( + google::protobuf::io::CodedInputStream* stream, TypeInfo* typeinfo, + const google::protobuf::Type& type) + : stream_(stream), typeinfo_(typeinfo), own_typeinfo_(false), type_(type) { + GOOGLE_LOG_IF(DFATAL, stream == NULL) << "Input stream is NULL."; +} + +ProtoStreamObjectSource::~ProtoStreamObjectSource() { + if (own_typeinfo_) { + delete typeinfo_; + } +} + +Status ProtoStreamObjectSource::NamedWriteTo(StringPiece name, + ObjectWriter* ow) const { + return WriteMessage(type_, name, 0, true, ow); +} + +const google::protobuf::Field* ProtoStreamObjectSource::FindAndVerifyField( + const google::protobuf::Type& type, uint32 tag) const { + // Lookup the new field in the type by tag number. + const google::protobuf::Field* field = FindFieldByNumber(type, tag >> 3); + // Verify if the field corresponds to the wire type in tag. + // If there is any discrepancy, mark the field as not found. + if (field != NULL) { + WireFormatLite::WireType expected_type = + WireFormatLite::WireTypeForFieldType( + static_cast(field->kind())); + WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag); + if (actual_type != expected_type && + (!IsPackable(*field) || + actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + field = NULL; + } + } + return field; +} + +Status ProtoStreamObjectSource::WriteMessage(const google::protobuf::Type& type, + StringPiece name, + const uint32 end_tag, + bool include_start_and_end, + ObjectWriter* ow) const { + const TypeRenderer* type_renderer = FindTypeRenderer(type.name()); + if (type_renderer != NULL) { + return (*type_renderer)(this, type, name, ow); + } + + const google::protobuf::Field* field = NULL; + string field_name; + // last_tag set to dummy value that is different from tag. + uint32 tag = stream_->ReadTag(), last_tag = tag + 1; + + if (include_start_and_end) { + ow->StartObject(name); + } + while (tag != end_tag) { + if (tag != last_tag) { // Update field only if tag is changed. + last_tag = tag; + field = FindAndVerifyField(type, tag); + if (field != NULL) { + field_name = field->name(); + } + } + if (field == NULL) { + // If we didn't find a field, skip this unknown tag. + // TODO(wpoon): Check return boolean value. + WireFormat::SkipField(stream_, tag, NULL); + tag = stream_->ReadTag(); + continue; + } + + if (field->cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + if (IsMap(*field)) { + ow->StartObject(field_name); + ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow)); + ow->EndObject(); + } else { + ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow)); + } + } else { + // Render the field. + RETURN_IF_ERROR(RenderField(field, field_name, ow)); + tag = stream_->ReadTag(); + } + } + if (include_start_and_end) { + ow->EndObject(); + } + return Status::OK; +} + +StatusOr ProtoStreamObjectSource::RenderList( + const google::protobuf::Field* field, StringPiece name, uint32 list_tag, + ObjectWriter* ow) const { + uint32 tag_to_return = 0; + ow->StartList(name); + if (IsPackable(*field) && + list_tag == + WireFormatLite::MakeTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + RETURN_IF_ERROR(RenderPacked(field, ow)); + // Since packed fields have a single tag, read another tag from stream to + // return. + tag_to_return = stream_->ReadTag(); + } else { + do { + RETURN_IF_ERROR(RenderField(field, "", ow)); + } while ((tag_to_return = stream_->ReadTag()) == list_tag); + } + ow->EndList(); + return tag_to_return; +} + +StatusOr ProtoStreamObjectSource::RenderMap( + const google::protobuf::Field* field, StringPiece name, uint32 list_tag, + ObjectWriter* ow) const { + const google::protobuf::Type* field_type = + typeinfo_->GetType(field->type_url()); + uint32 tag_to_return = 0; + if (IsPackable(*field) && + list_tag == + WireFormatLite::MakeTag(field->number(), + WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) { + RETURN_IF_ERROR(RenderPackedMapEntry(field_type, ow)); + tag_to_return = stream_->ReadTag(); + } else { + do { + RETURN_IF_ERROR(RenderMapEntry(field_type, ow)); + } while ((tag_to_return = stream_->ReadTag()) == list_tag); + } + return tag_to_return; +} + +Status ProtoStreamObjectSource::RenderMapEntry( + const google::protobuf::Type* type, ObjectWriter* ow) const { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // message length + int old_limit = stream_->PushLimit(buffer32); + string map_key; + for (uint32 tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { + const google::protobuf::Field* field = FindAndVerifyField(*type, tag); + if (field == NULL) { + WireFormat::SkipField(stream_, tag, NULL); + continue; + } + // Map field numbers are key = 1 and value = 2 + if (field->number() == 1) { + map_key = ReadFieldValueAsString(*field); + } else if (field->number() == 2) { + if (map_key.empty()) { + return Status(util::error::INTERNAL, "Map key must be non-empty"); + } + // Disable case normalization for map keys as they are just data. We + // retain them intact. + ow->DisableCaseNormalizationForNextKey(); + RETURN_IF_ERROR(RenderField(field, map_key, ow)); + } + } + stream_->PopLimit(old_limit); + + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderPacked( + const google::protobuf::Field* field, ObjectWriter* ow) const { + uint32 length; + stream_->ReadVarint32(&length); + int old_limit = stream_->PushLimit(length); + while (stream_->BytesUntilLimit() > 0) { + RETURN_IF_ERROR(RenderField(field, StringPiece(), ow)); + } + stream_->PopLimit(old_limit); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderPackedMapEntry( + const google::protobuf::Type* type, ObjectWriter* ow) const { + uint32 length; + stream_->ReadVarint32(&length); + int old_limit = stream_->PushLimit(length); + while (stream_->BytesUntilLimit() > 0) { + RETURN_IF_ERROR(RenderMapEntry(type, ow)); + } + stream_->PopLimit(old_limit); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderTimestamp( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + pair p = os->ReadSecondsAndNanos(type); + int64 seconds = p.first; + int32 nanos = p.second; + if (seconds > kMaxSeconds || seconds < kMinSeconds) { + return Status( + util::error::INTERNAL, + StrCat("Timestamp seconds exceeds limit for field: ", field_name)); + } + + if (nanos < 0 || nanos >= kNanosPerSecond) { + return Status( + util::error::INTERNAL, + StrCat("Timestamp nanos exceeds limit for field: ", field_name)); + } + + ow->RenderString(field_name, + ::google::protobuf::internal::FormatTime(seconds, nanos)); + + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderDuration( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + pair p = os->ReadSecondsAndNanos(type); + int64 seconds = p.first; + int32 nanos = p.second; + if (seconds > kMaxSeconds || seconds < kMinSeconds) { + return Status( + util::error::INTERNAL, + StrCat("Duration seconds exceeds limit for field: ", field_name)); + } + + if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { + return Status( + util::error::INTERNAL, + StrCat("Duration nanos exceeds limit for field: ", field_name)); + } + + string sign = ""; + if (seconds < 0) { + if (nanos > 0) { + return Status(util::error::INTERNAL, + StrCat( + "Duration nanos is non-negative, but seconds is " + "negative for field: ", + field_name)); + } + sign = "-"; + seconds = -seconds; + nanos = -nanos; + } else if (seconds == 0 && nanos < 0) { + sign = "-"; + nanos = -nanos; + } + string formatted_duration = StringPrintf("%s%lld%ss", sign.c_str(), seconds, + FormatNanos(nanos).c_str()); + ow->RenderString(field_name, formatted_duration); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderDouble(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint64 buffer64 = 0; // default value of Double wrapper value + if (tag != 0) { + os->stream_->ReadLittleEndian64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderDouble(field_name, bit_cast(buffer64)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderFloat(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32 = 0; // default value of Float wrapper value + if (tag != 0) { + os->stream_->ReadLittleEndian32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderFloat(field_name, bit_cast(buffer32)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint64 buffer64 = 0; // default value of Int64 wrapper value + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderInt64(field_name, bit_cast(buffer64)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderUInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint64 buffer64 = 0; // default value of UInt64 wrapper value + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderUint64(field_name, bit_cast(buffer64)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32 = 0; // default value of Int32 wrapper value + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderInt32(field_name, bit_cast(buffer32)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderUInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32 = 0; // default value of UInt32 wrapper value + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadTag(); + } + ow->RenderUint32(field_name, bit_cast(buffer32)); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderBool(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint64 buffer64 = 0; // results in 'false' value as default, which is the + // default value of Bool wrapper + if (tag != 0) { + os->stream_->ReadVarint64(&buffer64); + os->stream_->ReadTag(); + } + ow->RenderBool(field_name, buffer64 != 0); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderString(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32; + string str; // default value of empty for String wrapper + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); // string size. + os->stream_->ReadString(&str, buffer32); + os->stream_->ReadTag(); + } + ow->RenderString(field_name, str); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderBytes(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + uint32 buffer32; + string str; + if (tag != 0) { + os->stream_->ReadVarint32(&buffer32); + os->stream_->ReadString(&str, buffer32); + os->stream_->ReadTag(); + } + ow->RenderBytes(field_name, str); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderStruct(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + const google::protobuf::Field* field = NULL; + uint32 tag = os->stream_->ReadTag(); + ow->StartObject(field_name); + while (tag != 0) { + field = os->FindAndVerifyField(type, tag); + // google.protobuf.Struct has only one field that is a map. Hence we use + // RenderMap to render that field. + if (os->IsMap(*field)) { + ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow)); + } + } + ow->EndObject(); + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderStructValue( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + const google::protobuf::Field* field = NULL; + for (uint32 tag = os->stream_->ReadTag(); tag != 0; + tag = os->stream_->ReadTag()) { + field = os->FindAndVerifyField(type, tag); + if (field == NULL) { + WireFormat::SkipField(os->stream_, tag, NULL); + continue; + } + RETURN_IF_ERROR(os->RenderField(field, field_name, ow)); + } + return Status::OK; +} + +// TODO(skarvaje): Avoid code duplication of for loops and SkipField logic. +Status ProtoStreamObjectSource::RenderStructListValue( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + uint32 tag = os->stream_->ReadTag(); + + // Render empty list when we find empty ListValue message. + if (tag == 0) { + ow->StartList(field_name); + ow->EndList(); + return Status::OK; + } + + while (tag != 0) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field == NULL) { + WireFormat::SkipField(os->stream_, tag, NULL); + tag = os->stream_->ReadTag(); + continue; + } + ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow)); + } + return Status::OK; +} + +Status ProtoStreamObjectSource::RenderAny(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece field_name, + ObjectWriter* ow) { + // An Any is of the form { string type_url = 1; bytes value = 2; } + uint32 tag; + string type_url; + string value; + + // First read out the type_url and value from the proto stream + for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field == NULL) { + WireFormat::SkipField(os->stream_, tag, NULL); + continue; + } + // 'type_url' has field number of 1 and 'value' has field number 2 + // //google/protobuf/any.proto + if (field->number() == 1) { + // read type_url + uint32 type_url_size; + os->stream_->ReadVarint32(&type_url_size); + os->stream_->ReadString(&type_url, type_url_size); + } else if (field->number() == 2) { + // read value + uint32 value_size; + os->stream_->ReadVarint32(&value_size); + os->stream_->ReadString(&value, value_size); + } + } + + // If there is no value, we don't lookup the type, we just output it (if + // present). If both type and value are empty we output an empty object. + if (value.empty()) { + ow->StartObject(field_name); + if (!type_url.empty()) { + ow->RenderString("@type", type_url); + } + ow->EndObject(); + return util::Status::OK; + } + + // If there is a value but no type, we cannot render it, so report an error. + if (type_url.empty()) { + // TODO(sven): Add an external message once those are ready. + return util::Status(util::error::INTERNAL, + "Invalid Any, the type_url is missing."); + } + + util::StatusOr resolved_type = + os->typeinfo_->ResolveTypeUrl(type_url); + + if (!resolved_type.ok()) { + // Convert into an internal error, since this means the backend gave us + // an invalid response (missing or invalid type information). + return util::Status(util::error::INTERNAL, + resolved_type.status().error_message()); + } + // nested_type cannot be null at this time. + const google::protobuf::Type* nested_type = resolved_type.ValueOrDie(); + + // We know the type so we can render it. Recursively parse the nested stream + // using a nested ProtoStreamObjectSource using our nested type information. + google::protobuf::io::ArrayInputStream zero_copy_stream(value.data(), value.size()); + google::protobuf::io::CodedInputStream in_stream(&zero_copy_stream); + ProtoStreamObjectSource nested_os(&in_stream, os->typeinfo_, *nested_type); + + // We manually call start and end object here so we can inject the @type. + ow->StartObject(field_name); + ow->RenderString("@type", type_url); + util::Status result = + nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow); + ow->EndObject(); + return result; +} + +Status ProtoStreamObjectSource::RenderFieldMask( + const ProtoStreamObjectSource* os, const google::protobuf::Type& type, + StringPiece field_name, ObjectWriter* ow) { + string combined; + uint32 buffer32; + uint32 paths_field_tag = 0; + for (uint32 tag = os->stream_->ReadTag(); tag != 0; + tag = os->stream_->ReadTag()) { + if (paths_field_tag == 0) { + const google::protobuf::Field* field = os->FindAndVerifyField(type, tag); + if (field != NULL && field->number() == 1 && + field->name() == "paths") { + paths_field_tag = tag; + } + } + if (paths_field_tag != tag) { + return util::Status(util::error::INTERNAL, + "Invalid FieldMask, unexpected field."); + } + string str; + os->stream_->ReadVarint32(&buffer32); // string size. + os->stream_->ReadString(&str, buffer32); + if (!combined.empty()) { + combined.append(","); + } + combined.append(ConvertFieldMaskPath(str, &ToCamelCase)); + } + ow->RenderString(field_name, combined); + return Status::OK; +} + +hash_map* +ProtoStreamObjectSource::CreateRendererMap() { + hash_map* result = + new hash_map(); + (*result)["google.protobuf.Timestamp"] = + &ProtoStreamObjectSource::RenderTimestamp; + (*result)["google.protobuf.Duration"] = + &ProtoStreamObjectSource::RenderDuration; + (*result)["google.protobuf.DoubleValue"] = + &ProtoStreamObjectSource::RenderDouble; + (*result)["google.protobuf.FloatValue"] = + &ProtoStreamObjectSource::RenderFloat; + (*result)["google.protobuf.Int64Value"] = + &ProtoStreamObjectSource::RenderInt64; + (*result)["google.protobuf.UInt64Value"] = + &ProtoStreamObjectSource::RenderUInt64; + (*result)["google.protobuf.Int32Value"] = + &ProtoStreamObjectSource::RenderInt32; + (*result)["google.protobuf.UInt32Value"] = + &ProtoStreamObjectSource::RenderUInt32; + (*result)["google.protobuf.BoolValue"] = &ProtoStreamObjectSource::RenderBool; + (*result)["google.protobuf.StringValue"] = + &ProtoStreamObjectSource::RenderString; + (*result)["google.protobuf.BytesValue"] = + &ProtoStreamObjectSource::RenderBytes; + (*result)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny; + (*result)["google.protobuf.Struct"] = &ProtoStreamObjectSource::RenderStruct; + (*result)["google.protobuf.Value"] = + &ProtoStreamObjectSource::RenderStructValue; + (*result)["google.protobuf.ListValue"] = + &ProtoStreamObjectSource::RenderStructListValue; + (*result)["google.protobuf.FieldMask"] = + &ProtoStreamObjectSource::RenderFieldMask; + return result; +} + +// static +ProtoStreamObjectSource::TypeRenderer* +ProtoStreamObjectSource::FindTypeRenderer(const string& type_url) { + static hash_map* renderers = CreateRendererMap(); + return FindOrNull(*renderers, type_url); +} + +Status ProtoStreamObjectSource::RenderField( + const google::protobuf::Field* field, StringPiece field_name, + ObjectWriter* ow) const { + switch (field->kind()) { + case google::protobuf::Field_Kind_TYPE_BOOL: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + ow->RenderBool(field_name, buffer64 != 0); + break; + } + case google::protobuf::Field_Kind_TYPE_INT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + ow->RenderInt32(field_name, bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_INT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + ow->RenderInt64(field_name, bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + ow->RenderUint32(field_name, bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + ow->RenderUint64(field_name, bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED32: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + ow->RenderInt32(field_name, bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED64: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + ow->RenderInt64(field_name, bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED32: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + ow->RenderUint32(field_name, bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED64: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + ow->RenderUint64(field_name, bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_FLOAT: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + ow->RenderFloat(field_name, bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_DOUBLE: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + ow->RenderDouble(field_name, bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_ENUM: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + + // If the field represents an explicit NULL value, render null. + if (field->type_url() == kStructNullValueTypeUrl) { + ow->RenderNull(field_name); + break; + } + + // Get the nested enum type for this field. + // TODO(skarvaje): Avoid string manipulation. Find ways to speed this + // up. + const google::protobuf::Enum* en = typeinfo_->GetEnum(field->type_url()); + // Lookup the name of the enum, and render that. Skips unknown enums. + if (en != NULL) { + const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumber(*en, buffer32); + if (enum_value != NULL) { + ow->RenderString(field_name, enum_value->name()); + } + } else { + GOOGLE_LOG(INFO) << "Unkown enum skipped: " << field->type_url(); + } + break; + } + case google::protobuf::Field_Kind_TYPE_STRING: { + uint32 buffer32; + string str; + stream_->ReadVarint32(&buffer32); // string size. + stream_->ReadString(&str, buffer32); + ow->RenderString(field_name, str); + break; + } + case google::protobuf::Field_Kind_TYPE_BYTES: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // bytes size. + string value; + stream_->ReadString(&value, buffer32); + ow->RenderBytes(field_name, value); + break; + } + case google::protobuf::Field_Kind_TYPE_MESSAGE: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // message length + int old_limit = stream_->PushLimit(buffer32); + // Get the nested message type for this field. + const google::protobuf::Type* type = + typeinfo_->GetType(field->type_url()); + if (type == NULL) { + return Status(util::error::INTERNAL, + StrCat("Invalid configuration. Could not find the type: ", + field->type_url())); + } + RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow)); + if (!stream_->ConsumedEntireMessage()) { + return Status(util::error::INVALID_ARGUMENT, + "Nested protocol message not parsed in its entirety."); + } + stream_->PopLimit(old_limit); + break; + } + default: + break; + } + return Status::OK; +} + +// TODO(skarvaje): Fix this to avoid code duplication. +const string ProtoStreamObjectSource::ReadFieldValueAsString( + const google::protobuf::Field& field) const { + string result; + switch (field.kind()) { + case google::protobuf::Field_Kind_TYPE_BOOL: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + result = buffer64 != 0 ? "true" : "false"; + break; + } + case google::protobuf::Field_Kind_TYPE_INT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + result = SimpleItoa(bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_INT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + result = SimpleItoa(bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + result = SimpleItoa(bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + result = SimpleItoa(bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT32: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + result = SimpleItoa(WireFormatLite::ZigZagDecode32(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT64: { + uint64 buffer64; + stream_->ReadVarint64(&buffer64); + result = SimpleItoa(WireFormatLite::ZigZagDecode64(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED32: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = SimpleItoa(bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED64: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = SimpleItoa(bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED32: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = SimpleItoa(bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED64: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = SimpleItoa(bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_FLOAT: { + uint32 buffer32; + stream_->ReadLittleEndian32(&buffer32); + result = SimpleFtoa(bit_cast(buffer32)); + break; + } + case google::protobuf::Field_Kind_TYPE_DOUBLE: { + uint64 buffer64; + stream_->ReadLittleEndian64(&buffer64); + result = SimpleDtoa(bit_cast(buffer64)); + break; + } + case google::protobuf::Field_Kind_TYPE_ENUM: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); + // Get the nested enum type for this field. + // TODO(skarvaje): Avoid string manipulation. Find ways to speed this + // up. + const google::protobuf::Enum* en = typeinfo_->GetEnum(field.type_url()); + // Lookup the name of the enum, and render that. Skips unknown enums. + if (en != NULL) { + const google::protobuf::EnumValue* enum_value = + FindEnumValueByNumber(*en, buffer32); + if (enum_value != NULL) { + result = enum_value->name(); + } + } + break; + } + case google::protobuf::Field_Kind_TYPE_STRING: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // string size. + stream_->ReadString(&result, buffer32); + break; + } + case google::protobuf::Field_Kind_TYPE_BYTES: { + uint32 buffer32; + stream_->ReadVarint32(&buffer32); // bytes size. + stream_->ReadString(&result, buffer32); + break; + } + default: + break; + } + return result; +} + +// Field is a map if it is a repeated message and it has an option "map_type". +// TODO(skarvaje): Consider pre-computing the IsMap() into Field directly. +bool ProtoStreamObjectSource::IsMap( + const google::protobuf::Field& field) const { + const google::protobuf::Type* field_type = + typeinfo_->GetType(field.type_url()); + + // TODO(xiaofeng): Unify option names. + return field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE && + (GetBoolOptionOrDefault(field_type->options(), + "google.protobuf.MessageOptions.map_entry", false) || + GetBoolOptionOrDefault(field_type->options(), "map_entry", false)); +} + +std::pair ProtoStreamObjectSource::ReadSecondsAndNanos( + const google::protobuf::Type& type) const { + uint64 seconds = 0; + uint32 nanos = 0; + uint32 tag = 0; + int64 signed_seconds = 0; + int64 signed_nanos = 0; + + for (tag = stream_->ReadTag(); tag != 0; tag = stream_->ReadTag()) { + const google::protobuf::Field* field = FindAndVerifyField(type, tag); + if (field == NULL) { + WireFormat::SkipField(stream_, tag, NULL); + continue; + } + // 'seconds' has field number of 1 and 'nanos' has field number 2 + // //google/protobuf/timestamp.proto & duration.proto + if (field->number() == 1) { + // read seconds + stream_->ReadVarint64(&seconds); + signed_seconds = bit_cast(seconds); + } else if (field->number() == 2) { + // read nanos + stream_->ReadVarint32(&nanos); + signed_nanos = bit_cast(nanos); + } + } + return std::pair(signed_seconds, signed_nanos); +} + +namespace { +// TODO(skarvaje): Speed this up by not doing a linear scan. +const google::protobuf::Field* FindFieldByNumber( + const google::protobuf::Type& type, int number) { + for (int i = 0; i < type.fields_size(); ++i) { + if (type.fields(i).number() == number) { + return &type.fields(i); + } + } + return NULL; +} + +// TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable() +// using tech Field. +bool IsPackable(const google::protobuf::Field& field) { + return field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && + google::protobuf::FieldDescriptor::IsTypePackable( + static_cast(field.kind())); +} + +// TODO(skarvaje): Speed this up by not doing a linear scan. +const google::protobuf::EnumValue* FindEnumValueByNumber( + const google::protobuf::Enum& tech_enum, int number) { + for (int i = 0; i < tech_enum.enumvalue_size(); ++i) { + const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i); + if (ev.number() == number) { + return &ev; + } + } + return NULL; +} + +// TODO(skarvaje): Look into optimizing this by not doing computation on +// double. +const string FormatNanos(uint32 nanos) { + const char* format = + (nanos % 1000 != 0) ? "%.9f" : (nanos % 1000000 != 0) ? "%.6f" : "%.3f"; + string formatted = + StringPrintf(format, static_cast(nanos) / kNanosPerSecond); + // remove the leading 0 before decimal. + return formatted.substr(1); +} +} // namespace + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h new file mode 100644 index 00000000..4a4e6bbf --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectsource.h @@ -0,0 +1,245 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace google { +namespace protobuf { +class Field; +class Type; +} // namespace protobuf + + +namespace protobuf { +namespace util { +namespace converter { + +class TypeInfo; + +// An ObjectSource that can parse a stream of bytes as a protocol buffer. +// This implementation uses a tech Type for tag lookup. +// +// Sample usage: (suppose input is: string proto) +// ArrayInputStream arr_stream(proto.data(), proto.size()); +// CodedInputStream in_stream(&arr_stream); +// ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo, +// ); +// +// Status status = os.WriteTo(); +class LIBPROTOBUF_EXPORT ProtoStreamObjectSource : public ObjectSource { + public: + ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream, + TypeResolver* type_resolver, + const google::protobuf::Type& type); + + virtual ~ProtoStreamObjectSource(); + + virtual util::Status NamedWriteTo(StringPiece name, ObjectWriter* ow) const; + + protected: + // Writes a proto2 Message to the ObjectWriter. When the given end_tag is + // found this method will complete, allowing it to be used for parsing both + // nested messages (end with 0) and nested groups (end with group end tag). + // The include_start_and_end parameter allows this method to be called when + // already inside of an object, and skip calling StartObject and EndObject. + virtual util::Status WriteMessage(const google::protobuf::Type& descriptor, + StringPiece name, const uint32 end_tag, + bool include_start_and_end, + ObjectWriter* ow) const; + + private: + ProtoStreamObjectSource(google::protobuf::io::CodedInputStream* stream, + TypeInfo* typeinfo, + const google::protobuf::Type& type); + // Function that renders a well known type with a modified behavior. + typedef util::Status (*TypeRenderer)(const ProtoStreamObjectSource*, + const google::protobuf::Type&, + StringPiece, ObjectWriter*); + + // Looks up a field and verify its consistency with wire type in tag. + const google::protobuf::Field* FindAndVerifyField( + const google::protobuf::Type& type, uint32 tag) const; + + // TODO(skarvaje): Mark these methods as non-const as they modify internal + // state (stream_). + // + // Renders a repeating field (packed or unpacked). + // Returns the next tag after reading all sequential repeating elements. The + // caller should use this tag before reading more tags from the stream. + util::StatusOr RenderList(const google::protobuf::Field* field, + StringPiece name, uint32 list_tag, + ObjectWriter* ow) const; + // Renders a NWP map. + // Returns the next tag after reading all map entries. The caller should use + // this tag before reading more tags from the stream. + util::StatusOr RenderMap(const google::protobuf::Field* field, + StringPiece name, uint32 list_tag, + ObjectWriter* ow) const; + + // Renders an entry in a map, advancing stream pointers appropriately. + util::Status RenderMapEntry(const google::protobuf::Type* type, + ObjectWriter* ow) const; + + // Renders a packed repeating field. A packed field is stored as: + // {tag length item1 item2 item3} instead of the less efficient + // {tag item1 tag item2 tag item3}. + util::Status RenderPacked(const google::protobuf::Field* field, + ObjectWriter* ow) const; + + // Equivalent of RenderPacked, but for map entries. + util::Status RenderPackedMapEntry(const google::protobuf::Type* type, + ObjectWriter* ow) const; + + // Renders a google.protobuf.Timestamp value to ObjectWriter + static util::Status RenderTimestamp(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Renders a google.protobuf.Duration value to ObjectWriter + static util::Status RenderDuration(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Following RenderTYPE functions render well known types in + // google/protobuf/wrappers.proto corresponding to TYPE. + static util::Status RenderDouble(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderFloat(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderUInt64(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderUInt32(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderBool(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderString(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + static util::Status RenderBytes(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Renders a google.protobuf.Struct to ObjectWriter. + static util::Status RenderStruct(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Helper to render google.protobuf.Struct's Value fields to ObjectWriter. + static util::Status RenderStructValue(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Helper to render google.protobuf.Struct's ListValue fields to ObjectWriter. + static util::Status RenderStructListValue( + const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Render the "Any" type. + static util::Status RenderAny(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + // Render the "FieldMask" type. + static util::Status RenderFieldMask(const ProtoStreamObjectSource* os, + const google::protobuf::Type& type, + StringPiece name, ObjectWriter* ow); + + static hash_map* CreateRendererMap(); + static TypeRenderer* FindTypeRenderer(const string& type_url); + + // Renders a field value to the ObjectWriter. + util::Status RenderField(const google::protobuf::Field* field, + StringPiece field_name, ObjectWriter* ow) const; + + // Reads field value according to Field spec in 'field' and returns the read + // value as string. This only works for primitive datatypes (no message + // types). + const string ReadFieldValueAsString( + const google::protobuf::Field& field) const; + + // Utility function to detect proto maps. The 'field' MUST be repeated. + bool IsMap(const google::protobuf::Field& field) const; + + // Utility to read int64 and int32 values from a message type in stream_. + // Used for reading google.protobuf.Timestamp and Duration messages. + std::pair ReadSecondsAndNanos( + const google::protobuf::Type& type) const; + + // Input stream to read from. Ownership rests with the caller. + google::protobuf::io::CodedInputStream* stream_; + + // Type information for all the types used in the descriptor. Used to find + // google::protobuf::Type of nested messages/enums. + TypeInfo* typeinfo_; + // Whether this class owns the typeinfo_ object. If true the typeinfo_ object + // should be deleted in the destructor. + bool own_typeinfo_; + + // google::protobuf::Type of the message source. + const google::protobuf::Type& type_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTSOURCE_H__ diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc new file mode 100644 index 00000000..630393f2 --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectsource_test.cc @@ -0,0 +1,824 @@ +// 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 + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::Descriptor; +using google::protobuf::DescriptorPool; +using google::protobuf::FileDescriptorProto; +using google::protobuf::Message; +using google::protobuf::io::ArrayInputStream; +using google::protobuf::io::CodedInputStream; +using util::Status; +using google::protobuf::testing::Author; +using google::protobuf::testing::BadAuthor; +using google::protobuf::testing::BadNestedBook; +using google::protobuf::testing::Book; +using google::protobuf::testing::Book_Label; +using google::protobuf::testing::NestedBook; +using google::protobuf::testing::PackedPrimitive; +using google::protobuf::testing::Primitive; +using google::protobuf::testing::more_author; +using google::protobuf::testing::maps::MapOut; +using google::protobuf::testing::anys::AnyOut; +using google::protobuf::testing::anys::AnyM; +using google::protobuf::testing::FieldMaskTest; +using google::protobuf::testing::NestedFieldMask; +using google::protobuf::testing::structs::StructType; +using ::testing::_; + + +namespace { +string GetTypeUrl(const Descriptor* descriptor) { + return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name(); +} +} // namespace + +class ProtostreamObjectSourceTest + : public ::testing::TestWithParam { + protected: + ProtostreamObjectSourceTest() : helper_(GetParam()), mock_(), ow_(&mock_) { + helper_.ResetTypeInfo(Book::descriptor()); + } + + virtual ~ProtostreamObjectSourceTest() {} + + void DoTest(const Message& msg, const Descriptor* descriptor) { + Status status = ExecuteTest(msg, descriptor); + EXPECT_EQ(Status::OK, status); + } + + Status ExecuteTest(const Message& msg, const Descriptor* descriptor) { + ostringstream oss; + msg.SerializePartialToOstream(&oss); + string proto = oss.str(); + ArrayInputStream arr_stream(proto.data(), proto.size()); + CodedInputStream in_stream(&arr_stream); + + google::protobuf::scoped_ptr os( + helper_.NewProtoSource(&in_stream, GetTypeUrl(descriptor))); + return os->WriteTo(&mock_); + } + + void PrepareExpectingObjectWriterForRepeatedPrimitive() { + ow_.StartObject("") + ->StartList("rep_fix32") + ->RenderUint32("", bit_cast(3201)) + ->RenderUint32("", bit_cast(0)) + ->RenderUint32("", bit_cast(3202)) + ->EndList() + ->StartList("rep_u32") + ->RenderUint32("", bit_cast(3203)) + ->RenderUint32("", bit_cast(0)) + ->EndList() + ->StartList("rep_i32") + ->RenderInt32("", 0) + ->RenderInt32("", 3204) + ->RenderInt32("", 3205) + ->EndList() + ->StartList("rep_sf32") + ->RenderInt32("", 3206) + ->RenderInt32("", 0) + ->EndList() + ->StartList("rep_s32") + ->RenderInt32("", 0) + ->RenderInt32("", 3207) + ->RenderInt32("", 3208) + ->EndList() + ->StartList("rep_fix64") + ->RenderUint64("", bit_cast(6401L)) + ->RenderUint64("", bit_cast(0L)) + ->EndList() + ->StartList("rep_u64") + ->RenderUint64("", bit_cast(0L)) + ->RenderUint64("", bit_cast(6402L)) + ->RenderUint64("", bit_cast(6403L)) + ->EndList() + ->StartList("rep_i64") + ->RenderInt64("", 6404L) + ->RenderInt64("", 0L) + ->EndList() + ->StartList("rep_sf64") + ->RenderInt64("", 0L) + ->RenderInt64("", 6405L) + ->RenderInt64("", 6406L) + ->EndList() + ->StartList("rep_s64") + ->RenderInt64("", 6407L) + ->RenderInt64("", 0L) + ->EndList() + ->StartList("rep_float") + ->RenderFloat("", 0.0f) + ->RenderFloat("", 32.1f) + ->RenderFloat("", 32.2f) + ->EndList() + ->StartList("rep_double") + ->RenderDouble("", 64.1L) + ->RenderDouble("", 0.0L) + ->EndList() + ->StartList("rep_bool") + ->RenderBool("", true) + ->RenderBool("", false) + ->EndList() + ->EndObject(); + } + + Primitive PrepareRepeatedPrimitive() { + Primitive primitive; + primitive.add_rep_fix32(3201); + primitive.add_rep_fix32(0); + primitive.add_rep_fix32(3202); + primitive.add_rep_u32(3203); + primitive.add_rep_u32(0); + primitive.add_rep_i32(0); + primitive.add_rep_i32(3204); + primitive.add_rep_i32(3205); + primitive.add_rep_sf32(3206); + primitive.add_rep_sf32(0); + primitive.add_rep_s32(0); + primitive.add_rep_s32(3207); + primitive.add_rep_s32(3208); + primitive.add_rep_fix64(6401L); + primitive.add_rep_fix64(0L); + primitive.add_rep_u64(0L); + primitive.add_rep_u64(6402L); + primitive.add_rep_u64(6403L); + primitive.add_rep_i64(6404L); + primitive.add_rep_i64(0L); + primitive.add_rep_sf64(0L); + primitive.add_rep_sf64(6405L); + primitive.add_rep_sf64(6406L); + primitive.add_rep_s64(6407L); + primitive.add_rep_s64(0L); + primitive.add_rep_float(0.0f); + primitive.add_rep_float(32.1f); + primitive.add_rep_float(32.2f); + primitive.add_rep_double(64.1L); + primitive.add_rep_double(0.0); + primitive.add_rep_bool(true); + primitive.add_rep_bool(false); + + PrepareExpectingObjectWriterForRepeatedPrimitive(); + return primitive; + } + + PackedPrimitive PreparePackedPrimitive() { + PackedPrimitive primitive; + primitive.add_rep_fix32(3201); + primitive.add_rep_fix32(0); + primitive.add_rep_fix32(3202); + primitive.add_rep_u32(3203); + primitive.add_rep_u32(0); + primitive.add_rep_i32(0); + primitive.add_rep_i32(3204); + primitive.add_rep_i32(3205); + primitive.add_rep_sf32(3206); + primitive.add_rep_sf32(0); + primitive.add_rep_s32(0); + primitive.add_rep_s32(3207); + primitive.add_rep_s32(3208); + primitive.add_rep_fix64(6401L); + primitive.add_rep_fix64(0L); + primitive.add_rep_u64(0L); + primitive.add_rep_u64(6402L); + primitive.add_rep_u64(6403L); + primitive.add_rep_i64(6404L); + primitive.add_rep_i64(0L); + primitive.add_rep_sf64(0L); + primitive.add_rep_sf64(6405L); + primitive.add_rep_sf64(6406L); + primitive.add_rep_s64(6407L); + primitive.add_rep_s64(0L); + primitive.add_rep_float(0.0f); + primitive.add_rep_float(32.1f); + primitive.add_rep_float(32.2f); + primitive.add_rep_double(64.1L); + primitive.add_rep_double(0.0); + primitive.add_rep_bool(true); + primitive.add_rep_bool(false); + + PrepareExpectingObjectWriterForRepeatedPrimitive(); + return primitive; + } + + testing::TypeInfoTestHelper helper_; + + ::testing::NiceMock mock_; + ExpectingObjectWriter ow_; +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(ProtostreamObjectSourceTest, EmptyMessage) { + Book empty; + ow_.StartObject("")->EndObject(); + DoTest(empty, Book::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, Primitives) { + Primitive primitive; + primitive.set_fix32(3201); + primitive.set_u32(3202); + primitive.set_i32(3203); + primitive.set_sf32(3204); + primitive.set_s32(3205); + primitive.set_fix64(6401L); + primitive.set_u64(6402L); + primitive.set_i64(6403L); + primitive.set_sf64(6404L); + primitive.set_s64(6405L); + primitive.set_str("String Value"); + primitive.set_bytes("Some Bytes"); + primitive.set_float_(32.1f); + primitive.set_double_(64.1L); + primitive.set_bool_(true); + + ow_.StartObject("") + ->RenderUint32("fix32", bit_cast(3201)) + ->RenderUint32("u32", bit_cast(3202)) + ->RenderInt32("i32", 3203) + ->RenderInt32("sf32", 3204) + ->RenderInt32("s32", 3205) + ->RenderUint64("fix64", bit_cast(6401L)) + ->RenderUint64("u64", bit_cast(6402L)) + ->RenderInt64("i64", 6403L) + ->RenderInt64("sf64", 6404L) + ->RenderInt64("s64", 6405L) + ->RenderString("str", "String Value") + ->RenderBytes("bytes", "Some Bytes") + ->RenderFloat("float", 32.1f) + ->RenderDouble("double", 64.1L) + ->RenderBool("bool", true) + ->EndObject(); + DoTest(primitive, Primitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) { + Primitive primitive = PrepareRepeatedPrimitive(); + primitive.add_rep_str("String One"); + primitive.add_rep_str("String Two"); + primitive.add_rep_bytes("Some Bytes"); + + ow_.StartList("rep_str") + ->RenderString("", "String One") + ->RenderString("", "String Two") + ->EndList() + ->StartList("rep_bytes") + ->RenderBytes("", "Some Bytes") + ->EndList(); + DoTest(primitive, Primitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, NestedMessage) { + Author* author = new Author(); + author->set_id(101L); + author->set_name("Tolstoy"); + Book book; + book.set_title("My Book"); + book.set_allocated_author(author); + + ow_.StartObject("") + ->RenderString("title", "My Book") + ->StartObject("author") + ->RenderUint64("id", bit_cast(101L)) + ->RenderString("name", "Tolstoy") + ->EndObject() + ->EndObject(); + DoTest(book, Book::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, RepeatingField) { + Author author; + author.set_alive(false); + author.set_name("john"); + author.add_pseudonym("phil"); + author.add_pseudonym("bob"); + + ow_.StartObject("") + ->RenderBool("alive", false) + ->RenderString("name", "john") + ->StartList("pseudonym") + ->RenderString("", "phil") + ->RenderString("", "bob") + ->EndList() + ->EndObject(); + DoTest(author, Author::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) { + DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) { + // Protostream is packed, but parse with non-packed Primitive. + DoTest(PreparePackedPrimitive(), Primitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) { + // Protostream is not packed, but parse with PackedPrimitive. + DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, BadAuthor) { + Author author; + author.set_alive(false); + author.set_name("john"); + author.set_id(1234L); + author.add_pseudonym("phil"); + author.add_pseudonym("bob"); + + ow_.StartObject("") + ->StartList("alive") + ->RenderBool("", false) + ->EndList() + ->StartList("name") + ->RenderUint64("", static_cast('j')) + ->RenderUint64("", static_cast('o')) + ->RenderUint64("", static_cast('h')) + ->RenderUint64("", static_cast('n')) + ->EndList() + ->RenderString("pseudonym", "phil") + ->RenderString("pseudonym", "bob") + ->EndObject(); + // Protostream created with Author, but parsed with BadAuthor. + DoTest(author, BadAuthor::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) { + Book* book = new Book(); + book->set_length(250); + book->set_published(2014L); + NestedBook nested; + nested.set_allocated_book(book); + + ow_.StartObject("") + ->StartList("book") + ->RenderUint32("", 24) // tag for field length (3 << 3) + ->RenderUint32("", 250) + ->RenderUint32("", 32) // tag for field published (4 << 3) + ->RenderUint32("", 2014) + ->EndList() + ->EndObject(); + // Protostream created with NestedBook, but parsed with BadNestedBook. + DoTest(nested, BadNestedBook::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) { + BadNestedBook nested; + nested.add_book(1); + nested.add_book(2); + nested.add_book(3); + nested.add_book(4); + nested.add_book(5); + nested.add_book(6); + nested.add_book(7); + + ow_.StartObject("")->StartObject("book")->EndObject()->EndObject(); + // Protostream created with BadNestedBook, but parsed with NestedBook. + DoTest(nested, NestedBook::descriptor()); +} + +TEST_P(ProtostreamObjectSourceTest, + LongRepeatedListDoesNotBreakIntoMultipleJsonLists) { + Book book; + + int repeat = 10000; + for (int i = 0; i < repeat; ++i) { + Book_Label* label = book.add_labels(); + label->set_key(StrCat("i", i)); + label->set_value(StrCat("v", i)); + } + + // Make sure StartList and EndList are called exactly once (see b/18227499 for + // problems when this doesn't happen) + EXPECT_CALL(mock_, StartList(_)).Times(1); + EXPECT_CALL(mock_, EndList()).Times(1); + + DoTest(book, Book::descriptor()); +} + +class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest { + protected: + ProtostreamObjectSourceMapsTest() { + helper_.ResetTypeInfo(MapOut::descriptor()); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceMapsTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +// Tests JSON map. +// +// This is the example expected output. +// { +// "map1": { +// "key1": { +// "foo": "foovalue" +// }, +// "key2": { +// "foo": "barvalue" +// } +// }, +// "map2": { +// "nestedself": { +// "map1": { +// "nested_key1": { +// "foo": "nested_foo" +// } +// }, +// "bar": "nested_bar_string" +// } +// }, +// "map3": { +// "111": "one one one" +// }, +// "bar": "top bar" +// } +TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) { + MapOut out; + (*out.mutable_map1())["key1"].set_foo("foovalue"); + (*out.mutable_map1())["key2"].set_foo("barvalue"); + + MapOut* nested_value = &(*out.mutable_map2())["nestedself"]; + (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo"); + nested_value->set_bar("nested_bar_string"); + + (*out.mutable_map3())[111] = "one one one"; + + out.set_bar("top bar"); + + ow_.StartObject("") + ->StartObject("map1") + ->StartObject("key1") + ->RenderString("foo", "foovalue") + ->EndObject() + ->StartObject("key2") + ->RenderString("foo", "barvalue") + ->EndObject() + ->StartObject("map2") + ->StartObject("nestedself") + ->StartObject("map1") + ->StartObject("nested_key1") + ->RenderString("foo", "nested_foo") + ->EndObject() + ->EndObject() + ->RenderString("bar", "nested_bar_string") + ->EndObject() + ->EndObject() + ->StartObject("map3") + ->RenderString("111", "one one one") + ->EndObject() + ->EndObject() + ->RenderString("bar", "top bar") + ->EndObject(); + + DoTest(out, MapOut::descriptor()); +} + +class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest { + protected: + ProtostreamObjectSourceAnysTest() { + helper_.ResetTypeInfo(AnyOut::descriptor(), + google::protobuf::Any::descriptor()); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceAnysTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +// Tests JSON any support. +// +// This is the example expected output. +// { +// "any": { +// "@type": "type.googleapis.com/google.protobuf.testing.anys.AnyM" +// "foo": "foovalue" +// } +// } +TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + AnyM m; + m.set_foo("foovalue"); + any->PackFrom(m); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any nested_any; + nested_any.set_type_url( + "type.googleapis.com/google.protobuf.testing.anys.AnyM"); + + AnyM m; + m.set_foo("foovalue"); + nested_any.set_value(m.SerializeAsString()); + + any->set_value(nested_any.SerializeAsString()); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any nested_any; + nested_any.set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any second_nested_any; + second_nested_any.set_type_url( + "type.googleapis.com/google.protobuf.testing.anys.AnyM"); + + AnyM m; + m.set_foo("foovalue"); + second_nested_any.set_value(m.SerializeAsString()); + nested_any.set_value(second_nested_any.SerializeAsString()); + any->set_value(nested_any.SerializeAsString()); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject() + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) { + AnyOut out; + out.mutable_any(); + + ow_.StartObject("")->StartObject("any")->EndObject()->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) { + AnyOut out; + out.mutable_any()->set_type_url("foo.googleapis.com/my.Type"); + + ow_.StartObject("") + ->StartObject("any") + ->RenderString("@type", "foo.googleapis.com/my.Type") + ->EndObject() + ->EndObject(); + + DoTest(out, AnyOut::descriptor()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + + AnyM m; + m.set_foo("foovalue"); + any->set_value(m.SerializeAsString()); + + // We start the "AnyOut" part and then fail when we hit the Any object. + ow_.StartObject(""); + + Status status = ExecuteTest(out, AnyOut::descriptor()); + EXPECT_EQ(util::error::INTERNAL, status.error_code()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("foo.googleapis.com/my.own.Type"); + + AnyM m; + m.set_foo("foovalue"); + any->set_value(m.SerializeAsString()); + + // We start the "AnyOut" part and then fail when we hit the Any object. + ow_.StartObject(""); + + Status status = ExecuteTest(out, AnyOut::descriptor()); + EXPECT_EQ(util::error::INTERNAL, status.error_code()); +} + +TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/unknown.Type"); + + AnyM m; + m.set_foo("foovalue"); + any->set_value(m.SerializeAsString()); + + // We start the "AnyOut" part and then fail when we hit the Any object. + ow_.StartObject(""); + + Status status = ExecuteTest(out, AnyOut::descriptor()); + EXPECT_EQ(util::error::INTERNAL, status.error_code()); +} + +class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest { + protected: + ProtostreamObjectSourceStructTest() { + helper_.ResetTypeInfo(StructType::descriptor(), + google::protobuf::Struct::descriptor()); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceStructTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +// Tests struct +// +// "object": { +// "k1": 123, +// "k2": true +// } +TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) { + StructType out; + google::protobuf::Struct* s = out.mutable_object(); + s->mutable_fields()->operator[]("k1").set_number_value(123); + s->mutable_fields()->operator[]("k2").set_bool_value(true); + + ow_.StartObject("") + ->StartObject("object") + ->RenderDouble("k1", 123) + ->RenderBool("k2", true) + ->EndObject() + ->EndObject(); + + DoTest(out, StructType::descriptor()); +} + +TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) { + StructType out; + google::protobuf::Struct* s = out.mutable_object(); + s->mutable_fields()->operator[]("k1"); + + ow_.StartObject("")->StartObject("object")->EndObject()->EndObject(); + + DoTest(out, StructType::descriptor()); +} + +class ProtostreamObjectSourceFieldMaskTest + : public ProtostreamObjectSourceTest { + protected: + ProtostreamObjectSourceFieldMaskTest() { + helper_.ResetTypeInfo(FieldMaskTest::descriptor(), + google::protobuf::FieldMask::descriptor()); + } +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtostreamObjectSourceFieldMaskTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) { + FieldMaskTest out; + out.set_id("1"); + out.mutable_single_mask()->add_paths("path1"); + out.mutable_single_mask()->add_paths("snake_case_path2"); + ::google::protobuf::FieldMask* mask = out.add_repeated_mask(); + mask->add_paths("path3"); + mask = out.add_repeated_mask(); + mask->add_paths("snake_case_path4"); + mask->add_paths("path5"); + NestedFieldMask* nested = out.add_nested_mask(); + nested->set_data("data"); + nested->mutable_single_mask()->add_paths("nested.path1"); + nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2"); + mask = nested->add_repeated_mask(); + mask->add_paths("nested_field.path3"); + mask->add_paths("nested.snake_case_path4"); + mask = nested->add_repeated_mask(); + mask->add_paths("nested.path5"); + mask = nested->add_repeated_mask(); + mask->add_paths( + "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case." + "map_field[\"map_key_sho\\\"uld_be_ignored\"]"); + + ow_.StartObject("") + ->RenderString("id", "1") + ->RenderString("single_mask", "path1,snakeCasePath2") + ->StartList("repeated_mask") + ->RenderString("", "path3") + ->RenderString("", "snakeCasePath4,path5") + ->EndList() + ->StartList("nested_mask") + ->StartObject("") + ->RenderString("data", "data") + ->RenderString("single_mask", "nested.path1,nestedField.snakeCasePath2") + ->StartList("repeated_mask") + ->RenderString("", "nestedField.path3,nested.snakeCasePath4") + ->RenderString("", "nested.path5") + ->RenderString("", + "snakeCase.mapField[\"map_key_should_be_ignored\"]." + "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_" + "ignored\"]") + ->EndList() + ->EndObject() + ->EndList() + ->EndObject(); + + DoTest(out, FieldMaskTest::descriptor()); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc new file mode 100644 index 00000000..f9ddbf32 --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -0,0 +1,1557 @@ +// 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::internal::WireFormatLite; +using google::protobuf::io::CodedOutputStream; +using util::error::INVALID_ARGUMENT; +using util::Status; +using util::StatusOr; + + +ProtoStreamObjectWriter::ProtoStreamObjectWriter( + TypeResolver* type_resolver, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener) + : master_type_(type), + typeinfo_(TypeInfo::NewTypeInfo(type_resolver)), + own_typeinfo_(true), + done_(false), + element_(NULL), + size_insert_(), + output_(output), + buffer_(), + adapter_(&buffer_), + stream_(new CodedOutputStream(&adapter_)), + listener_(listener), + invalid_depth_(0), + tracker_(new ObjectLocationTracker()) {} + +ProtoStreamObjectWriter::ProtoStreamObjectWriter( + TypeInfo* typeinfo, const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener) + : master_type_(type), + typeinfo_(typeinfo), + own_typeinfo_(false), + done_(false), + element_(NULL), + size_insert_(), + output_(output), + buffer_(), + adapter_(&buffer_), + stream_(new CodedOutputStream(&adapter_)), + listener_(listener), + invalid_depth_(0), + tracker_(new ObjectLocationTracker()) {} + +ProtoStreamObjectWriter::~ProtoStreamObjectWriter() { + // Cleanup explicitly in order to avoid destructor stack overflow when input + // is deeply nested. + while (element_ != NULL) { + element_.reset(element_->pop()); + } + if (own_typeinfo_) { + delete typeinfo_; + } +} + +namespace { + +// Writes an INT32 field, including tag to the stream. +inline Status WriteInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteInt32(field_number, i32.ValueOrDie(), stream); + } + return i32.status(); +} + +// writes an SFIXED32 field, including tag, to the stream. +inline Status WriteSFixed32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteSFixed32(field_number, i32.ValueOrDie(), stream); + } + return i32.status(); +} + +// Writes an SINT32 field, including tag, to the stream. +inline Status WriteSInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr i32 = data.ToInt32(); + if (i32.ok()) { + WireFormatLite::WriteSInt32(field_number, i32.ValueOrDie(), stream); + } + return i32.status(); +} + +// Writes a FIXED32 field, including tag, to the stream. +inline Status WriteFixed32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr u32 = data.ToUint32(); + if (u32.ok()) { + WireFormatLite::WriteFixed32(field_number, u32.ValueOrDie(), stream); + } + return u32.status(); +} + +// Writes a UINT32 field, including tag, to the stream. +inline Status WriteUInt32(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr u32 = data.ToUint32(); + if (u32.ok()) { + WireFormatLite::WriteUInt32(field_number, u32.ValueOrDie(), stream); + } + return u32.status(); +} + +// Writes an INT64 field, including tag, to the stream. +inline Status WriteInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteInt64(field_number, i64.ValueOrDie(), stream); + } + return i64.status(); +} + +// Writes an SFIXED64 field, including tag, to the stream. +inline Status WriteSFixed64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteSFixed64(field_number, i64.ValueOrDie(), stream); + } + return i64.status(); +} + +// Writes an SINT64 field, including tag, to the stream. +inline Status WriteSInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr i64 = data.ToInt64(); + if (i64.ok()) { + WireFormatLite::WriteSInt64(field_number, i64.ValueOrDie(), stream); + } + return i64.status(); +} + +// Writes a FIXED64 field, including tag, to the stream. +inline Status WriteFixed64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr u64 = data.ToUint64(); + if (u64.ok()) { + WireFormatLite::WriteFixed64(field_number, u64.ValueOrDie(), stream); + } + return u64.status(); +} + +// Writes a UINT64 field, including tag, to the stream. +inline Status WriteUInt64(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr u64 = data.ToUint64(); + if (u64.ok()) { + WireFormatLite::WriteUInt64(field_number, u64.ValueOrDie(), stream); + } + return u64.status(); +} + +// Writes a DOUBLE field, including tag, to the stream. +inline Status WriteDouble(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr d = data.ToDouble(); + if (d.ok()) { + WireFormatLite::WriteDouble(field_number, d.ValueOrDie(), stream); + } + return d.status(); +} + +// Writes a FLOAT field, including tag, to the stream. +inline Status WriteFloat(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr f = data.ToFloat(); + if (f.ok()) { + WireFormatLite::WriteFloat(field_number, f.ValueOrDie(), stream); + } + return f.status(); +} + +// Writes a BOOL field, including tag, to the stream. +inline Status WriteBool(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr b = data.ToBool(); + if (b.ok()) { + WireFormatLite::WriteBool(field_number, b.ValueOrDie(), stream); + } + return b.status(); +} + +// Writes a BYTES field, including tag, to the stream. +inline Status WriteBytes(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr c = data.ToBytes(); + if (c.ok()) { + WireFormatLite::WriteBytes(field_number, c.ValueOrDie(), stream); + } + return c.status(); +} + +// Writes a STRING field, including tag, to the stream. +inline Status WriteString(int field_number, const DataPiece& data, + CodedOutputStream* stream) { + StatusOr s = data.ToString(); + if (s.ok()) { + WireFormatLite::WriteString(field_number, s.ValueOrDie(), stream); + } + return s.status(); +} + +// Writes an ENUM field, including tag, to the stream. +inline Status WriteEnum(int field_number, const DataPiece& data, + const google::protobuf::Enum* enum_type, + CodedOutputStream* stream) { + StatusOr e = data.ToEnum(enum_type); + if (e.ok()) { + WireFormatLite::WriteEnum(field_number, e.ValueOrDie(), stream); + } + return e.status(); +} + +// Given a google::protobuf::Type, returns the set of all required fields. +std::set GetRequiredFields( + const google::protobuf::Type& type) { + std::set required; + for (int i = 0; i < type.fields_size(); i++) { + const google::protobuf::Field& field = type.fields(i); + if (field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) { + required.insert(&field); + } + } + return required; +} + +// Utility method to split a string representation of Timestamp or Duration and +// return the parts. +void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds, + StringPiece* nanos) { + size_t idx = input.rfind('.'); + if (idx != string::npos) { + *seconds = input.substr(0, idx); + *nanos = input.substr(idx + 1); + } else { + *seconds = input; + *nanos = StringPiece(); + } +} + +} // namespace + +ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent) + : parent_(parent), + ow_(), + invalid_(false), + data_(), + output_(&data_), + depth_(0), + has_injected_value_message_(false) {} + +ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {} + +void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) { + ++depth_; + // If an object writer is absent, that means we have not called StartAny() + // before reaching here. This is an invalid state. StartAny() gets called + // whenever we see an "@type" being rendered (see AnyWriter::RenderDataPiece). + if (ow_ == NULL) { + // Make sure we are not already in an invalid state. This avoids making + // multiple unnecessary InvalidValue calls. + if (!invalid_) { + parent_->InvalidValue("Any", + StrCat("Missing or invalid @type for any field in ", + parent_->master_type_.name())); + invalid_ = true; + } + } else if (!has_injected_value_message_ || depth_ != 1 || name != "value") { + // We don't propagate to ow_ StartObject("value") calls for nested Anys or + // Struct at depth 1 as they are nested one level deep with an injected + // "value" field. + ow_->StartObject(name); + } +} + +bool ProtoStreamObjectWriter::AnyWriter::EndObject() { + --depth_; + // As long as depth_ >= 0, we know we haven't reached the end of Any. + // Propagate these EndObject() calls to the contained ow_. If we are in a + // nested Any or Struct type, ignore the second to last EndObject call (depth_ + // == -1) + if (ow_ != NULL && (!has_injected_value_message_ || depth_ >= 0)) { + ow_->EndObject(); + } + // A negative depth_ implies that we have reached the end of Any + // object. Now we write out its contents. + if (depth_ < 0) { + WriteAny(); + return false; + } + return true; +} + +void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) { + ++depth_; + // We expect ow_ to be present as this call only makes sense inside an Any. + if (ow_ == NULL) { + if (!invalid_) { + parent_->InvalidValue("Any", + StrCat("Missing or invalid @type for any field in ", + parent_->master_type_.name())); + invalid_ = true; + } + } else { + ow_->StartList(name); + } +} + +void ProtoStreamObjectWriter::AnyWriter::EndList() { + --depth_; + if (depth_ < 0) { + GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible"; + depth_ = 0; + } + // We don't write an error on the close, only on the open + if (ow_ != NULL) { + ow_->EndList(); + } +} + +void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece( + StringPiece name, const DataPiece& value) { + // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type" + // should go to the contained ow_ as they indicate nested Anys. + if (depth_ == 0 && ow_ == NULL && name == "@type") { + StartAny(value); + } else if (ow_ == NULL) { + if (!invalid_) { + parent_->InvalidValue("Any", + StrCat("Missing or invalid @type for any field in ", + parent_->master_type_.name())); + invalid_ = true; + } + } else { + // Check to see if the data needs to be rendered with well-known-type + // renderer. + const TypeRenderer* type_renderer = + FindTypeRenderer(GetFullTypeWithUrl(ow_->master_type_.name())); + if (type_renderer) { + // TODO(rikka): Don't just ignore the util::Status object! + (*type_renderer)(ow_.get(), value); + } else { + ow_->RenderDataPiece(name, value); + } + } +} + +void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) { + // Figure out the type url. This is a copy-paste from WriteString but we also + // need the value, so we can't just call through to that. + if (value.type() == DataPiece::TYPE_STRING) { + type_url_ = value.str().ToString(); + } else { + StatusOr s = value.ToString(); + if (!s.ok()) { + parent_->InvalidValue("String", s.status().error_message()); + invalid_ = true; + return; + } + type_url_ = s.ValueOrDie(); + } + // Resolve the type url, and report an error if we failed to resolve it. + StatusOr resolved_type = + parent_->typeinfo_->ResolveTypeUrl(type_url_); + if (!resolved_type.ok()) { + parent_->InvalidValue("Any", resolved_type.status().error_message()); + invalid_ = true; + return; + } + // At this point, type is never null. + const google::protobuf::Type* type = resolved_type.ValueOrDie(); + + // If this is the case of an Any in an Any or Struct in an Any, we need to + // expect a StartObject call with "value" while we're at depth_ 0, which we + // should ignore (not propagate to our nested object writer). We also need to + // ignore the second-to-last EndObject call, and not propagate that either. + if (type->name() == kAnyType || type->name() == kStructType) { + has_injected_value_message_ = true; + } + + // Create our object writer and initialize it with the first StartObject + // call. + ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo_, *type, &output_, + parent_->listener_)); + ow_->StartObject(""); +} + +void ProtoStreamObjectWriter::AnyWriter::WriteAny() { + if (ow_ == NULL) { + // If we had no object writer, we never got any content, so just return + // immediately, which is equivalent to writing an empty Any. + return; + } + // Render the type_url and value fields directly to the stream. + // type_url has tag 1 and value has tag 2. + WireFormatLite::WriteString(1, type_url_, parent_->stream_.get()); + if (!data_.empty()) { + WireFormatLite::WriteBytes(2, data_, parent_->stream_.get()); + } +} + +ProtoStreamObjectWriter::ProtoElement::ProtoElement( + TypeInfo* typeinfo, const google::protobuf::Type& type, + ProtoStreamObjectWriter* enclosing) + : BaseElement(NULL), + ow_(enclosing), + any_(), + field_(NULL), + typeinfo_(typeinfo), + type_(type), + required_fields_(GetRequiredFields(type)), + is_repeated_type_(false), + size_index_(-1), + array_index_(-1), + element_type_(GetElementType(type_)) { + if (element_type_ == ANY) { + any_.reset(new AnyWriter(ow_)); + } +} + +ProtoStreamObjectWriter::ProtoElement::ProtoElement( + ProtoStreamObjectWriter::ProtoElement* parent, + const google::protobuf::Field* field, const google::protobuf::Type& type, + ElementType element_type) + : BaseElement(parent), + ow_(this->parent()->ow_), + any_(), + field_(field), + typeinfo_(this->parent()->typeinfo_), + type_(type), + is_repeated_type_(element_type == ProtoElement::LIST || + element_type == ProtoElement::STRUCT_LIST || + element_type == ProtoElement::MAP || + element_type == ProtoElement::STRUCT_MAP), + size_index_(!is_repeated_type_ && + field->kind() == + google::protobuf::Field_Kind_TYPE_MESSAGE + ? ow_->size_insert_.size() + : -1), + array_index_(is_repeated_type_ ? 0 : -1), + element_type_(element_type) { + if (!is_repeated_type_) { + if (field->cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + // Update array_index_ if it is an explicit list. + if (this->parent()->array_index_ >= 0) this->parent()->array_index_++; + } else { + this->parent()->RegisterField(field); + } + if (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { + required_fields_ = GetRequiredFields(type_); + int start_pos = ow_->stream_->ByteCount(); + // length of serialized message is the final buffer position minus + // starting buffer position, plus length adjustments for size fields + // of any nested messages. We start with -start_pos here, so we only + // need to add the final buffer position to it at the end. + SizeInfo info = {start_pos, -start_pos}; + ow_->size_insert_.push_back(info); + } + } + if (element_type == ANY) { + any_.reset(new AnyWriter(ow_)); + } +} + +ProtoStreamObjectWriter::ProtoElement* +ProtoStreamObjectWriter::ProtoElement::pop() { + // Calls the registered error listener for any required field(s) not yet + // seen. + for (set::iterator it = + required_fields_.begin(); + it != required_fields_.end(); ++it) { + ow_->MissingField((*it)->name()); + } + // Computes the total number of proto bytes used by a message, also adjusts + // the size of all parent messages by the length of this size field. + // If size_index_ < 0, this is not a message, so no size field is added. + if (size_index_ >= 0) { + // Add the final buffer position to compute the total length of this + // serialized message. The stored value (before this addition) already + // contains the total length of the size fields of all nested messages + // minus the initial buffer position. + ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount(); + // Calculate the length required to serialize the size field of the + // message, and propagate this additional size information upward to + // all enclosing messages. + int size = ow_->size_insert_[size_index_].size; + int length = CodedOutputStream::VarintSize32(size); + for (ProtoElement* e = parent(); e != NULL; e = e->parent()) { + // Only nested messages have size field, lists do not have size field. + if (e->size_index_ >= 0) { + ow_->size_insert_[e->size_index_].size += length; + } + } + } + return BaseElement::pop(); +} + +void ProtoStreamObjectWriter::ProtoElement::RegisterField( + const google::protobuf::Field* field) { + if (!required_fields_.empty() && + field->cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REQUIRED) { + required_fields_.erase(field); + } +} + +string ProtoStreamObjectWriter::ProtoElement::ToString() const { + if (parent() == NULL) return ""; + string loc = parent()->ToString(); + if (field_->cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED || + parent()->field_ != field_) { + string name = field_->name(); + int i = 0; + while (i < name.size() && (ascii_isalnum(name[i]) || name[i] == '_')) ++i; + if (i > 0 && i == name.size()) { // safe field name + if (loc.empty()) { + loc = name; + } else { + StrAppend(&loc, ".", name); + } + } else { + StrAppend(&loc, "[\"", CEscape(name), "\"]"); + } + } + if (field_->cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && + array_index_ > 0) { + StrAppend(&loc, "[", array_index_ - 1, "]"); + } + return loc.empty() ? "." : loc; +} + +inline void ProtoStreamObjectWriter::InvalidName(StringPiece unknown_name, + StringPiece message) { + listener_->InvalidName(location(), ToSnakeCase(unknown_name), message); +} + +inline void ProtoStreamObjectWriter::InvalidValue(StringPiece type_name, + StringPiece value) { + listener_->InvalidValue(location(), type_name, value); +} + +inline void ProtoStreamObjectWriter::MissingField(StringPiece missing_name) { + listener_->MissingField(location(), missing_name); +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject( + StringPiece name) { + // Starting the root message. Create the root ProtoElement and return. + if (element_ == NULL) { + if (!name.empty()) { + InvalidName(name, "Root element should not be named."); + } + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + + // If master type is a special type that needs extra values to be written to + // stream, we write those values. + if (master_type_.name() == kStructType) { + StartStruct(NULL); + } else if (master_type_.name() == kStructValueType) { + // We got a StartObject call with google.protobuf.Value field. This means + // we are starting an object within google.protobuf.Value type. The only + // object within that type is a struct type. So start a struct. + const google::protobuf::Field* field = StartStructValueInStruct(NULL); + StartStruct(field); + } + return this; + } + + const google::protobuf::Field* field = NULL; + if (element_ != NULL && element_->IsAny()) { + element_->any()->StartObject(name); + return this; + } else if (element_ != NULL && + (element_->IsMap() || element_->IsStructMap())) { + field = StartMapEntry(name); + if (element_->IsStructMapEntry()) { + // If the top element is a map entry, this means we are starting another + // struct within a struct. + field = StartStructValueInStruct(field); + } + } else if (element_ != NULL && element_->IsStructList()) { + // If the top element is a list, then we are starting a list field within a + // struct. + field = Lookup(name); + field = StartStructValueInStruct(field); + } else { + field = BeginNamed(name, false); + } + if (field == NULL) { + return this; + } + + const google::protobuf::Type* type = LookupType(field); + if (type == NULL) { + ++invalid_depth_; + InvalidName(name, + StrCat("Missing descriptor for field: ", field->type_url())); + return this; + } + + if (field->type_url() == GetFullTypeWithUrl(kStructType)) { + // Start a struct object. + StartStruct(field); + } else if (field->type_url() == GetFullTypeWithUrl(kStructValueType)) { + // We got a StartObject call with google.protobuf.Value field. This means we + // are starting an object within google.protobuf.Value type. The only object + // within that type is a struct type. So start a struct. + field = StartStructValueInStruct(field); + StartStruct(field); + } else if (field->type_url() == GetFullTypeWithUrl(kAnyType)) { + // Begin an Any. We can't do the real work till we get the @type field. + WriteTag(*field); + element_.reset( + new ProtoElement(element_.release(), field, *type, ProtoElement::ANY)); + } else if (IsMap(*field)) { + // Begin a map. + // A map is triggered by a StartObject() call if the current field has a map + // type. Map values are written to proto in a manner detailed in comments + // above StartMapEntry() function. + element_.reset( + new ProtoElement(element_.release(), field, *type, ProtoElement::MAP)); + } else { + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::MESSAGE)); + } + return this; +} + +// Proto3 maps are represented on the wire as a message with +// "key" and a "value". +// +// For example, the syntax: +// map map_field = N; +// +// is represented as: +// message MapFieldEntry { +// option map_entry = true; // marks the map construct in the descriptor +// +// key_type key = 1; +// value_type value = 2; +// } +// repeated MapFieldEntry map_field = N; +// +// See go/proto3-maps for more information. +const google::protobuf::Field* ProtoStreamObjectWriter::StartMapEntry( + StringPiece name) { + // top of stack is already a map field + const google::protobuf::Field* field = element_->field(); + const google::protobuf::Type& type = element_->type(); + // If we come from a regular map, use MAP_ENTRY or if we come from a struct, + // use STRUCT_MAP_ENTRY. These values are used later in StartObject/StartList + // or RenderDataPiece for making appropriate decisions. + ProtoElement::ElementType element_type = element_->IsStructMap() + ? ProtoElement::STRUCT_MAP_ENTRY + : ProtoElement::MAP_ENTRY; + WriteTag(*field); + element_.reset( + new ProtoElement(element_.release(), field, type, element_type)); + RenderDataPiece("key", DataPiece(name)); + return BeginNamed("value", false); +} + +// Starts a google.protobuf.Struct. +// 'field' represents a field in a message of type google.protobuf.Struct. A +// struct contains a map with name 'fields'. This function starts this map as +// well. +// When 'field' is NULL, it means that the top level message is of struct +// type. +void ProtoStreamObjectWriter::StartStruct( + const google::protobuf::Field* field) { + const google::protobuf::Type* type = NULL; + if (field) { + type = LookupType(field); + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT)); + } + const google::protobuf::Field* struct_field = BeginNamed("fields", false); + + if (!struct_field) { + // It is a programmatic error if this happens. Log an error. + GOOGLE_LOG(ERROR) << "Invalid internal state. Cannot find 'fields' within " + << (field ? field->type_url() : "google.protobuf.Struct"); + return; + } + + type = LookupType(struct_field); + element_.reset(new ProtoElement(element_.release(), struct_field, *type, + ProtoElement::STRUCT_MAP)); +} + +// Starts a "struct_value" within struct.proto's google.protobuf.Value type. +// 'field' should be of the type google.protobuf.Value. +// Returns the field identifying "struct_value" within the given field. +// +// If field is NULL, then we are starting struct_value at the top-level, in +// this case skip writing any tag information for the passed field. +const google::protobuf::Field* +ProtoStreamObjectWriter::StartStructValueInStruct( + const google::protobuf::Field* field) { + if (field) { + const google::protobuf::Type* type = LookupType(field); + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT_VALUE)); + } + return BeginNamed("struct_value", false); +} + +// Starts a "list_value" within struct.proto's google.protobuf.Value type. +// 'field' should be of the type google.protobuf.Value. +// Returns the field identifying "list_value" within the given field. +// +// If field is NULL, then we are starting list_value at the top-level, in +// this case skip writing any tag information for the passed field. +const google::protobuf::Field* ProtoStreamObjectWriter::StartListValueInStruct( + const google::protobuf::Field* field) { + if (field) { + const google::protobuf::Type* type = LookupType(field); + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT_VALUE)); + } + const google::protobuf::Field* list_value = BeginNamed("list_value", false); + + if (!list_value) { + // It is a programmatic error if this happens. Log an error. + GOOGLE_LOG(ERROR) << "Invalid internal state. Cannot find 'list_value' within " + << (field ? field->type_url() : "google.protobuf.Value"); + return field; + } + + return StartRepeatedValuesInListValue(list_value); +} + +// Starts the repeated "values" field in struct.proto's +// google.protobuf.ListValue type. 'field' should be of type +// google.protobuf.ListValue. +// +// If field is NULL, then we are starting ListValue at the top-level, in +// this case skip writing any tag information for the passed field. +const google::protobuf::Field* +ProtoStreamObjectWriter::StartRepeatedValuesInListValue( + const google::protobuf::Field* field) { + if (field) { + const google::protobuf::Type* type = LookupType(field); + WriteTag(*field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT_LIST_VALUE)); + } + return BeginNamed("values", true); +} + +void ProtoStreamObjectWriter::SkipElements() { + if (element_ == NULL) return; + + ProtoElement::ElementType element_type = element_->element_type(); + while (element_type == ProtoElement::STRUCT || + element_type == ProtoElement::STRUCT_LIST_VALUE || + element_type == ProtoElement::STRUCT_VALUE || + element_type == ProtoElement::STRUCT_MAP_ENTRY || + element_type == ProtoElement::MAP_ENTRY) { + element_.reset(element_->pop()); + element_type = + element_ != NULL ? element_->element_type() : ProtoElement::MESSAGE; + } +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() { + if (invalid_depth_ > 0) { + --invalid_depth_; + return this; + } + if (element_ != NULL && element_->IsAny()) { + if (element_->any()->EndObject()) { + return this; + } + } + if (element_ != NULL) { + element_.reset(element_->pop()); + } + + // Skip sentinel elements added to keep track of new proto3 types - map, + // struct. + SkipElements(); + + // If ending the root element, + // then serialize the full message with calculated sizes. + if (element_ == NULL) { + WriteRootMessage(); + } + return this; +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(StringPiece name) { + const google::protobuf::Field* field = NULL; + // Since we cannot have a top-level repeated item in protobuf, the only way + // element_ can be null when here is when we start a top-level list + // google.protobuf.ListValue. + if (element_ == NULL) { + if (!name.empty()) { + InvalidName(name, "Root element should not be named."); + } + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + + // If master type is a special type that needs extra values to be written to + // stream, we write those values. + if (master_type_.name() == kStructValueType) { + // We got a StartList with google.protobuf.Value master type. This means + // we have to start the "list_value" within google.protobuf.Value. + field = StartListValueInStruct(NULL); + } else if (master_type_.name() == kStructListValueType) { + // We got a StartList with google.protobuf.ListValue master type. This + // means we have to start the "values" within google.protobuf.ListValue. + field = StartRepeatedValuesInListValue(NULL); + } + + // field is NULL when master_type_ is anything other than + // google.protobuf.Value or google.protobuf.ListValue. + if (field) { + const google::protobuf::Type* type = LookupType(field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::STRUCT_LIST)); + } + return this; + } + + if (element_->IsAny()) { + element_->any()->StartList(name); + return this; + } + // The type of element we push to stack. + ProtoElement::ElementType element_type = ProtoElement::LIST; + + // Check if we need to start a map. This can heppen when there is either a map + // or a struct type within a list. + if (element_->IsMap() || element_->IsStructMap()) { + field = StartMapEntry(name); + if (field == NULL) return this; + + if (element_->IsStructMapEntry()) { + // If the top element is a map entry, this means we are starting a list + // within a struct or a map. + // An example sequence of calls would be + // StartObject -> StartList + field = StartListValueInStruct(field); + if (field == NULL) return this; + } + + element_type = ProtoElement::STRUCT_LIST; + } else if (element_->IsStructList()) { + // If the top element is a STRUCT_LIST, this means we are starting a list + // within the current list (inside a struct). + // An example call sequence would be + // StartObject -> StartList -> StartList + // with StartObject starting a struct. + + // Lookup the last list type in element stack as we are adding an element of + // the same type. + field = Lookup(name); + if (field == NULL) return this; + + field = StartListValueInStruct(field); + if (field == NULL) return this; + + element_type = ProtoElement::STRUCT_LIST; + } else { + // Lookup field corresponding to 'name'. If it is a google.protobuf.Value + // or google.protobuf.ListValue type, then StartList is a valid call, start + // this list. + // We cannot use Lookup() here as it will produce InvalidName() error if the + // field is not found. We do not want to error here as it would cause us to + // report errors twice, once here and again later in BeginNamed() call. + // Also we ignore if the field is not found here as it is caught later. + field = typeinfo_->FindField(&element_->type(), name); + + // It is an error to try to bind to map, which behind the scenes is a list. + if (field && IsMap(*field)) { + // Push field to stack for error location tracking & reporting. + element_.reset(new ProtoElement(element_.release(), field, + *LookupType(field), + ProtoElement::MESSAGE)); + InvalidValue("Map", "Cannot bind a list to map."); + ++invalid_depth_; + element_->pop(); + return this; + } + + if (field && field->type_url() == GetFullTypeWithUrl(kStructValueType)) { + // There are 2 cases possible: + // a. g.p.Value is repeated + // b. g.p.Value is not repeated + // + // For case (a), the StartList should bind to the repeated g.p.Value. + // For case (b), the StartList should bind to g.p.ListValue within the + // g.p.Value. + // + // This means, for case (a), we treat it just like any other repeated + // message, except we would apply an appropriate element_type so future + // Start or Render calls are routed appropriately. + if (field->cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + field = StartListValueInStruct(field); + } + element_type = ProtoElement::STRUCT_LIST; + } else if (field && + field->type_url() == GetFullTypeWithUrl(kStructListValueType)) { + // We got a StartList with google.protobuf.ListValue master type. This + // means we have to start the "values" within google.protobuf.ListValue. + field = StartRepeatedValuesInListValue(field); + } else { + // If no special types are to be bound, fall back to normal processing of + // StartList. + field = BeginNamed(name, true); + } + if (field == NULL) return this; + } + + const google::protobuf::Type* type = LookupType(field); + if (type == NULL) { + ++invalid_depth_; + InvalidName(name, + StrCat("Missing descriptor for field: ", field->type_url())); + return this; + } + + element_.reset( + new ProtoElement(element_.release(), field, *type, element_type)); + return this; +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndList() { + if (invalid_depth_ > 0) { + --invalid_depth_; + } else if (element_ != NULL) { + if (element_->IsAny()) { + element_->any()->EndList(); + } else { + element_.reset(element_->pop()); + // Skip sentinel elements added to keep track of new proto3 types - map, + // struct. + SkipElements(); + } + } + + // When element_ is NULL, we have reached the root message type. Write out + // the bytes. + if (element_ == NULL) { + WriteRootMessage(); + } + return this; +} + +Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + string struct_field_name; + switch (data.type()) { + // Our JSON parser parses numbers as either int64, uint64, or double. + case DataPiece::TYPE_INT64: + case DataPiece::TYPE_UINT64: + case DataPiece::TYPE_DOUBLE: { + struct_field_name = "number_value"; + break; + } + case DataPiece::TYPE_STRING: { + struct_field_name = "string_value"; + break; + } + case DataPiece::TYPE_BOOL: { + struct_field_name = "bool_value"; + break; + } + case DataPiece::TYPE_NULL: { + struct_field_name = "null_value"; + break; + } + default: { + return Status(INVALID_ARGUMENT, + "Invalid struct data type. Only number, string, boolean or " + "null values are supported."); + } + } + ow->RenderDataPiece(struct_field_name, data); + return Status::OK; +} + +Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() != DataPiece::TYPE_STRING) { + return Status(INVALID_ARGUMENT, + StrCat("Invalid data type for timestamp, value is ", + data.ValueAsStringOrDefault(""))); + } + + StringPiece value(data.str()); + + int64 seconds; + int32 nanos; + if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds, + &nanos)) { + return Status(INVALID_ARGUMENT, StrCat("Invalid time format: ", value)); + } + + + ow->RenderDataPiece("seconds", DataPiece(seconds)); + ow->RenderDataPiece("nanos", DataPiece(nanos)); + return Status::OK; +} + +static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow, + StringPiece path) { + ow->RenderDataPiece("paths", + DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase))); + return Status::OK; +} + +Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() != DataPiece::TYPE_STRING) { + return Status(INVALID_ARGUMENT, + StrCat("Invalid data type for field mask, value is ", + data.ValueAsStringOrDefault(""))); + } + + // TODO(tsun): figure out how to do proto descriptor based snake case + // conversions as much as possible. Because ToSnakeCase sometimes returns the + // wrong value. + google::protobuf::scoped_ptr > callback( + NewPermanentCallback(&RenderOneFieldPath, ow)); + return DecodeCompactFieldMaskPaths(data.str(), callback.get()); +} + +Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + if (data.type() != DataPiece::TYPE_STRING) { + return Status(INVALID_ARGUMENT, + StrCat("Invalid data type for duration, value is ", + data.ValueAsStringOrDefault(""))); + } + + StringPiece value(data.str()); + + if (!value.ends_with("s")) { + return Status(INVALID_ARGUMENT, + "Illegal duration format; duration must end with 's'"); + } + value = value.substr(0, value.size() - 1); + int sign = 1; + if (value.starts_with("-")) { + sign = -1; + value = value.substr(1); + } + + StringPiece s_secs, s_nanos; + SplitSecondsAndNanos(value, &s_secs, &s_nanos); + uint64 unsigned_seconds; + if (!safe_strtou64(s_secs, &unsigned_seconds)) { + return Status(INVALID_ARGUMENT, + "Invalid duration format, failed to parse seconds"); + } + + double d_nanos = 0; + if (!safe_strtod("0." + s_nanos.ToString(), &d_nanos)) { + return Status(INVALID_ARGUMENT, + "Invalid duration format, failed to parse nanos seconds"); + } + + int32 nanos = sign * static_cast(d_nanos * kNanosPerSecond); + int64 seconds = sign * unsigned_seconds; + + if (seconds > kMaxSeconds || seconds < kMinSeconds || + nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) { + return Status(INVALID_ARGUMENT, "Duration value exceeds limits"); + } + + ow->RenderDataPiece("seconds", DataPiece(seconds)); + ow->RenderDataPiece("nanos", DataPiece(nanos)); + return Status::OK; +} + +Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow, + const DataPiece& data) { + ow->RenderDataPiece("value", data); + return Status::OK; +} + +ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece( + StringPiece name, const DataPiece& data) { + Status status; + if (invalid_depth_ > 0) return this; + if (element_ != NULL && element_->IsAny()) { + element_->any()->RenderDataPiece(name, data); + return this; + } + + const google::protobuf::Field* field = NULL; + string type_url; + bool is_map_entry = false; + if (element_ == NULL) { + type_url = GetFullTypeWithUrl(master_type_.name()); + } else { + if (element_->IsMap() || element_->IsStructMap()) { + is_map_entry = true; + field = StartMapEntry(name); + } else { + field = Lookup(name); + } + if (field == NULL) { + return this; + } + type_url = field->type_url(); + } + + // Check if there are any well known type renderers available for type_url. + const TypeRenderer* type_renderer = FindTypeRenderer(type_url); + if (type_renderer != NULL) { + // Push the current element to stack so lookups in type_renderer will + // find the fields. We do an EndObject soon after, which pops this. This is + // safe because all well-known types are messages. + if (element_ == NULL) { + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + } else { + if (field) { + WriteTag(*field); + const google::protobuf::Type* type = LookupType(field); + element_.reset(new ProtoElement(element_.release(), field, *type, + ProtoElement::MESSAGE)); + } + } + status = (*type_renderer)(this, data); + if (!status.ok()) { + InvalidValue(type_url, + StrCat("Field '", name, "', ", status.error_message())); + } + EndObject(); + return this; + } else if (element_ == NULL) { // no message type found at root + element_.reset(new ProtoElement(typeinfo_, master_type_, this)); + InvalidName(name, "Root element must be a message."); + return this; + } + + if (field == NULL) { + return this; + } + const google::protobuf::Type* type = LookupType(field); + if (type == NULL) { + InvalidName(name, + StrCat("Missing descriptor for field: ", field->type_url())); + return this; + } + + // Whether we should pop at the end. Set to true if the data field is a + // message type, which can happen in case of struct values. + bool should_pop = false; + + RenderSimpleDataPiece(*field, *type, data); + + if (should_pop && element_ != NULL) { + element_.reset(element_->pop()); + } + + if (is_map_entry) { + // Ending map is the same as ending an object. + EndObject(); + } + return this; +} + +void ProtoStreamObjectWriter::RenderSimpleDataPiece( + const google::protobuf::Field& field, const google::protobuf::Type& type, + const DataPiece& data) { + // If we are rendering explicit null values and the backend proto field is not + // of the google.protobuf.NullType type, we do nothing. + if (data.type() == DataPiece::TYPE_NULL && + field.type_url() != kStructNullValueTypeUrl) { + return; + } + + // Pushing a ProtoElement and then pop it off at the end for 2 purposes: + // error location reporting and required field accounting. + element_.reset(new ProtoElement(element_.release(), &field, type, + ProtoElement::MESSAGE)); + + // Make sure that field represents a simple data type. + if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN || + field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { + InvalidValue(field.type_url().empty() + ? google::protobuf::Field_Kind_Name(field.kind()) + : field.type_url(), + data.ValueAsStringOrDefault("")); + return; + } + + Status status; + switch (field.kind()) { + case google::protobuf::Field_Kind_TYPE_INT32: { + status = WriteInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED32: { + status = WriteSFixed32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT32: { + status = WriteSInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED32: { + status = WriteFixed32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT32: { + status = WriteUInt32(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_INT64: { + status = WriteInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_SFIXED64: { + status = WriteSFixed64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_SINT64: { + status = WriteSInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_FIXED64: { + status = WriteFixed64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_UINT64: { + status = WriteUInt64(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_DOUBLE: { + status = WriteDouble(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_FLOAT: { + status = WriteFloat(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_BOOL: { + status = WriteBool(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_BYTES: { + status = WriteBytes(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_STRING: { + status = WriteString(field.number(), data, stream_.get()); + break; + } + case google::protobuf::Field_Kind_TYPE_ENUM: { + status = WriteEnum(field.number(), data, + typeinfo_->GetEnum(field.type_url()), stream_.get()); + break; + } + default: // TYPE_GROUP or TYPE_MESSAGE + status = Status(INVALID_ARGUMENT, data.ToString().ValueOrDie()); + } + if (!status.ok()) { + InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), + status.error_message()); + } + element_.reset(element_->pop()); +} + +// Map of functions that are responsible for rendering well known type +// represented by the key. +hash_map* +ProtoStreamObjectWriter::CreateRendererMap() { + google::protobuf::scoped_ptr > + result(new hash_map()); + (*result)["type.googleapis.com/google.protobuf.Timestamp"] = + &ProtoStreamObjectWriter::RenderTimestamp; + (*result)["type.googleapis.com/google.protobuf.Duration"] = + &ProtoStreamObjectWriter::RenderDuration; + (*result)["type.googleapis.com/google.protobuf.FieldMask"] = + &ProtoStreamObjectWriter::RenderFieldMask; + (*result)["type.googleapis.com/google.protobuf.Double"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Float"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Int64"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.UInt64"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Int32"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.UInt32"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Bool"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.String"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Bytes"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.DoubleValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.FloatValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Int64Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.UInt64Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Int32Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.UInt32Value"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.BoolValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.StringValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.BytesValue"] = + &ProtoStreamObjectWriter::RenderWrapperType; + (*result)["type.googleapis.com/google.protobuf.Value"] = + &ProtoStreamObjectWriter::RenderStructValue; + return result.release(); +} + +ProtoStreamObjectWriter::TypeRenderer* +ProtoStreamObjectWriter::FindTypeRenderer(const string& type_url) { + static hash_map* renderers = CreateRendererMap(); + return FindOrNull(*renderers, type_url); +} + +ProtoStreamObjectWriter::ProtoElement::ElementType +ProtoStreamObjectWriter::GetElementType(const google::protobuf::Type& type) { + if (type.name() == kAnyType) { + return ProtoElement::ANY; + } else if (type.name() == kStructType) { + return ProtoElement::STRUCT; + } else if (type.name() == kStructValueType) { + return ProtoElement::STRUCT_VALUE; + } else if (type.name() == kStructListValueType) { + return ProtoElement::STRUCT_LIST_VALUE; + } else { + return ProtoElement::MESSAGE; + } +} + +const google::protobuf::Field* ProtoStreamObjectWriter::BeginNamed( + StringPiece name, bool is_list) { + if (invalid_depth_ > 0) { + ++invalid_depth_; + return NULL; + } + const google::protobuf::Field* field = Lookup(name); + if (field == NULL) { + ++invalid_depth_; + // InvalidName() already called in Lookup(). + return NULL; + } + if (is_list && + field->cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + ++invalid_depth_; + InvalidName(name, "Proto field is not repeating, cannot start list."); + return NULL; + } + return field; +} + +const google::protobuf::Field* ProtoStreamObjectWriter::Lookup( + StringPiece unnormalized_name) { + ProtoElement* e = element(); + if (e == NULL) { + InvalidName(unnormalized_name, "Root element must be a message."); + return NULL; + } + if (unnormalized_name.empty()) { + // Objects in repeated field inherit the same field descriptor. + if (e->field() == NULL) { + InvalidName(unnormalized_name, "Proto fields must have a name."); + } else if (e->field()->cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + InvalidName(unnormalized_name, "Proto fields must have a name."); + return NULL; + } + return e->field(); + } + const google::protobuf::Field* field = + typeinfo_->FindField(&e->type(), unnormalized_name); + if (field == NULL) InvalidName(unnormalized_name, "Cannot find field."); + return field; +} + +const google::protobuf::Type* ProtoStreamObjectWriter::LookupType( + const google::protobuf::Field* field) { + return (field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE + ? typeinfo_->GetType(field->type_url()) + : &element_->type()); +} + +// Looks up the oneof struct field based on the data type. +StatusOr +ProtoStreamObjectWriter::LookupStructField(DataPiece::Type type) { + const google::protobuf::Field* field = NULL; + switch (type) { + // Our JSON parser parses numbers as either int64, uint64, or double. + case DataPiece::TYPE_INT64: + case DataPiece::TYPE_UINT64: + case DataPiece::TYPE_DOUBLE: { + field = Lookup("number_value"); + break; + } + case DataPiece::TYPE_STRING: { + field = Lookup("string_value"); + break; + } + case DataPiece::TYPE_BOOL: { + field = Lookup("bool_value"); + break; + } + case DataPiece::TYPE_NULL: { + field = Lookup("null_value"); + break; + } + default: { return Status(INVALID_ARGUMENT, "Invalid struct data type"); } + } + if (field == NULL) { + return Status(INVALID_ARGUMENT, "Could not lookup struct field"); + } + return field; +} + +void ProtoStreamObjectWriter::WriteRootMessage() { + GOOGLE_DCHECK(!done_); + int curr_pos = 0; + // Calls the destructor of CodedOutputStream to remove any uninitialized + // memory from the Cord before we read it. + stream_.reset(NULL); + const void* data; + int length; + google::protobuf::io::ArrayInputStream input_stream(buffer_.data(), buffer_.size()); + while (input_stream.Next(&data, &length)) { + if (length == 0) continue; + int num_bytes = length; + // Write up to where we need to insert the size field. + // The number of bytes we may write is the smaller of: + // - the current fragment size + // - the distance to the next position where a size field needs to be + // inserted. + if (!size_insert_.empty() && + size_insert_.front().pos - curr_pos < num_bytes) { + num_bytes = size_insert_.front().pos - curr_pos; + } + output_->Append(static_cast(data), num_bytes); + if (num_bytes < length) { + input_stream.BackUp(length - num_bytes); + } + curr_pos += num_bytes; + // Insert the size field. + // size_insert_.front(): the next pair to be written. + // size_insert_.front().pos: position of the size field. + // size_insert_.front().size: the size (integer) to be inserted. + if (!size_insert_.empty() && curr_pos == size_insert_.front().pos) { + // Varint32 occupies at most 10 bytes. + uint8 insert_buffer[10]; + uint8* insert_buffer_pos = CodedOutputStream::WriteVarint32ToArray( + size_insert_.front().size, insert_buffer); + output_->Append(reinterpret_cast(insert_buffer), + insert_buffer_pos - insert_buffer); + size_insert_.pop_front(); + } + } + output_->Flush(); + stream_.reset(new CodedOutputStream(&adapter_)); + done_ = true; +} + +bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) { + if (field.type_url().empty() || + field.kind() != google::protobuf::Field_Kind_TYPE_MESSAGE || + field.cardinality() != + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED) { + return false; + } + const google::protobuf::Type* field_type = + typeinfo_->GetType(field.type_url()); + + return GetBoolOptionOrDefault(field_type->options(), + "google.protobuf.MessageOptions.map_entry", false); +} + +void ProtoStreamObjectWriter::WriteTag(const google::protobuf::Field& field) { + WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType( + static_cast(field.kind())); + stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type)); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h new file mode 100644 index 00000000..f17278b4 --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectwriter.h @@ -0,0 +1,455 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace io { +class CodedOutputStream; +} // namespace io +} // namespace protobuf + + +namespace protobuf { +class Type; +class Field; +} // namespace protobuf + + +namespace protobuf { +namespace util { +namespace converter { + +class ObjectLocationTracker; + +// An ObjectWriter that can write protobuf bytes directly from writer events. +// +// It also supports streaming. +class LIBPROTOBUF_EXPORT ProtoStreamObjectWriter : public StructuredObjectWriter { + public: + // Constructor. Does not take ownership of any parameter passed in. + ProtoStreamObjectWriter(TypeResolver* type_resolver, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener); + virtual ~ProtoStreamObjectWriter(); + + // ObjectWriter methods. + virtual ProtoStreamObjectWriter* StartObject(StringPiece name); + virtual ProtoStreamObjectWriter* EndObject(); + virtual ProtoStreamObjectWriter* StartList(StringPiece name); + virtual ProtoStreamObjectWriter* EndList(); + virtual ProtoStreamObjectWriter* RenderBool(StringPiece name, + const bool value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderInt32(StringPiece name, + const int32 value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderUint32(StringPiece name, + const uint32 value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderInt64(StringPiece name, + const int64 value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderUint64(StringPiece name, + const uint64 value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderDouble(StringPiece name, + const double value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderFloat(StringPiece name, + const float value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderString(StringPiece name, + StringPiece value) { + return RenderDataPiece(name, DataPiece(value)); + } + virtual ProtoStreamObjectWriter* RenderBytes(StringPiece name, + StringPiece value) { + return RenderDataPiece(name, DataPiece(value, false)); + } + virtual ProtoStreamObjectWriter* RenderNull(StringPiece name) { + return RenderDataPiece(name, DataPiece::NullData()); + } + + // Renders a DataPiece 'value' into a field whose wire type is determined + // from the given field 'name'. + ProtoStreamObjectWriter* RenderDataPiece(StringPiece name, + const DataPiece& value); + + // Returns the location tracker to use for tracking locations for errors. + const LocationTrackerInterface& location() { + return element_ != NULL ? *element_ : *tracker_; + } + + // When true, we finished writing to output a complete message. + bool done() const { return done_; } + + private: + // Function that renders a well known type with modified behavior. + typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*, + const DataPiece&); + + // Handles writing Anys out using nested object writers and the like. + class LIBPROTOBUF_EXPORT AnyWriter { + public: + explicit AnyWriter(ProtoStreamObjectWriter* parent); + ~AnyWriter(); + + // Passes a StartObject call through to the Any writer. + void StartObject(StringPiece name); + + // Passes an EndObject call through to the Any. Returns true if the any + // handled the EndObject call, false if the Any is now all done and is no + // longer needed. + bool EndObject(); + + // Passes a StartList call through to the Any writer. + void StartList(StringPiece name); + + // Passes an EndList call through to the Any writer. + void EndList(); + + // Renders a data piece on the any. + void RenderDataPiece(StringPiece name, const DataPiece& value); + + private: + // Handles starting up the any once we have a type. + void StartAny(const DataPiece& value); + + // Writes the Any out to the parent writer in its serialized form. + void WriteAny(); + + // The parent of this writer, needed for various bits such as type info and + // the listeners. + ProtoStreamObjectWriter* parent_; + + // The nested object writer, used to write events. + google::protobuf::scoped_ptr ow_; + + // The type_url_ that this Any represents. + string type_url_; + + // Whether this any is invalid. This allows us to only report an invalid + // Any message a single time rather than every time we get a nested field. + bool invalid_; + + // The output data and wrapping ByteSink. + string data_; + strings::StringByteSink output_; + + // The depth within the Any, so we can track when we're done. + int depth_; + + // True if the message type contained in Any has a special "value" message + // injected. This is true for well-known message types like Any or Struct. + bool has_injected_value_message_; + }; + + class LIBPROTOBUF_EXPORT ProtoElement : public BaseElement, public LocationTrackerInterface { + public: + // Indicates the type of element. Special types like LIST, MAP, MAP_ENTRY, + // STRUCT etc. are used to deduce other information based on their position + // on the stack of elements. + enum ElementType { + MESSAGE, // Simple message + LIST, // List/repeated element + MAP, // Proto3 map type + MAP_ENTRY, // Proto3 map message type, with 'key' and 'value' fields + ANY, // Proto3 Any type + STRUCT, // Proto3 struct type + STRUCT_VALUE, // Struct's Value message type + STRUCT_LIST, // List type indicator within a struct + STRUCT_LIST_VALUE, // Struct Value's ListValue message type + STRUCT_MAP, // Struct within a struct type + STRUCT_MAP_ENTRY // Struct map's entry type with 'key' and 'value' + // fields + }; + + // Constructor for the root element. No parent nor field. + ProtoElement(TypeInfo* typeinfo, const google::protobuf::Type& type, + ProtoStreamObjectWriter* enclosing); + + // Constructor for a field of an element. + ProtoElement(ProtoElement* parent, const google::protobuf::Field* field, + const google::protobuf::Type& type, ElementType element_type); + + virtual ~ProtoElement() {} + + // Called just before the destructor for clean up: + // - reports any missing required fields + // - computes the space needed by the size field, and augment the + // length of all parent messages by this additional space. + // - releases and returns the parent pointer. + ProtoElement* pop(); + + // Accessors + const google::protobuf::Field* field() const { return field_; } + const google::protobuf::Type& type() const { return type_; } + + // These functions return true if the element type is corresponding to the + // type in function name. + bool IsMap() { return element_type_ == MAP; } + bool IsStructMap() { return element_type_ == STRUCT_MAP; } + bool IsStructMapEntry() { return element_type_ == STRUCT_MAP_ENTRY; } + bool IsStructList() { return element_type_ == STRUCT_LIST; } + bool IsAny() { return element_type_ == ANY; } + + ElementType element_type() { return element_type_; } + + void RegisterField(const google::protobuf::Field* field); + virtual string ToString() const; + + AnyWriter* any() const { return any_.get(); } + + virtual ProtoElement* parent() const { + return static_cast(BaseElement::parent()); + } + + private: + // Used for access to variables of the enclosing instance of + // ProtoStreamObjectWriter. + ProtoStreamObjectWriter* ow_; + + // A writer for Any objects, handles all Any-related nonsense. + google::protobuf::scoped_ptr any_; + + // Describes the element as a field in the parent message. + // field_ is NULL if and only if this element is the root element. + const google::protobuf::Field* field_; + + // TypeInfo to lookup types. + TypeInfo* typeinfo_; + + // Additional variables if this element is a message: + // (Root element is always a message). + // descriptor_ : describes allowed fields in the message. + // required_fields_: set of required fields. + // is_repeated_type_ : true if the element is of type list or map. + // size_index_ : index into ProtoStreamObjectWriter::size_insert_ + // for later insertion of serialized message length. + const google::protobuf::Type& type_; + std::set required_fields_; + const bool is_repeated_type_; + const int size_index_; + + // Tracks position in repeated fields, needed for LocationTrackerInterface. + int array_index_; + + // The type of this element, see enum for permissible types. + ElementType element_type_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement); + }; + + // Container for inserting 'size' information at the 'pos' position. + struct SizeInfo { + const int pos; + int size; + }; + + ProtoStreamObjectWriter(TypeInfo* typeinfo, + const google::protobuf::Type& type, + strings::ByteSink* output, ErrorListener* listener); + + ProtoElement* element() { return element_.get(); } + + // Helper methods for calling ErrorListener. See error_listener.h. + void InvalidName(StringPiece unknown_name, StringPiece message); + void InvalidValue(StringPiece type_name, StringPiece value); + void MissingField(StringPiece missing_name); + + // Common code for BeginObject() and BeginList() that does invalid_depth_ + // bookkeeping associated with name lookup. + const google::protobuf::Field* BeginNamed(StringPiece name, bool is_list); + + // Lookup the field in the current element. Looks in the base descriptor + // and in any extension. This will report an error if the field cannot be + // found or if multiple matching extensions are found. + const google::protobuf::Field* Lookup(StringPiece name); + + // Lookup the field type in the type descriptor. Returns NULL if the type + // is not known. + const google::protobuf::Type* LookupType( + const google::protobuf::Field* field); + + // Looks up the oneof struct Value field depending on the type. + // On failure to find, it returns an appropriate error. + util::StatusOr LookupStructField( + DataPiece::Type type); + + // Starts an entry in map. This will be called after placing map element at + // the top of the stack. Uses this information to write map entries. + const google::protobuf::Field* StartMapEntry(StringPiece name); + + // Starts a google.protobuf.Struct. + // 'field' is of type google.protobuf.Struct. + // If field is NULL, it indicates that the top-level message is a struct + // type. + void StartStruct(const google::protobuf::Field* field); + + // Starts another struct within a struct. + // 'field' is of type google.protobuf.Value (see struct.proto). + const google::protobuf::Field* StartStructValueInStruct( + const google::protobuf::Field* field); + + // Starts a list within a struct. + // 'field' is of type google.protobuf.ListValue (see struct.proto). + const google::protobuf::Field* StartListValueInStruct( + const google::protobuf::Field* field); + + // Starts the repeated "values" field in struct.proto's + // google.protobuf.ListValue type. 'field' should be of type + // google.protobuf.ListValue. + const google::protobuf::Field* StartRepeatedValuesInListValue( + const google::protobuf::Field* field); + + // Pops sentinel elements off the stack. + void SkipElements(); + + // Write serialized output to the final output ByteSink, inserting all + // the size information for nested messages that are missing from the + // intermediate Cord buffer. + void WriteRootMessage(); + + // Returns true if the field is a map. + bool IsMap(const google::protobuf::Field& field); + + // Returns true if the field is an any. + bool IsAny(const google::protobuf::Field& field); + + // Helper method to write proto tags based on the given field. + void WriteTag(const google::protobuf::Field& field); + + // Helper function to render primitive data types in DataPiece. + void RenderSimpleDataPiece(const google::protobuf::Field& field, + const google::protobuf::Type& type, + const DataPiece& data); + + // Renders google.protobuf.Value in struct.proto. It picks the right oneof + // type based on value's type. + static util::Status RenderStructValue(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Renders google.protobuf.Timestamp value. + static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Renders google.protobuf.FieldMask value. + static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Renders google.protobuf.Duration value. + static util::Status RenderDuration(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Renders wrapper message types for primitive types in + // google/protobuf/wrappers.proto. + static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow, + const DataPiece& value); + + // Helper functions to create the map and find functions responsible for + // rendering well known types, keyed by type URL. + static hash_map* CreateRendererMap(); + static TypeRenderer* FindTypeRenderer(const string& type_url); + + // Returns the ProtoElement::ElementType for the given Type. + static ProtoElement::ElementType GetElementType( + const google::protobuf::Type& type); + + // Variables for describing the structure of the input tree: + // master_type_: descriptor for the whole protobuf message. + // typeinfo_ : the TypeInfo object to lookup types. + const google::protobuf::Type& master_type_; + TypeInfo* typeinfo_; + // Whether we own the typeinfo_ object. + bool own_typeinfo_; + + // Indicates whether we finished writing root message completely. + bool done_; + + // Variable for internal state processing: + // element_ : the current element. + // size_insert_: sizes of nested messages. + // pos - position to insert the size field. + // size - size value to be inserted. + google::protobuf::scoped_ptr element_; + std::deque size_insert_; + + // Variables for output generation: + // output_ : pointer to an external ByteSink for final user-visible output. + // buffer_ : buffer holding partial message before being ready for output_. + // adapter_ : internal adapter between CodedOutputStream and Cord buffer_. + // stream_ : wrapper for writing tags and other encodings in wire format. + strings::ByteSink* output_; + string buffer_; + google::protobuf::io::StringOutputStream adapter_; + google::protobuf::scoped_ptr stream_; + + // Variables for error tracking and reporting: + // listener_ : a place to report any errors found. + // invalid_depth_: number of enclosing invalid nested messages. + // tracker_ : the root location tracker interface. + ErrorListener* listener_; + int invalid_depth_; + google::protobuf::scoped_ptr tracker_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTOSTREAM_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc new file mode 100644 index 00000000..bd4f29f5 --- /dev/null +++ b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc @@ -0,0 +1,1513 @@ +// 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 + +#include // For size_t + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +using google::protobuf::testing::Author; +using google::protobuf::testing::Book; +using google::protobuf::testing::Book_Data; +using google::protobuf::testing::Primitive; +using google::protobuf::testing::Publisher; +using google::protobuf::Descriptor; +using google::protobuf::DescriptorPool; +using google::protobuf::DynamicMessageFactory; +using google::protobuf::FileDescriptorProto; +using google::protobuf::Message; +using google::protobuf::io::ArrayInputStream; +using strings::GrowingArrayByteSink; +using ::testing::_; +using ::testing::Args; +using google::protobuf::testing::anys::AnyM; +using google::protobuf::testing::anys::AnyOut; +using google::protobuf::testing::FieldMaskTest; +using google::protobuf::testing::maps::MapIn; +using google::protobuf::testing::structs::StructType; +using google::protobuf::testing::timestampduration::TimestampDuration; + + +namespace { +string GetTypeUrl(const Descriptor* descriptor) { + return string(kTypeServiceBaseUrl) + "/" + descriptor->full_name(); +} +} // namespace + +class BaseProtoStreamObjectWriterTest + : public ::testing::TestWithParam { + protected: + BaseProtoStreamObjectWriterTest() + : helper_(GetParam()), + listener_(), + output_(new GrowingArrayByteSink(1000)), + ow_() {} + + explicit BaseProtoStreamObjectWriterTest(const Descriptor* descriptor) + : helper_(GetParam()), + listener_(), + output_(new GrowingArrayByteSink(1000)), + ow_() { + vector descriptors; + descriptors.push_back(descriptor); + ResetTypeInfo(descriptors); + } + + explicit BaseProtoStreamObjectWriterTest( + vector descriptors) + : helper_(GetParam()), + listener_(), + output_(new GrowingArrayByteSink(1000)), + ow_() { + ResetTypeInfo(descriptors); + } + + void ResetTypeInfo(vector descriptors) { + GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!"; + helper_.ResetTypeInfo(descriptors); + ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(), + &listener_)); + } + + virtual ~BaseProtoStreamObjectWriterTest() {} + + void CheckOutput(const Message& expected, int expected_length) { + size_t nbytes; + google::protobuf::scoped_array buffer(output_->GetBuffer(&nbytes)); + if (expected_length >= 0) { + EXPECT_EQ(expected_length, nbytes); + } + string str(buffer.get(), nbytes); + + std::stringbuf str_buf(str, std::ios_base::in); + std::istream istream(&str_buf); + google::protobuf::scoped_ptr message(expected.New()); + message->ParsePartialFromIstream(&istream); + + EXPECT_EQ(expected.DebugString(), message->DebugString()); + } + + void CheckOutput(const Message& expected) { CheckOutput(expected, -1); } + + const google::protobuf::Type* GetType(const Descriptor* descriptor) { + return helper_.GetTypeInfo()->GetType(GetTypeUrl(descriptor)); + } + + testing::TypeInfoTestHelper helper_; + MockErrorListener listener_; + google::protobuf::scoped_ptr output_; + google::protobuf::scoped_ptr ow_; +}; + +MATCHER_P(HasObjectLocation, expected, + "Verifies the expected object location") { + string actual = std::tr1::get<0>(arg).ToString(); + if (actual.compare(expected) == 0) return true; + *result_listener << "actual location is: " << actual; + return false; +} + +class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterTest() + : BaseProtoStreamObjectWriterTest(Book::descriptor()) {} + + virtual ~ProtoStreamObjectWriterTest() {} +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + ProtoStreamObjectWriterTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(ProtoStreamObjectWriterTest, EmptyObject) { + Book empty; + ow_->StartObject("")->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, SimpleObject) { + string content("My content"); + + Book book; + book.set_title("My Title"); + book.set_length(222); + book.set_content(content); + + ow_->StartObject("") + ->RenderString("title", "My Title") + ->RenderInt32("length", 222) + ->RenderBytes("content", content) + ->EndObject(); + CheckOutput(book); +} + +TEST_P(ProtoStreamObjectWriterTest, SimpleMessage) { + Book book; + book.set_title("Some Book"); + book.set_length(102); + Publisher* publisher = book.mutable_publisher(); + publisher->set_name("My Publisher"); + Author* robert = book.mutable_author(); + robert->set_alive(true); + robert->set_name("robert"); + robert->add_pseudonym("bob"); + robert->add_pseudonym("bobby"); + robert->add_friend_()->set_name("john"); + + ow_->StartObject("") + ->RenderString("title", "Some Book") + ->RenderInt32("length", 102) + ->StartObject("publisher") + ->RenderString("name", "My Publisher") + ->EndObject() + ->StartObject("author") + ->RenderBool("alive", true) + ->RenderString("name", "robert") + ->StartList("pseudonym") + ->RenderString("", "bob") + ->RenderString("", "bobby") + ->EndList() + ->StartList("friend") + ->StartObject("") + ->RenderString("name", "john") + ->EndObject() + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(book); +} + +TEST_P(ProtoStreamObjectWriterTest, PrimitiveFromStringConversion) { + Primitive full; + full.set_fix32(101); + full.set_u32(102); + full.set_i32(-103); + full.set_sf32(-104); + full.set_s32(-105); + full.set_fix64(40000000001L); + full.set_u64(40000000002L); + full.set_i64(-40000000003L); + full.set_sf64(-40000000004L); + full.set_s64(-40000000005L); + full.set_str("string1"); + full.set_bytes("Some Bytes"); + full.set_float_(3.14f); + full.set_double_(-4.05L); + full.set_bool_(true); + full.add_rep_fix32(201); + full.add_rep_u32(202); + full.add_rep_i32(-203); + full.add_rep_sf32(-204); + full.add_rep_s32(-205); + full.add_rep_fix64(80000000001L); + full.add_rep_u64(80000000002L); + full.add_rep_i64(-80000000003L); + full.add_rep_sf64(-80000000004L); + full.add_rep_s64(-80000000005L); + full.add_rep_str("string2"); + full.add_rep_bytes("More Bytes"); + full.add_rep_float(6.14f); + full.add_rep_double(-8.05L); + full.add_rep_bool(false); + + ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()), + output_.get(), &listener_)); + + ow_->StartObject("") + ->RenderString("fix32", "101") + ->RenderString("u32", "102") + ->RenderString("i32", "-103") + ->RenderString("sf32", "-104") + ->RenderString("s32", "-105") + ->RenderString("fix64", "40000000001") + ->RenderString("u64", "40000000002") + ->RenderString("i64", "-40000000003") + ->RenderString("sf64", "-40000000004") + ->RenderString("s64", "-40000000005") + ->RenderString("str", "string1") + ->RenderString("bytes", "U29tZSBCeXRlcw==") // "Some Bytes" + ->RenderString("float", "3.14") + ->RenderString("double", "-4.05") + ->RenderString("bool", "true") + ->StartList("rep_fix32") + ->RenderString("", "201") + ->EndList() + ->StartList("rep_u32") + ->RenderString("", "202") + ->EndList() + ->StartList("rep_i32") + ->RenderString("", "-203") + ->EndList() + ->StartList("rep_sf32") + ->RenderString("", "-204") + ->EndList() + ->StartList("rep_s32") + ->RenderString("", "-205") + ->EndList() + ->StartList("rep_fix64") + ->RenderString("", "80000000001") + ->EndList() + ->StartList("rep_u64") + ->RenderString("", "80000000002") + ->EndList() + ->StartList("rep_i64") + ->RenderString("", "-80000000003") + ->EndList() + ->StartList("rep_sf64") + ->RenderString("", "-80000000004") + ->EndList() + ->StartList("rep_s64") + ->RenderString("", "-80000000005") + ->EndList() + ->StartList("rep_str") + ->RenderString("", "string2") + ->EndList() + ->StartList("rep_bytes") + ->RenderString("", "TW9yZSBCeXRlcw==") // "More Bytes" + ->EndList() + ->StartList("rep_float") + ->RenderString("", "6.14") + ->EndList() + ->StartList("rep_double") + ->RenderString("", "-8.05") + ->EndList() + ->StartList("rep_bool") + ->RenderString("", "false") + ->EndList() + ->EndObject(); + CheckOutput(full); +} + +TEST_P(ProtoStreamObjectWriterTest, InfinityInputTest) { + Primitive full; + full.set_double_(std::numeric_limits::infinity()); + full.set_float_(std::numeric_limits::infinity()); + full.set_str("-Infinity"); + + ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()), + output_.get(), &listener_)); + + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"), + StringPiece("\"Infinity\""))) + .With(Args<0>(HasObjectLocation("i32"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"), + StringPiece("\"Infinity\""))) + .With(Args<0>(HasObjectLocation("u32"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"), + StringPiece("\"-Infinity\""))) + .With(Args<0>(HasObjectLocation("sf64"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"), + StringPiece("\"Infinity\""))) + .With(Args<0>(HasObjectLocation("bool"))); + + ow_->StartObject("") + ->RenderString("double", "Infinity") + ->RenderString("float", "Infinity") + ->RenderString("i32", "Infinity") + ->RenderString("u32", "Infinity") + ->RenderString("sf64", "-Infinity") + ->RenderString("str", "-Infinity") + ->RenderString("bool", "Infinity") + ->EndObject(); + CheckOutput(full); +} + +TEST_P(ProtoStreamObjectWriterTest, NaNInputTest) { + Primitive full; + full.set_double_(std::numeric_limits::quiet_NaN()); + full.set_float_(std::numeric_limits::quiet_NaN()); + full.set_str("NaN"); + + ow_.reset(helper_.NewProtoWriter(GetTypeUrl(Primitive::descriptor()), + output_.get(), &listener_)); + + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"), + StringPiece("\"NaN\""))) + .With(Args<0>(HasObjectLocation("i32"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"), + StringPiece("\"NaN\""))) + .With(Args<0>(HasObjectLocation("u32"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"), + StringPiece("\"NaN\""))) + .With(Args<0>(HasObjectLocation("sf64"))); + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("TYPE_BOOL"), StringPiece("\"NaN\""))) + .With(Args<0>(HasObjectLocation("bool"))); + + ow_->StartObject("") + ->RenderString("double", "NaN") + ->RenderString("float", "NaN") + ->RenderString("i32", "NaN") + ->RenderString("u32", "NaN") + ->RenderString("sf64", "NaN") + ->RenderString("str", "NaN") + ->RenderString("bool", "NaN") + ->EndObject(); + + CheckOutput(full); +} + +TEST_P(ProtoStreamObjectWriterTest, ImplicitPrimitiveList) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("The Author"); + author->add_pseudonym("first"); + author->add_pseudonym("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "The Author") + ->RenderString("pseudonym", "first") + ->RenderString("pseudonym", "second") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, + LastWriteWinsOnNonRepeatedPrimitiveFieldWithDuplicates) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "first") + ->RenderString("name", "second") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, ExplicitPrimitiveList) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("The Author"); + author->add_pseudonym("first"); + author->add_pseudonym("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "The Author") + ->StartList("pseudonym") + ->RenderString("", "first") + ->RenderString("", "second") + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitPrimitiveList) { + Book expected; + expected.set_allocated_author(new Author()); + + EXPECT_CALL( + listener_, + InvalidName( + _, StringPiece("name"), + StringPiece("Proto field is not repeating, cannot start list."))) + .With(Args<0>(HasObjectLocation("author"))); + ow_->StartObject("") + ->StartObject("author") + ->StartList("name") + ->RenderString("", "first") + ->RenderString("", "second") + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, ImplicitMessageList) { + Book expected; + Author* outer = expected.mutable_author(); + outer->set_name("outer"); + outer->set_alive(true); + Author* first = outer->add_friend_(); + first->set_name("first"); + Author* second = outer->add_friend_(); + second->set_name("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "outer") + ->RenderBool("alive", true) + ->StartObject("friend") + ->RenderString("name", "first") + ->EndObject() + ->StartObject("friend") + ->RenderString("name", "second") + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, + LastWriteWinsOnNonRepeatedMessageFieldWithDuplicates) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("The Author"); + Publisher* publisher = expected.mutable_publisher(); + publisher->set_name("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "The Author") + ->EndObject() + ->StartObject("publisher") + ->RenderString("name", "first") + ->EndObject() + ->StartObject("publisher") + ->RenderString("name", "second") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, ExplicitMessageList) { + Book expected; + Author* outer = expected.mutable_author(); + outer->set_name("outer"); + outer->set_alive(true); + Author* first = outer->add_friend_(); + first->set_name("first"); + Author* second = outer->add_friend_(); + second->set_name("second"); + + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "outer") + ->RenderBool("alive", true) + ->StartList("friend") + ->StartObject("") + ->RenderString("name", "first") + ->EndObject() + ->StartObject("") + ->RenderString("name", "second") + ->EndObject() + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitMessageList) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("The Author"); + + EXPECT_CALL( + listener_, + InvalidName( + _, StringPiece("publisher"), + StringPiece("Proto field is not repeating, cannot start list."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "The Author") + ->EndObject() + ->StartList("publisher") + ->StartObject("") + ->RenderString("name", "first") + ->EndObject() + ->StartObject("") + ->RenderString("name", "second") + ->EndObject() + ->EndList() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtRoot) { + Book empty; + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtAuthorFriend) { + Book expected; + Author* paul = expected.mutable_author(); + paul->set_name("Paul"); + Author* mark = paul->add_friend_(); + mark->set_name("Mark"); + Author* john = paul->add_friend_(); + john->set_name("John"); + Author* luke = paul->add_friend_(); + luke->set_name("Luke"); + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("address"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation("author.friend[1]"))); + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "Paul") + ->StartList("friend") + ->StartObject("") + ->RenderString("name", "Mark") + ->EndObject() + ->StartObject("") + ->RenderString("name", "John") + ->RenderString("address", "Patmos") + ->EndObject() + ->StartObject("") + ->RenderString("name", "Luke") + ->EndObject() + ->EndList() + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtRoot) { + Book empty; + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtAuthor) { + Book expected; + Author* author = expected.mutable_author(); + author->set_name("William"); + author->add_pseudonym("Bill"); + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("wife"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation("author"))); + ow_->StartObject("") + ->StartObject("author") + ->RenderString("name", "William") + ->StartObject("wife") + ->RenderString("name", "Hilary") + ->EndObject() + ->RenderString("pseudonym", "Bill") + ->EndObject() + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownListAtRoot) { + Book empty; + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->StartList("unknown")->EndList()->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, UnknownListAtPublisher) { + Book expected; + expected.set_title("Brainwashing"); + Publisher* publisher = expected.mutable_publisher(); + publisher->set_name("propaganda"); + + EXPECT_CALL(listener_, InvalidName(_, StringPiece("alliance"), + StringPiece("Cannot find field."))) + .With(Args<0>(HasObjectLocation("publisher"))); + ow_->StartObject("") + ->StartObject("publisher") + ->RenderString("name", "propaganda") + ->StartList("alliance") + ->EndList() + ->EndObject() + ->RenderString("title", "Brainwashing") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, MissingRequiredField) { + Book expected; + expected.set_title("My Title"); + expected.set_allocated_publisher(new Publisher()); + + EXPECT_CALL(listener_, MissingField(_, StringPiece("name"))) + .With(Args<0>(HasObjectLocation("publisher"))); + ow_->StartObject("") + ->StartObject("publisher") + ->EndObject() + ->RenderString("title", "My Title") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, InvalidFieldValueAtRoot) { + Book empty; + + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"), + StringPiece("\"garbage\""))) + .With(Args<0>(HasObjectLocation("length"))); + ow_->StartObject("")->RenderString("length", "garbage")->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, MultipleInvalidFieldValues) { + Book expected; + expected.set_title("My Title"); + + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"), + StringPiece("\"-400\""))) + .With(Args<0>(HasObjectLocation("length"))); + EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT64"), + StringPiece("\"3.14\""))) + .With(Args<0>(HasObjectLocation("published"))); + ow_->StartObject("") + ->RenderString("length", "-400") + ->RenderString("published", "3.14") + ->RenderString("title", "My Title") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtRoot) { + Book empty; + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->RenderFloat("", 3.14)->EndObject(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtAuthor) { + Book expected; + expected.set_title("noname"); + expected.set_allocated_author(new Author()); + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation("author"))); + ow_->StartObject("") + ->StartObject("author") + ->RenderInt32("", 123) + ->EndObject() + ->RenderString("title", "noname") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, UnnamedListAtRoot) { + Book expected; + expected.set_title("noname"); + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("") + ->StartList("") + ->EndList() + ->RenderString("title", "noname") + ->EndObject(); + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterTest, RootNamedObject) { + Book expected; + expected.set_title("Annie"); + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece("oops"), + StringPiece("Root element should not be named."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("oops")->RenderString("title", "Annie")->EndObject(); + CheckOutput(expected, 7); +} + +TEST_P(ProtoStreamObjectWriterTest, RootNamedList) { + Book empty; + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece("oops"), + StringPiece("Root element should not be named."))) + .With(Args<0>(HasObjectLocation(""))); + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartList("oops")->RenderString("", "item")->EndList(); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, RootUnnamedField) { + Book empty; + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Root element must be a message."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->RenderBool("", true); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, RootNamedField) { + Book empty; + + EXPECT_CALL(listener_, + InvalidName(_, StringPiece("oops"), + StringPiece("Root element must be a message."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->RenderBool("oops", true); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, NullValue) { + Book empty; + + ow_->RenderNull(""); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, NullValueForMessageField) { + Book empty; + + ow_->RenderNull("author"); + CheckOutput(empty, 0); +} + +TEST_P(ProtoStreamObjectWriterTest, NullValueForPrimitiveField) { + Book empty; + + ow_->RenderNull("length"); + CheckOutput(empty, 0); +} + +class ProtoStreamObjectWriterTimestampDurationTest + : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterTimestampDurationTest() { + vector descriptors; + descriptors.push_back(TimestampDuration::descriptor()); + descriptors.push_back(google::protobuf::Timestamp::descriptor()); + descriptors.push_back(google::protobuf::Duration::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) { + TimestampDuration timestamp; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece( + "Field 'ts', Illegal timestamp format; timestamps " + "must end with 'Z'"))); + + ow_->StartObject("")->RenderString("ts", "")->EndObject(); + CheckOutput(timestamp); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) { + TimestampDuration timestamp; + + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece( + "Field 'ts', Invalid time format: Failed to parse input"))); + + ow_->StartObject("")->RenderString("ts", "Z")->EndObject(); + CheckOutput(timestamp); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) { + TimestampDuration timestamp; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece( + "Field 'ts', Invalid time format, failed to parse nano " + "seconds"))); + + ow_->StartObject("") + ->RenderString("ts", "1970-01-01T00:00:00.ABZ") + ->EndObject(); + CheckOutput(timestamp); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) { + TimestampDuration timestamp; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece("Field 'ts', Timestamp value exceeds limits"))); + + ow_->StartObject("") + ->RenderString("ts", "-8032-10-18T00:00:00.000Z") + ->EndObject(); + CheckOutput(timestamp); +} + +// TODO(skarvaje): Write a test for nanos that exceed limit. Currently, it is +// not possible to construct a test case where nanos exceed limit because of +// floating point arithmetic. + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) { + TimestampDuration duration; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece( + "Field 'dur', Illegal duration format; duration must " + "end with 's'"))); + + ow_->StartObject("")->RenderString("dur", "")->EndObject(); + CheckOutput(duration); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) { + TimestampDuration duration; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece( + "Field 'dur', Invalid duration format, failed to parse " + "seconds"))); + + ow_->StartObject("")->RenderString("dur", "s")->EndObject(); + CheckOutput(duration); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) { + TimestampDuration duration; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece( + "Field 'dur', Invalid duration format, failed to " + "parse nanos seconds"))); + + ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject(); + CheckOutput(duration); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError4) { + TimestampDuration duration; + + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece("Field 'dur', Duration value exceeds limits"))); + + ow_->StartObject("")->RenderString("dur", "315576000002s")->EndObject(); + CheckOutput(duration); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, + MismatchedTimestampTypeInput) { + TimestampDuration timestamp; + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"), + StringPiece( + "Field 'ts', Invalid data type for timestamp, value is null"))) + .With(Args<0>(HasObjectLocation("ts"))); + ow_->StartObject("")->RenderNull("ts")->EndObject(); + CheckOutput(timestamp); +} + +TEST_P(ProtoStreamObjectWriterTimestampDurationTest, + MismatchedDurationTypeInput) { + TimestampDuration duration; + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.Duration"), + StringPiece( + "Field 'dur', Invalid data type for duration, value is null"))) + .With(Args<0>(HasObjectLocation("dur"))); + ow_->StartObject("")->RenderNull("dur")->EndObject(); + CheckOutput(duration); +} + +class ProtoStreamObjectWriterStructTest + : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterStructTest() { + vector descriptors; + descriptors.push_back(StructType::descriptor()); + descriptors.push_back(google::protobuf::Struct::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +// TODO(skarvaje): Write tests for failure cases. +TEST_P(ProtoStreamObjectWriterStructTest, StructRenderSuccess) { + StructType struct_type; + google::protobuf::Struct* s = struct_type.mutable_object(); + s->mutable_fields()->operator[]("k1").set_number_value(123); + s->mutable_fields()->operator[]("k2").set_bool_value(true); + + ow_->StartObject("") + ->StartObject("object") + ->RenderDouble("k1", 123) + ->RenderBool("k2", true) + ->EndObject() + ->EndObject(); + CheckOutput(struct_type); +} + +TEST_P(ProtoStreamObjectWriterStructTest, StructNullInputSuccess) { + StructType struct_type; + EXPECT_CALL(listener_, + InvalidName(_, StringPiece(""), + StringPiece("Proto fields must have a name."))) + .With(Args<0>(HasObjectLocation(""))); + ow_->StartObject("")->RenderNull("")->EndObject(); + CheckOutput(struct_type); +} + +TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) { + StructType struct_type; + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("type.googleapis.com/google.protobuf.Struct"), + StringPiece("true"))) + .With(Args<0>(HasObjectLocation("object"))); + + ow_->StartObject("")->RenderBool("object", true)->EndObject(); + CheckOutput(struct_type); +} + +class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterMapTest() + : BaseProtoStreamObjectWriterTest(MapIn::descriptor()) {} +}; + +TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) { + MapIn mm; + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Map"), + StringPiece("Cannot bind a list to map."))) + .With(Args<0>(HasObjectLocation("map_input"))); + ow_->StartObject("") + ->StartList("map_input") + ->RenderString("a", "b") + ->EndList() + ->EndObject(); + CheckOutput(mm); +} + +class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterAnyTest() { + vector descriptors; + descriptors.push_back(AnyOut::descriptor()); + descriptors.push_back(google::protobuf::DoubleValue::descriptor()); + descriptors.push_back(google::protobuf::Any::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) { + AnyOut any; + google::protobuf::Any* any_type = any.mutable_any(); + any_type->set_type_url("type.googleapis.com/google.protobuf.DoubleValue"); + google::protobuf::DoubleValue d; + d.set_value(40.2); + any_type->set_value(d.SerializeAsString()); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue") + ->RenderDouble("value", 40.2) + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any nested_any; + nested_any.set_type_url( + "type.googleapis.com/google.protobuf.testing.anys.AnyM"); + + AnyM m; + m.set_foo("foovalue"); + nested_any.set_value(m.SerializeAsString()); + + any->set_value(nested_any.SerializeAsString()); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject() + ->EndObject(); + + CheckOutput(out, 115); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) { + AnyOut out; + ::google::protobuf::Any* any = out.mutable_any(); + any->set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any nested_any; + nested_any.set_type_url("type.googleapis.com/google.protobuf.Any"); + + ::google::protobuf::Any second_nested_any; + second_nested_any.set_type_url( + "type.googleapis.com/google.protobuf.testing.anys.AnyM"); + + AnyM m; + m.set_foo("foovalue"); + second_nested_any.set_value(m.SerializeAsString()); + + nested_any.set_value(second_nested_any.SerializeAsString()); + any->set_value(nested_any.SerializeAsString()); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", "type.googleapis.com/google.protobuf.Any") + ->StartObject("value") + ->RenderString("@type", + "type.googleapis.com/google.protobuf.testing.anys.AnyM") + ->RenderString("foo", "foovalue") + ->EndObject() + ->EndObject() + ->EndObject() + ->EndObject(); + + CheckOutput(out, 159); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) { + AnyOut out; + out.mutable_any(); + + ow_->StartObject("")->StartObject("any")->EndObject()->EndObject(); + + CheckOutput(out, 2); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) { + AnyOut any; + + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing or invalid @type for any field in " + "google.protobuf.testing.anys.AnyOut"))); + + ow_->StartObject("") + ->StartObject("any") + ->StartObject("another") + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) { + AnyOut any; + + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing or invalid @type for any field in " + "google.protobuf.testing.anys.AnyOut"))); + + ow_->StartObject("") + ->StartObject("any") + ->StartList("another") + ->EndObject() + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) { + AnyOut any; + + EXPECT_CALL(listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Missing or invalid @type for any field in " + "google.protobuf.testing.anys.AnyOut"))); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("value", "somevalue") + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) { + AnyOut any; + + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece( + "Invalid type URL, type URLs must be of the form " + "'type.googleapis.com/', got: " + "type.other.com/some.Type"))); + + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.other.com/some.Type") + ->RenderDouble("value", 40.2) + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) { + AnyOut any; + + EXPECT_CALL( + listener_, + InvalidValue(_, StringPiece("Any"), + StringPiece("Invalid type URL, unknown type: some.Type"))); + ow_->StartObject("") + ->StartObject("any") + ->RenderString("@type", "type.googleapis.com/some.Type") + ->RenderDouble("value", 40.2) + ->EndObject() + ->EndObject(); + CheckOutput(any); +} + +TEST_P(ProtoStreamObjectWriterAnyTest, AnyNullInputFails) { + AnyOut any; + + ow_->StartObject("")->RenderNull("any")->EndObject(); + CheckOutput(any); +} + +class ProtoStreamObjectWriterFieldMaskTest + : public BaseProtoStreamObjectWriterTest { + protected: + ProtoStreamObjectWriterFieldMaskTest() { + vector descriptors; + descriptors.push_back(FieldMaskTest::descriptor()); + descriptors.push_back(google::protobuf::FieldMask::descriptor()); + ResetTypeInfo(descriptors); + } +}; + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) { + FieldMaskTest expected; + expected.set_id("1"); + expected.mutable_single_mask()->add_paths("path1"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", "path1"); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MutipleMasksInCompactForm) { + FieldMaskTest expected; + expected.set_id("1"); + expected.mutable_single_mask()->add_paths("camel_case1"); + expected.mutable_single_mask()->add_paths("camel_case2"); + expected.mutable_single_mask()->add_paths("camel_case3"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", "camelCase1,camelCase2,camelCase3"); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, RepeatedFieldMaskTest) { + FieldMaskTest expected; + expected.set_id("1"); + google::protobuf::FieldMask* mask = expected.add_repeated_mask(); + mask->add_paths("field1"); + mask->add_paths("field2"); + expected.add_repeated_mask()->add_paths("field3"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->StartList("repeated_mask"); + ow_->RenderString("", "field1,field2"); + ow_->RenderString("", "field3"); + ow_->EndList(); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, EmptyFieldMaskTest) { + FieldMaskTest expected; + expected.set_id("1"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", ""); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) { + FieldMaskTest expected; + expected.set_id("1"); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + // Case1 + ow_->RenderString("single_mask", + "outerField(camelCase1,camelCase2,camelCase3)"); + expected.mutable_single_mask()->add_paths("outer_field.camel_case1"); + expected.mutable_single_mask()->add_paths("outer_field.camel_case2"); + expected.mutable_single_mask()->add_paths("outer_field.camel_case3"); + + ow_->StartList("repeated_mask"); + + ow_->RenderString("", "a(field1,field2)"); + google::protobuf::FieldMask* mask = expected.add_repeated_mask(); + mask->add_paths("a.field1"); + mask->add_paths("a.field2"); + + ow_->RenderString("", "a(field3)"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.field3"); + + ow_->RenderString("", "a()"); + expected.add_repeated_mask(); + + ow_->RenderString("", "a(,)"); + expected.add_repeated_mask(); + + ow_->RenderString("", "a(field1(field2(field3)))"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.field1.field2.field3"); + + ow_->RenderString("", "a(field1(field2(field3,field4),field5),field6)"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.field1.field2.field3"); + mask->add_paths("a.field1.field2.field4"); + mask->add_paths("a.field1.field5"); + mask->add_paths("a.field6"); + + ow_->RenderString("", "a(id,field1(id,field2(field3,field4),field5),field6)"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.id"); + mask->add_paths("a.field1.id"); + mask->add_paths("a.field1.field2.field3"); + mask->add_paths("a.field1.field2.field4"); + mask->add_paths("a.field1.field5"); + mask->add_paths("a.field6"); + + ow_->RenderString("", "a(((field3,field4)))"); + mask = expected.add_repeated_mask(); + mask->add_paths("a.field3"); + mask->add_paths("a.field4"); + + ow_->EndList(); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) { + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask 'a(b,c))'. " + "Cannot find matching '(' for all ')'."))); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", "a(b,c))"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreOpenThanCloseParentheses) { + EXPECT_CALL( + listener_, + InvalidValue( + _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask 'a(((b,c)'. Cannot " + "find matching ')' for all '('."))); + + ow_->StartObject(""); + ow_->RenderString("id", "1"); + ow_->RenderString("single_mask", "a(((b,c)"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, PathWithMapKeyShouldWork) { + FieldMaskTest expected; + expected.mutable_single_mask()->add_paths("path.to.map[\"key1\"]"); + expected.mutable_single_mask()->add_paths( + "path.to.map[\"e\\\"[]][scape\\\"\"]"); + expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]"); + + ow_->StartObject(""); + ow_->RenderString("single_mask", + "path.to.map[\"key1\"],path.to.map[\"e\\\"[]][scape\\\"\"]," + "path.to.map[\"key2\"]"); + ow_->EndObject(); + + CheckOutput(expected); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, + MapKeyMustBeAtTheEndOfAPathSegment) { + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. " + "Map keys should be at the end of a path segment."))); + + ow_->StartObject(""); + ow_->RenderString("single_mask", + "path.to.map[\"key1\"]a,path.to.map[\"key2\"]"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) { + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"key1\"'. Map keys should be " + "represented as [\"some_key\"]."))); + + ow_->StartObject(""); + ow_->RenderString("single_mask", "path.to.map[\"key1\""); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) { + EXPECT_CALL( + listener_, + InvalidValue(_, + StringPiece("type.googleapis.com/google.protobuf.FieldMask"), + StringPiece( + "Field 'single_mask', Invalid FieldMask " + "'path.to.map[\"ke\"y1\"]'. Map keys should be " + "represented as [\"some_key\"]."))); + + ow_->StartObject(""); + ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]"); + ow_->EndObject(); +} + +TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) { + FieldMaskTest expected; + expected.mutable_single_mask()->add_paths( + "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War孙天涌,./?><\\\\\"]"); + expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]"); + + ow_->StartObject(""); + ow_->RenderString( + "single_mask", + "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War孙天涌,./?><\\\\\"]," + "path.to.map[\"key2\"]"); + ow_->EndObject(); + + CheckOutput(expected); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter.h b/src/google/protobuf/util/internal/snake2camel_objectwriter.h new file mode 100644 index 00000000..1a32bc56 --- /dev/null +++ b/src/google/protobuf/util/internal/snake2camel_objectwriter.h @@ -0,0 +1,187 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__ + +#include + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// Snake2CamelObjectWriter is an ObjectWriter than translates each field name +// from snake_case to camelCase. Typical usage is: +// ProtoStreamObjectSource psos(...); +// JsonObjectWriter jow(...); +// Snake2CamelObjectWriter snake_to_camel(&jow); +// psos.writeTo(&snake_to_camel); +class Snake2CamelObjectWriter : public ObjectWriter { + public: + explicit Snake2CamelObjectWriter(ObjectWriter* ow) + : ow_(ow), normalize_case_(true) {} + virtual ~Snake2CamelObjectWriter() {} + + // ObjectWriter methods. + virtual Snake2CamelObjectWriter* StartObject(StringPiece name) { + ow_->StartObject(ShouldNormalizeCase(name) + ? StringPiece(StringPiece(ToCamelCase(name))) + : name); + return this; + } + + virtual Snake2CamelObjectWriter* EndObject() { + ow_->EndObject(); + return this; + } + + virtual Snake2CamelObjectWriter* StartList(StringPiece name) { + ow_->StartList(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) + : name); + return this; + } + + virtual Snake2CamelObjectWriter* EndList() { + ow_->EndList(); + return this; + } + + virtual Snake2CamelObjectWriter* RenderBool(StringPiece name, bool value) { + ow_->RenderBool( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderInt32(StringPiece name, int32 value) { + ow_->RenderInt32( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderUint32(StringPiece name, + uint32 value) { + ow_->RenderUint32( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderInt64(StringPiece name, int64 value) { + ow_->RenderInt64( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderUint64(StringPiece name, + uint64 value) { + ow_->RenderUint64( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderDouble(StringPiece name, + double value) { + ow_->RenderDouble( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderFloat(StringPiece name, float value) { + ow_->RenderFloat( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderString(StringPiece name, + StringPiece value) { + ow_->RenderString( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderBytes(StringPiece name, + StringPiece value) { + ow_->RenderBytes( + ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) : name, + value); + return this; + } + + virtual Snake2CamelObjectWriter* RenderNull(StringPiece name) { + ow_->RenderNull(ShouldNormalizeCase(name) ? StringPiece(ToCamelCase(name)) + : name); + return this; + } + + virtual Snake2CamelObjectWriter* DisableCaseNormalizationForNextKey() { + normalize_case_ = false; + return this; + } + + private: + ObjectWriter* ow_; + bool normalize_case_; + + bool ShouldNormalizeCase(StringPiece name) { + if (normalize_case_) { + return !IsCamel(name); + } else { + normalize_case_ = true; + return false; + } + } + + bool IsCamel(StringPiece name) { + return name.empty() || (ascii_islower(name[0]) && !name.contains("_")); + } + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Snake2CamelObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_SNAKE2CAMEL_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc new file mode 100644 index 00000000..67388c3b --- /dev/null +++ b/src/google/protobuf/util/internal/snake2camel_objectwriter_test.cc @@ -0,0 +1,311 @@ +// 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 +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +class Snake2CamelObjectWriterTest : public ::testing::Test { + protected: + Snake2CamelObjectWriterTest() : mock_(), expects_(&mock_), testing_(&mock_) {} + virtual ~Snake2CamelObjectWriterTest() {} + + MockObjectWriter mock_; + ExpectingObjectWriter expects_; + Snake2CamelObjectWriter testing_; +}; + +TEST_F(Snake2CamelObjectWriterTest, Empty) { + // Set expectation + expects_.StartObject("")->EndObject(); + + // Actual testing + testing_.StartObject("")->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, UnderscoresOnly) { + // Set expectation + expects_.StartObject("") + ->RenderInt32("", 1) + ->RenderInt32("", 2) + ->RenderInt32("", 3) + ->RenderInt32("", 4) + ->RenderInt32("", 5) + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderInt32("_", 1) + ->RenderInt32("__", 2) + ->RenderInt32("___", 3) + ->RenderInt32("____", 4) + ->RenderInt32("_____", 5) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, LowercaseOnly) { + // Set expectation + expects_.StartObject("") + ->RenderString("key", "value") + ->RenderString("abracadabra", "magic") + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("key", "value") + ->RenderString("abracadabra", "magic") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, UppercaseOnly) { + // Set expectation + expects_.StartObject("") + ->RenderString("key", "VALUE") + ->RenderString("abracadabra", "MAGIC") + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("KEY", "VALUE") + ->RenderString("ABRACADABRA", "MAGIC") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, CamelCase) { + // Set expectation + expects_.StartObject("") + ->RenderString("camelCase", "camelCase") + ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog", + "theQuickBrownFoxJumpsOverTheLazyDog") + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("camelCase", "camelCase") + ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog", + "theQuickBrownFoxJumpsOverTheLazyDog") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, FirstCapCamelCase) { + // Sets expectation + expects_.StartObject("camel") + ->RenderString("camelCase", "CamelCase") + ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog", + "TheQuickBrownFoxJumpsOverTheLazyDog") + ->EndObject(); + + // Actual testing + testing_.StartObject("Camel") + ->RenderString("CamelCase", "CamelCase") + ->RenderString("TheQuickBrownFoxJumpsOverTheLazyDog", + "TheQuickBrownFoxJumpsOverTheLazyDog") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, LastCapCamelCase) { + // Sets expectation + expects_.StartObject("lastCapCamelCasE")->EndObject(); + + // Actual testing + testing_.StartObject("lastCapCamelCasE")->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, MixedCapCamelCase) { + // Sets expectation + expects_.StartObject("googleIsTheBest") + ->RenderFloat("iLoveGOOGLE", 1.61803f) + ->RenderFloat("goGoogleGO", 2.71828f) + ->RenderFloat("gBikeISCool", 3.14159f) + ->EndObject(); + + // Actual testing + testing_.StartObject("GOOGLEIsTheBest") + ->RenderFloat("ILoveGOOGLE", 1.61803f) + ->RenderFloat("GOGoogleGO", 2.71828f) + ->RenderFloat("GBikeISCool", 3.14159f) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, MixedCase) { + // Sets expectation + expects_.StartObject("snakeCaseCamelCase") + ->RenderBool("camelCaseSnakeCase", false) + ->RenderBool("mixedCamelAndUnderScores", false) + ->RenderBool("goGOOGLEGo", true) + ->EndObject(); + + // Actual testing + testing_.StartObject("snake_case_camelCase") + ->RenderBool("camelCase_snake_case", false) + ->RenderBool("MixedCamel_And_UnderScores", false) + ->RenderBool("Go_GOOGLEGo", true) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, SnakeCase) { + // Sets expectation + expects_.StartObject("") + ->RenderString("snakeCase", "snake_case") + ->RenderString("theQuickBrownFoxJumpsOverTheLazyDog", + "the_quick_brown_fox_jumps_over_the_lazy_dog") + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("snake_case", "snake_case") + ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog", + "the_quick_brown_fox_jumps_over_the_lazy_dog") + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, FirstCapSnakeCase) { + // Sets expectation + expects_.StartObject("firstCapSnakeCase") + ->RenderBool("helloWorld", true) + ->EndObject(); + + // Actual testing + testing_.StartObject("First_Cap_Snake_Case") + ->RenderBool("Hello_World", true) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, AllCapSnakeCase) { + // Sets expectation + expects_.StartObject("allCAPSNAKECASE") + ->RenderDouble("nyseGOOGL", 600.0L) + ->RenderDouble("aBCDE", 1.0L) + ->RenderDouble("klMNOP", 2.0L) + ->RenderDouble("abcIJKPQRXYZ", 3.0L) + ->EndObject(); + + // Actual testing + testing_.StartObject("ALL_CAP_SNAKE_CASE") + ->RenderDouble("NYSE_GOOGL", 600.0L) + ->RenderDouble("A_B_C_D_E", 1.0L) + ->RenderDouble("KL_MN_OP", 2.0L) + ->RenderDouble("ABC_IJK_PQR_XYZ", 3.0L) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, RepeatedUnderScoreSnakeCase) { + // Sets expectation + expects_.StartObject("") + ->RenderInt32("doubleUnderscoreSnakeCase", 2) + ->RenderInt32("tripleUnderscoreFirstCap", 3) + ->RenderInt32("quadrupleUNDERSCOREALLCAP", 4) + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderInt32("double__underscore__snake__case", 2) + ->RenderInt32("Triple___Underscore___First___Cap", 3) + ->RenderInt32("QUADRUPLE____UNDERSCORE____ALL____CAP", 4) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, LeadingUnderscoreSnakeCase) { + // Sets expectation + expects_.StartObject("leadingUnderscoreSnakeCase") + ->RenderUint32("leadingDoubleUnderscore", 2) + ->RenderUint32("leadingTripleUnderscoreFirstCap", 3) + ->RenderUint32("leadingQUADRUPLEUNDERSCOREALLCAP", 4) + ->EndObject(); + + // Actual testing + testing_.StartObject("_leading_underscore_snake_case") + ->RenderUint32("__leading_double_underscore", 2) + ->RenderUint32("___Leading_Triple_Underscore_First_Cap", 3) + ->RenderUint32("____LEADING_QUADRUPLE_UNDERSCORE_ALL_CAP", 4) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, TrailingUnderscoreSnakeCase) { + // Sets expectation + expects_.StartObject("trailingUnderscoreSnakeCase") + ->RenderInt64("trailingDoubleUnderscore", 2L) + ->RenderInt64("trailingTripleUnderscoreFirstCap", 3L) + ->RenderInt64("trailingQUADRUPLEUNDERSCOREALLCAP", 4L) + ->EndObject(); + + // Actual testing + testing_.StartObject("trailing_underscore_snake_case") + ->RenderInt64("trailing_double_underscore__", 2L) + ->RenderInt64("Trailing_Triple_Underscore_First_Cap___", 3L) + ->RenderInt64("TRAILING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, EnclosingUnderscoreSnakeCase) { + // Sets expectation + expects_.StartObject("enclosingUnderscoreSnakeCase") + ->RenderUint64("enclosingDoubleUnderscore", 2L) + ->RenderUint64("enclosingTripleUnderscoreFirstCap", 3L) + ->RenderUint64("enclosingQUADRUPLEUNDERSCOREALLCAP", 4L) + ->EndObject(); + + // Actual testing + testing_.StartObject("_enclosing_underscore_snake_case_") + ->RenderUint64("__enclosing_double_underscore__", 2L) + ->RenderUint64("___Enclosing_Triple_Underscore_First_Cap___", 3L) + ->RenderUint64("____ENCLOSING_QUADRUPLE_UNDERSCORE_ALL_CAP____", 4L) + ->EndObject(); +} + +TEST_F(Snake2CamelObjectWriterTest, DisableCaseNormalizationOnlyDisablesFirst) { + // Sets expectation + expects_.StartObject("") + ->RenderString("snakeCase", "snake_case") + ->RenderString( + "the_quick_brown_fox_jumps_over_the_lazy_dog", // case retained + "the_quick_brown_fox_jumps_over_the_lazy_dog") + ->RenderBool("theSlowFox", true) // disable case not in effect + ->EndObject(); + + // Actual testing + testing_.StartObject("") + ->RenderString("snake_case", "snake_case") + ->DisableCaseNormalizationForNextKey() + ->RenderString("the_quick_brown_fox_jumps_over_the_lazy_dog", + "the_quick_brown_fox_jumps_over_the_lazy_dog") + ->RenderBool("the_slow_fox", true) + ->EndObject(); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h new file mode 100644 index 00000000..3f065d6b --- /dev/null +++ b/src/google/protobuf/util/internal/structured_objectwriter.h @@ -0,0 +1,118 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ + +#include +#ifndef _SHARED_PTR_H +#include +#endif + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +// An StructuredObjectWriter is an ObjectWriter for writing +// tree-structured data in a stream of events representing objects +// and collections. Implementation of this interface can be used to +// write an object stream to an in-memory structure, protobufs, +// JSON, XML, or any other output format desired. The ObjectSource +// interface is typically used as the source of an object stream. +// +// See JsonObjectWriter for a sample implementation of +// StructuredObjectWriter and its use. +// +// Derived classes could be thread-unsafe. +class LIBPROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter { + public: + virtual ~StructuredObjectWriter() {} + + protected: + // A base element class for subclasses to extend, makes tracking state easier. + // + // StructuredObjectWriter behaves as a visitor. BaseElement represents a node + // in the input tree. Implementation of StructuredObjectWriter should also + // extend BaseElement to keep track of the location in the input tree. + class LIBPROTOBUF_EXPORT BaseElement { + public: + // Takes ownership of the parent Element. + explicit BaseElement(BaseElement* parent) + : parent_(parent), level_(parent == NULL ? 0 : parent->level() + 1) {} + virtual ~BaseElement() {} + + // Releases ownership of the parent and returns a pointer to it. + template + ElementType* pop() { + return down_cast(parent_.release()); + } + + // Returns true if this element is the root. + bool is_root() const { return parent_ == NULL; } + + // Returns the number of hops from this element to the root element. + int level() const { return level_; } + + protected: + // Returns pointer to parent element without releasing ownership. + virtual BaseElement* parent() const { return parent_.get(); } + + private: + // Pointer to the parent Element. + google::protobuf::scoped_ptr parent_; + + // Number of hops to the root Element. + // The root Element has NULL parent_ and a level_ of 0. + const int level_; + + GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseElement); + }; + + StructuredObjectWriter() {} + + // Returns the current element. Used for indentation and name overrides. + virtual BaseElement* element() = 0; + + private: + // Do not add any data members to this class. + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StructuredObjectWriter); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_STRUCTURED_OBJECTWRITER_H__ diff --git a/src/google/protobuf/util/internal/testdata/anys.proto b/src/google/protobuf/util/internal/testdata/anys.proto new file mode 100644 index 00000000..18c59cbb --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/anys.proto @@ -0,0 +1,53 @@ +// 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. + +// Proto to test Proto3 Any serialization. +syntax = "proto3"; + +package google.protobuf.testing.anys; +option java_package = "com.google.protobuf.testing.anys"; + +import "google/protobuf/any.proto"; + +message AnyIn { + string something = 1; +} + +message AnyOut { + google.protobuf.Any any = 1; +} + +message AnyM { + string foo = 1; +} + +service TestService { + rpc Call(AnyIn) returns (AnyOut); +} diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto new file mode 100644 index 00000000..6e2f109b --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/books.proto @@ -0,0 +1,171 @@ +// 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. + +// Author: sven@google.com (Sven Mawson) +// +// Sample protos for testing. +syntax = "proto2"; + +package google.protobuf.testing; + +// A book +message Book { + optional string title = 1; + optional Author author = 2; + optional uint32 length = 3; + optional int64 published = 4; + optional bytes content = 5; + + optional group Data = 6 { + optional uint32 year = 7; + optional string copyright = 8; + } + + message Label { + optional string key = 1; + optional string value = 2; + } + + optional Publisher publisher = 9; + repeated Label labels = 10; + + extensions 200 to 499; +} + +// A publisher of a book, tests required fields. +message Publisher { + required string name = 1; +} + +// An author of a book +message Author { + optional uint64 id = 1; + optional string name = 2; + repeated string pseudonym = 3; + optional bool alive = 4; + repeated Author friend = 5; +} + +// For testing resiliency of our protostream parser. +// Field numbers of Author are reused for something else. +message BadAuthor { + optional string id = 1; // non-length-delimited to length-delimited. + repeated uint64 name = 2; // string to repeated (both length-delimited). + optional string pseudonym = 3; // Repeated to optional. + repeated bool alive = 4 [packed=true]; // Optional to repeated. +} + +// All primitive types +message Primitive { + // 32 bit numbers: + optional fixed32 fix32 = 1; + optional uint32 u32 = 2; + optional int32 i32 = 3; + optional sfixed32 sf32 = 4; + optional sint32 s32 = 5; + + // 64 bit numbers: + optional fixed64 fix64 = 6; + optional uint64 u64 = 7; + optional int64 i64 = 8; + optional sfixed64 sf64 = 9; + optional sint64 s64 = 10; + + // The other stuff. + optional string str = 11; + optional bytes bytes = 12; + optional float float = 13; + optional double double = 14; + optional bool bool = 15; + + // repeated 32 bit numbers: + repeated fixed32 rep_fix32 = 16; + repeated uint32 rep_u32 = 17; + repeated int32 rep_i32 = 18; + repeated sfixed32 rep_sf32 = 19; + repeated sint32 rep_s32 = 20; + + // repeated 64 bit numbers: + repeated fixed64 rep_fix64 = 21; + repeated uint64 rep_u64 = 22; + repeated int64 rep_i64 = 23; + repeated sfixed64 rep_sf64 = 24; + repeated sint64 rep_s64 = 25; + + // repeated other stuff: + repeated string rep_str = 26; + repeated bytes rep_bytes = 27; + repeated float rep_float = 28; + repeated double rep_double = 29; + repeated bool rep_bool = 30; +} + +// Test packed versions of all repeated primitives. +// The field numbers should match their non-packed version in Primitive message. +message PackedPrimitive { + // repeated 32 bit numbers: + repeated fixed32 rep_fix32 = 16 [packed=true]; + repeated uint32 rep_u32 = 17 [packed=true]; + repeated int32 rep_i32 = 18 [packed=true]; + repeated sfixed32 rep_sf32 = 19 [packed=true]; + repeated sint32 rep_s32 = 20 [packed=true]; + + // repeated 64 bit numbers: + repeated fixed64 rep_fix64 = 21 [packed=true]; + repeated uint64 rep_u64 = 22 [packed=true]; + repeated int64 rep_i64 = 23 [packed=true]; + repeated sfixed64 rep_sf64 = 24 [packed=true]; + repeated sint64 rep_s64 = 25 [packed=true]; + + // repeated other stuff: + repeated float rep_float = 28 [packed=true]; + repeated double rep_double = 29 [packed=true]; + repeated bool rep_bool = 30 [packed=true]; +} + +// Test extensions. +extend Book { + repeated Author more_author = 201; +} + +// Test nested extensions. +message NestedBook { + extend Book { + optional NestedBook another_book = 301; + } + // Recurse + optional Book book = 1; +} + +// For testing resiliency of our protostream parser. +// Field number of NestedBook is reused for something else. +message BadNestedBook { + repeated uint32 book = 1 [packed=true]; // Packed to optional message. +} diff --git a/src/google/protobuf/util/internal/testdata/default_value.proto b/src/google/protobuf/util/internal/testdata/default_value.proto new file mode 100644 index 00000000..ecfc8119 --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/default_value.proto @@ -0,0 +1,162 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf.testing; + +import "google/protobuf/any.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/wrappers.proto"; + +message DefaultValueTestCases { + DoubleMessage empty_double = 1; + DoubleMessage double_with_default_value = 2; + DoubleMessage double_with_nondefault_value = 3; + DoubleMessage repeated_double = 4; + DoubleMessage nested_message = 5; + DoubleMessage repeated_nested_message = 6; + StructMessage empty_struct = 201; + StructMessage empty_struct2 = 202; + StructMessage struct_with_null_value = 203; + StructMessage struct_with_values = 204; + StructMessage struct_with_nested_struct = 205; + StructMessage struct_with_nested_list = 206; + StructMessage struct_with_list_of_nulls = 207; + StructMessage struct_with_list_of_lists = 208; + StructMessage struct_with_list_of_structs = 209; + google.protobuf.Struct top_level_struct = 210; + ValueMessage value_wrapper_simple = 212; + ValueMessage value_wrapper_with_struct = 213; + ValueMessage value_wrapper_with_list = 214; + ListValueMessage list_value_wrapper = 215; + google.protobuf.Value top_level_value_simple = 216; + google.protobuf.Value top_level_value_with_struct = 217; + google.protobuf.Value top_level_value_with_list = 218; + google.protobuf.ListValue top_level_listvalue = 219; + AnyMessage empty_any = 301; + AnyMessage type_only_any = 302; + AnyMessage recursive_any = 303; + AnyMessage any_with_message_value = 304; + AnyMessage any_with_nested_message = 305; + AnyMessage any_with_message_containing_map = 306; + AnyMessage any_with_message_containing_struct = 307; + google.protobuf.Any top_level_any = 308; + StringtoIntMap empty_map = 401; + StringtoIntMap string_to_int = 402; + IntToStringMap int_to_string = 403; + MixedMap mixed1 = 404; + MixedMap2 mixed2 = 405; + MessageMap map_of_objects = 406; + DoubleValueMessage double_value = 501; + DoubleValueMessage double_value_default = 502; +} + +message DoubleMessage { + double double_value = 1; + repeated double repeated_double = 2; + DoubleMessage nested_message = 3; + repeated DoubleMessage repeated_nested_message = 4; + google.protobuf.DoubleValue double_wrapper = 100; +} + +message StructMessage { + google.protobuf.Struct struct = 1; +} + +message ValueMessage { + google.protobuf.Value value = 1; +} + +message ListValueMessage { + google.protobuf.ListValue shopping_list = 1; +} +message RequestMessage { + string content = 1; +} + +// A test service. +service DefaultValueTestService { + // A test method. + rpc Call(RequestMessage) returns (DefaultValueTestCases); +} + +message AnyMessage { + google.protobuf.Any any = 1; + AnyData data = 2; +} + +message AnyData { + int32 attr = 1; + string str = 2; + repeated string msgs = 3; + AnyData nested_data = 4; + map map_data = 7; + google.protobuf.Struct struct_data = 8; + repeated AnyData repeated_data = 9; +} + +message StringtoIntMap { + map map = 1; +} + +message IntToStringMap { + map map = 1; +} + +message MixedMap { + string msg = 1; + map map = 2; + int32 int_value = 3; +} + +message MixedMap2 { + enum E { + E0 = 0; + E1 = 1; + E2 = 2; + E3 = 3; + } + map map = 1; + E ee = 2; + string msg = 4; +} + +message MessageMap { + message M { + int32 inner_int = 1; + string inner_text = 2; + } + map map = 1; +} + +message DoubleValueMessage { + google.protobuf.DoubleValue double = 1; +} diff --git a/src/google/protobuf/util/internal/testdata/default_value_test.proto b/src/google/protobuf/util/internal/testdata/default_value_test.proto new file mode 100644 index 00000000..21b85e6d --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/default_value_test.proto @@ -0,0 +1,46 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf.testing; + +message DefaultValueTest { + double double_value = 1; + repeated double repeated_double = 2; + float float_value = 3; + int64 int64_value = 5; + uint64 uint64_value = 7; + int32 int32_value = 9; + uint32 uint32_value = 11; + bool bool_value = 13; + string string_value = 15; + bytes bytes_value = 17 [ctype = CORD]; +} diff --git a/src/google/protobuf/util/internal/testdata/field_mask.proto b/src/google/protobuf/util/internal/testdata/field_mask.proto new file mode 100644 index 00000000..e8b2bc5f --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/field_mask.proto @@ -0,0 +1,71 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf.testing; + +import "google/protobuf/field_mask.proto"; + +message NestedFieldMask { + string data = 1; + google.protobuf.FieldMask single_mask = 2; + repeated google.protobuf.FieldMask repeated_mask = 3; +} + +message FieldMaskTest { + string id = 1; + google.protobuf.FieldMask single_mask = 2; + repeated google.protobuf.FieldMask repeated_mask = 3; + repeated NestedFieldMask nested_mask = 4; +} + +message FieldMaskTestCases { + FieldMaskWrapper single_mask = 1; + FieldMaskWrapper multiple_mask = 2; + FieldMaskWrapper snake_camel = 3; + FieldMaskWrapper empty_field = 4; + FieldMaskWrapper apiary_format1 = 5; + FieldMaskWrapper apiary_format2 = 6; + FieldMaskWrapper apiary_format3 = 7; + FieldMaskWrapper map_key1 = 8; + FieldMaskWrapper map_key2 = 9; + FieldMaskWrapper map_key3 = 10; + FieldMaskWrapper map_key4 = 11; + FieldMaskWrapper map_key5 = 12; +} + +message FieldMaskWrapper { + google.protobuf.FieldMask mask = 1; +} + +service FieldMaskTestService { + rpc Call(FieldMaskTestCases) returns (FieldMaskTestCases); +} diff --git a/src/google/protobuf/util/internal/testdata/maps.proto b/src/google/protobuf/util/internal/testdata/maps.proto new file mode 100644 index 00000000..7fb42a26 --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/maps.proto @@ -0,0 +1,57 @@ +// 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. + +// Proto to test proto3 maps. +syntax = "proto3"; + +package google.protobuf.testing.maps; +option java_package = "com.google.protobuf.testing.maps"; + +message MapIn { + string other = 1; + repeated string things = 2; + map map_input = 3; +} + +message MapOut { + map map1 = 1; + map map2 = 2; + map map3 = 3; + string bar = 4; +} + +message MapM { + string foo = 1; +} + +service TestService { + rpc Call1(MapIn) returns (MapOut); + rpc Call2(MapIn) returns (MapOut); +} diff --git a/src/google/protobuf/util/internal/testdata/struct.proto b/src/google/protobuf/util/internal/testdata/struct.proto new file mode 100644 index 00000000..c15aba0d --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/struct.proto @@ -0,0 +1,45 @@ +// 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. + +// Proto to test proto3 struct. +syntax = "proto3"; + +package google.protobuf.testing.structs; +option java_package = "com.google.protobuf.testing.structs"; + +import "google/protobuf/struct.proto"; + +message StructType { + google.protobuf.Struct object = 1; +} + +service TestService { + rpc Call(StructType) returns (StructType); +} diff --git a/src/google/protobuf/util/internal/testdata/timestamp_duration.proto b/src/google/protobuf/util/internal/testdata/timestamp_duration.proto new file mode 100644 index 00000000..56351f16 --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/timestamp_duration.proto @@ -0,0 +1,47 @@ +// 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. + +// Proto to test proto3 Timestamp and Duration. +syntax = "proto3"; + +package google.protobuf.testing.timestampduration; +option java_package = "com.google.protobuf.testing.timestampduration"; + +import "google/protobuf/timestamp.proto"; +import "google/protobuf/duration.proto"; + +message TimestampDuration { + google.protobuf.Timestamp ts = 1; + google.protobuf.Duration dur = 2; +} + +service TestService { + rpc Call(TimestampDuration) returns (TimestampDuration); +} diff --git a/src/google/protobuf/util/internal/testdata/wrappers.proto b/src/google/protobuf/util/internal/testdata/wrappers.proto new file mode 100644 index 00000000..eabc99f2 --- /dev/null +++ b/src/google/protobuf/util/internal/testdata/wrappers.proto @@ -0,0 +1,100 @@ +// 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. + +syntax = "proto3"; + +package google.protobuf.testing; + +import "google/protobuf/wrappers.proto"; + +// Top-level test cases proto used by MarshallingTest. See description +// at the top of the class MarshallingTest for details on how to write +// test cases. +message WrappersTestCases { + DoubleWrapper double_wrapper = 1; + FloatWrapper float_wrapper = 2; + Int64Wrapper int64_wrapper = 3; + UInt64Wrapper uint64_wrapper = 4; + Int32Wrapper int32_wrapper = 5; + UInt32Wrapper uint32_wrapper = 6; + BoolWrapper bool_wrapper = 7; + StringWrapper string_wrapper = 8; + BytesWrapper bytes_wrapper = 9; + + DoubleWrapper double_wrapper_default = 10; + FloatWrapper float_wrapper_default = 11; + Int64Wrapper int64_wrapper_default = 12; + UInt64Wrapper uint64_wrapper_default = 13; + Int32Wrapper int32_wrapper_default = 14; + UInt32Wrapper uint32_wrapper_default = 15; + BoolWrapper bool_wrapper_default = 16; + StringWrapper string_wrapper_default = 17; + BytesWrapper bytes_wrapper_default = 18; +} + +message DoubleWrapper { + google.protobuf.DoubleValue double = 1; +} + +message FloatWrapper { + google.protobuf.FloatValue float = 1; +} + +message Int64Wrapper { + google.protobuf.Int64Value int64 = 1; +} + +message UInt64Wrapper { + google.protobuf.UInt64Value uint64 = 1; +} + +message Int32Wrapper { + google.protobuf.Int32Value int32 = 1; +} + +message UInt32Wrapper { + google.protobuf.UInt32Value uint32 = 1; +} + +message BoolWrapper { + google.protobuf.BoolValue bool = 1; +} + +message StringWrapper { + google.protobuf.StringValue string = 1; +} + +message BytesWrapper { + google.protobuf.BytesValue bytes = 1; +} + +service WrappersTestService { + rpc Call(WrappersTestCases) returns (WrappersTestCases); +} diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc new file mode 100644 index 00000000..6392e18c --- /dev/null +++ b/src/google/protobuf/util/internal/type_info.cc @@ -0,0 +1,171 @@ +// 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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { + +// A TypeInfo that looks up information provided by a TypeResolver. +class TypeInfoForTypeResolver : public TypeInfo { + public: + explicit TypeInfoForTypeResolver(TypeResolver* type_resolver) + : type_resolver_(type_resolver) {} + + virtual ~TypeInfoForTypeResolver() { + DeleteCachedTypes(&cached_types_); + DeleteCachedTypes(&cached_enums_); + } + + virtual util::StatusOr ResolveTypeUrl( + StringPiece type_url) { + map::iterator it = cached_types_.find(type_url); + if (it != cached_types_.end()) { + return it->second; + } + // Stores the string value so it can be referenced using StringPiece in the + // cached_types_ map. + const string& string_type_url = + *string_storage_.insert(type_url.ToString()).first; + google::protobuf::scoped_ptr type(new google::protobuf::Type()); + util::Status status = + type_resolver_->ResolveMessageType(string_type_url, type.get()); + StatusOrType result = + status.ok() ? StatusOrType(type.release()) : StatusOrType(status); + cached_types_[string_type_url] = result; + return result; + } + + virtual const google::protobuf::Type* GetType(StringPiece type_url) { + StatusOrType result = ResolveTypeUrl(type_url); + return result.ok() ? result.ValueOrDie() : NULL; + } + + virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) { + map::iterator it = cached_enums_.find(type_url); + if (it != cached_enums_.end()) { + return it->second.ok() ? it->second.ValueOrDie() : NULL; + } + // Stores the string value so it can be referenced using StringPiece in the + // cached_enums_ map. + const string& string_type_url = + *string_storage_.insert(type_url.ToString()).first; + google::protobuf::scoped_ptr enum_type( + new google::protobuf::Enum()); + util::Status status = + type_resolver_->ResolveEnumType(string_type_url, enum_type.get()); + StatusOrEnum result = + status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status); + cached_enums_[string_type_url] = result; + return result.ok() ? result.ValueOrDie() : NULL; + } + + virtual const google::protobuf::Field* FindField( + const google::protobuf::Type* type, StringPiece camel_case_name) { + if (indexed_types_.find(type) == indexed_types_.end()) { + PopulateNameLookupTable(type); + indexed_types_.insert(type); + } + StringPiece name = + FindWithDefault(camel_case_name_table_, camel_case_name, StringPiece()); + if (name.empty()) { + // Didn't find a mapping. Use whatever provided. + name = camel_case_name; + } + return FindFieldInTypeOrNull(type, name); + } + + private: + typedef util::StatusOr StatusOrType; + typedef util::StatusOr StatusOrEnum; + + template + static void DeleteCachedTypes(map* cached_types) { + for (typename map::iterator it = cached_types->begin(); + it != cached_types->end(); ++it) { + if (it->second.ok()) { + delete it->second.ValueOrDie(); + } + } + } + + void PopulateNameLookupTable(const google::protobuf::Type* type) { + for (int i = 0; i < type->fields_size(); ++i) { + const google::protobuf::Field& field = type->fields(i); + StringPiece name = field.name(); + StringPiece camel_case_name = + *string_storage_.insert(ToCamelCase(name)).first; + const StringPiece* existing = InsertOrReturnExisting( + &camel_case_name_table_, camel_case_name, name); + if (existing && *existing != name) { + GOOGLE_LOG(WARNING) << "Field '" << name << "' and '" << *existing + << "' map to the same camel case name '" << camel_case_name + << "'."; + } + } + } + + TypeResolver* type_resolver_; + + // Stores string values that will be referenced by StringPieces in + // cached_types_, cached_enums_ and camel_case_name_table_. + set string_storage_; + + map cached_types_; + map cached_enums_; + + set indexed_types_; + map camel_case_name_table_; +}; +} // namespace + +TypeInfo* TypeInfo::NewTypeInfo(TypeResolver* type_resolver) { + return new TypeInfoForTypeResolver(type_resolver); +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h new file mode 100644 index 00000000..04ed78df --- /dev/null +++ b/src/google/protobuf/util/internal/type_info.h @@ -0,0 +1,87 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +// Internal helper class for type resolving. Note that this class is not +// thread-safe and should only be accessed in one thread. +class TypeInfo { + public: + TypeInfo() {} + virtual ~TypeInfo() {} + + // Resolves a type url into a Type. If the type url is invalid, returns + // INVALID_ARGUMENT error status. If the type url is valid but the + // corresponding type cannot be found, returns a NOT_FOUND error status. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual util::StatusOr ResolveTypeUrl( + StringPiece type_url) = 0; + + // Resolves a type url into a Type. Like ResolveTypeUrl() but returns + // NULL if the type url is invalid or the type cannot be found. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual const google::protobuf::Type* GetType(StringPiece type_url) = 0; + + // Resolves a type url for an enum. Returns NULL if the type url is + // invalid or the type cannot be found. + // + // This TypeInfo class retains the ownership of the returned pointer. + virtual const google::protobuf::Enum* GetEnum(StringPiece type_url) = 0; + + // Looks up a field in the specified type given a CamelCase name. + virtual const google::protobuf::Field* FindField( + const google::protobuf::Type* type, StringPiece camel_case_name) = 0; + + static TypeInfo* NewTypeInfo(TypeResolver* type_resolver); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeInfo); +}; + +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_H__ diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc new file mode 100644 index 00000000..f7aea857 --- /dev/null +++ b/src/google/protobuf/util/internal/type_info_test_helper.cc @@ -0,0 +1,130 @@ +// 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 + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +namespace testing { + + +void TypeInfoTestHelper::ResetTypeInfo( + const vector& descriptors) { + switch (type_) { + case USE_TYPE_RESOLVER: { + const DescriptorPool* pool = descriptors[0]->file()->pool(); + for (int i = 1; i < descriptors.size(); ++i) { + GOOGLE_CHECK(pool == descriptors[i]->file()->pool()) + << "Descriptors from different pools are not supported."; + } + type_resolver_.reset( + NewTypeResolverForDescriptorPool(kTypeServiceBaseUrl, pool)); + typeinfo_.reset(TypeInfo::NewTypeInfo(type_resolver_.get())); + return; + } + } + GOOGLE_LOG(FATAL) << "Can not reach here."; +} + +void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor) { + vector descriptors; + descriptors.push_back(descriptor); + ResetTypeInfo(descriptors); +} + +void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor1, + const Descriptor* descriptor2) { + vector descriptors; + descriptors.push_back(descriptor1); + descriptors.push_back(descriptor2); + ResetTypeInfo(descriptors); +} + +TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); } + +ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource( + io::CodedInputStream* coded_input, const string& type_url) { + const google::protobuf::Type* type = typeinfo_->GetType(type_url); + switch (type_) { + case USE_TYPE_RESOLVER: { + return new ProtoStreamObjectSource(coded_input, type_resolver_.get(), + *type); + } + } + GOOGLE_LOG(FATAL) << "Can not reach here."; +} + +ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter( + const string& type_url, strings::ByteSink* output, + ErrorListener* listener) { + const google::protobuf::Type* type = typeinfo_->GetType(type_url); + switch (type_) { + case USE_TYPE_RESOLVER: { + return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output, + listener); + } + } + GOOGLE_LOG(FATAL) << "Can not reach here."; +} + +DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter( + const string& type_url, ObjectWriter* writer) { + const google::protobuf::Type* type = typeinfo_->GetType(type_url); + switch (type_) { + case USE_TYPE_RESOLVER: { + return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer); + } + } + GOOGLE_LOG(FATAL) << "Can not reach here."; +} + +} // namespace testing +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h new file mode 100644 index 00000000..6916a73b --- /dev/null +++ b/src/google/protobuf/util/internal/type_info_test_helper.h @@ -0,0 +1,98 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { +namespace testing { + +enum TypeInfoSource { + USE_TYPE_RESOLVER, +}; + +// In the unit-tests we want to test two scenarios: one with type info from +// ServiceTypeInfo, the other with type info from TypeResolver. This class +// wraps the detail of where the type info is from and provides the same +// interface so the same unit-test code can test both scenarios. +class TypeInfoTestHelper { + public: + explicit TypeInfoTestHelper(TypeInfoSource type) : type_(type) {} + + // Creates a TypeInfo object for the given set of descriptors. + void ResetTypeInfo(const vector& descriptors); + + // Convinent overloads. + void ResetTypeInfo(const Descriptor* descriptor); + void ResetTypeInfo(const Descriptor* descriptor1, + const Descriptor* descriptor2); + + // Returns the TypeInfo created after ResetTypeInfo. + TypeInfo* GetTypeInfo(); + + ProtoStreamObjectSource* NewProtoSource(io::CodedInputStream* coded_input, + const string& type_url); + + ProtoStreamObjectWriter* NewProtoWriter(const string& type_url, + strings::ByteSink* output, + ErrorListener* listener); + + DefaultValueObjectWriter* NewDefaultValueWriter(const string& type_url, + ObjectWriter* writer); + + private: + TypeInfoSource type_; + google::protobuf::scoped_ptr typeinfo_; + google::protobuf::scoped_ptr type_resolver_; +}; +} // namespace testing +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_TYPE_INFO_TEST_HELPER_H__ diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc new file mode 100644 index 00000000..b6ec19b6 --- /dev/null +++ b/src/google/protobuf/util/internal/utility.cc @@ -0,0 +1,332 @@ +// 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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace converter { + +namespace { +const StringPiece SkipWhiteSpace(StringPiece str) { + StringPiece::size_type i; + for (i = 0; i < str.size() && isspace(str[i]); ++i) {} + GOOGLE_DCHECK(i == str.size() || !isspace(str[i])); + return StringPiece(str, i); +} +} // namespace + +bool GetBoolOptionOrDefault( + const google::protobuf::RepeatedPtrField& options, + const string& option_name, bool default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == NULL) { + return default_value; + } + return GetBoolFromAny(opt->value()); +} + +int64 GetInt64OptionOrDefault( + const google::protobuf::RepeatedPtrField& options, + const string& option_name, int64 default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == NULL) { + return default_value; + } + return GetInt64FromAny(opt->value()); +} + +double GetDoubleOptionOrDefault( + const google::protobuf::RepeatedPtrField& options, + const string& option_name, double default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == NULL) { + return default_value; + } + return GetDoubleFromAny(opt->value()); +} + +string GetStringOptionOrDefault( + const google::protobuf::RepeatedPtrField& options, + const string& option_name, const string& default_value) { + const google::protobuf::Option* opt = FindOptionOrNull(options, option_name); + if (opt == NULL) { + return default_value; + } + return GetStringFromAny(opt->value()); +} + +template +void ParseFromAny(const string& data, T* result) { + result->ParseFromString(data); +} + +// Returns a boolean value contained in Any type. +// TODO(skarvaje): Add type checking & error messages here. +bool GetBoolFromAny(const google::protobuf::Any& any) { + google::protobuf::BoolValue b; + ParseFromAny(any.value(), &b); + return b.value(); +} + +int64 GetInt64FromAny(const google::protobuf::Any& any) { + google::protobuf::Int64Value i; + ParseFromAny(any.value(), &i); + return i.value(); +} + +double GetDoubleFromAny(const google::protobuf::Any& any) { + google::protobuf::DoubleValue i; + ParseFromAny(any.value(), &i); + return i.value(); +} + +string GetStringFromAny(const google::protobuf::Any& any) { + google::protobuf::StringValue s; + ParseFromAny(any.value(), &s); + return s.value(); +} + +const StringPiece GetTypeWithoutUrl(StringPiece type_url) { + size_t idx = type_url.rfind('/'); + return type_url.substr(idx + 1); +} + +const string GetFullTypeWithUrl(StringPiece simple_type) { + return StrCat(kTypeServiceBaseUrl, "/", simple_type); +} + +const google::protobuf::Option* FindOptionOrNull( + const google::protobuf::RepeatedPtrField& options, + const string& option_name) { + for (int i = 0; i < options.size(); ++i) { + const google::protobuf::Option& opt = options.Get(i); + if (opt.name() == option_name) { + return &opt; + } + } + return NULL; +} + +const google::protobuf::Field* FindFieldInTypeOrNull( + const google::protobuf::Type* type, StringPiece field_name) { + if (type != NULL) { + for (int i = 0; i < type->fields_size(); ++i) { + const google::protobuf::Field& field = type->fields(i); + if (field.name() == field_name) { + return &field; + } + } + } + return NULL; +} + +const google::protobuf::EnumValue* FindEnumValueByNameOrNull( + const google::protobuf::Enum* enum_type, StringPiece enum_name) { + if (enum_type != NULL) { + for (int i = 0; i < enum_type->enumvalue_size(); ++i) { + const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); + if (enum_value.name() == enum_name) { + return &enum_value; + } + } + } + return NULL; +} + +const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( + const google::protobuf::Enum* enum_type, int32 value) { + if (enum_type != NULL) { + for (int i = 0; i < enum_type->enumvalue_size(); ++i) { + const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i); + if (enum_value.number() == value) { + return &enum_value; + } + } + } + return NULL; +} + +string ToCamelCase(const StringPiece input) { + bool capitalize_next = false; + bool was_cap = true; + bool is_cap = false; + bool first_word = true; + string result; + result.reserve(input.size()); + + for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) { + is_cap = ascii_isupper(input[i]); + if (input[i] == '_') { + capitalize_next = true; + if (!result.empty()) first_word = false; + continue; + } else if (first_word) { + // Consider when the current character B is capitalized, + // first word ends when: + // 1) following a lowercase: "...aB..." + // 2) followed by a lowercase: "...ABc..." + if (!result.empty() && is_cap && + (!was_cap || (i + 1 < input.size() && ascii_islower(input[i + 1])))) { + first_word = false; + } else { + result.push_back(ascii_tolower(input[i])); + continue; + } + } else if (capitalize_next) { + capitalize_next = false; + if (ascii_islower(input[i])) { + result.push_back(ascii_toupper(input[i])); + continue; + } + } + result.push_back(input[i]); + } + return result; +} + +string ToSnakeCase(StringPiece input) { + bool was_not_underscore = false; // Initialize to false for case 1 (below) + bool was_not_cap = false; + string result; + result.reserve(input.size() << 1); + + for (size_t i = 0; i < input.size(); ++i) { + if (ascii_isupper(input[i])) { + // Consider when the current character B is capitalized: + // 1) At beginning of input: "B..." => "b..." + // (e.g. "Biscuit" => "biscuit") + // 2) Following a lowercase: "...aB..." => "...a_b..." + // (e.g. "gBike" => "g_bike") + // 3) At the end of input: "...AB" => "...ab" + // (e.g. "GoogleLAB" => "google_lab") + // 4) Followed by a lowercase: "...ABc..." => "...a_bc..." + // (e.g. "GBike" => "g_bike") + if (was_not_underscore && // case 1 out + (was_not_cap || // case 2 in, case 3 out + (i + 1 < input.size() && // case 3 out + ascii_islower(input[i + 1])))) { // case 4 in + // We add an underscore for case 2 and case 4. + result.push_back('_'); + } + result.push_back(ascii_tolower(input[i])); + was_not_underscore = true; + was_not_cap = false; + } else { + result.push_back(input[i]); + was_not_underscore = input[i] != '_'; + was_not_cap = true; + } + } + return result; +} + +set* well_known_types_ = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(well_known_types_init_); +const char* well_known_types_name_array_[] = { + "google.protobuf.Timestamp", "google.protobuf.Duration", + "google.protobuf.DoubleValue", "google.protobuf.FloatValue", + "google.protobuf.Int64Value", "google.protobuf.UInt64Value", + "google.protobuf.Int32Value", "google.protobuf.UInt32Value", + "google.protobuf.BoolValue", "google.protobuf.StringValue", + "google.protobuf.BytesValue", "google.protobuf.FieldMask"}; + +void DeleteWellKnownTypes() { delete well_known_types_; } + +void InitWellKnownTypes() { + well_known_types_ = new set; + for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) { + well_known_types_->insert(well_known_types_name_array_[i]); + } + google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes); +} + +bool IsWellKnownType(const string& type_name) { + InitWellKnownTypes(); + return ContainsKey(*well_known_types_, type_name); +} + +bool IsValidBoolString(const string& bool_string) { + return bool_string == "true" || bool_string == "false" || + bool_string == "1" || bool_string == "0"; +} + +bool IsMap(const google::protobuf::Field& field, + const google::protobuf::Type& type) { + return (field.cardinality() == + google::protobuf::Field_Cardinality_CARDINALITY_REPEATED && + GetBoolOptionOrDefault(type.options(), + "google.protobuf.MessageOptions.map_entry", false)); +} + +string DoubleAsString(double value) { + if (value == std::numeric_limits::infinity()) return "Infinity"; + if (value == -std::numeric_limits::infinity()) return "-Infinity"; + if (isnan(value)) return "NaN"; + + return SimpleDtoa(value); +} + +string FloatAsString(float value) { + if (isfinite(value)) return SimpleFtoa(value); + return DoubleAsString(value); +} + +bool SafeStrToFloat(StringPiece str, float *value) { + double double_value; + if (!safe_strtod(str, &double_value)) { + return false; + } + *value = static_cast(double_value); + + if ((*value == numeric_limits::infinity()) || + (*value == -numeric_limits::infinity())) { + return false; + } + return true; +} + +} // namespace converter +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h new file mode 100644 index 00000000..56ae1a25 --- /dev/null +++ b/src/google/protobuf/util/internal/utility.h @@ -0,0 +1,187 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ +#define GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ + +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace google { +namespace protobuf { +class Method; +class Any; +class Bool; +class Option; +class Field; +class Type; +class Enum; +class EnumValue; +} // namespace protobuf + + +namespace protobuf { +namespace util { +namespace converter { +// Finds the tech option identified by option_name. Parses the boolean value and +// returns it. +// When the option with the given name is not found, default_value is returned. +bool GetBoolOptionOrDefault( + const google::protobuf::RepeatedPtrField& options, + const string& option_name, bool default_value); + +// Returns int64 option value. If the option isn't found, returns the +// default_value. +int64 GetInt64OptionOrDefault( + const google::protobuf::RepeatedPtrField& options, + const string& option_name, int64 default_value); + +// Returns double option value. If the option isn't found, returns the +// default_value. +double GetDoubleOptionOrDefault( + const google::protobuf::RepeatedPtrField& options, + const string& option_name, double default_value); + +// Returns string option value. If the option isn't found, returns the +// default_value. +string GetStringOptionOrDefault( + const google::protobuf::RepeatedPtrField& options, + const string& option_name, const string& default_value); + +// Returns a boolean value contained in Any type. +// TODO(skarvaje): Make these utilities dealing with Any types more generic, +// add more error checking and move to a more public/sharable location so others +// can use. +bool GetBoolFromAny(const google::protobuf::Any& any); + +// Returns int64 value contained in Any type. +int64 GetInt64FromAny(const google::protobuf::Any& any); + +// Returns double value contained in Any type. +double GetDoubleFromAny(const google::protobuf::Any& any); + +// Returns string value contained in Any type. +string GetStringFromAny(const google::protobuf::Any& any); + +// Returns the type string without the url prefix. e.g.: If the passed type is +// 'type.googleapis.com/tech.type.Bool', the returned value is 'tech.type.Bool'. +const StringPiece GetTypeWithoutUrl(StringPiece type_url); + +// Returns the simple_type with the base type url (kTypeServiceBaseUrl) +// prefixed. +// +// E.g: +// GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string +// "type.googleapis.com/google.protobuf.Timestamp". +const string GetFullTypeWithUrl(StringPiece simple_type); + +// Finds and returns option identified by name and option_name within the +// provided map. Returns NULL if none found. +const google::protobuf::Option* FindOptionOrNull( + const google::protobuf::RepeatedPtrField& options, + const string& option_name); + +// Finds and returns the field identified by field_name in the passed tech Type +// object. Returns NULL if none found. +const google::protobuf::Field* FindFieldInTypeOrNull( + const google::protobuf::Type* type, StringPiece field_name); + +// Finds and returns the EnumValue identified by enum_name in the passed tech +// Enum object. Returns NULL if none found. +const google::protobuf::EnumValue* FindEnumValueByNameOrNull( + const google::protobuf::Enum* enum_type, StringPiece enum_name); + +// Finds and returns the EnumValue identified by value in the passed tech +// Enum object. Returns NULL if none found. +const google::protobuf::EnumValue* FindEnumValueByNumberOrNull( + const google::protobuf::Enum* enum_type, int32 value); + +// Converts input to camel-case and returns it. +// Tests are in wrappers/translator/snake2camel_objectwriter_test.cc +// TODO(skarvaje): Isolate tests for this function and put them in +// utility_test.cc +string ToCamelCase(const StringPiece input); + +// Converts input to snake_case and returns it. +string ToSnakeCase(StringPiece input); + +// Returns true if type_name represents a well-known type. +bool IsWellKnownType(const string& type_name); + +// Returns true if 'bool_string' represents a valid boolean value. Only "true", +// "false", "0" and "1" are allowed. +bool IsValidBoolString(const string& bool_string); + +// Returns true if "field" is a protobuf map field based on its type. +bool IsMap(const google::protobuf::Field& field, + const google::protobuf::Type& type); + +// Infinity/NaN-aware conversion to string. +string DoubleAsString(double value); +string FloatAsString(float value); + +// Convert from int32, int64, uint32, uint64, double or float to string. +template +string ValueAsString(T value) { + return SimpleItoa(value); +} + +template <> +inline string ValueAsString(float value) { + return FloatAsString(value); +} + +template <> +inline string ValueAsString(double value) { + return DoubleAsString(value); +} + +// Converts a string to float. Unlike safe_strtof, conversion will fail if the +// value fits into double but not float (e.g., DBL_MAX). +bool SafeStrToFloat(StringPiece str, float* value); +} // namespace converter +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_CONVERTER_UTILITY_H__ diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto new file mode 100644 index 00000000..7a282868 --- /dev/null +++ b/src/google/protobuf/util/json_format_proto3.proto @@ -0,0 +1,157 @@ +// 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. + +syntax = "proto3"; + +package proto3; + + +import "google/protobuf/duration.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/any.proto"; +import "google/protobuf/field_mask.proto"; + +enum EnumType { + FOO = 0; + BAR = 1; +} + +message MessageType { + int32 value = 1; +} + +message TestMessage { + bool bool_value = 1; + int32 int32_value = 2; + int64 int64_value = 3; + uint32 uint32_value = 4; + uint64 uint64_value = 5; + float float_value = 6; + double double_value = 7; + string string_value = 8; + bytes bytes_value = 9; + EnumType enum_value = 10; + MessageType message_value = 11; + + repeated bool repeated_bool_value = 21; + repeated int32 repeated_int32_value = 22; + repeated int64 repeated_int64_value = 23; + repeated uint32 repeated_uint32_value = 24; + repeated uint64 repeated_uint64_value = 25; + repeated float repeated_float_value = 26; + repeated double repeated_double_value = 27; + repeated string repeated_string_value = 28; + repeated bytes repeated_bytes_value = 29; + repeated EnumType repeated_enum_value = 30; + repeated MessageType repeated_message_value = 31; +} + +message TestOneof { + // In JSON format oneof fields behave mostly the same as optional + // fields except that: + // 1. Oneof fields have field presence information and will be + // printed if it's set no matter whether it's the default value. + // 2. Multiple oneof fields in the same oneof cannot appear at the + // same time in the input. + oneof oneof_value { + int32 oneof_int32_value = 1; + string oneof_string_value = 2; + bytes oneof_bytes_value = 3; + EnumType oneof_enum_value = 4; + MessageType oneof_message_value = 5; + } +} + +message TestMap { + map bool_map = 1; + map int32_map = 2; + map int64_map = 3; + map uint32_map = 4; + map uint64_map = 5; + map string_map = 6; +} + +message TestWrapper { + google.protobuf.BoolValue bool_value = 1; + google.protobuf.Int32Value int32_value = 2; + google.protobuf.Int64Value int64_value = 3; + google.protobuf.UInt32Value uint32_value = 4; + google.protobuf.UInt64Value uint64_value = 5; + google.protobuf.FloatValue float_value = 6; + google.protobuf.DoubleValue double_value = 7; + google.protobuf.StringValue string_value = 8; + google.protobuf.BytesValue bytes_value = 9; + + repeated google.protobuf.BoolValue repeated_bool_value = 11; + repeated google.protobuf.Int32Value repeated_int32_value = 12; + repeated google.protobuf.Int64Value repeated_int64_value = 13; + repeated google.protobuf.UInt32Value repeated_uint32_value = 14; + repeated google.protobuf.UInt64Value repeated_uint64_value = 15; + repeated google.protobuf.FloatValue repeated_float_value = 16; + repeated google.protobuf.DoubleValue repeated_double_value = 17; + repeated google.protobuf.StringValue repeated_string_value = 18; + repeated google.protobuf.BytesValue repeated_bytes_value = 19; +} + +message TestTimestamp { + google.protobuf.Timestamp value = 1; + repeated google.protobuf.Timestamp repeated_value = 2; +} + +message TestDuration { + google.protobuf.Duration value = 1; + repeated google.protobuf.Duration repeated_value = 2; +} + +message TestFieldMask { + google.protobuf.FieldMask value = 1; +} + +message TestStruct { + google.protobuf.Struct value = 1; + repeated google.protobuf.Struct repeated_value = 2; +} + +message TestAny { + google.protobuf.Any value = 1; + repeated google.protobuf.Any repeated_value = 2; +} + +message TestValue { + google.protobuf.Value value = 1; + repeated google.protobuf.Value repeated_value = 2; +} + +message TestListValue { + google.protobuf.ListValue value = 1; + repeated google.protobuf.ListValue repeated_value = 2; +} diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc new file mode 100644 index 00000000..6cd40fd5 --- /dev/null +++ b/src/google/protobuf/util/json_util.cc @@ -0,0 +1,142 @@ +// 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { + +namespace internal { +void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) { + while (len > 0) { + void* buffer; + int length; + if (!stream_->Next(&buffer, &length)) { + // There isn't a way for ByteSink to report errors. + return; + } + if (len < length) { + memcpy(buffer, bytes, len); + stream_->BackUp(length - len); + break; + } else { + memcpy(buffer, bytes, length); + bytes += length; + len -= length; + } + } +} +} // namespace internal + +util::Status BinaryToJsonStream(TypeResolver* resolver, + const string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output, + const JsonOptions& options) { + io::CodedInputStream in_stream(binary_input); + google::protobuf::Type type; + RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); + converter::ProtoStreamObjectSource proto_source(&in_stream, resolver, type); + io::CodedOutputStream out_stream(json_output); + converter::JsonObjectWriter json_writer(options.add_whitespace ? " " : "", + &out_stream); + converter::Snake2CamelObjectWriter snake2camel_writer(&json_writer); + if (options.always_print_primitive_fields) { + converter::DefaultValueObjectWriter default_value_writer( + resolver, type, &snake2camel_writer); + return proto_source.WriteTo(&default_value_writer); + } else { + return proto_source.WriteTo(&snake2camel_writer); + } +} + +util::Status BinaryToJsonString(TypeResolver* resolver, + const string& type_url, + const string& binary_input, + string* json_output, + const JsonOptions& options) { + io::ArrayInputStream input_stream(binary_input.data(), binary_input.size()); + io::StringOutputStream output_stream(json_output); + return BinaryToJsonStream(resolver, type_url, &input_stream, &output_stream, + options); +} + +util::Status JsonToBinaryStream(TypeResolver* resolver, + const string& type_url, + io::ZeroCopyInputStream* json_input, + io::ZeroCopyOutputStream* binary_output) { + google::protobuf::Type type; + RETURN_IF_ERROR(resolver->ResolveMessageType(type_url, &type)); + internal::ZeroCopyStreamByteSink sink(binary_output); + converter::NoopErrorListener listener; + converter::ProtoStreamObjectWriter proto_writer(resolver, type, &sink, + &listener); + + converter::JsonStreamParser parser(&proto_writer); + const void* buffer; + int length; + while (json_input->Next(&buffer, &length)) { + if (length == 0) continue; + RETURN_IF_ERROR( + parser.Parse(StringPiece(static_cast(buffer), length))); + } + RETURN_IF_ERROR(parser.FinishParse()); + + return util::Status::OK; +} + +util::Status JsonToBinaryString(TypeResolver* resolver, + const string& type_url, + const string& json_input, + string* binary_output) { + io::ArrayInputStream input_stream(json_input.data(), json_input.size()); + io::StringOutputStream output_stream(binary_output); + return JsonToBinaryStream(resolver, type_url, &input_stream, &output_stream); +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h new file mode 100644 index 00000000..86594487 --- /dev/null +++ b/src/google/protobuf/util/json_util.h @@ -0,0 +1,132 @@ +// 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. + +// Utility functions to convert between protobuf binary format and proto3 JSON +// format. +#ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ +#define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ + +#include +#include + +namespace google { +namespace protobuf { +namespace io { +class ZeroCopyInputStream; +class ZeroCopyOutputStream; +} // namespace io +namespace util { + +struct JsonOptions { + // Whether to add spaces, line breaks and indentation to make the JSON output + // easy to read. + bool add_whitespace; + // Whether to always print primitive fields. By default primitive fields with + // default values will be omitted in JSON joutput. For example, an int32 field + // set to 0 will be omitted. Set this flag to true will override the default + // behavior and print primitive fields regardless of their values. + bool always_print_primitive_fields; + + JsonOptions() : add_whitespace(false), + always_print_primitive_fields(false) { + } +}; + +// Converts protobuf binary data to JSON. +// The conversion will fail if: +// 1. TypeResolver fails to resolve a type. +// 2. input is not valid protobuf wire format, or conflicts with the type +// information returned by TypeResolver. +// Note that unknown fields will be discarded silently. +util::Status BinaryToJsonStream(TypeResolver* resolver, + const string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output, + const JsonOptions& options); + +inline util::Status BinaryToJsonStream( + TypeResolver* resolver, const string& type_url, + io::ZeroCopyInputStream* binary_input, + io::ZeroCopyOutputStream* json_output) { + return BinaryToJsonStream(resolver, type_url, binary_input, json_output, + JsonOptions()); +} + +util::Status BinaryToJsonString(TypeResolver* resolver, + const string& type_url, + const string& binary_input, + string* json_output, + const JsonOptions& options); + +inline util::Status BinaryToJsonString(TypeResolver* resolver, + const string& type_url, + const string& binary_input, + string* json_output) { + return BinaryToJsonString(resolver, type_url, binary_input, json_output, + JsonOptions()); +} + +// Converts JSON data to protobuf binary format. +// The conversion will fail if: +// 1. TypeResolver fails to resolve a type. +// 2. input is not valid JSON format, or conflicts with the type +// information returned by TypeResolver. +// 3. input has unknown fields. +util::Status JsonToBinaryStream(TypeResolver* resolver, + const string& type_url, + io::ZeroCopyInputStream* json_input, + io::ZeroCopyOutputStream* binary_output); + +util::Status JsonToBinaryString(TypeResolver* resolver, + const string& type_url, + const string& json_input, + string* binary_output); + +namespace internal { +// Internal helper class. Put in the header so we can write unit-tests for it. +class LIBPROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink { + public: + explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream) + : stream_(stream) {} + + virtual void Append(const char* bytes, size_t len); + + private: + io::ZeroCopyOutputStream* stream_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink); +}; +} // namespace internal + +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc new file mode 100644 index 00000000..8399b408 --- /dev/null +++ b/src/google/protobuf/util/json_util_test.cc @@ -0,0 +1,277 @@ +// 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 + +#include +#include + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace { + +using proto3::FOO; +using proto3::BAR; +using proto3::TestMessage; + +static const char kTypeUrlPrefix[] = "type.googleapis.com"; + +static string GetTypeUrl(const Descriptor* message) { + return string(kTypeUrlPrefix) + "/" + message->full_name(); +} + +// As functions defined in json_util.h are just thin wrappers around the +// JSON conversion code in //net/proto2/util/converter, in this test we +// only cover some very basic cases to make sure the wrappers have forwarded +// parameters to the underlying implementation correctly. More detailed +// tests are contained in the //net/proto2/util/converter directory. +class JsonUtilTest : public testing::Test { + protected: + JsonUtilTest() { + resolver_.reset(NewTypeResolverForDescriptorPool( + kTypeUrlPrefix, DescriptorPool::generated_pool())); + } + + string ToJson(const Message& message, const JsonOptions& options) { + string result; + GOOGLE_CHECK_OK(BinaryToJsonString(resolver_.get(), + GetTypeUrl(message.GetDescriptor()), + message.SerializeAsString(), &result, options)); + return result; + } + + bool FromJson(const string& json, Message* message) { + string binary; + GOOGLE_CHECK_OK(JsonToBinaryString( + resolver_.get(), GetTypeUrl(message->GetDescriptor()), json, &binary)); + return message->ParseFromString(binary); + } + + google::protobuf::scoped_ptr resolver_; +}; + +TEST_F(JsonUtilTest, TestWhitespaces) { + TestMessage m; + m.mutable_message_value(); + + JsonOptions options; + EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options)); + options.add_whitespace = true; + EXPECT_EQ( + "{\n" + " \"messageValue\": {}\n" + "}\n", + ToJson(m, options)); +} + +TEST_F(JsonUtilTest, TestDefaultValues) { + TestMessage m; + JsonOptions options; + EXPECT_EQ("{}", ToJson(m, options)); + options.always_print_primitive_fields = true; + EXPECT_EQ( + "{\"boolValue\":false," + "\"int32Value\":0," + "\"int64Value\":\"0\"," + "\"uint32Value\":0," + "\"uint64Value\":\"0\"," + "\"floatValue\":0," + "\"doubleValue\":0," + "\"stringValue\":\"\"," + "\"bytesValue\":\"\"," + // TODO(xiaofeng): The default enum value should be FOO. I believe + // this is a bug in DefaultValueObjectWriter. + "\"enumValue\":null" + "}", + ToJson(m, options)); +} + +TEST_F(JsonUtilTest, ParseMessage) { + // Some random message but good enough to verify that the parsing warpper + // functions are working properly. + string input = + "{\n" + " \"int32Value\": 1024,\n" + " \"repeatedInt32Value\": [1, 2],\n" + " \"messageValue\": {\n" + " \"value\": 2048\n" + " },\n" + " \"repeatedMessageValue\": [\n" + " {\"value\": 40}, {\"value\": 96}\n" + " ]\n" + "}\n"; + TestMessage m; + ASSERT_TRUE(FromJson(input, &m)); + EXPECT_EQ(1024, m.int32_value()); + ASSERT_EQ(2, m.repeated_int32_value_size()); + EXPECT_EQ(1, m.repeated_int32_value(0)); + EXPECT_EQ(2, m.repeated_int32_value(1)); + EXPECT_EQ(2048, m.message_value().value()); + ASSERT_EQ(2, m.repeated_message_value_size()); + EXPECT_EQ(40, m.repeated_message_value(0).value()); + EXPECT_EQ(96, m.repeated_message_value(1).value()); +} + +typedef pair Segment; +// A ZeroCopyOutputStream that writes to multiple buffers. +class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream { + public: + explicit SegmentedZeroCopyOutputStream(list segments) + : segments_(segments), last_segment_(NULL, 0), byte_count_(0) {} + + virtual bool Next(void** buffer, int* length) { + if (segments_.empty()) { + return false; + } + last_segment_ = segments_.front(); + segments_.pop_front(); + *buffer = last_segment_.first; + *length = last_segment_.second; + byte_count_ += *length; + return true; + } + + virtual void BackUp(int length) { + GOOGLE_CHECK(length <= last_segment_.second); + segments_.push_front( + Segment(last_segment_.first + last_segment_.second - length, length)); + last_segment_ = Segment(last_segment_.first, last_segment_.second - length); + byte_count_ -= length; + } + + virtual int64 ByteCount() const { return byte_count_; } + + private: + list segments_; + Segment last_segment_; + int64 byte_count_; +}; + +// This test splits the output buffer and also the input data into multiple +// segments and checks that the implementation of ZeroCopyStreamByteSink +// handles all possible cases correctly. +TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) { + static const int kOutputBufferLength = 10; + // An exhaustive test takes too long, skip some combinations to make the test + // run faster. + static const int kSkippedPatternCount = 7; + + char buffer[kOutputBufferLength]; + for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1)); + split_pattern += kSkippedPatternCount) { + // Split the buffer into small segments according to the split_pattern. + list segments; + int segment_start = 0; + for (int i = 0; i < kOutputBufferLength - 1; ++i) { + if (split_pattern & (1 << i)) { + segments.push_back( + Segment(buffer + segment_start, i - segment_start + 1)); + segment_start = i + 1; + } + } + segments.push_back( + Segment(buffer + segment_start, kOutputBufferLength - segment_start)); + + // Write exactly 10 bytes through the ByteSink. + string input_data = "0123456789"; + for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1)); + input_pattern += kSkippedPatternCount) { + memset(buffer, 0, sizeof(buffer)); + { + SegmentedZeroCopyOutputStream output_stream(segments); + internal::ZeroCopyStreamByteSink byte_sink(&output_stream); + int start = 0; + for (int j = 0; j < input_data.length() - 1; ++j) { + if (input_pattern & (1 << j)) { + byte_sink.Append(&input_data[start], j - start + 1); + start = j + 1; + } + } + byte_sink.Append(&input_data[start], input_data.length() - start); + } + EXPECT_EQ(input_data, string(buffer, input_data.length())); + } + + // Write only 9 bytes through the ByteSink. + input_data = "012345678"; + for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1)); + input_pattern += kSkippedPatternCount) { + memset(buffer, 0, sizeof(buffer)); + { + SegmentedZeroCopyOutputStream output_stream(segments); + internal::ZeroCopyStreamByteSink byte_sink(&output_stream); + int start = 0; + for (int j = 0; j < input_data.length() - 1; ++j) { + if (input_pattern & (1 << j)) { + byte_sink.Append(&input_data[start], j - start + 1); + start = j + 1; + } + } + byte_sink.Append(&input_data[start], input_data.length() - start); + } + EXPECT_EQ(input_data, string(buffer, input_data.length())); + EXPECT_EQ(0, buffer[input_data.length()]); + } + + // Write 11 bytes through the ByteSink. The extra byte will just + // be ignored. + input_data = "0123456789A"; + for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1)); + input_pattern += kSkippedPatternCount) { + memset(buffer, 0, sizeof(buffer)); + { + SegmentedZeroCopyOutputStream output_stream(segments); + internal::ZeroCopyStreamByteSink byte_sink(&output_stream); + int start = 0; + for (int j = 0; j < input_data.length() - 1; ++j) { + if (input_pattern & (1 << j)) { + byte_sink.Append(&input_data[start], j - start + 1); + start = j + 1; + } + } + byte_sink.Append(&input_data[start], input_data.length() - start); + } + EXPECT_EQ(input_data.substr(0, kOutputBufferLength), + string(buffer, kOutputBufferLength)); + } + } +} + +} // namespace +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc new file mode 100644 index 00000000..50485633 --- /dev/null +++ b/src/google/protobuf/util/message_differencer.cc @@ -0,0 +1,1629 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file defines static methods and classes for comparing Protocol +// Messages (see //google/protobuf/util/message_differencer.h for more +// information). + +#include + +#include +#include +#ifndef _SHARED_PTR_H +#include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace util { + +// When comparing a repeated field as map, MultipleFieldMapKeyComparator can +// be used to specify multiple fields as key for key comparison. +// Two elements of a repeated field will be regarded as having the same key +// iff they have the same value for every specified key field. +// Note that you can also specify only one field as key. +class MessageDifferencer::MultipleFieldsMapKeyComparator + : public MessageDifferencer::MapKeyComparator { + public: + MultipleFieldsMapKeyComparator( + MessageDifferencer* message_differencer, + const vector >& key_field_paths) + : message_differencer_(message_differencer), + key_field_paths_(key_field_paths) { + GOOGLE_CHECK(!key_field_paths_.empty()); + for (int i = 0; i < key_field_paths_.size(); ++i) { + GOOGLE_CHECK(!key_field_paths_[i].empty()); + } + } + MultipleFieldsMapKeyComparator( + MessageDifferencer* message_differencer, + const FieldDescriptor* key) + : message_differencer_(message_differencer) { + vector key_field_path; + key_field_path.push_back(key); + key_field_paths_.push_back(key_field_path); + } + bool IsMatch( + const Message& message1, + const Message& message2, + const vector& parent_fields) const override { + for (int i = 0; i < key_field_paths_.size(); ++i) { + if (!IsMatchInternal(message1, message2, parent_fields, + key_field_paths_[i], 0)) { + return false; + } + } + return true; + } + private: + bool IsMatchInternal( + const Message& message1, + const Message& message2, + const vector& parent_fields, + const vector& key_field_path, + int path_index) const { + const FieldDescriptor* field = key_field_path[path_index]; + vector current_parent_fields(parent_fields); + if (path_index == key_field_path.size() - 1) { + if (field->is_repeated()) { + if (!message_differencer_->CompareRepeatedField( + message1, message2, field, ¤t_parent_fields)) { + return false; + } + } else { + if (!message_differencer_->CompareFieldValueUsingParentFields( + message1, message2, field, -1, -1, ¤t_parent_fields)) { + return false; + } + } + return true; + } else { + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + bool has_field1 = reflection1->HasField(message1, field); + bool has_field2 = reflection2->HasField(message2, field); + if (!has_field1 && !has_field2) { + return true; + } + if (has_field1 != has_field2) { + return false; + } + SpecificField specific_field; + specific_field.field = field; + current_parent_fields.push_back(specific_field); + return IsMatchInternal( + reflection1->GetMessage(message1, field), + reflection2->GetMessage(message2, field), + current_parent_fields, + key_field_path, + path_index + 1); + } + } + MessageDifferencer* message_differencer_; + vector > key_field_paths_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator); +}; + +bool MessageDifferencer::Equals(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::Equivalent(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT); + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::ApproximatelyEquals(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_float_comparison( + MessageDifferencer::APPROXIMATE); + + return differencer.Compare(message1, message2); +} + +bool MessageDifferencer::ApproximatelyEquivalent(const Message& message1, + const Message& message2) { + MessageDifferencer differencer; + differencer.set_message_field_comparison(MessageDifferencer::EQUIVALENT); + differencer.set_float_comparison(MessageDifferencer::APPROXIMATE); + + return differencer.Compare(message1, message2); +} + +// =========================================================================== + +MessageDifferencer::MessageDifferencer() + : reporter_(NULL), + field_comparator_(NULL), + message_field_comparison_(EQUAL), + scope_(FULL), + repeated_field_comparison_(AS_LIST), + report_matches_(false), + output_string_(NULL) { } + +MessageDifferencer::~MessageDifferencer() { + for (int i = 0; i < owned_key_comparators_.size(); ++i) { + delete owned_key_comparators_[i]; + } + for (int i = 0; i < ignore_criteria_.size(); ++i) { + delete ignore_criteria_[i]; + } +} + +void MessageDifferencer::set_field_comparator(FieldComparator* comparator) { + GOOGLE_CHECK(comparator) << "Field comparator can't be NULL."; + field_comparator_ = comparator; +} + +void MessageDifferencer::set_message_field_comparison( + MessageFieldComparison comparison) { + message_field_comparison_ = comparison; +} + +void MessageDifferencer::set_scope(Scope scope) { + scope_ = scope; +} + +MessageDifferencer::Scope MessageDifferencer::scope() { + return scope_; +} + +void MessageDifferencer::set_float_comparison(FloatComparison comparison) { + default_field_comparator_.set_float_comparison( + comparison == EXACT ? + DefaultFieldComparator::EXACT : DefaultFieldComparator::APPROXIMATE); +} + +void MessageDifferencer::set_repeated_field_comparison( + RepeatedFieldComparison comparison) { + repeated_field_comparison_ = comparison; +} + +void MessageDifferencer::TreatAsSet(const FieldDescriptor* field) { + GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " + << field->full_name(); + const MapKeyComparator* key_comparator = GetMapKeyComparator(field); + GOOGLE_CHECK(key_comparator == NULL) + << "Cannot treat this repeated field as both Map and Set for" + << " comparison. Field name is: " << field->full_name(); + set_fields_.insert(field); +} + +void MessageDifferencer::TreatAsMap(const FieldDescriptor* field, + const FieldDescriptor* key) { + GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " + << field->full_name(); + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) + << "Field has to be message type. Field name is: " + << field->full_name(); + GOOGLE_CHECK(key->containing_type() == field->message_type()) + << key->full_name() + << " must be a direct subfield within the repeated field " + << field->full_name() << ", not " << key->containing_type()->full_name(); + GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end()) + << "Cannot treat this repeated field as both Map and Set for " + << "comparison."; + MapKeyComparator* key_comparator = + new MultipleFieldsMapKeyComparator(this, key); + owned_key_comparators_.push_back(key_comparator); + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::TreatAsMapWithMultipleFieldsAsKey( + const FieldDescriptor* field, + const vector& key_fields) { + vector > key_field_paths; + for (int i = 0; i < key_fields.size(); ++i) { + vector key_field_path; + key_field_path.push_back(key_fields[i]); + key_field_paths.push_back(key_field_path); + } + TreatAsMapWithMultipleFieldPathsAsKey(field, key_field_paths); +} + +void MessageDifferencer::TreatAsMapWithMultipleFieldPathsAsKey( + const FieldDescriptor* field, + const vector >& key_field_paths) { + GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " + << field->full_name(); + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) + << "Field has to be message type. Field name is: " + << field->full_name(); + for (int i = 0; i < key_field_paths.size(); ++i) { + const vector& key_field_path = key_field_paths[i]; + for (int j = 0; j < key_field_path.size(); ++j) { + const FieldDescriptor* parent_field = + j == 0 ? field : key_field_path[j - 1]; + const FieldDescriptor* child_field = key_field_path[j]; + GOOGLE_CHECK(child_field->containing_type() == parent_field->message_type()) + << child_field->full_name() + << " must be a direct subfield within the field: " + << parent_field->full_name(); + if (j != 0) { + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, parent_field->cpp_type()) + << parent_field->full_name() << " has to be of type message."; + GOOGLE_CHECK(!parent_field->is_repeated()) + << parent_field->full_name() << " cannot be a repeated field."; + } + } + } + GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end()) + << "Cannot treat this repeated field as both Map and Set for " + << "comparison."; + MapKeyComparator* key_comparator = + new MultipleFieldsMapKeyComparator(this, key_field_paths); + owned_key_comparators_.push_back(key_comparator); + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::TreatAsMapUsingKeyComparator( + const FieldDescriptor* field, + const MapKeyComparator* key_comparator) { + GOOGLE_CHECK(field->is_repeated()) << "Field must be repeated: " + << field->full_name(); + GOOGLE_CHECK_EQ(FieldDescriptor::CPPTYPE_MESSAGE, field->cpp_type()) + << "Field has to be message type. Field name is: " + << field->full_name(); + GOOGLE_CHECK(set_fields_.find(field) == set_fields_.end()) + << "Cannot treat this repeated field as both Map and Set for " + << "comparison."; + map_field_key_comparator_[field] = key_comparator; +} + +void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) { + ignore_criteria_.push_back(ignore_criteria); +} + +void MessageDifferencer::IgnoreField(const FieldDescriptor* field) { + ignored_fields_.insert(field); +} + +void MessageDifferencer::SetFractionAndMargin(const FieldDescriptor* field, + double fraction, double margin) { + default_field_comparator_.SetFractionAndMargin(field, fraction, margin); +} + +void MessageDifferencer::ReportDifferencesToString(string* output) { + GOOGLE_DCHECK(output) << "Specified output string was NULL"; + + output_string_ = output; + output_string_->clear(); +} + +void MessageDifferencer::ReportDifferencesTo(Reporter* reporter) { + // If an output string is set, clear it to prevent + // it superceding the specified reporter. + if (output_string_) { + output_string_ = NULL; + } + + reporter_ = reporter; +} + +bool MessageDifferencer::FieldBefore(const FieldDescriptor* field1, + const FieldDescriptor* field2) { + // Handle sentinel values (i.e. make sure NULLs are always ordered + // at the end of the list). + if (field1 == NULL) { + return false; + } + + if (field2 == NULL) { + return true; + } + + // Always order fields by their tag number + return (field1->number() < field2->number()); +} + +bool MessageDifferencer::Compare(const Message& message1, + const Message& message2) { + vector parent_fields; + + bool result = false; + + // Setup the internal reporter if need be. + if (output_string_) { + io::StringOutputStream output_stream(output_string_); + StreamReporter reporter(&output_stream); + reporter_ = &reporter; + result = Compare(message1, message2, &parent_fields); + reporter_ = NULL; + } else { + result = Compare(message1, message2, &parent_fields); + } + + return result; +} + +bool MessageDifferencer::CompareWithFields( + const Message& message1, + const Message& message2, + const vector& message1_fields_arg, + const vector& message2_fields_arg) { + if (message1.GetDescriptor() != message2.GetDescriptor()) { + GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " + << "descriptors."; + return false; + } + + vector parent_fields; + + bool result = false; + + vector message1_fields(message1_fields_arg); + vector message2_fields(message2_fields_arg); + + std::sort(message1_fields.begin(), message1_fields.end(), FieldBefore); + std::sort(message2_fields.begin(), message2_fields.end(), FieldBefore); + // Append NULL sentinel values. + message1_fields.push_back(NULL); + message2_fields.push_back(NULL); + + // Setup the internal reporter if need be. + if (output_string_) { + io::StringOutputStream output_stream(output_string_); + StreamReporter reporter(&output_stream); + reporter_ = &reporter; + result = CompareRequestedFieldsUsingSettings( + message1, message2, message1_fields, message2_fields, &parent_fields); + reporter_ = NULL; + } else { + result = CompareRequestedFieldsUsingSettings( + message1, message2, message1_fields, message2_fields, &parent_fields); + } + + return result; +} + +bool MessageDifferencer::Compare( + const Message& message1, + const Message& message2, + vector* parent_fields) { + const Descriptor* descriptor1 = message1.GetDescriptor(); + const Descriptor* descriptor2 = message2.GetDescriptor(); + if (descriptor1 != descriptor2) { + GOOGLE_LOG(DFATAL) << "Comparison between two messages with different " + << "descriptors."; + return false; + } + // Expand google.protobuf.Any payload if possible. + if (descriptor1->full_name() == internal::kAnyFullTypeName) { + google::protobuf::scoped_ptr data1; + google::protobuf::scoped_ptr data2; + if (UnpackAny(message1, &data1) && UnpackAny(message2, &data2)) { + return Compare(*data1, *data2, parent_fields); + } + } + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + + // Retrieve all the set fields, including extensions. + vector message1_fields; + vector message2_fields; + + reflection1->ListFields(message1, &message1_fields); + reflection2->ListFields(message2, &message2_fields); + + // Add sentinel values to deal with the + // case where the number of the fields in + // each list are different. + message1_fields.push_back(NULL); + message2_fields.push_back(NULL); + + bool unknown_compare_result = true; + // Ignore unknown fields in EQUIVALENT mode + if (message_field_comparison_ != EQUIVALENT) { + const google::protobuf::UnknownFieldSet* unknown_field_set1 = + &reflection1->GetUnknownFields(message1); + const google::protobuf::UnknownFieldSet* unknown_field_set2 = + &reflection2->GetUnknownFields(message2); + if (!CompareUnknownFields(message1, message2, + *unknown_field_set1, *unknown_field_set2, + parent_fields)) { + if (reporter_ == NULL) { + return false; + }; + unknown_compare_result = false; + } + } + + return CompareRequestedFieldsUsingSettings( + message1, message2, + message1_fields, message2_fields, + parent_fields) && unknown_compare_result; +} + +bool MessageDifferencer::CompareRequestedFieldsUsingSettings( + const Message& message1, + const Message& message2, + const vector& message1_fields, + const vector& message2_fields, + vector* parent_fields) { + if (scope_ == FULL) { + if (message_field_comparison_ == EQUIVALENT) { + // We need to merge the field lists of both messages (i.e. + // we are merely checking for a difference in field values, + // rather than the addition or deletion of fields). + vector fields_union; + CombineFields(message1_fields, FULL, message2_fields, FULL, + &fields_union); + return CompareWithFieldsInternal(message1, message2, fields_union, + fields_union, parent_fields); + } else { + // Simple equality comparison, use the unaltered field lists. + return CompareWithFieldsInternal(message1, message2, message1_fields, + message2_fields, parent_fields); + } + } else { + if (message_field_comparison_ == EQUIVALENT) { + // We use the list of fields for message1 for both messages when + // comparing. This way, extra fields in message2 are ignored, + // and missing fields in message2 use their default value. + return CompareWithFieldsInternal(message1, message2, message1_fields, + message1_fields, parent_fields); + } else { + // We need to consider the full list of fields for message1 + // but only the intersection for message2. This way, any fields + // only present in message2 will be ignored, but any fields only + // present in message1 will be marked as a difference. + vector fields_intersection; + CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL, + &fields_intersection); + return CompareWithFieldsInternal(message1, message2, message1_fields, + fields_intersection, parent_fields); + } + } +} + +void MessageDifferencer::CombineFields( + const vector& fields1, + Scope fields1_scope, + const vector& fields2, + Scope fields2_scope, + vector* combined_fields) { + + int index1 = 0; + int index2 = 0; + + while (index1 < fields1.size() && index2 < fields2.size()) { + const FieldDescriptor* field1 = fields1[index1]; + const FieldDescriptor* field2 = fields2[index2]; + + if (FieldBefore(field1, field2)) { + if (fields1_scope == FULL) { + combined_fields->push_back(fields1[index1]); + } + ++index1; + } else if (FieldBefore(field2, field1)) { + if (fields2_scope == FULL) { + combined_fields->push_back(fields2[index2]); + } + ++index2; + } else { + combined_fields->push_back(fields1[index1]); + ++index1; + ++index2; + } + } +} + +bool MessageDifferencer::CompareWithFieldsInternal( + const Message& message1, + const Message& message2, + const vector& message1_fields, + const vector& message2_fields, + vector* parent_fields) { + bool isDifferent = false; + int field_index1 = 0; + int field_index2 = 0; + + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + + while (true) { + const FieldDescriptor* field1 = message1_fields[field_index1]; + const FieldDescriptor* field2 = message2_fields[field_index2]; + + // Once we have reached sentinel values, we are done the comparison. + if (field1 == NULL && field2 == NULL) { + break; + } + + // Check for differences in the field itself. + if (FieldBefore(field1, field2)) { + // Field 1 is not in the field list for message 2. + if (IsIgnored(message1, message2, field1, *parent_fields)) { + // We are ignoring field1. Report the ignore and move on to + // the next field in message1_fields. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field1; + + parent_fields->push_back(specific_field); + reporter_->ReportIgnored(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + ++field_index1; + continue; + } + + if (reporter_ != NULL) { + int count = field1->is_repeated() ? + reflection1->FieldSize(message1, field1) : 1; + + for (int i = 0; i < count; ++i) { + SpecificField specific_field; + specific_field.field = field1; + specific_field.index = field1->is_repeated() ? i : -1; + + parent_fields->push_back(specific_field); + reporter_->ReportDeleted(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + isDifferent = true; + } else { + return false; + } + + ++field_index1; + continue; + } else if (FieldBefore(field2, field1)) { + // Field 2 is not in the field list for message 1. + if (IsIgnored(message1, message2, field2, *parent_fields)) { + // We are ignoring field2. Report the ignore and move on to + // the next field in message2_fields. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field2; + + parent_fields->push_back(specific_field); + reporter_->ReportIgnored(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + ++field_index2; + continue; + } + + if (reporter_ != NULL) { + int count = field2->is_repeated() ? + reflection2->FieldSize(message2, field2) : 1; + + for (int i = 0; i < count; ++i) { + SpecificField specific_field; + specific_field.field = field2; + specific_field.index = field2->is_repeated() ? i : -1; + specific_field.new_index = specific_field.index; + + parent_fields->push_back(specific_field); + reporter_->ReportAdded(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + isDifferent = true; + } else { + return false; + } + + ++field_index2; + continue; + } + + // By this point, field1 and field2 are guarenteed to point to the same + // field, so we can now compare the values. + if (IsIgnored(message1, message2, field1, *parent_fields)) { + // Ignore this field. Report and move on. + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field1; + + parent_fields->push_back(specific_field); + reporter_->ReportIgnored(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + ++field_index1; + ++field_index2; + continue; + } + + bool fieldDifferent = false; + if (field1->is_repeated()) { + fieldDifferent = !CompareRepeatedField(message1, message2, field1, + parent_fields); + if (fieldDifferent) { + if (reporter_ == NULL) return false; + isDifferent = true; + } + } else { + fieldDifferent = !CompareFieldValueUsingParentFields( + message1, message2, field1, -1, -1, parent_fields); + + // If we have found differences, either report them or terminate if + // no reporter is present. + if (fieldDifferent && reporter_ == NULL) { + return false; + } + + if (reporter_ != NULL) { + SpecificField specific_field; + specific_field.field = field1; + parent_fields->push_back(specific_field); + if (fieldDifferent) { + reporter_->ReportModified(message1, message2, *parent_fields); + isDifferent = true; + } else if (report_matches_) { + reporter_->ReportMatched(message1, message2, *parent_fields); + } + parent_fields->pop_back(); + } + } + // Increment the field indicies. + ++field_index1; + ++field_index2; + } + + return !isDifferent; +} + +bool MessageDifferencer::IsMatch(const FieldDescriptor* repeated_field, + const MapKeyComparator* key_comparator, + const Message* message1, + const Message* message2, + const vector& parent_fields, + int index1, int index2) { + vector current_parent_fields(parent_fields); + if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + return CompareFieldValueUsingParentFields( + *message1, *message2, repeated_field, index1, index2, + ¤t_parent_fields); + } + // Back up the Reporter and output_string_. They will be reset in the + // following code. + Reporter* backup_reporter = reporter_; + string* output_string = output_string_; + reporter_ = NULL; + output_string_ = NULL; + bool match; + + if (key_comparator == NULL) { + match = CompareFieldValueUsingParentFields( + *message1, *message2, repeated_field, index1, index2, + ¤t_parent_fields); + } else { + const Reflection* reflection1 = message1->GetReflection(); + const Reflection* reflection2 = message2->GetReflection(); + const Message& m1 = + reflection1->GetRepeatedMessage(*message1, repeated_field, index1); + const Message& m2 = + reflection2->GetRepeatedMessage(*message2, repeated_field, index2); + SpecificField specific_field; + specific_field.field = repeated_field; + current_parent_fields.push_back(specific_field); + match = key_comparator->IsMatch(m1, m2, current_parent_fields); + } + + reporter_ = backup_reporter; + output_string_ = output_string; + return match; +} + +bool MessageDifferencer::CompareRepeatedField( + const Message& message1, + const Message& message2, + const FieldDescriptor* repeated_field, + vector* parent_fields) { + // the input FieldDescriptor is guaranteed to be repeated field. + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + const int count1 = reflection1->FieldSize(message1, repeated_field); + const int count2 = reflection2->FieldSize(message2, repeated_field); + const bool treated_as_subset = IsTreatedAsSubset(repeated_field); + + // If the field is not treated as subset and no detailed reports is needed, + // we do a quick check on the number of the elements to avoid unnecessary + // comparison. + if (count1 != count2 && reporter_ == NULL && !treated_as_subset) { + return false; + } + // A match can never be found if message1 has more items than message2. + if (count1 > count2 && reporter_ == NULL) { + return false; + } + + // These two list are used for store the index of the correspondent + // element in peer repeated field. + vector match_list1; + vector match_list2; + + // Try to match indices of the repeated fields. Return false if match fails + // and there's no detailed report needed. + if (!MatchRepeatedFieldIndices(message1, message2, repeated_field, + *parent_fields, &match_list1, &match_list2) && + reporter_ == NULL) { + return false; + } + + bool fieldDifferent = false; + SpecificField specific_field; + specific_field.field = repeated_field; + + // At this point, we have already matched pairs of fields (with the reporting + // to be done later). Now to check if the paired elements are different. + for (int i = 0; i < count1; i++) { + if (match_list1[i] == -1) continue; + specific_field.index = i; + specific_field.new_index = match_list1[i]; + + const bool result = CompareFieldValueUsingParentFields( + message1, message2, repeated_field, i, specific_field.new_index, + parent_fields); + + // If we have found differences, either report them or terminate if + // no reporter is present. Note that ReportModified, ReportMoved, and + // ReportMatched are all mutually exclusive. + if (!result) { + if (reporter_ == NULL) return false; + parent_fields->push_back(specific_field); + reporter_->ReportModified(message1, message2, *parent_fields); + parent_fields->pop_back(); + fieldDifferent = true; + } else if (reporter_ != NULL && + specific_field.index != specific_field.new_index) { + parent_fields->push_back(specific_field); + reporter_->ReportMoved(message1, message2, *parent_fields); + parent_fields->pop_back(); + } else if (report_matches_ && reporter_ != NULL) { + parent_fields->push_back(specific_field); + reporter_->ReportMatched(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + } + + // Report any remaining additions or deletions. + for (int i = 0; i < count2; ++i) { + if (match_list2[i] != -1) continue; + if (!treated_as_subset) { + fieldDifferent = true; + } + + if (reporter_ == NULL) continue; + specific_field.index = i; + specific_field.new_index = i; + parent_fields->push_back(specific_field); + reporter_->ReportAdded(message1, message2, *parent_fields); + parent_fields->pop_back(); + } + + for (int i = 0; i < count1; ++i) { + if (match_list1[i] != -1) continue; + specific_field.index = i; + parent_fields->push_back(specific_field); + reporter_->ReportDeleted(message1, message2, *parent_fields); + parent_fields->pop_back(); + fieldDifferent = true; + } + return !fieldDifferent; +} + +bool MessageDifferencer::CompareFieldValue(const Message& message1, + const Message& message2, + const FieldDescriptor* field, + int index1, + int index2) { + return CompareFieldValueUsingParentFields(message1, message2, field, index1, + index2, NULL); +} + +bool MessageDifferencer::CompareFieldValueUsingParentFields( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + vector* parent_fields) { + FieldContext field_context(parent_fields); + FieldComparator::ComparisonResult result = GetFieldComparisonResult( + message1, message2, field, index1, index2, &field_context); + + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + result == FieldComparator::RECURSE) { + // Get the nested messages and compare them using one of the Compare + // methods. + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + const Message& m1 = field->is_repeated() ? + reflection1->GetRepeatedMessage(message1, field, index1) : + reflection1->GetMessage(message1, field); + const Message& m2 = field->is_repeated() ? + reflection2->GetRepeatedMessage(message2, field, index2) : + reflection2->GetMessage(message2, field); + + // parent_fields is used in calls to Reporter methods. + if (parent_fields != NULL) { + // Append currently compared field to the end of parent_fields. + SpecificField specific_field; + specific_field.field = field; + specific_field.index = index1; + specific_field.new_index = index2; + parent_fields->push_back(specific_field); + const bool compare_result = Compare(m1, m2, parent_fields); + parent_fields->pop_back(); + return compare_result; + } else { + // Recreates parent_fields as if m1 and m2 had no parents. + return Compare(m1, m2); + } + } else { + return (result == FieldComparator::SAME); + } +} + +bool MessageDifferencer::CheckPathChanged( + const vector& field_path) { + for (int i = 0; i < field_path.size(); ++i) { + if (field_path[i].index != field_path[i].new_index) return true; + } + return false; +} + +bool MessageDifferencer::IsTreatedAsSet(const FieldDescriptor* field) { + if (!field->is_repeated()) return false; + if (field->is_map()) return true; + if (repeated_field_comparison_ == AS_SET) return true; + return (set_fields_.find(field) != set_fields_.end()); +} + +bool MessageDifferencer::IsTreatedAsSubset(const FieldDescriptor* field) { + return scope_ == PARTIAL && + (IsTreatedAsSet(field) || GetMapKeyComparator(field) != NULL); +} + +bool MessageDifferencer::IsIgnored( + const Message& message1, + const Message& message2, + const FieldDescriptor* field, + const vector& parent_fields) { + if (ignored_fields_.find(field) != ignored_fields_.end()) { + return true; + } + for (int i = 0; i < ignore_criteria_.size(); ++i) { + if (ignore_criteria_[i]->IsIgnored(message1, message2, field, + parent_fields)) { + return true; + } + } + return false; +} + +const MessageDifferencer::MapKeyComparator* MessageDifferencer + ::GetMapKeyComparator(const FieldDescriptor* field) { + if (!field->is_repeated()) return NULL; + if (map_field_key_comparator_.find(field) != + map_field_key_comparator_.end()) { + return map_field_key_comparator_[field]; + } + return NULL; +} + +namespace { + +typedef pair IndexUnknownFieldPair; + +struct UnknownFieldOrdering { + inline bool operator()(const IndexUnknownFieldPair& a, + const IndexUnknownFieldPair& b) const { + if (a.second->number() < b.second->number()) return true; + if (a.second->number() > b.second->number()) return false; + return a.second->type() < b.second->type(); + } +}; + +} // namespace + +bool MessageDifferencer::UnpackAny(const Message& any, + google::protobuf::scoped_ptr* data) { + const Reflection* reflection = any.GetReflection(); + const FieldDescriptor* type_url_field; + const FieldDescriptor* value_field; + if (!internal::GetAnyFieldDescriptors(any, &type_url_field, &value_field)) { + return false; + } + const string& type_url = reflection->GetString(any, type_url_field); + string full_type_name; + if (!internal::ParseAnyTypeUrl(type_url, &full_type_name)) { + return false; + } + + const google::protobuf::Descriptor* desc = + any.GetDescriptor()->file()->pool()->FindMessageTypeByName( + full_type_name); + if (desc == NULL) { + GOOGLE_LOG(ERROR) << "Proto type '" << full_type_name << "' not found"; + return false; + } + + if (dynamic_message_factory_ == NULL) { + dynamic_message_factory_.reset(new DynamicMessageFactory()); + } + data->reset(dynamic_message_factory_->GetPrototype(desc)->New()); + string serialized_value = reflection->GetString(any, value_field); + if (!(*data)->ParseFromString(serialized_value)) { + GOOGLE_LOG(ERROR) << "Failed to parse value for " << full_type_name; + return false; + } + return true; +} + +bool MessageDifferencer::CompareUnknownFields( + const Message& message1, const Message& message2, + const google::protobuf::UnknownFieldSet& unknown_field_set1, + const google::protobuf::UnknownFieldSet& unknown_field_set2, + vector* parent_field) { + // Ignore unknown fields in EQUIVALENT mode. + if (message_field_comparison_ == EQUIVALENT) return true; + + if (unknown_field_set1.empty() && unknown_field_set2.empty()) { + return true; + } + + bool is_different = false; + + // We first sort the unknown fields by field number and type (in other words, + // in tag order), making sure to preserve ordering of values with the same + // tag. This allows us to report only meaningful differences between the + // two sets -- that is, differing values for the same tag. We use + // IndexUnknownFieldPairs to keep track of the field's original index for + // reporting purposes. + vector fields1; // unknown_field_set1, sorted + vector fields2; // unknown_field_set2, sorted + fields1.reserve(unknown_field_set1.field_count()); + fields2.reserve(unknown_field_set2.field_count()); + + for (int i = 0; i < unknown_field_set1.field_count(); i++) { + fields1.push_back(std::make_pair(i, &unknown_field_set1.field(i))); + } + for (int i = 0; i < unknown_field_set2.field_count(); i++) { + fields2.push_back(std::make_pair(i, &unknown_field_set2.field(i))); + } + + UnknownFieldOrdering is_before; + std::stable_sort(fields1.begin(), fields1.end(), is_before); + std::stable_sort(fields2.begin(), fields2.end(), is_before); + + // In order to fill in SpecificField::index, we have to keep track of how + // many values we've seen with the same field number and type. + // current_repeated points at the first field in this range, and + // current_repeated_start{1,2} are the indexes of the first field in the + // range within fields1 and fields2. + const UnknownField* current_repeated = NULL; + int current_repeated_start1 = 0; + int current_repeated_start2 = 0; + + // Now that we have two sorted lists, we can detect fields which appear only + // in one list or the other by traversing them simultaneously. + int index1 = 0; + int index2 = 0; + while (index1 < fields1.size() || index2 < fields2.size()) { + enum { ADDITION, DELETION, MODIFICATION, COMPARE_GROUPS, + NO_CHANGE } change_type; + + // focus_field is the field we're currently reporting on. (In the case + // of a modification, it's the field on the left side.) + const UnknownField* focus_field; + bool match = false; + + if (index2 == fields2.size() || + (index1 < fields1.size() && + is_before(fields1[index1], fields2[index2]))) { + // fields1[index1] is not present in fields2. + change_type = DELETION; + focus_field = fields1[index1].second; + } else if (index1 == fields1.size() || + is_before(fields2[index2], fields1[index1])) { + // fields2[index2] is not present in fields1. + if (scope_ == PARTIAL) { + // Ignore. + ++index2; + continue; + } + change_type = ADDITION; + focus_field = fields2[index2].second; + } else { + // Field type and number are the same. See if the values differ. + change_type = MODIFICATION; + focus_field = fields1[index1].second; + + switch (focus_field->type()) { + case UnknownField::TYPE_VARINT: + match = fields1[index1].second->varint() == + fields2[index2].second->varint(); + break; + case UnknownField::TYPE_FIXED32: + match = fields1[index1].second->fixed32() == + fields2[index2].second->fixed32(); + break; + case UnknownField::TYPE_FIXED64: + match = fields1[index1].second->fixed64() == + fields2[index2].second->fixed64(); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + match = fields1[index1].second->length_delimited() == + fields2[index2].second->length_delimited(); + break; + case UnknownField::TYPE_GROUP: + // We must deal with this later, after building the SpecificField. + change_type = COMPARE_GROUPS; + break; + } + if (match && change_type != COMPARE_GROUPS) { + change_type = NO_CHANGE; + } + } + + if (current_repeated == NULL || + focus_field->number() != current_repeated->number() || + focus_field->type() != current_repeated->type()) { + // We've started a new repeated field. + current_repeated = focus_field; + current_repeated_start1 = index1; + current_repeated_start2 = index2; + } + + if (change_type == NO_CHANGE && reporter_ == NULL) { + // Fields were already compared and matched and we have no reporter. + ++index1; + ++index2; + continue; + } + + if (change_type == ADDITION || change_type == DELETION || + change_type == MODIFICATION) { + if (reporter_ == NULL) { + // We found a difference and we have no reproter. + return false; + } + is_different = true; + } + + // Build the SpecificField. This is slightly complicated. + SpecificField specific_field; + specific_field.unknown_field_number = focus_field->number(); + specific_field.unknown_field_type = focus_field->type(); + + specific_field.unknown_field_set1 = &unknown_field_set1; + specific_field.unknown_field_set2 = &unknown_field_set2; + + if (change_type != ADDITION) { + specific_field.unknown_field_index1 = fields1[index1].first; + } + if (change_type != DELETION) { + specific_field.unknown_field_index2 = fields2[index2].first; + } + + // Calculate the field index. + if (change_type == ADDITION) { + specific_field.index = index2 - current_repeated_start2; + specific_field.new_index = index2 - current_repeated_start2; + } else { + specific_field.index = index1 - current_repeated_start1; + specific_field.new_index = index2 - current_repeated_start2; + } + + parent_field->push_back(specific_field); + + switch (change_type) { + case ADDITION: + reporter_->ReportAdded(message1, message2, *parent_field); + ++index2; + break; + case DELETION: + reporter_->ReportDeleted(message1, message2, *parent_field); + ++index1; + break; + case MODIFICATION: + reporter_->ReportModified(message1, message2, *parent_field); + ++index1; + ++index2; + break; + case COMPARE_GROUPS: + if (!CompareUnknownFields(message1, message2, + fields1[index1].second->group(), + fields2[index2].second->group(), + parent_field)) { + if (reporter_ == NULL) return false; + is_different = true; + reporter_->ReportModified(message1, message2, *parent_field); + } + ++index1; + ++index2; + break; + case NO_CHANGE: + ++index1; + ++index2; + if (report_matches_) { + reporter_->ReportMatched(message1, message2, *parent_field); + } + } + + parent_field->pop_back(); + } + + return !is_different; +} + +namespace { + +// Find maximum bipartite matching using the argumenting path algorithm. +class MaximumMatcher { + public: + typedef ResultCallback2 NodeMatchCallback; + // MaximumMatcher takes ownership of the passed in callback and uses it to + // determine whether a node on the left side of the bipartial graph matches + // a node on the right side. count1 is the number of nodes on the left side + // of the graph and count2 to is the number of nodes on the right side. + // Every node is referred to using 0-based indices. + // If a maximum match is found, the result will be stored in match_list1 and + // match_list2. match_list1[i] == j means the i-th node on the left side is + // matched to the j-th node on the right side and match_list2[x] == y means + // the x-th node on the right side is matched to y-th node on the left side. + // match_list1[i] == -1 means the node is not matched. Same with match_list2. + MaximumMatcher(int count1, int count2, NodeMatchCallback* callback, + vector* match_list1, vector* match_list2); + // Find a maximum match and return the number of matched node pairs. + // If early_return is true, this method will return 0 immediately when it + // finds that not all nodes on the left side can be matched. + int FindMaximumMatch(bool early_return); + private: + // Determines whether the node on the left side of the bipartial graph + // matches the one on the right side. + bool Match(int left, int right); + // Find an argumenting path starting from the node v on the left side. If a + // path can be found, update match_list2_ to reflect the path and return + // true. + bool FindArgumentPathDFS(int v, vector* visited); + + int count1_; + int count2_; + google::protobuf::scoped_ptr match_callback_; + map, bool> cached_match_results_; + vector* match_list1_; + vector* match_list2_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher); +}; + +MaximumMatcher::MaximumMatcher(int count1, int count2, + NodeMatchCallback* callback, + vector* match_list1, + vector* match_list2) + : count1_(count1), count2_(count2), match_callback_(callback), + match_list1_(match_list1), match_list2_(match_list2) { + match_list1_->assign(count1, -1); + match_list2_->assign(count2, -1); +} + +int MaximumMatcher::FindMaximumMatch(bool early_return) { + int result = 0; + for (int i = 0; i < count1_; ++i) { + vector visited(count1_); + if (FindArgumentPathDFS(i, &visited)) { + ++result; + } else if (early_return) { + return 0; + } + } + // Backfill match_list1_ as we only filled match_list2_ when finding + // argumenting pathes. + for (int i = 0; i < count2_; ++i) { + if ((*match_list2_)[i] != -1) { + (*match_list1_)[(*match_list2_)[i]] = i; + } + } + return result; +} + +bool MaximumMatcher::Match(int left, int right) { + pair p(left, right); + map, bool>::iterator it = cached_match_results_.find(p); + if (it != cached_match_results_.end()) { + return it->second; + } + cached_match_results_[p] = match_callback_->Run(left, right); + return cached_match_results_[p]; +} + +bool MaximumMatcher::FindArgumentPathDFS(int v, vector* visited) { + (*visited)[v] = true; + // We try to match those un-matched nodes on the right side first. This is + // the step that the navie greedy matching algorithm uses. In the best cases + // where the greedy algorithm can find a maximum matching, we will always + // find a match in this step and the performance will be identical to the + // greedy algorithm. + for (int i = 0; i < count2_; ++i) { + int matched = (*match_list2_)[i]; + if (matched == -1 && Match(v, i)) { + (*match_list2_)[i] = v; + return true; + } + } + // Then we try those already matched nodes and see if we can find an + // alternaive match for the node matched to them. + // The greedy algorithm will stop before this and fail to produce the + // correct result. + for (int i = 0; i < count2_; ++i) { + int matched = (*match_list2_)[i]; + if (matched != -1 && Match(v, i)) { + if (!(*visited)[matched] && FindArgumentPathDFS(matched, visited)) { + (*match_list2_)[i] = v; + return true; + } + } + } + return false; +} + +} // namespace + +bool MessageDifferencer::MatchRepeatedFieldIndices( + const Message& message1, + const Message& message2, + const FieldDescriptor* repeated_field, + const vector& parent_fields, + vector* match_list1, + vector* match_list2) { + const int count1 = + message1.GetReflection()->FieldSize(message1, repeated_field); + const int count2 = + message2.GetReflection()->FieldSize(message2, repeated_field); + const MapKeyComparator* key_comparator = GetMapKeyComparator(repeated_field); + + match_list1->assign(count1, -1); + match_list2->assign(count2, -1); + + SpecificField specific_field; + specific_field.field = repeated_field; + + bool success = true; + // Find potential match if this is a special repeated field. + if (key_comparator != NULL || IsTreatedAsSet(repeated_field)) { + if (scope_ == PARTIAL) { + // When partial matching is enabled, Compare(a, b) && Compare(a, c) + // doesn't neccessarily imply Compare(b, c). Therefore a naive greedy + // algorithm will fail to find a maximum matching. + // Here we use the argumenting path algorithm. + MaximumMatcher::NodeMatchCallback* callback = NewPermanentCallback( + this, &MessageDifferencer::IsMatch, repeated_field, key_comparator, + &message1, &message2, parent_fields); + MaximumMatcher matcher(count1, count2, callback, match_list1, + match_list2); + // If diff info is not needed, we should end the matching process as + // soon as possible if not all items can be matched. + bool early_return = (reporter_ == NULL); + int match_count = matcher.FindMaximumMatch(early_return); + if (match_count != count1 && reporter_ == NULL) return false; + success = success && (match_count == count1); + } else { + for (int i = 0; i < count1; ++i) { + // Indicates any matched elements for this repeated field. + bool match = false; + + specific_field.index = i; + specific_field.new_index = i; + + for (int j = 0; j < count2; j++) { + if (match_list2->at(j) != -1) continue; + specific_field.index = i; + specific_field.new_index = j; + + match = IsMatch(repeated_field, key_comparator, + &message1, &message2, parent_fields, i, j); + + if (match) { + match_list1->at(specific_field.index) = specific_field.new_index; + match_list2->at(specific_field.new_index) = specific_field.index; + break; + } + } + if (!match && reporter_ == NULL) return false; + success = success && match; + } + } + } else { + // If this field should be treated as list, just label the match_list. + for (int i = 0; i < count1 && i < count2; i++) { + match_list1->at(i) = i; + match_list2->at(i) = i; + } + } + + return success; +} + +FieldComparator::ComparisonResult MessageDifferencer::GetFieldComparisonResult( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + const FieldContext* field_context) { + FieldComparator* comparator = field_comparator_ != NULL ? + field_comparator_ : &default_field_comparator_; + return comparator->Compare(message1, message2, field, + index1, index2, field_context); +} + +// =========================================================================== + +MessageDifferencer::Reporter::Reporter() { } +MessageDifferencer::Reporter::~Reporter() {} + +// =========================================================================== + +MessageDifferencer::MapKeyComparator::MapKeyComparator() {} +MessageDifferencer::MapKeyComparator::~MapKeyComparator() {} + +// =========================================================================== + +MessageDifferencer::IgnoreCriteria::IgnoreCriteria() {} +MessageDifferencer::IgnoreCriteria::~IgnoreCriteria() {} + +// =========================================================================== + +// Note that the printer's delimiter is not used, because if we are given a +// printer, we don't know its delimiter. +MessageDifferencer::StreamReporter::StreamReporter( + io::ZeroCopyOutputStream* output) : printer_(new io::Printer(output, '$')), + delete_printer_(true), + report_modified_aggregates_(false) { } + +MessageDifferencer::StreamReporter::StreamReporter( + io::Printer* printer) : printer_(printer), + delete_printer_(false), + report_modified_aggregates_(false) { } + +MessageDifferencer::StreamReporter::~StreamReporter() { + if (delete_printer_) delete printer_; +} + +void MessageDifferencer::StreamReporter::PrintPath( + const vector& field_path, bool left_side) { + for (int i = 0; i < field_path.size(); ++i) { + if (i > 0) { + printer_->Print("."); + } + + SpecificField specific_field = field_path[i]; + + if (specific_field.field != NULL) { + if (specific_field.field->is_extension()) { + printer_->Print("($name$)", "name", + specific_field.field->full_name()); + } else { + printer_->PrintRaw(specific_field.field->name()); + } + } else { + printer_->PrintRaw(SimpleItoa(specific_field.unknown_field_number)); + } + if (left_side && specific_field.index >= 0) { + printer_->Print("[$name$]", "name", SimpleItoa(specific_field.index)); + } + if (!left_side && specific_field.new_index >= 0) { + printer_->Print("[$name$]", "name", SimpleItoa(specific_field.new_index)); + } + } +} + +void MessageDifferencer:: +StreamReporter::PrintValue(const Message& message, + const vector& field_path, + bool left_side) { + const SpecificField& specific_field = field_path.back(); + const FieldDescriptor* field = specific_field.field; + if (field != NULL) { + string output; + int index = left_side ? specific_field.index : specific_field.new_index; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + const Reflection* reflection = message.GetReflection(); + const Message& field_message = field->is_repeated() ? + reflection->GetRepeatedMessage(message, field, index) : + reflection->GetMessage(message, field); + output = field_message.ShortDebugString(); + if (output.empty()) { + printer_->Print("{ }"); + } else { + printer_->Print("{ $name$ }", "name", output); + } + } else { + TextFormat::PrintFieldValueToString(message, field, index, &output); + printer_->PrintRaw(output); + } + } else { + const UnknownFieldSet* unknown_fields = + (left_side ? + specific_field.unknown_field_set1 : + specific_field.unknown_field_set2); + const UnknownField* unknown_field = &unknown_fields->field( + left_side ? + specific_field.unknown_field_index1 : + specific_field.unknown_field_index2); + PrintUnknownFieldValue(unknown_field); + } +} + +void MessageDifferencer:: +StreamReporter::PrintUnknownFieldValue(const UnknownField* unknown_field) { + GOOGLE_CHECK(unknown_field != NULL) << " Cannot print NULL unknown_field."; + + string output; + switch (unknown_field->type()) { + case UnknownField::TYPE_VARINT: + output = SimpleItoa(unknown_field->varint()); + break; + case UnknownField::TYPE_FIXED32: + output = StrCat("0x", strings::Hex(unknown_field->fixed32(), + strings::ZERO_PAD_8)); + break; + case UnknownField::TYPE_FIXED64: + output = StrCat("0x", strings::Hex(unknown_field->fixed64(), + strings::ZERO_PAD_16)); + break; + case UnknownField::TYPE_LENGTH_DELIMITED: + output = StringPrintf("\"%s\"", + CEscape(unknown_field->length_delimited()).c_str()); + break; + case UnknownField::TYPE_GROUP: + // TODO(kenton): Print the contents of the group like we do for + // messages. Requires an equivalent of ShortDebugString() for + // UnknownFieldSet. + output = "{ ... }"; + break; + } + printer_->PrintRaw(output); +} + +void MessageDifferencer::StreamReporter::Print(const string& str) { + printer_->Print(str.c_str()); +} + +void MessageDifferencer::StreamReporter::ReportAdded( + const Message& message1, + const Message& message2, + const vector& field_path) { + printer_->Print("added: "); + PrintPath(field_path, false); + printer_->Print(": "); + PrintValue(message2, field_path, false); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportDeleted( + const Message& message1, + const Message& message2, + const vector& field_path) { + printer_->Print("deleted: "); + PrintPath(field_path, true); + printer_->Print(": "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines +} + +void MessageDifferencer::StreamReporter::ReportModified( + const Message& message1, + const Message& message2, + const vector& field_path) { + if (!report_modified_aggregates_ && field_path.back().field == NULL) { + if (field_path.back().unknown_field_type == UnknownField::TYPE_GROUP) { + // Any changes to the subfields have already been printed. + return; + } + } else if (!report_modified_aggregates_) { + if (field_path.back().field->cpp_type() == + FieldDescriptor::CPPTYPE_MESSAGE) { + // Any changes to the subfields have already been printed. + return; + } + } + + printer_->Print("modified: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print(": "); + PrintValue(message1, field_path, true); + printer_->Print(" -> "); + PrintValue(message2, field_path, false); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportMoved( + const Message& message1, + const Message& message2, + const vector& field_path) { + printer_->Print("moved: "); + PrintPath(field_path, true); + printer_->Print(" -> "); + PrintPath(field_path, false); + printer_->Print(" : "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportMatched( + const Message& message1, + const Message& message2, + const vector& field_path) { + printer_->Print("matched: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print(" : "); + PrintValue(message1, field_path, true); + printer_->Print("\n"); // Print for newlines. +} + +void MessageDifferencer::StreamReporter::ReportIgnored( + const Message& message1, + const Message& message2, + const vector& field_path) { + printer_->Print("ignored: "); + PrintPath(field_path, true); + if (CheckPathChanged(field_path)) { + printer_->Print(" -> "); + PrintPath(field_path, false); + } + printer_->Print("\n"); // Print for newlines. +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h new file mode 100644 index 00000000..05548897 --- /dev/null +++ b/src/google/protobuf/util/message_differencer.h @@ -0,0 +1,817 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file defines static methods and classes for comparing Protocol +// Messages. +// +// Aug. 2008: Added Unknown Fields Comparison for messages. +// Aug. 2009: Added different options to compare repeated fields. +// Apr. 2010: Moved field comparison to FieldComparator. + +#ifndef GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ +#define GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ + +#include +#include +#include +#include +#include // FieldDescriptor +#include // Message +#include +#include + +namespace google { +namespace protobuf { + +class DynamicMessageFactory; +class FieldDescriptor; + +namespace io { +class ZeroCopyOutputStream; +class Printer; +} + +namespace util { + +class FieldContext; // declared below MessageDifferencer + +// A basic differencer that can be used to determine +// the differences between two specified Protocol Messages. If any differences +// are found, the Compare method will return false, and any differencer reporter +// specified via ReportDifferencesTo will have its reporting methods called (see +// below for implementation of the report). Based off of the original +// ProtocolDifferencer implementation in //net/proto/protocol-differencer.h +// (Thanks Todd!). +// +// MessageDifferencer REQUIRES that compared messages be the same type, defined +// as messages that share the same descriptor. If not, the behavior of this +// class is undefined. +// +// People disagree on what MessageDifferencer should do when asked to compare +// messages with different descriptors. Some people think it should always +// return false. Others expect it to try to look for similar fields and +// compare them anyway -- especially if the descriptors happen to be identical. +// If we chose either of these behaviors, some set of people would find it +// surprising, and could end up writing code expecting the other behavior +// without realizing their error. Therefore, we forbid that usage. +// +// This class is implemented based on the proto2 reflection. The performance +// should be good enough for normal usages. However, for places where the +// performance is extremely sensitive, there are several alternatives: +// - Comparing serialized string +// Downside: false negatives (there are messages that are the same but their +// serialized strings are different). +// - Equals code generator by compiler plugin (net/proto2/contrib/equals_plugin) +// Downside: more generated code; maintenance overhead for the additional rule +// (must be in sync with the original proto_library). +// +// Note on handling of google.protobuf.Any: MessageDifferencer automatically +// unpacks Any::value into a Message and compares its individual fields. +// Messages encoded in a repeated Any cannot be compared using TreatAsMap. +// +// +// Note on thread-safety: MessageDifferencer is *not* thread-safe. You need to +// guard it with a lock to use the same MessageDifferencer instance from +// multiple threads. Note that it's fine to call static comparison methods +// (like MessageDifferencer::Equals) concurrently. +class LIBPROTOBUF_EXPORT MessageDifferencer { + public: + // Determines whether the supplied messages are equal. Equality is defined as + // all fields within the two messages being set to the same value. Primitive + // fields and strings are compared by value while embedded messages/groups + // are compared as if via a recursive call. Use IgnoreField() and Compare() + // if some fields should be ignored in the comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool Equals(const Message& message1, const Message& message2); + + // Determines whether the supplied messages are equivalent. Equivalency is + // defined as all fields within the two messages having the same value. This + // differs from the Equals method above in that fields with default values + // are considered set to said value automatically. For details on how default + // values are defined for each field type, see http://shortn/_x2Gv6XFrWt. + // Also, Equivalent() ignores unknown fields. Use IgnoreField() and Compare() + // if some fields should be ignored in the comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool Equivalent(const Message& message1, const Message& message2); + + // Determines whether the supplied messages are approximately equal. + // Approximate equality is defined as all fields within the two messages + // being approximately equal. Primitive (non-float) fields and strings are + // compared by value, floats are compared using MathUtil::AlmostEquals() and + // embedded messages/groups are compared as if via a recursive call. Use + // IgnoreField() and Compare() if some fields should be ignored in the + // comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool ApproximatelyEquals(const Message& message1, + const Message& message2); + + // Determines whether the supplied messages are approximately equivalent. + // Approximate equivalency is defined as all fields within the two messages + // being approximately equivalent. As in + // MessageDifferencer::ApproximatelyEquals, primitive (non-float) fields and + // strings are compared by value, floats are compared using + // MathUtil::AlmostEquals() and embedded messages/groups are compared as if + // via a recursive call. However, fields with default values are considered + // set to said value, as per MessageDiffencer::Equivalent. Use IgnoreField() + // and Compare() if some fields should be ignored in the comparison. + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + static bool ApproximatelyEquivalent(const Message& message1, + const Message& message2); + + // Identifies an individual field in a message instance. Used for field_path, + // below. + struct SpecificField { + // For known fields, "field" is filled in and "unknown_field_number" is -1. + // For unknown fields, "field" is NULL, "unknown_field_number" is the field + // number, and "unknown_field_type" is its type. + const FieldDescriptor* field; + int unknown_field_number; + UnknownField::Type unknown_field_type; + + // If this a repeated field, "index" is the index within it. For unknown + // fields, this is the index of the field among all unknown fields of the + // same field number and type. + int index; + + // If "field" is a repeated field which is being treated as a map or + // a set (see TreatAsMap() and TreatAsSet(), below), new_index indicates + // the index the position to which the element has moved. This only + // applies to ReportMoved() and (in the case of TreatAsMap()) + // ReportModified(). In all other cases, "new_index" will have the same + // value as "index". + int new_index; + + // For unknown fields, these are the pointers to the UnknownFieldSet + // containing the unknown fields. In certain cases (e.g. proto1's + // MessageSet, or nested groups of unknown fields), these may differ from + // the messages' internal UnknownFieldSets. + const UnknownFieldSet* unknown_field_set1; + const UnknownFieldSet* unknown_field_set2; + + // For unknown fields, these are the index of the field within the + // UnknownFieldSets. One or the other will be -1 when + // reporting an addition or deletion. + int unknown_field_index1; + int unknown_field_index2; + + SpecificField() + : field(NULL), + unknown_field_number(-1), + index(-1), + new_index(-1), + unknown_field_set1(NULL), + unknown_field_set2(NULL), + unknown_field_index1(-1), + unknown_field_index2(-1) {} + }; + + // Abstract base class from which all MessageDifferencer + // reporters derive. The five Report* methods below will be called when + // a field has been added, deleted, modified, moved, or matched. The third + // argument is a vector of FieldDescriptor pointers which describes the chain + // of fields that was taken to find the current field. For example, for a + // field found in an embedded message, the vector will contain two + // FieldDescriptors. The first will be the field of the embedded message + // itself and the second will be the actual field in the embedded message + // that was added/deleted/modified. + class LIBPROTOBUF_EXPORT Reporter { + public: + Reporter(); + virtual ~Reporter(); + + // Reports that a field has been added into Message2. + virtual void ReportAdded( + const Message& message1, const Message& message2, + const vector& field_path) = 0; + + // Reports that a field has been deleted from Message1. + virtual void ReportDeleted( + const Message& message1, + const Message& message2, + const vector& field_path) = 0; + + // Reports that the value of a field has been modified. + virtual void ReportModified( + const Message& message1, + const Message& message2, + const vector& field_path) = 0; + + // Reports that a repeated field has been moved to another location. This + // only applies when using TreatAsSet or TreatAsMap() -- see below. Also + // note that for any given field, ReportModified and ReportMoved are + // mutually exclusive. If a field has been both moved and modified, then + // only ReportModified will be called. + virtual void ReportMoved( + const Message& message1, + const Message& message2, + const vector& field_path) { } + + // Reports that two fields match. Useful for doing side-by-side diffs. + // This function is mutually exclusive with ReportModified and ReportMoved. + // Note that you must call set_report_matches(true) before calling Compare + // to make use of this function. + virtual void ReportMatched( + const Message& message1, + const Message& message2, + const vector& field_path) { } + + // Reports that two fields would have been compared, but the + // comparison has been skipped because the field was marked as + // 'ignored' using IgnoreField(). This function is mutually + // exclusive with all the other Report() functions. + // + // The contract of ReportIgnored is slightly different than the + // other Report() functions, in that |field_path.back().index| is + // always equal to -1, even if the last field is repeated. This is + // because while the other Report() functions indicate where in a + // repeated field the action (Addition, Deletion, etc...) + // happened, when a repeated field is 'ignored', the differencer + // simply calls ReportIgnored on the repeated field as a whole and + // moves on without looking at its individual elements. + // + // Furthermore, ReportIgnored() does not indicate whether the + // fields were in fact equal or not, as Compare() does not inspect + // these fields at all. It is up to the Reporter to decide whether + // the fields are equal or not (perhaps with a second call to + // Compare()), if it cares. + virtual void ReportIgnored( + const Message& message1, + const Message& message2, + const vector& field_path) { } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter); + }; + + // MapKeyComparator is used to determine if two elements have the same key + // when comparing elements of a repeated field as a map. + class LIBPROTOBUF_EXPORT MapKeyComparator { + public: + MapKeyComparator(); + virtual ~MapKeyComparator(); + + // The first IsMatch without parent_fields is only for backward + // compatibility. New users should override the second one instead. + // + // Deprecated. + // TODO(ykzhu): remove this function. + virtual bool IsMatch(const Message& message1, + const Message& message2) const { + GOOGLE_CHECK(false) << "This function shouldn't get called"; + return false; + } + virtual bool IsMatch(const Message& message1, + const Message& message2, + const vector& parent_fields) const { + return IsMatch(message1, message2); + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator); + }; + + // Abstract base class from which all IgnoreCriteria derive. + // By adding IgnoreCriteria more complex ignore logic can be implemented. + // IgnoreCriteria are registed with AddIgnoreCriteria. For each compared + // field IsIgnored is called on each added IgnoreCriteria until one returns + // true or all return false. + // IsIgnored is called for fields where at least one side has a value. + class LIBPROTOBUF_EXPORT IgnoreCriteria { + public: + IgnoreCriteria(); + virtual ~IgnoreCriteria(); + + // Returns true if the field should be ignored. + virtual bool IsIgnored( + const Message& message1, + const Message& message2, + const FieldDescriptor* field, + const vector& parent_fields) = 0; + }; + + // To add a Reporter, construct default here, then use ReportDifferencesTo or + // ReportDifferencesToString. + explicit MessageDifferencer(); + + ~MessageDifferencer(); + + enum MessageFieldComparison { + EQUAL, // Fields must be present in both messages + // for the messages to be considered the same. + EQUIVALENT, // Fields with default values are considered set + // for comparison purposes even if not explicitly + // set in the messages themselves. Unknown fields + // are ignored. + }; + + enum Scope { + FULL, // All fields of both messages are considered in the comparison. + PARTIAL // Only fields present in the first message are considered; fields + // set only in the second message will be skipped during + // comparison. + }; + + // DEPRECATED. Use FieldComparator::FloatComparison instead. + enum FloatComparison { + EXACT, // Floats and doubles are compared exactly. + APPROXIMATE // Floats and doubles are compared using the + // MathUtil::AlmostEquals method. + }; + + enum RepeatedFieldComparison { + AS_LIST, // Repeated fields are compared in order. Differing values at + // the same index are reported using ReportModified(). If the + // repeated fields have different numbers of elements, the + // unpaired elements are reported using ReportAdded() or + // ReportDeleted(). + AS_SET, // Treat all the repeated fields as sets by default. + // See TreatAsSet(), as below. + }; + + // The elements of the given repeated field will be treated as a set for + // diffing purposes, so different orderings of the same elements will be + // considered equal. Elements which are present on both sides of the + // comparison but which have changed position will be reported with + // ReportMoved(). Elements which only exist on one side or the other are + // reported with ReportAdded() and ReportDeleted() regardless of their + // positions. ReportModified() is never used for this repeated field. If + // the only differences between the compared messages is that some fields + // have been moved, then the comparison returns true. + // + // If the scope of comparison is set to PARTIAL, then in addition to what's + // above, extra values added to repeated fields of the second message will + // not cause the comparison to fail. + // + // Note that set comparison is currently O(k * n^2) (where n is the total + // number of elements, and k is the average size of each element). In theory + // it could be made O(n * k) with a more complex hashing implementation. Feel + // free to contribute one if the current implementation is too slow for you. + // If partial matching is also enabled, the time complexity will be O(k * n^2 + // + n^3) in which n^3 is the time complexity of the maximum matching + // algorithm. + // + // REQUIRES: field->is_repeated() + void TreatAsSet(const FieldDescriptor* field); + + // The elements of the given repeated field will be treated as a map for + // diffing purposes, with |key| being the map key. Thus, elements with the + // same key will be compared even if they do not appear at the same index. + // Differences are reported similarly to TreatAsSet(), except that + // ReportModified() is used to report elements with the same key but + // different values. Note that if an element is both moved and modified, + // only ReportModified() will be called. As with TreatAsSet, if the only + // differences between the compared messages is that some fields have been + // moved, then the comparison returns true. See TreatAsSet for notes on + // performance. + // + // REQUIRES: field->is_repeated() + // REQUIRES: field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + // REQUIRES: key->containing_type() == field->message_type() + void TreatAsMap(const FieldDescriptor* field, const FieldDescriptor* key); + // Same as TreatAsMap except that this method will use multiple fields as + // the key in comparison. All specified fields in 'key_fields' should be + // present in the compared elements. Two elements will be treated as having + // the same key iff they have the same value for every specified field. There + // are two steps in the comparison process. The first one is key matching. + // Every element from one message will be compared to every element from + // the other message. Only fields in 'key_fields' are compared in this step + // to decide if two elements have the same key. The second step is value + // comparison. Those pairs of elements with the same key (with equal value + // for every field in 'key_fields') will be compared in this step. + // Time complexity of the first step is O(s * m * n ^ 2) where s is the + // average size of the fields specified in 'key_fields', m is the number of + // fields in 'key_fields' and n is the number of elements. If partial + // matching is enabled, an extra O(n^3) will be incured by the maximum + // matching algorithm. The second step is O(k * n) where k is the average + // size of each element. + void TreatAsMapWithMultipleFieldsAsKey( + const FieldDescriptor* field, + const vector& key_fields); + // Same as TreatAsMapWithMultipleFieldsAsKey, except that each of the field + // do not necessarily need to be a direct subfield. Each element in + // key_field_paths indicate a path from the message being compared, listing + // successive subfield to reach the key field. + // + // REQUIRES: + // for key_field_path in key_field_paths: + // key_field_path[0]->containing_type() == field->message_type() + // for i in [0, key_field_path.size() - 1): + // key_field_path[i+1]->containing_type() == + // key_field_path[i]->message_type() + // key_field_path[i]->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE + // !key_field_path[i]->is_repeated() + void TreatAsMapWithMultipleFieldPathsAsKey( + const FieldDescriptor* field, + const vector >& key_field_paths); + + // Uses a custom MapKeyComparator to determine if two elements have the same + // key when comparing a repeated field as a map. + // The caller is responsible to delete the key_comparator. + // This method varies from TreatAsMapWithMultipleFieldsAsKey only in the + // first key matching step. Rather than comparing some specified fields, it + // will invoke the IsMatch method of the given 'key_comparator' to decide if + // two elements have the same key. + void TreatAsMapUsingKeyComparator( + const FieldDescriptor* field, + const MapKeyComparator* key_comparator); + + // Add a custom ignore criteria that is evaluated in addition to the + // ignored fields added with IgnoreField. + // Takes ownership of ignore_criteria. + void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria); + + // Indicates that any field with the given descriptor should be + // ignored for the purposes of comparing two messages. This applies + // to fields nested in the message structure as well as top level + // ones. When the MessageDifferencer encounters an ignored field, + // ReportIgnored is called on the reporter, if one is specified. + // + // The only place where the field's 'ignored' status is not applied is when + // it is being used as a key in a field passed to TreatAsMap or is one of + // the fields passed to TreatAsMapWithMultipleFieldsAsKey. + // In this case it is compared in key matching but after that it's ignored + // in value comparison. + void IgnoreField(const FieldDescriptor* field); + + // Sets the field comparator used to determine differences between protocol + // buffer fields. By default it's set to a DefaultFieldComparator instance. + // MessageDifferencer doesn't take ownership over the passed object. + // Note that this method must be called before Compare for the comparator to + // be used. + void set_field_comparator(FieldComparator* comparator); + + // DEPRECATED. Pass a DefaultFieldComparator instance instead. + // Sets the fraction and margin for the float comparison of a given field. + // Uses MathUtil::WithinFractionOrMargin to compare the values. + // NOTE: this method does nothing if differencer's field comparator has been + // set to a custom object. + // + // REQUIRES: field->cpp_type == FieldDescriptor::CPPTYPE_DOUBLE or + // field->cpp_type == FieldDescriptor::CPPTYPE_FLOAT + // REQUIRES: float_comparison_ == APPROXIMATE + void SetFractionAndMargin(const FieldDescriptor* field, double fraction, + double margin); + + // Sets the type of comparison (as defined in the MessageFieldComparison + // enumeration above) that is used by this differencer when determining how + // to compare fields in messages. + void set_message_field_comparison(MessageFieldComparison comparison); + + // Tells the differencer whether or not to report matches. This method must + // be called before Compare. The default for a new differencer is false. + void set_report_matches(bool report_matches) { + report_matches_ = report_matches; + } + + // Sets the scope of the comparison (as defined in the Scope enumeration + // above) that is used by this differencer when determining which fields to + // compare between the messages. + void set_scope(Scope scope); + + // Returns the current scope used by this differencer. + Scope scope(); + + // DEPRECATED. Pass a DefaultFieldComparator instance instead. + // Sets the type of comparison (as defined in the FloatComparison enumeration + // above) that is used by this differencer when comparing float (and double) + // fields in messages. + // NOTE: this method does nothing if differencer's field comparator has been + // set to a custom object. + void set_float_comparison(FloatComparison comparison); + + // Sets the type of comparison for repeated field (as defined in the + // RepeatedFieldComparison enumeration above) that is used by this + // differencer when compare repeated fields in messages. + void set_repeated_field_comparison(RepeatedFieldComparison comparison); + + // Compares the two specified messages, returning true if they are the same, + // false otherwise. If this method returns false, any changes between the + // two messages will be reported if a Reporter was specified via + // ReportDifferencesTo (see also ReportDifferencesToString). + // + // This method REQUIRES that the two messages have the same + // Descriptor (message1.GetDescriptor() == message2.GetDescriptor()). + bool Compare(const Message& message1, const Message& message2); + + // Same as above, except comparing only the list of fields specified by the + // two vectors of FieldDescriptors. + bool CompareWithFields(const Message& message1, const Message& message2, + const vector& message1_fields, + const vector& message2_fields); + + // Automatically creates a reporter that will output the differences + // found (if any) to the specified output string pointer. Note that this + // method must be called before Compare. + void ReportDifferencesToString(string* output); + + // Tells the MessageDifferencer to report differences via the specified + // reporter. Note that this method must be called before Compare for + // the reporter to be used. It is the responsibility of the caller to delete + // this object. + // If the provided pointer equals NULL, the MessageDifferencer stops reporting + // differences to any previously set reporters or output strings. + void ReportDifferencesTo(Reporter* reporter); + + // An implementation of the MessageDifferencer Reporter that outputs + // any differences found in human-readable form to the supplied + // ZeroCopyOutputStream or Printer. If a printer is used, the delimiter + // *must* be '$'. + class LIBPROTOBUF_EXPORT StreamReporter : public Reporter { + public: + explicit StreamReporter(io::ZeroCopyOutputStream* output); + explicit StreamReporter(io::Printer* printer); // delimiter '$' + virtual ~StreamReporter(); + + // When set to true, the stream reporter will also output aggregates nodes + // (i.e. messages and groups) whose subfields have been modified. When + // false, will only report the individual subfields. Defaults to false. + void set_report_modified_aggregates(bool report) { + report_modified_aggregates_ = report; + } + + // The following are implementations of the methods described above. + virtual void ReportAdded(const Message& message1, const Message& message2, + const vector& field_path); + + virtual void ReportDeleted(const Message& message1, + const Message& message2, + const vector& field_path); + + virtual void ReportModified(const Message& message1, + const Message& message2, + const vector& field_path); + + virtual void ReportMoved(const Message& message1, + const Message& message2, + const vector& field_path); + + virtual void ReportMatched(const Message& message1, + const Message& message2, + const vector& field_path); + + virtual void ReportIgnored(const Message& message1, + const Message& message2, + const vector& field_path); + + protected: + // Prints the specified path of fields to the buffer. + virtual void PrintPath(const vector& field_path, + bool left_side); + + // Prints the value of fields to the buffer. left_side is true if the + // given message is from the left side of the comparison, false if it + // was the right. This is relevant only to decide whether to follow + // unknown_field_index1 or unknown_field_index2 when an unknown field + // is encountered in field_path. + virtual void PrintValue(const Message& message, + const vector& field_path, + bool left_side); + + // Prints the specified path of unknown fields to the buffer. + virtual void PrintUnknownFieldValue(const UnknownField* unknown_field); + + // Just print a string + void Print(const string& str); + + private: + io::Printer* printer_; + bool delete_printer_; + bool report_modified_aggregates_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter); + }; + + private: + // A MapKeyComparator to be used in TreatAsMapUsingKeyComparator. + // Implementation of this class needs to do field value comparison which + // relies on some private methods of MessageDifferencer. That's why this + // class is declared as a nested class of MessageDifferencer. + class MultipleFieldsMapKeyComparator; + // Returns true if field1's number() is less than field2's. + static bool FieldBefore(const FieldDescriptor* field1, + const FieldDescriptor* field2); + + // Combine the two lists of fields into the combined_fields output vector. + // All fields present in both lists will always be included in the combined + // list. Fields only present in one of the lists will only appear in the + // combined list if the corresponding fields_scope option is set to FULL. + void CombineFields(const vector& fields1, + Scope fields1_scope, + const vector& fields2, + Scope fields2_scope, + vector* combined_fields); + + // Internal version of the Compare method which performs the actual + // comparison. The parent_fields vector is a vector containing field + // descriptors of all fields accessed to get to this comparison operation + // (i.e. if the current message is an embedded message, the parent_fields + // vector will contain the field that has this embedded message). + bool Compare(const Message& message1, const Message& message2, + vector* parent_fields); + + // Compares all the unknown fields in two messages. + bool CompareUnknownFields(const Message& message1, const Message& message2, + const google::protobuf::UnknownFieldSet&, + const google::protobuf::UnknownFieldSet&, + vector* parent_fields); + + // Compares the specified messages for the requested field lists. The field + // lists are modified depending on comparison settings, and then passed to + // CompareWithFieldsInternal. + bool CompareRequestedFieldsUsingSettings( + const Message& message1, const Message& message2, + const vector& message1_fields, + const vector& message2_fields, + vector* parent_fields); + + // Compares the specified messages with the specified field lists. + bool CompareWithFieldsInternal( + const Message& message1, const Message& message2, + const vector& message1_fields, + const vector& message2_fields, + vector* parent_fields); + + // Compares the repeated fields, and report the error. + bool CompareRepeatedField(const Message& message1, const Message& message2, + const FieldDescriptor* field, + vector* parent_fields); + + // Shorthand for CompareFieldValueUsingParentFields with NULL parent_fields. + bool CompareFieldValue(const Message& message1, + const Message& message2, + const FieldDescriptor* field, + int index1, + int index2); + + // Compares the specified field on the two messages, returning + // true if they are the same, false otherwise. For repeated fields, + // this method only compares the value in the specified index. This method + // uses Compare functions to recurse into submessages. + // The parent_fields vector is used in calls to a Reporter instance calls. + // It can be NULL, in which case the MessageDifferencer will create new + // list of parent messages if it needs to recursively compare the given field. + // To avoid confusing users you should not set it to NULL unless you modified + // Reporter to handle the change of parent_fields correctly. + bool CompareFieldValueUsingParentFields(const Message& message1, + const Message& message2, + const FieldDescriptor* field, + int index1, + int index2, + vector* parent_fields); + + // Compares the specified field on the two messages, returning comparison + // result, as returned by appropriate FieldComparator. + FieldComparator::ComparisonResult GetFieldComparisonResult( + const Message& message1, const Message& message2, + const FieldDescriptor* field, int index1, int index2, + const FieldContext* field_context); + + // Check if the two elements in the repeated field are match to each other. + // if the key_comprator is NULL, this function returns true when the two + // elements are equal. + bool IsMatch(const FieldDescriptor* repeated_field, + const MapKeyComparator* key_comparator, + const Message* message1, const Message* message2, + const vector& parent_fields, + int index1, int index2); + + // Returns true when this repeated field has been configured to be treated + // as a set. + bool IsTreatedAsSet(const FieldDescriptor* field); + + // Returns true when this repeated field is to be compared as a subset, ie. + // has been configured to be treated as a set or map and scope is set to + // PARTIAL. + bool IsTreatedAsSubset(const FieldDescriptor* field); + + // Returns true if this field is to be ignored when this + // MessageDifferencer compares messages. + bool IsIgnored( + const Message& message1, + const Message& message2, + const FieldDescriptor* field, + const vector& parent_fields); + + // Returns MapKeyComparator* when this field has been configured to + // be treated as a map. If not, returns NULL. + const MapKeyComparator* GetMapKeyComparator(const FieldDescriptor* field); + + // Attempts to match indices of a repeated field, so that the contained values + // match. Clears output vectors and sets their values to indices of paired + // messages, ie. if message1[0] matches message2[1], then match_list1[0] == 1 + // and match_list2[1] == 0. The unmatched indices are indicated by -1. + // This method returns false if the match failed. However, it doesn't mean + // that the comparison succeeds when this method returns true (you need to + // double-check in this case). + bool MatchRepeatedFieldIndices(const Message& message1, + const Message& message2, + const FieldDescriptor* repeated_field, + const vector& parent_fields, + vector* match_list1, + vector* match_list2); + + // If "any" is of type google.protobuf.Any, extract its payload using + // DynamicMessageFactory and store in "data". + bool UnpackAny(const Message& any, google::protobuf::scoped_ptr* data); + + // Checks if index is equal to new_index in all the specific fields. + static bool CheckPathChanged(const vector& parent_fields); + + // Defines a map between field descriptors and their MapKeyComparators. + // Used for repeated fields when they are configured as TreatAsMap. + typedef map FieldKeyComparatorMap; + + // Defines a set to store field descriptors. Used for repeated fields when + // they are configured as TreatAsSet. + typedef set FieldSet; + + Reporter* reporter_; + DefaultFieldComparator default_field_comparator_; + FieldComparator* field_comparator_; + MessageFieldComparison message_field_comparison_; + Scope scope_; + RepeatedFieldComparison repeated_field_comparison_; + + FieldSet set_fields_; + // Keeps track of MapKeyComparators that are created within + // MessageDifferencer. These MapKeyComparators should be deleted + // before MessageDifferencer is destroyed. + // When TreatAsMap or TreatAsMapWithMultipleFieldsAsKey is called, we don't + // store the supplied FieldDescriptors directly. Instead, a new + // MapKeyComparator is created for comparison purpose. + vector owned_key_comparators_; + FieldKeyComparatorMap map_field_key_comparator_; + vector ignore_criteria_; + + FieldSet ignored_fields_; + + bool compare_unknown_fields_; + bool report_matches_; + + string* output_string_; + + google::protobuf::scoped_ptr dynamic_message_factory_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer); +}; + +// This class provides extra information to the FieldComparator::Compare +// function. +class LIBPROTOBUF_EXPORT FieldContext { + public: + explicit FieldContext( + vector* parent_fields) + : parent_fields_(parent_fields) {} + + vector* parent_fields() const { + return parent_fields_; + } + + private: + vector* parent_fields_; +}; + +} +} + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__ diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc new file mode 100755 index 00000000..bd19f695 --- /dev/null +++ b/src/google/protobuf/util/message_differencer_unittest.cc @@ -0,0 +1,3132 @@ +// 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. + +// Author: jschorr@google.com (Joseph Schorr) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// TODO(ksroka): Move some of these tests to field_comparator_test.cc. + +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace { + + +const FieldDescriptor* GetFieldDescriptor( + const Message& message, const string& field_name) { + vector field_path = + Split(field_name, ".", true); + const Descriptor* descriptor = message.GetDescriptor(); + const FieldDescriptor* field = NULL; + for (int i = 0; i < field_path.size(); i++) { + field = descriptor->FindFieldByName(field_path[i]); + descriptor = field->message_type(); + } + return field; +} + +void ExpectEqualsWithDifferencer(util::MessageDifferencer* differencer, + const Message& msg1, + const Message& msg2) { + differencer->set_scope(util::MessageDifferencer::FULL); + EXPECT_TRUE(differencer->Compare(msg1, msg2)); + + differencer->set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer->Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicEqualityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicInequalityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(-1); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldInequalityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.add_repeated_int32(-1); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, MapFieldEqualityTest) { + // Create the testing protos + unittest::TestMap msg1; + unittest::TestMap msg2; + + MapTestUtil::MapReflectionTester tester(unittest::TestMap::descriptor()); + tester.SetMapFieldsViaReflection(&msg1); + tester.SetMapFieldsViaReflection(&msg2); + tester.SwapMapsViaReflection(&msg1); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialEqualityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEqualityTestExtraField) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.clear_optional_int32(); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEqualityTestSkipRequiredField) { + // Create the testing protos + unittest::TestRequired msg1; + unittest::TestRequired msg2; + + msg1.set_a(401); + msg2.set_a(401); + msg2.set_b(402); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialInequalityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(-1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialInequalityMissingFieldTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg2.clear_optional_int32(); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldPartialInequalityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.add_repeated_int32(-1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicEquivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + +TEST(MessageDifferencerTest, EquivalencyNotEqualTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.clear_optional_int32(); + msg2.set_optional_int32(0); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicInequivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(-1); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicEquivalencyNonSetTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicInequivalencyNonSetTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + msg1.set_optional_int32(-1); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicPartialEquivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEquivalencyNotEqualTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(0); + msg2.clear_optional_int32(); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEquivalencyTestExtraField) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.clear_optional_int32(); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, PartialEquivalencyTestSkipRequiredField) { + // Create the testing protos + unittest::TestRequired msg1; + unittest::TestRequired msg2; + + msg1.set_a(401); + msg2.set_a(401); + msg2.set_b(402); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialInequivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + msg1.set_optional_int32(-1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialEquivalencyNonSetTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicPartialInequivalencyNonSetTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + msg1.set_optional_int32(-1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, ApproximateEqualityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, ApproximateModifiedEqualityTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + const float v1 = 2.300005f; + const float v2 = 2.300006f; + msg1.set_optional_float(v1); + msg2.set_optional_float(v2); + + // Compare + ASSERT_NE(v1, v2) << "Should not be the same: " << v1 << ", " << v2; + ASSERT_FLOAT_EQ(v1, v2) << "Should be approx. equal: " << v1 << ", " << v2; + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, ApproximateEquivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); +} + +TEST(MessageDifferencerTest, ApproximateModifiedEquivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Modify the approximateness requirement + const float v1 = 2.300005f; + const float v2 = 2.300006f; + msg1.set_optional_float(v1); + msg2.set_optional_float(v2); + + // Compare + ASSERT_NE(v1, v2) << "Should not be the same: " << v1 << ", " << v2; + ASSERT_FLOAT_EQ(v1, v2) << "Should be approx. equal: " << v1 << ", " << v2; + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); + + // Modify the equivalency requirement too + msg1.clear_optional_int32(); + msg2.set_optional_int32(0); + + // Compare. Now should only pass on ApproximatelyEquivalent + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); + EXPECT_FALSE(util::MessageDifferencer::Equivalent(msg1, msg2)); + EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquals(msg1, msg2)); + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); +} + +TEST(MessageDifferencerTest, ApproximateInequivalencyTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Should fail on equivalency + msg1.set_optional_int32(-1); + EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); + + // Make these fields the same again. + msg1.set_optional_int32(0); + msg2.set_optional_int32(0); + EXPECT_TRUE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); + + // Should fail on approximate equality check + const float v1 = 2.3f; + const float v2 = 9.3f; + msg1.set_optional_float(v1); + msg2.set_optional_float(v2); + EXPECT_FALSE(util::MessageDifferencer::ApproximatelyEquivalent(msg1, + msg2)); +} + +TEST(MessageDifferencerTest, WithinFractionOrMarginFloatTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Should fail on approximate equality check + const float v1 = 100.0f; + const float v2 = 109.9f; + msg1.set_optional_float(v1); + msg2.set_optional_float(v2); + + // Compare + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + const FieldDescriptor* fd = + msg1.GetDescriptor()->FindFieldByName("optional_float"); + + // Set float comparison to exact, margin and fraction value should not matter. + differencer.set_float_comparison(util::MessageDifferencer::EXACT); + // Set margin for float comparison. + differencer.SetFractionAndMargin(fd, 0.0, 10.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Margin and fraction float comparison is activated when float comparison is + // set to approximate. + differencer.set_float_comparison(util::MessageDifferencer::APPROXIMATE); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Test out float comparison with fraction. + differencer.SetFractionAndMargin(fd, 0.2, 0.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Should fail since the fraction is smaller than error. + differencer.SetFractionAndMargin(fd, 0.01, 0.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Should pass if either fraction or margin are satisfied. + differencer.SetFractionAndMargin(fd, 0.01, 10.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Make sure that the margin and fraction only affects the field that it was + // set for. + msg1.set_default_float(v1); + msg2.set_default_float(v2); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + msg1.set_default_float(v1); + msg2.set_default_float(v1); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, WithinFractionOrMarginDoubleTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Should fail on approximate equality check + const double v1 = 100.0; + const double v2 = 109.9; + msg1.set_optional_double(v1); + msg2.set_optional_double(v2); + + // Compare + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Set comparison to exact, margin and fraction value should not matter. + differencer.set_float_comparison(util::MessageDifferencer::EXACT); + // Set margin for float comparison. + const FieldDescriptor* fd = + msg1.GetDescriptor()->FindFieldByName("optional_double"); + differencer.SetFractionAndMargin(fd, 0.0, 10.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Margin and fraction comparison is activated when float comparison is + // set to approximate. + differencer.set_float_comparison(util::MessageDifferencer::APPROXIMATE); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Test out comparison with fraction. + differencer.SetFractionAndMargin(fd, 0.2, 0.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Should fail since the fraction is smaller than error. + differencer.SetFractionAndMargin(fd, 0.01, 0.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Should pass if either fraction or margin are satisfied. + differencer.SetFractionAndMargin(fd, 0.01, 10.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Make sure that the margin and fraction only affects the field that it was + // set for. + msg1.set_default_double(v1); + msg2.set_default_double(v2); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + msg1.set_default_double(v1); + msg2.set_default_double(v1); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, WithinDefaultFractionOrMarginDoubleTest) { + // Create the testing protos + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + // Should fail on approximate equality check + const double v1 = 100.0; + const double v2 = 109.9; + msg1.set_optional_double(v1); + msg2.set_optional_double(v2); + + util::MessageDifferencer differencer; + + // Compare + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Set up a custom field comparitor, with a default fraction and margin for + // float and double comparison. + util::DefaultFieldComparator field_comparitor; + field_comparitor.SetDefaultFractionAndMargin(0.0, 10.0); + differencer.set_field_comparator(&field_comparitor); + + // Set comparison to exact, margin and fraction value should not matter. + field_comparitor.set_float_comparison(util::DefaultFieldComparator::EXACT); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Margin and fraction comparison is activated when float comparison is + // set to approximate. + field_comparitor.set_float_comparison( + util::DefaultFieldComparator::APPROXIMATE); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Test out comparison with fraction. + field_comparitor.SetDefaultFractionAndMargin(0.2, 0.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Should fail since the fraction is smaller than error. + field_comparitor.SetDefaultFractionAndMargin(0.01, 0.0); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Should pass if either fraction or margin are satisfied. + field_comparitor.SetDefaultFractionAndMargin(0.01, 10.0); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Make sure that the default margin and fraction affects all fields + msg1.set_default_double(v1); + msg2.set_default_double(v2); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicFieldOrderingsTest) { + // Create the testing protos + unittest::TestFieldOrderings msg1; + unittest::TestFieldOrderings msg2; + + TestUtil::SetAllFieldsAndExtensions(&msg1); + TestUtil::SetAllFieldsAndExtensions(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicFieldOrderingInequalityTest) { + // Create the testing protos + unittest::TestFieldOrderings msg1; + unittest::TestFieldOrderings msg2; + + TestUtil::SetAllFieldsAndExtensions(&msg1); + TestUtil::SetAllFieldsAndExtensions(&msg2); + + msg1.set_my_float(15.00); + msg2.set_my_float(16.00); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, BasicExtensionTest) { + // Create the testing protos + unittest::TestAllExtensions msg1; + unittest::TestAllExtensions msg2; + + TestUtil::SetAllExtensions(&msg1); + TestUtil::SetAllExtensions(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + + +TEST(MessageDifferencerTest, BasicExtensionInequalityTest) { + // Create the testing protos + unittest::TestAllExtensions msg1; + unittest::TestAllExtensions msg2; + + TestUtil::SetAllExtensions(&msg1); + TestUtil::SetAllExtensions(&msg2); + + msg1.SetExtension(unittest::optional_int32_extension, 101); + msg2.SetExtension(unittest::optional_int32_extension, 102); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, OneofTest) { + // Create the testing protos + unittest::TestOneof2 msg1; + unittest::TestOneof2 msg2; + + TestUtil::SetOneof1(&msg1); + TestUtil::SetOneof1(&msg2); + + // Compare + EXPECT_TRUE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, OneofInequalityTest) { + // Create the testing protos + unittest::TestOneof2 msg1; + unittest::TestOneof2 msg2; + + TestUtil::SetOneof1(&msg1); + TestUtil::SetOneof2(&msg2); + + // Compare + EXPECT_FALSE(util::MessageDifferencer::Equals(msg1, msg2)); +} + +TEST(MessageDifferencerTest, UnknownFieldPartialEqualTest) { + unittest::TestEmptyMessage empty1; + unittest::TestEmptyMessage empty2; + + UnknownFieldSet* unknown1 = empty1.mutable_unknown_fields(); + UnknownFieldSet* unknown2 = empty2.mutable_unknown_fields(); + + unknown1->AddVarint(243, 122); + unknown1->AddLengthDelimited(245, "abc"); + unknown1->AddGroup(246)->AddFixed32(248, 1); + unknown1->mutable_field(2)->mutable_group()->AddFixed32(248, 2); + + unknown2->AddVarint(243, 122); + unknown2->AddLengthDelimited(245, "abc"); + unknown2->AddGroup(246)->AddFixed32(248, 1); + unknown2->mutable_field(2)->mutable_group()->AddFixed32(248, 2); + + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(empty1, empty2)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsEqualityAllTest) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector fields1; + vector fields2; + msg1.GetReflection()->ListFields(msg1, &fields1); + msg2.GetReflection()->ListFields(msg2, &fields2); + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsInequalityAllTest) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + + vector fields1; + vector fields2; + msg1.GetReflection()->ListFields(msg1, &fields1); + msg2.GetReflection()->ListFields(msg2, &fields2); + + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsEmptyListAlwaysSucceeds) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + + vector empty_fields; + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, + empty_fields, empty_fields)); + + TestUtil::SetAllFields(&msg2); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, + empty_fields, empty_fields)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsCompareWithSelf) { + unittest::TestAllTypes msg1; + TestUtil::SetAllFields(&msg1); + + vector fields; + msg1.GetReflection()->ListFields(msg1, &fields); + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg1, fields, fields)); + + { + // Compare with a subset of fields. + vector compare_fields; + for (int i = 0; i < fields.size(); ++i) { + if (i % 2 == 0) { + compare_fields.push_back(fields[i]); + } + } + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg1, + compare_fields, compare_fields)); + } + { + // Specify a different set of fields to compare, even though we're using the + // same message. This should fail, since we are explicitly saying that the + // set of fields are different. + vector compare_fields1; + vector compare_fields2; + for (int i = 0; i < fields.size(); ++i) { + if (i % 2 == 0) { + compare_fields1.push_back(fields[i]); + } else { + compare_fields2.push_back(fields[i]); + } + } + EXPECT_FALSE(differencer.CompareWithFields( + msg1, msg1, compare_fields1, compare_fields2)); + } +} + +TEST(MessageDifferencerTest, SpecifiedFieldsEqualityAllShuffledTest) { + // This is a public function, so make sure there are no assumptions about the + // list of fields. Randomly shuffle them to make sure that they are properly + // ordered for comparison. + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector fields1; + vector fields2; + msg1.GetReflection()->ListFields(msg1, &fields1); + msg2.GetReflection()->ListFields(msg2, &fields2); + + std::random_shuffle(fields1.begin(), fields1.end()); + std::random_shuffle(fields2.begin(), fields2.end()); + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsSubsetEqualityTest) { + // Specify a set of fields to compare. All the fields are equal. + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector fields1; + msg1.GetReflection()->ListFields(msg1, &fields1); + + vector compare_fields; + // Only compare the field descriptors with even indices. + for (int i = 0; i < fields1.size(); ++i) { + if (i % 2 == 0) { + compare_fields.push_back(fields1[i]); + } + } + + util::MessageDifferencer differencer; + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, + compare_fields, compare_fields)); +} + +TEST(MessageDifferencerTest, + SpecifiedFieldsSubsetIgnoresOtherFieldDifferencesTest) { + // Specify a set of fields to compare, but clear all the other fields in one + // of the messages. This should fail a regular compare, but CompareWithFields + // should succeed. + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector fields1; + const Reflection* reflection = msg1.GetReflection(); + reflection->ListFields(msg1, &fields1); + + vector compare_fields; + // Only compare the field descriptors with even indices. + for (int i = 0; i < fields1.size(); ++i) { + if (i % 2 == 0) { + compare_fields.push_back(fields1[i]); + } else { + reflection->ClearField(&msg2, fields1[i]); + } + } + + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, + compare_fields, compare_fields)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsDetectsDifferencesTest) { + // Change all of the repeated fields in one of the messages, and use only + // those fields for comparison. + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + TestUtil::ModifyRepeatedFields(&msg2); + + vector fields1; + msg1.GetReflection()->ListFields(msg1, &fields1); + + vector compare_fields; + // Only compare the repeated field descriptors. + for (int i = 0; i < fields1.size(); ++i) { + if (fields1[i]->is_repeated()) { + compare_fields.push_back(fields1[i]); + } + } + + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, + compare_fields, compare_fields)); +} + +TEST(MessageDifferencerTest, SpecifiedFieldsEquivalenceAllTest) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + + TestUtil::SetAllFields(&msg1); + TestUtil::SetAllFields(&msg2); + + vector fields1; + vector fields2; + msg1.GetReflection()->ListFields(msg1, &fields1); + msg2.GetReflection()->ListFields(msg2, &fields2); + + util::MessageDifferencer differencer; + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, + SpecifiedFieldsEquivalenceIgnoresOtherFieldDifferencesTest) { + unittest::TestAllTypes msg1; + unittest::TestAllTypes msg2; + const Descriptor* desc = msg1.GetDescriptor(); + + const FieldDescriptor* optional_int32_desc = + desc->FindFieldByName("optional_int32"); + const FieldDescriptor* optional_int64_desc = + desc->FindFieldByName("optional_int64"); + const FieldDescriptor* default_int64_desc = + desc->FindFieldByName("default_int64"); + ASSERT_TRUE(optional_int32_desc != NULL); + ASSERT_TRUE(optional_int64_desc != NULL); + ASSERT_TRUE(default_int64_desc != NULL); + msg1.set_optional_int32(0); + msg2.set_optional_int64(0); + msg1.set_default_int64(default_int64_desc->default_value_int64()); + + // Set a field to a non-default value so we know that field selection is + // actually doing something. + msg2.set_optional_uint64(23); + + vector fields1; + vector fields2; + fields1.push_back(optional_int32_desc); + fields1.push_back(default_int64_desc); + + fields2.push_back(optional_int64_desc); + + util::MessageDifferencer differencer; + EXPECT_FALSE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields1, fields2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_SetOfSet) { + // Create the testing protos + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->add_ra(1); item->add_ra(2); item->add_ra(3); + item = msg1.add_item(); + item->add_ra(5); item->add_ra(6); + item = msg1.add_item(); + item->add_ra(1); item->add_ra(3); + item = msg1.add_item(); + item->add_ra(6); item->add_ra(7); item->add_ra(8); + + item = msg2.add_item(); + item->add_ra(6); item->add_ra(5); + item = msg2.add_item(); + item->add_ra(6); item->add_ra(8); item->add_ra(7); + item = msg2.add_item(); + item->add_ra(1); item->add_ra(3); + item = msg2.add_item(); + item->add_ra(3); item->add_ra(2); item->add_ra(1); + + // Compare + util::MessageDifferencer differencer; + differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_Combination) { + // Create the testing protos + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, with key = "a" + // Treat "item.ra" also as Set + // Treat "rv" as Set + // Treat "rw" as List + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->set_a(3); + item->add_ra(1); item->add_ra(2); item->add_ra(3); + item = msg1.add_item(); + item->set_a(4); + item->add_ra(5); item->add_ra(6); + item = msg1.add_item(); + item->set_a(1); + item->add_ra(1); item->add_ra(3); + item = msg1.add_item(); + item->set_a(2); + item->add_ra(6); item->add_ra(7); item->add_ra(8); + + item = msg2.add_item(); + item->set_a(4); + item->add_ra(6); item->add_ra(5); + item = msg2.add_item(); + item->set_a(2); + item->add_ra(6); item->add_ra(8); item->add_ra(7); + item = msg2.add_item(); + item->set_a(1); + item->add_ra(1); item->add_ra(3); + item = msg2.add_item(); + item->set_a(3); + item->add_ra(3); item->add_ra(2); item->add_ra(1); + + msg1.add_rv(3); + msg1.add_rv(4); + msg1.add_rv(7); + msg1.add_rv(0); + msg2.add_rv(4); + msg2.add_rv(3); + msg2.add_rv(0); + msg2.add_rv(7); + + msg1.add_rw("nothing"); msg2.add_rw("nothing"); + msg1.add_rw("should"); msg2.add_rw("should"); + msg1.add_rw("change"); msg2.add_rw("change"); + + // Compare + util::MessageDifferencer differencer; + differencer.TreatAsMap(msg1.GetDescriptor()->FindFieldByName("item"), + item->GetDescriptor()->FindFieldByName("a")); + differencer.TreatAsSet(msg1.GetDescriptor()->FindFieldByName("rv")); + differencer.TreatAsSet(item->GetDescriptor()->FindFieldByName("ra")); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_Partial) { + protobuf_unittest::TestDiffMessage msg1; + // message msg1 { + // item { a: 1; b: "11" } + // } + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->set_a(1); + item->set_b("11"); + + protobuf_unittest::TestDiffMessage msg2; + // message msg2 { + // item { a: 2; b: "22" } + // item { a: 1; b: "11" } + // } + item = msg2.add_item(); + item->set_a(2); + item->set_b("22"); + item = msg2.add_item(); + item->set_a(1); + item->set_b("11"); + + // Compare + util::MessageDifferencer differencer; + differencer.TreatAsMap(GetFieldDescriptor(msg1, "item"), + GetFieldDescriptor(msg1, "item.a")); + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_Duplicates) { + protobuf_unittest::TestDiffMessage a, b, c; + // message a: { + // rv: 0 + // rv: 1 + // rv: 0 + // } + a.add_rv(0); + a.add_rv(1); + a.add_rv(0); + // message b: { + // rv: 0 + // rv: 0 + // rv: 1 + // } + b.add_rv(0); + b.add_rv(0); + b.add_rv(1); + // message c: { + // rv: 0 + // rv: 1 + // } + c.add_rv(0); + c.add_rv(1); + util::MessageDifferencer differencer; + differencer.TreatAsSet(GetFieldDescriptor(a, "rv")); + EXPECT_TRUE(differencer.Compare(b, a)); + EXPECT_FALSE(differencer.Compare(c, a)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_PartialSimple) { + protobuf_unittest::TestDiffMessage a, b, c; + // message a: { + // rm { c: 1 } + // rm { c: 0 } + // } + a.add_rm()->set_c(1); + a.add_rm()->set_c(0); + // message b: { + // rm { c: 1 } + // rm {} + // } + b.add_rm()->set_c(1); + b.add_rm(); + // message c: { + // rm {} + // rm { c: 1 } + // } + c.add_rm(); + c.add_rm()->set_c(1); + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + differencer.TreatAsSet(GetFieldDescriptor(a, "rm")); + EXPECT_TRUE(differencer.Compare(b, a)); + EXPECT_TRUE(differencer.Compare(c, a)); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_Partial) { + protobuf_unittest::TestDiffMessage msg1, msg2; + // message msg1: { + // rm { a: 1 } + // rm { b: 2 } + // rm { c: 3 } + // } + msg1.add_rm()->set_a(1); + msg1.add_rm()->set_b(2); + msg1.add_rm()->set_c(3); + // message msg2: { + // rm { a: 1; c: 3 } + // rm { b: 2; c: 3 } + // rm { b: 2 } + // } + protobuf_unittest::TestField* field = msg2.add_rm(); + field->set_a(1); + field->set_c(3); + field = msg2.add_rm(); + field->set_b(2); + field->set_c(3); + field = msg2.add_rm(); + field->set_b(2); + + util::MessageDifferencer differencer; + differencer.set_scope(util::MessageDifferencer::PARTIAL); + differencer.TreatAsSet(GetFieldDescriptor(msg1, "rm")); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_MultipleFieldsAsKey) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, with key = ("a", "ra") + // Treat "item.ra" as Set + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + // key => value: (1, {2, 3}) => "a" + item->set_a(1); + item->add_ra(2); + item->add_ra(3); + item->set_b("a"); + item = msg1.add_item(); + // key => value: (2, {1, 3}) => "b" + item->set_a(2); + item->add_ra(1); + item->add_ra(3); + item->set_b("b"); + item = msg1.add_item(); + // key => value: (1, {1, 3}) => "c" + item->set_a(1); + item->add_ra(1); + item->add_ra(3); + item->set_b("c"); + + item = msg2.add_item(); + // key => value: (1, {1, 3}) => "c" + item->set_a(1); + item->add_ra(3); + item->add_ra(1); + item->set_b("c"); + item = msg2.add_item(); + // key => value: (1, {2, 3}) => "a" + item->set_a(1); + item->add_ra(3); + item->add_ra(2); + item->set_b("a"); + item = msg2.add_item(); + // key => value: (2, {1, 3}) => "b" + item->set_a(2); + item->add_ra(3); + item->add_ra(1); + item->set_b("b"); + + // Compare + util::MessageDifferencer differencer; + differencer.TreatAsSet(GetFieldDescriptor(msg1, "item.ra")); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + vector key_fields; + key_fields.push_back(GetFieldDescriptor(msg1, "item.a")); + key_fields.push_back(GetFieldDescriptor(msg1, "item.ra")); + differencer.TreatAsMapWithMultipleFieldsAsKey( + GetFieldDescriptor(msg1, "item"), key_fields); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Introduce some differences. + msg1.clear_item(); + msg2.clear_item(); + item = msg1.add_item(); + item->set_a(4); + item->add_ra(5); + item->add_ra(6); + item->set_b("hello"); + item = msg2.add_item(); + item->set_a(4); + item->add_ra(6); + item->add_ra(5); + item->set_b("world"); + string output; + differencer.ReportDifferencesToString(&output); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "moved: item[0].ra[0] -> item[0].ra[1] : 5\n" + "moved: item[0].ra[1] -> item[0].ra[0] : 6\n" + "modified: item[0].b: \"hello\" -> \"world\"\n", + output); +} + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_MultipleFieldPathsAsKey) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, with key = ("m.a", "m.rc") + // Treat "item.m.rc" as Set + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + // key => value: (1, {2, 3}) => "a" + item->mutable_m()->set_a(1); + item->mutable_m()->add_rc(2); + item->mutable_m()->add_rc(3); + item->set_b("a"); + item = msg1.add_item(); + // key => value: (2, {1, 3}) => "b" + item->mutable_m()->set_a(2); + item->mutable_m()->add_rc(1); + item->mutable_m()->add_rc(3); + item->set_b("b"); + item = msg1.add_item(); + // key => value: (1, {1, 3}) => "c" + item->mutable_m()->set_a(1); + item->mutable_m()->add_rc(1); + item->mutable_m()->add_rc(3); + item->set_b("c"); + + item = msg2.add_item(); + // key => value: (1, {1, 3}) => "c" + item->mutable_m()->set_a(1); + item->mutable_m()->add_rc(3); + item->mutable_m()->add_rc(1); + item->set_b("c"); + item = msg2.add_item(); + // key => value: (1, {2, 3}) => "a" + item->mutable_m()->set_a(1); + item->mutable_m()->add_rc(3); + item->mutable_m()->add_rc(2); + item->set_b("a"); + item = msg2.add_item(); + // key => value: (2, {1, 3}) => "b" + item->mutable_m()->set_a(2); + item->mutable_m()->add_rc(3); + item->mutable_m()->add_rc(1); + item->set_b("b"); + + // Compare + util::MessageDifferencer differencer; + differencer.TreatAsSet(GetFieldDescriptor(msg1, "item.m.rc")); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + vector > key_field_paths; + vector key_field_path1; + key_field_path1.push_back(GetFieldDescriptor(msg1, "item.m")); + key_field_path1.push_back(GetFieldDescriptor(msg1, "item.m.a")); + vector key_field_path2; + key_field_path2.push_back(GetFieldDescriptor(msg1, "item.m")); + key_field_path2.push_back(GetFieldDescriptor(msg1, "item.m.rc")); + key_field_paths.push_back(key_field_path1); + key_field_paths.push_back(key_field_path2); + differencer.TreatAsMapWithMultipleFieldPathsAsKey( + GetFieldDescriptor(msg1, "item"), key_field_paths); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + + // Introduce some differences. + msg1.clear_item(); + msg2.clear_item(); + item = msg1.add_item(); + item->mutable_m()->set_a(4); + item->mutable_m()->add_rc(5); + item->mutable_m()->add_rc(6); + item->set_b("hello"); + item = msg2.add_item(); + item->mutable_m()->set_a(4); + item->mutable_m()->add_rc(6); + item->mutable_m()->add_rc(5); + item->set_b("world"); + string output; + differencer.ReportDifferencesToString(&output); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "modified: item[0].b: \"hello\" -> \"world\"\n" + "moved: item[0].m.rc[0] -> item[0].m.rc[1] : 5\n" + "moved: item[0].m.rc[1] -> item[0].m.rc[0] : 6\n", + output); +} + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_IgnoredKeyFields) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, with key = ("a", "ra") + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->set_a(1); + item->add_ra(2); + item->set_b("hello"); + item = msg2.add_item(); + item->set_a(1); + item->add_ra(3); + item->set_b("world"); + // Compare + util::MessageDifferencer differencer; + vector key_fields; + key_fields.push_back(GetFieldDescriptor(msg1, "item.a")); + key_fields.push_back(GetFieldDescriptor(msg1, "item.ra")); + differencer.TreatAsMapWithMultipleFieldsAsKey( + GetFieldDescriptor(msg1, "item"), key_fields); + string output; + differencer.ReportDifferencesToString(&output); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "added: item[0]: { a: 1 ra: 3 b: \"world\" }\n" + "deleted: item[0]: { a: 1 ra: 2 b: \"hello\" }\n", + output); + // Ignored fields that are listed as parts of the key are still used + // in key comparison, but they're not used in value comparison. + differencer.IgnoreField(GetFieldDescriptor(msg1, "item.ra")); + output.clear(); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "added: item[0]: { a: 1 ra: 3 b: \"world\" }\n" + "deleted: item[0]: { a: 1 ra: 2 b: \"hello\" }\n", + output); + // Ignoring a field in the key is different from treating the left fields + // as key. That is: + // (key = ("a", "ra") && ignore "ra") != (key = ("a") && ignore "ra") + util::MessageDifferencer differencer2; + differencer2.TreatAsMap(GetFieldDescriptor(msg1, "item"), + GetFieldDescriptor(msg1, "item.a")); + differencer2.IgnoreField(GetFieldDescriptor(msg1, "item.ra")); + output.clear(); + differencer2.ReportDifferencesToString(&output); + EXPECT_FALSE(differencer2.Compare(msg1, msg2)); + EXPECT_EQ( + "ignored: item[0].ra\n" + "modified: item[0].b: \"hello\" -> \"world\"\n", + output); +} + +static const char* const kIgnoredFields[] = {"rm.b", "rm.m.b"}; + +class TestIgnorer : public util::MessageDifferencer::IgnoreCriteria { + public: + bool IsIgnored( + const Message& message1, const Message& message2, + const FieldDescriptor* field, + const vector& parent_fields) + override { + string name = ""; + for (int i = 0; i < parent_fields.size(); ++i) { + name += parent_fields[i].field->name() + "."; + } + name += field->name(); + for (int i = 0; i < GOOGLE_ARRAYSIZE(kIgnoredFields); ++i) { + if (name.compare(kIgnoredFields[i]) == 0) { + return true; + } + } + return false; + } +}; + +TEST(MessageDifferencerTest, TreatRepeatedFieldAsSetWithIgnoredFields) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + TextFormat::MergeFromString("rm { a: 11\n b: 12 }", &msg1); + TextFormat::MergeFromString("rm { a: 11\n b: 13 }", &msg2); + util::MessageDifferencer differ; + differ.TreatAsSet(GetFieldDescriptor(msg1, "rm")); + differ.AddIgnoreCriteria(new TestIgnorer); + EXPECT_TRUE(differ.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, TreatRepeatedFieldAsMapWithIgnoredKeyFields) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + TextFormat::MergeFromString("rm { a: 11\n m { a: 12\n b: 13\n } }", &msg1); + TextFormat::MergeFromString("rm { a: 11\n m { a: 12\n b: 14\n } }", &msg2); + util::MessageDifferencer differ; + differ.TreatAsMap(GetFieldDescriptor(msg1, "rm"), + GetFieldDescriptor(msg1, "rm.m")); + differ.AddIgnoreCriteria(new TestIgnorer); + EXPECT_TRUE(differ.Compare(msg1, msg2)); +} + +// Takes the product of all elements of item.ra as the key for key comparison. +class ValueProductMapKeyComparator + : public util::MessageDifferencer::MapKeyComparator { + public: + virtual bool IsMatch(const Message &message1, + const Message &message2) const { + const Reflection* reflection1 = message1.GetReflection(); + const Reflection* reflection2 = message2.GetReflection(); + // FieldDescriptor for item.ra + const FieldDescriptor* ra_field = + message1.GetDescriptor()->FindFieldByName("ra"); + // Get the product of all elements in item.ra + int result1 = 1, result2 = 1; + for (int i = 0; i < reflection1->FieldSize(message1, ra_field); ++i) { + result1 *= reflection1->GetRepeatedInt32(message1, ra_field, i); + } + for (int i = 0; i < reflection2->FieldSize(message2, ra_field); ++i) { + result2 *= reflection2->GetRepeatedInt32(message2, ra_field, i); + } + return result1 == result2; + } +}; + +TEST(MessageDifferencerTest, RepeatedFieldMapTest_CustomMapKeyComparator) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + // Treat "item" as Map, using custom key comparator to determine if two + // elements have the same key. + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->add_ra(6); + item->add_ra(35); + item->set_b("hello"); + item = msg2.add_item(); + item->add_ra(10); + item->add_ra(21); + item->set_b("hello"); + util::MessageDifferencer differencer; + ValueProductMapKeyComparator key_comparator; + differencer.TreatAsMapUsingKeyComparator( + GetFieldDescriptor(msg1, "item"), &key_comparator); + string output; + differencer.ReportDifferencesToString(&output); + // Though the above two messages have different values for item.ra, they + // are regarded as having the same key because 6 * 35 == 10 * 21. That's + // how the key comparator determines if the two have the same key. + // However, in value comparison, all fields of the message are taken into + // consideration, so they are different because their item.ra fields have + // different values using normal value comparison. + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "modified: item[0].ra[0]: 6 -> 10\n" + "modified: item[0].ra[1]: 35 -> 21\n", + output); + differencer.IgnoreField(GetFieldDescriptor(msg1, "item.ra")); + output.clear(); + // item.ra is ignored in value comparison, so the two messages equal. + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + EXPECT_EQ("ignored: item[0].ra\n", output); +} + +TEST(MessageDifferencerTest, RepeatedFieldSetTest_Subset) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + msg1.add_rv(3); + msg1.add_rv(8); + msg1.add_rv(2); + msg2.add_rv(2); + msg2.add_rv(3); + msg2.add_rv(5); + msg2.add_rv(8); + + util::MessageDifferencer differencer; + + // Fail with only partial scope set. + differencer.set_scope(util::MessageDifferencer::PARTIAL); + differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_LIST); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Fail with only set-like comparison set. + differencer.set_scope(util::MessageDifferencer::FULL); + differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET); + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + // Succeed with scope and repeated field comparison set properly. + differencer.set_scope(util::MessageDifferencer::PARTIAL); + differencer.set_repeated_field_comparison(util::MessageDifferencer::AS_SET); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, IgnoreField_Single) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + + msg2.set_c(5); + msg2.add_rc(1); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "c")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_Repeated) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + msg1.add_rc(2); + + msg2.set_c(3); + msg2.add_rc(1); + msg2.add_rc(3); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "rc")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_Message) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestField* field; + + field = msg1.add_rm(); + field->set_c(3); + + field = msg2.add_rm(); + field->set_c(4); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "rm")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_Group) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(3); + + item = msg2.add_item(); + item->set_a(4); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "item")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_Missing) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + + msg2.add_rc(1); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "c")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); + ExpectEqualsWithDifferencer(&differencer, msg2, msg1); +} + +TEST(MessageDifferencerTest, IgnoreField_Multiple) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + msg1.add_rc(2); + + msg2.set_c(5); + msg2.add_rc(1); + msg2.add_rc(3); + + const FieldDescriptor* c = GetFieldDescriptor(msg1, "c"); + const FieldDescriptor* rc = GetFieldDescriptor(msg1, "rc"); + + { // Ignore c + util::MessageDifferencer differencer; + differencer.IgnoreField(c); + + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + } + { // Ignore rc + util::MessageDifferencer differencer; + differencer.IgnoreField(rc); + + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + } + { // Ignore both + util::MessageDifferencer differencer; + differencer.IgnoreField(c); + differencer.IgnoreField(rc); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); + } +} + +TEST(MessageDifferencerTest, IgnoreField_NestedMessage) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestField* field; + + field = msg1.add_rm(); + field->set_c(3); + field->add_rc(1); + + field = msg2.add_rm(); + field->set_c(4); + field->add_rc(1); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "rm.c")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_NestedGroup) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(3); + item->set_b("foo"); + + item = msg2.add_item(); + item->set_a(4); + item->set_b("foo"); + + util::MessageDifferencer differencer; + differencer.IgnoreField(GetFieldDescriptor(msg1, "item.a")); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_InsideSet) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(1); + item->set_b("foo"); + item->add_ra(1); + + item = msg1.add_item(); + item->set_a(2); + item->set_b("bar"); + item->add_ra(2); + + item = msg2.add_item(); + item->set_a(2); + item->set_b("bar"); + item->add_ra(2); + + item = msg2.add_item(); + item->set_a(1); + item->set_b("baz"); + item->add_ra(1); + + const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item"); + const FieldDescriptor* b = GetFieldDescriptor(msg1, "item.b"); + + util::MessageDifferencer differencer; + differencer.IgnoreField(b); + differencer.TreatAsSet(item_desc); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_InsideMap) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(1); + item->set_b("foo"); + item->add_ra(1); + + item = msg1.add_item(); + item->set_a(2); + item->set_b("bar"); + item->add_ra(2); + + item = msg2.add_item(); + item->set_a(2); + item->set_b("bar"); + item->add_ra(2); + + item = msg2.add_item(); + item->set_a(1); + item->set_b("baz"); + item->add_ra(1); + + const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item"); + const FieldDescriptor* a = GetFieldDescriptor(msg1, "item.a"); + const FieldDescriptor* b = GetFieldDescriptor(msg1, "item.b"); + + util::MessageDifferencer differencer; + differencer.IgnoreField(b); + differencer.TreatAsMap(item_desc, a); + + ExpectEqualsWithDifferencer(&differencer, msg1, msg2); +} + +TEST(MessageDifferencerTest, IgnoreField_DoesNotIgnoreKey) { + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item; + + item = msg1.add_item(); + item->set_a(1); + item->set_b("foo"); + item->add_ra(1); + + item = msg2.add_item(); + item->set_a(2); + item->set_b("foo"); + item->add_ra(1); + + const FieldDescriptor* item_desc = GetFieldDescriptor(msg1, "item"); + const FieldDescriptor* a = GetFieldDescriptor(msg1, "item.a"); + + util::MessageDifferencer differencer; + differencer.IgnoreField(a); + differencer.TreatAsMap(item_desc, a); + + EXPECT_FALSE(differencer.Compare(msg1, msg2)); +} + +TEST(MessageDifferencerTest, IgnoreField_TrumpsCompareWithFields) { + protobuf_unittest::TestField msg1; + protobuf_unittest::TestField msg2; + + msg1.set_c(3); + msg1.add_rc(1); + msg1.add_rc(2); + + msg2.set_c(3); + msg2.add_rc(1); + msg2.add_rc(3); + + const FieldDescriptor* c = GetFieldDescriptor(msg1, "c"); + const FieldDescriptor* rc = GetFieldDescriptor(msg1, "rc"); + + vector fields; + fields.push_back(c); + fields.push_back(rc); + + util::MessageDifferencer differencer; + differencer.IgnoreField(rc); + + differencer.set_scope(util::MessageDifferencer::FULL); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields, fields)); + + differencer.set_scope(util::MessageDifferencer::PARTIAL); + EXPECT_TRUE(differencer.CompareWithFields(msg1, msg2, fields, fields)); +} + + +// Test class to save a copy of the last field_context.parent_fields() vector +// passed to the comparison function. +class ParentSavingFieldComparator : public util::FieldComparator { + public: + ParentSavingFieldComparator() {} + + virtual ComparisonResult Compare( + const google::protobuf::Message& message_1, + const google::protobuf::Message& message_2, + const google::protobuf::FieldDescriptor* field, + int index_1, int index_2, + const google::protobuf::util::FieldContext* field_context) { + if (field_context) + parent_fields_ = *(field_context->parent_fields()); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + return RECURSE; + } else { + return SAME; + } + } + + vector parent_fields() { + return parent_fields_; + } + + private: + vector parent_fields_; +}; + +// Tests if MessageDifferencer sends the parent fields in the FieldContext +// parameter. +TEST(MessageDifferencerTest, FieldContextParentFieldsTest) { + protobuf_unittest::TestDiffMessage msg1; + msg1.add_rm()->set_c(1); + protobuf_unittest::TestDiffMessage msg2; + msg2.add_rm()->set_c(1); + + ParentSavingFieldComparator field_comparator; + util::MessageDifferencer differencer; + differencer.set_field_comparator(&field_comparator); + differencer.Compare(msg1, msg2); + + // We want only one parent with the name "rm" + ASSERT_EQ(1, field_comparator.parent_fields().size()); + EXPECT_EQ("rm", field_comparator.parent_fields()[0].field->name()); +} + + +class ComparisonTest : public testing::Test { + protected: + ComparisonTest() : use_equivalency_(false), repeated_field_as_set_(false) { + // Setup the test. + TestUtil::SetAllFields(&proto1_); + TestUtil::SetAllFields(&proto2_); + + TestUtil::SetAllExtensions(&proto1ex_); + TestUtil::SetAllExtensions(&proto2ex_); + + TestUtil::SetAllFieldsAndExtensions(&orderings_proto1_); + TestUtil::SetAllFieldsAndExtensions(&orderings_proto2_); + + unknown1_ = empty1_.mutable_unknown_fields(); + unknown2_ = empty2_.mutable_unknown_fields(); + } + + ~ComparisonTest() { } + + void SetSpecialFieldOption(const Message& message, + util::MessageDifferencer* d) { + if (!ignored_field_.empty()) { + d->IgnoreField(GetFieldDescriptor(message, ignored_field_)); + } + + if (repeated_field_as_set_) { + d->set_repeated_field_comparison(util::MessageDifferencer::AS_SET); + } + + if (!set_field_.empty()) { + d->TreatAsSet(GetFieldDescriptor(message, set_field_)); + } + + if (!map_field_.empty() && !map_key_.empty()) { + d->TreatAsMap(GetFieldDescriptor(message, map_field_), + GetFieldDescriptor(message, map_field_ + "." + map_key_)); + } + } + + string Run(const Message& msg1, const Message& msg2) { + string output; + + // Setup the comparison. + util::MessageDifferencer differencer; + differencer.ReportDifferencesToString(&output); + + if (use_equivalency_) { + differencer.set_message_field_comparison( + util::MessageDifferencer::EQUIVALENT); + } + + SetSpecialFieldOption(msg1, &differencer); + + // Conduct the comparison. + EXPECT_FALSE(differencer.Compare(msg1, msg2)); + + return output; + } + + string Run() { + return Run(proto1_, proto2_); + } + + string RunOrder() { + return Run(orderings_proto1_, orderings_proto2_); + } + + string RunEx() { + return Run(proto1ex_, proto2ex_); + } + + string RunDiff() { + return Run(proto1diff_, proto2diff_); + } + + string RunUn() { + return Run(empty1_, empty2_); + } + + void use_equivalency() { + use_equivalency_ = true; + } + + void repeated_field_as_set() { + repeated_field_as_set_ = true; + } + + void field_as_set(const string& field) { + set_field_ = field; + } + + void field_as_map(const string& field, const string& key) { + map_field_ = field; + map_key_ = key; + } + + void ignore_field(const string& field) { + ignored_field_ = field; + } + + unittest::TestAllTypes proto1_; + unittest::TestAllTypes proto2_; + + unittest::TestFieldOrderings orderings_proto1_; + unittest::TestFieldOrderings orderings_proto2_; + + unittest::TestAllExtensions proto1ex_; + unittest::TestAllExtensions proto2ex_; + + unittest::TestDiffMessage proto1diff_; + unittest::TestDiffMessage proto2diff_; + + unittest::TestEmptyMessage empty1_; + unittest::TestEmptyMessage empty2_; + + UnknownFieldSet* unknown1_; + UnknownFieldSet* unknown2_; + + bool use_equivalency_; + bool repeated_field_as_set_; + + string set_field_; + string map_field_; + string map_key_; + string ignored_field_; +}; + +// Basic tests. +TEST_F(ComparisonTest, AdditionTest) { + proto1_.clear_optional_int32(); + + EXPECT_EQ("added: optional_int32: 101\n", + Run()); +} + +TEST_F(ComparisonTest, Addition_OrderTest) { + orderings_proto1_.clear_my_int(); + + EXPECT_EQ("added: my_int: 1\n", + RunOrder()); +} + +TEST_F(ComparisonTest, DeletionTest) { + proto2_.clear_optional_int32(); + + EXPECT_EQ("deleted: optional_int32: 101\n", + Run()); +} + +TEST_F(ComparisonTest, Deletion_OrderTest) { + orderings_proto2_.clear_my_string(); + + EXPECT_EQ("deleted: my_string: \"foo\"\n", + RunOrder()); +} + +TEST_F(ComparisonTest, RepeatedDeletionTest) { + proto2_.clear_repeated_int32(); + + EXPECT_EQ("deleted: repeated_int32[0]: 201\n" + "deleted: repeated_int32[1]: 301\n", + Run()); +} + +TEST_F(ComparisonTest, ModificationTest) { + proto1_.set_optional_int32(-1); + + EXPECT_EQ("modified: optional_int32: -1 -> 101\n", + Run()); +} + +// Basic equivalency tests. +TEST_F(ComparisonTest, EquivalencyAdditionTest) { + use_equivalency(); + + proto1_.clear_optional_int32(); + + EXPECT_EQ("modified: optional_int32: 0 -> 101\n", + Run()); +} + +TEST_F(ComparisonTest, EquivalencyDeletionTest) { + use_equivalency(); + + proto2_.clear_optional_int32(); + + EXPECT_EQ("modified: optional_int32: 101 -> 0\n", + Run()); +} + +// Group tests. +TEST_F(ComparisonTest, GroupAdditionTest) { + proto1_.mutable_optionalgroup()->clear_a(); + + EXPECT_EQ("added: optionalgroup.a: 117\n", + Run()); +} + +TEST_F(ComparisonTest, GroupDeletionTest) { + proto2_.mutable_optionalgroup()->clear_a(); + + EXPECT_EQ("deleted: optionalgroup.a: 117\n", + Run()); +} + +TEST_F(ComparisonTest, GroupModificationTest) { + proto1_.mutable_optionalgroup()->set_a(2); + + EXPECT_EQ("modified: optionalgroup.a: 2 -> 117\n", + Run()); +} + +TEST_F(ComparisonTest, GroupFullAdditionTest) { + proto1_.clear_optionalgroup(); + + // Note the difference in the output between this and GroupAdditionTest. + EXPECT_EQ("added: optionalgroup: { a: 117 }\n", + Run()); +} + +TEST_F(ComparisonTest, GroupFullDeletionTest) { + proto2_.clear_optionalgroup(); + + EXPECT_EQ("deleted: optionalgroup: { a: 117 }\n", + Run()); +} + +TEST_F(ComparisonTest, RepeatedSetOptionTest) { + repeated_field_as_set(); + + proto2_.clear_repeatedgroup(); + proto1_.clear_repeatedgroup(); + proto1_.add_repeatedgroup()->set_a(317); + proto2_.add_repeatedgroup()->set_a(909); + proto2_.add_repeatedgroup()->set_a(907); + proto1_.add_repeatedgroup()->set_a(904); + proto1_.add_repeatedgroup()->set_a(907); + proto1_.add_repeatedgroup()->set_a(909); + + EXPECT_EQ("moved: repeatedgroup[2] -> repeatedgroup[1] : { a: 907 }\n" + "moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n" + "deleted: repeatedgroup[0]: { a: 317 }\n" + "deleted: repeatedgroup[1]: { a: 904 }\n", + Run()); +} + +TEST_F(ComparisonTest, RepeatedSetOptionTest_Ex) { + repeated_field_as_set(); + + proto1ex_.ClearExtension(protobuf_unittest::repeated_nested_message_extension); + proto2ex_.ClearExtension(protobuf_unittest::repeated_nested_message_extension); + proto2ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(909); + proto2ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(907); + proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(904); + proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(907); + proto1ex_.AddExtension(protobuf_unittest::repeated_nested_message_extension) + ->set_bb(909); + + EXPECT_EQ("moved: (protobuf_unittest.repeated_nested_message_extension)[2] ->" + " (protobuf_unittest.repeated_nested_message_extension)[0] :" + " { bb: 909 }\n" + "deleted: (protobuf_unittest.repeated_nested_message_extension)[0]:" + " { bb: 904 }\n", + RunEx()); +} + +TEST_F(ComparisonTest, RepeatedMapFieldTest_Group) { + field_as_map("repeatedgroup", "a"); + proto1_.clear_repeatedgroup(); + proto2_.clear_repeatedgroup(); + + proto1_.add_repeatedgroup()->set_a(317); // deleted + proto1_.add_repeatedgroup()->set_a(904); // deleted + proto1_.add_repeatedgroup()->set_a(907); // moved from + proto1_.add_repeatedgroup()->set_a(909); // moved from + + proto2_.add_repeatedgroup()->set_a(909); // moved to + proto2_.add_repeatedgroup()->set_a(318); // added + proto2_.add_repeatedgroup()->set_a(907); // moved to + + EXPECT_EQ("moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n" + "added: repeatedgroup[1]: { a: 318 }\n" + "deleted: repeatedgroup[0]: { a: 317 }\n" + "deleted: repeatedgroup[1]: { a: 904 }\n", + Run()); +} + +TEST_F(ComparisonTest, RepeatedMapFieldTest_MessageKey) { + // Use m as key, but use b as value. + field_as_map("item", "m"); + + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + + // The following code creates one deletion, one addition and two moved fields + // on the messages. + item->mutable_m()->set_c(0); + item->set_b("first"); + item = msg1.add_item(); + item->mutable_m()->set_c(2); + item->set_b("second"); + item = msg1.add_item(); item->set_b("null"); // empty key moved + item = msg1.add_item(); + item->mutable_m()->set_c(3); + item->set_b("third"); // deletion + item = msg1.add_item(); + item->mutable_m()->set_c(2); + item->set_b("second"); // duplicated key ( deletion ) + item = msg2.add_item(); + item->mutable_m()->set_c(2); + item->set_b("second"); // modification + item = msg2.add_item(); + item->mutable_m()->set_c(4); + item->set_b("fourth"); // addition + item = msg2.add_item(); + item->mutable_m()->set_c(0); + item->set_b("fist"); // move with change + item = msg2.add_item(); item->set_b("null"); + + EXPECT_EQ( + "modified: item[0].b -> item[2].b: \"first\" -> \"fist\"\n" + "moved: item[1] -> item[0] : { b: \"second\" m { c: 2 } }\n" + "moved: item[2] -> item[3] : { b: \"null\" }\n" + "added: item[1]: { b: \"fourth\" m { c: 4 } }\n" + "deleted: item[3]: { b: \"third\" m { c: 3 } }\n" + "deleted: item[4]: { b: \"second\" m { c: 2 } }\n", + Run(msg1, msg2)); +} + +TEST_F(ComparisonTest, RepeatedFieldSetTest_SetOfSet) { + repeated_field_as_set(); + // Create the testing protos + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->add_ra(1); item->add_ra(2); item->add_ra(3); + item = msg1.add_item(); + item->add_ra(5); item->add_ra(6); + item = msg1.add_item(); + item->add_ra(1); item->add_ra(3); + item = msg1.add_item(); + item->add_ra(6); item->add_ra(7); item->add_ra(8); + + item = msg2.add_item(); + item->add_ra(6); item->add_ra(5); + item = msg2.add_item(); + item->add_ra(6); item->add_ra(8); + item = msg2.add_item(); + item->add_ra(1); item->add_ra(3); + item = msg2.add_item(); + item->add_ra(3); item->add_ra(2); item->add_ra(1); + + // Compare + EXPECT_EQ("moved: item[0].ra[0] -> item[3].ra[2] : 1\n" + "moved: item[0].ra[2] -> item[3].ra[0] : 3\n" + "moved: item[0] -> item[3] : { ra: 1 ra: 2 ra: 3 }\n" + "moved: item[1].ra[0] -> item[0].ra[1] : 5\n" + "moved: item[1].ra[1] -> item[0].ra[0] : 6\n" + "moved: item[1] -> item[0] : { ra: 5 ra: 6 }\n" + "added: item[1]: { ra: 6 ra: 8 }\n" + "deleted: item[3]: { ra: 6 ra: 7 ra: 8 }\n", + Run(msg1, msg2)); +} + +TEST_F(ComparisonTest, RepeatedMapFieldTest_RepeatedKey) { + // used rb as a key, but b is the value. + repeated_field_as_set(); + field_as_map("item", "rb"); + + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->add_rb("a"); + item->add_rb("b"); + item->set_b("first"); + + item = msg2.add_item(); + item->add_rb("c"); + item->set_b("second"); + + item = msg2.add_item(); + item->add_rb("b"); + item->add_rb("a"); + item->set_b("fist"); + + + EXPECT_EQ("modified: item[0].b -> item[1].b: \"first\" -> \"fist\"\n" + "moved: item[0].rb[0] -> item[1].rb[1] : \"a\"\n" + "moved: item[0].rb[1] -> item[1].rb[0] : \"b\"\n" + "added: item[0]: { b: \"second\" rb: \"c\" }\n", + Run(msg1, msg2)); +} + +TEST_F(ComparisonTest, RepeatedMapFieldTest_RepeatedMessageKey) { + field_as_map("item", "rm"); + + protobuf_unittest::TestDiffMessage msg1; + protobuf_unittest::TestDiffMessage msg2; + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + protobuf_unittest::TestField* key = item->add_rm(); + key->set_c(2); key->add_rc(10); key->add_rc(10); + item = msg1.add_item(); key = item->add_rm(); + key->set_c(0); key->add_rc(1); key->add_rc(2); + key = item->add_rm(); + key->set_c(0); + item->add_rb("first"); + + item = msg2.add_item(); + item->CopyFrom(msg1.item(1)); + item->add_rb("second"); + + EXPECT_EQ("added: item[0].rb[1]: \"second\"\n" + "deleted: item[0]: { rm { c: 2 rc: 10 rc: 10 } }\n", + Run(msg1, msg2)); +} + +TEST_F(ComparisonTest, RepeatedSetOptionTest_Unknown) { + // Currently, as_set option doens't have affects on unknown field. + // If needed, this feature will be added by request. + repeated_field_as_set(); + unknown1_->AddGroup(245)->AddFixed32(248, 1); + unknown2_->AddGroup(245)->AddFixed32(248, 3); + unknown2_->AddGroup(245)->AddFixed32(248, 1); + + // We expect it behaves the same as normal comparison. + EXPECT_EQ("modified: 245[0].248[0]: 0x00000001 -> 0x00000003\n" + "added: 245[1]: { ... }\n", + RunUn()); +} + +TEST_F(ComparisonTest, Matching_Unknown) { + unknown1_->AddGroup(245)->AddFixed32(248, 1); + unknown2_->AddGroup(245)->AddFixed32(248, 1); + unknown1_->AddGroup(245)->AddFixed32(248, 3); + unknown2_->AddGroup(245)->AddFixed32(248, 3); + unknown2_->AddLengthDelimited(242, "cat"); + unknown2_->AddGroup(246)->AddFixed32(248, 4); + + // report_match is false so only added/modified fields are expected. + EXPECT_EQ("added: 242[0]: \"cat\"\n" + "added: 246[0]: { ... }\n", + RunUn()); +} + +TEST_F(ComparisonTest, RepeatedSetFieldTest) { + field_as_set("repeatedgroup"); + + proto1_.clear_repeatedgroup(); + proto2_.clear_repeatedgroup(); + proto2_.add_repeatedgroup()->set_a(909); + proto2_.add_repeatedgroup()->set_a(907); + proto1_.add_repeatedgroup()->set_a(317); + proto1_.add_repeatedgroup()->set_a(904); + proto1_.add_repeatedgroup()->set_a(907); + proto1_.add_repeatedgroup()->set_a(909); + + EXPECT_EQ("moved: repeatedgroup[2] -> repeatedgroup[1] : { a: 907 }\n" + "moved: repeatedgroup[3] -> repeatedgroup[0] : { a: 909 }\n" + "deleted: repeatedgroup[0]: { a: 317 }\n" + "deleted: repeatedgroup[1]: { a: 904 }\n", + Run()); +} + +// Embedded message tests. +TEST_F(ComparisonTest, EmbeddedAdditionTest) { + proto1_.mutable_optional_nested_message()->clear_bb(); + + EXPECT_EQ("added: optional_nested_message.bb: 118\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedDeletionTest) { + proto2_.mutable_optional_nested_message()->clear_bb(); + + EXPECT_EQ("deleted: optional_nested_message.bb: 118\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedModificationTest) { + proto1_.mutable_optional_nested_message()->set_bb(2); + + EXPECT_EQ("modified: optional_nested_message.bb: 2 -> 118\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedFullAdditionTest) { + proto1_.clear_optional_nested_message(); + + EXPECT_EQ("added: optional_nested_message: { bb: 118 }\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedPartialAdditionTest) { + proto1_.clear_optional_nested_message(); + proto2_.mutable_optional_nested_message()->clear_bb(); + + EXPECT_EQ("added: optional_nested_message: { }\n", + Run()); +} + +TEST_F(ComparisonTest, EmbeddedFullDeletionTest) { + proto2_.clear_optional_nested_message(); + + EXPECT_EQ("deleted: optional_nested_message: { bb: 118 }\n", + Run()); +} + +// Repeated element tests. +TEST_F(ComparisonTest, BasicRepeatedTest) { + proto1_.clear_repeated_int32(); + proto2_.clear_repeated_int32(); + + proto1_.add_repeated_int32(500); + proto1_.add_repeated_int32(501); + proto1_.add_repeated_int32(502); + proto1_.add_repeated_int32(503); + proto1_.add_repeated_int32(500); + + proto2_.add_repeated_int32(500); + proto2_.add_repeated_int32(509); + proto2_.add_repeated_int32(502); + proto2_.add_repeated_int32(504); + + EXPECT_EQ("modified: repeated_int32[1]: 501 -> 509\n" + "modified: repeated_int32[3]: 503 -> 504\n" + "deleted: repeated_int32[4]: 500\n", + Run()); +} + +TEST_F(ComparisonTest, BasicRepeatedTest_SetOption) { + repeated_field_as_set(); + proto1_.clear_repeated_int32(); + proto2_.clear_repeated_int32(); + + proto1_.add_repeated_int32(501); + proto1_.add_repeated_int32(502); + proto1_.add_repeated_int32(503); + proto1_.add_repeated_int32(500); + proto1_.add_repeated_int32(500); + + proto2_.add_repeated_int32(500); + proto2_.add_repeated_int32(509); + proto2_.add_repeated_int32(503); + proto2_.add_repeated_int32(502); + proto2_.add_repeated_int32(504); + + EXPECT_EQ("moved: repeated_int32[1] -> repeated_int32[3] : 502\n" + "moved: repeated_int32[3] -> repeated_int32[0] : 500\n" + "added: repeated_int32[1]: 509\n" + "added: repeated_int32[4]: 504\n" + "deleted: repeated_int32[0]: 501\n" + "deleted: repeated_int32[4]: 500\n", + Run()); +} + +TEST_F(ComparisonTest, BasicRepeatedTest_SetField) { + field_as_set("repeated_int32"); + proto1_.clear_repeated_int32(); + proto2_.clear_repeated_int32(); + + proto1_.add_repeated_int32(501); + proto1_.add_repeated_int32(502); + proto1_.add_repeated_int32(503); + proto1_.add_repeated_int32(500); + proto1_.add_repeated_int32(500); + + proto2_.add_repeated_int32(500); + proto2_.add_repeated_int32(509); + proto2_.add_repeated_int32(503); + proto2_.add_repeated_int32(502); + proto2_.add_repeated_int32(504); + + EXPECT_EQ("moved: repeated_int32[1] -> repeated_int32[3] : 502\n" + "moved: repeated_int32[3] -> repeated_int32[0] : 500\n" + "added: repeated_int32[1]: 509\n" + "added: repeated_int32[4]: 504\n" + "deleted: repeated_int32[0]: 501\n" + "deleted: repeated_int32[4]: 500\n", + Run()); +} + +// Multiple action tests. +TEST_F(ComparisonTest, AddDeleteTest) { + proto1_.clear_optional_int32(); + proto2_.clear_optional_int64(); + + EXPECT_EQ("added: optional_int32: 101\n" + "deleted: optional_int64: 102\n", + Run()); +} + +TEST_F(ComparisonTest, AddDelete_FieldOrderingTest) { + orderings_proto1_.ClearExtension(unittest::my_extension_string); + orderings_proto2_.clear_my_int(); + + EXPECT_EQ("deleted: my_int: 1\n" + "added: (protobuf_unittest.my_extension_string): \"bar\"\n", + RunOrder()); +} + +TEST_F(ComparisonTest, AllThreeTest) { + proto1_.clear_optional_int32(); + proto2_.clear_optional_float(); + proto2_.set_optional_string("hello world!"); + + EXPECT_EQ("added: optional_int32: 101\n" + "deleted: optional_float: 111\n" + "modified: optional_string: \"115\" -> \"hello world!\"\n", + Run()); +} + +TEST_F(ComparisonTest, SandwhichTest) { + proto1_.clear_optional_int64(); + proto1_.clear_optional_uint32(); + + proto2_.clear_optional_uint64(); + + EXPECT_EQ("added: optional_int64: 102\n" + "added: optional_uint32: 103\n" + "deleted: optional_uint64: 104\n", + Run()); +} + +TEST_F(ComparisonTest, IgnoredNoChangeTest) { + proto1diff_.set_v(3); + proto2diff_.set_v(3); + proto2diff_.set_w("foo"); + + ignore_field("v"); + + EXPECT_EQ("ignored: v\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredAddTest) { + proto2diff_.set_v(3); + proto2diff_.set_w("foo"); + + ignore_field("v"); + + EXPECT_EQ("ignored: v\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredDeleteTest) { + proto1diff_.set_v(3); + proto2diff_.set_w("foo"); + + ignore_field("v"); + + EXPECT_EQ("ignored: v\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredModifyTest) { + proto1diff_.set_v(3); + proto2diff_.set_v(4); + proto2diff_.set_w("foo"); + + ignore_field("v"); + + EXPECT_EQ("ignored: v\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredRepeatedAddTest) { + proto1diff_.add_rv(3); + proto1diff_.add_rv(4); + + proto2diff_.add_rv(3); + proto2diff_.add_rv(4); + proto2diff_.add_rv(5); + + proto2diff_.set_w("foo"); + + ignore_field("rv"); + + EXPECT_EQ("ignored: rv\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredRepeatedDeleteTest) { + proto1diff_.add_rv(3); + proto1diff_.add_rv(4); + proto1diff_.add_rv(5); + + proto2diff_.add_rv(3); + proto2diff_.add_rv(4); + + proto2diff_.set_w("foo"); + + ignore_field("rv"); + + EXPECT_EQ("ignored: rv\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredRepeatedModifyTest) { + proto1diff_.add_rv(3); + proto1diff_.add_rv(4); + + proto2diff_.add_rv(3); + proto2diff_.add_rv(5); + + proto2diff_.set_w("foo"); + + ignore_field("rv"); + + EXPECT_EQ("ignored: rv\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredWholeNestedMessage) { + proto1diff_.mutable_m()->set_c(3); + proto2diff_.mutable_m()->set_c(4); + + proto2diff_.set_w("foo"); + + ignore_field("m"); + + EXPECT_EQ("added: w: \"foo\"\n" + "ignored: m\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredNestedField) { + proto1diff_.mutable_m()->set_c(3); + proto2diff_.mutable_m()->set_c(4); + + proto2diff_.set_w("foo"); + + ignore_field("m.c"); + + EXPECT_EQ("added: w: \"foo\"\n" + "ignored: m.c\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredRepeatedNested) { + proto1diff_.add_rm()->set_c(0); + proto1diff_.add_rm()->set_c(1); + proto2diff_.add_rm()->set_c(2); + proto2diff_.add_rm()->set_c(3); + + proto2diff_.set_w("foo"); + + ignore_field("rm.c"); + + EXPECT_EQ("ignored: rm[0].c\n" + "ignored: rm[1].c\n" + "added: w: \"foo\"\n", + RunDiff()); +} + +TEST_F(ComparisonTest, IgnoredNestedRepeated) { + proto1diff_.mutable_m()->add_rc(23); + proto1diff_.mutable_m()->add_rc(24); + proto2diff_.mutable_m()->add_rc(25); + + proto2diff_.set_w("foo"); + + ignore_field("m.rc"); + + EXPECT_EQ("added: w: \"foo\"\n" + "ignored: m.rc\n", + RunDiff()); +} + +TEST_F(ComparisonTest, ExtensionTest) { + proto1ex_.SetExtension(unittest::optional_int32_extension, 401); + proto2ex_.SetExtension(unittest::optional_int32_extension, 402); + + proto1ex_.ClearExtension(unittest::optional_int64_extension); + proto2ex_.SetExtension(unittest::optional_int64_extension, 403); + + EXPECT_EQ( + "modified: (protobuf_unittest.optional_int32_extension): 401 -> 402\n" + "added: (protobuf_unittest.optional_int64_extension): 403\n", + RunEx()); +} + +TEST_F(ComparisonTest, MatchedUnknownFieldTagTest) { + unknown1_->AddVarint(240, 122); + unknown2_->AddVarint(240, 121); + unknown1_->AddFixed32(241, 1); + unknown2_->AddFixed64(241, 2); + unknown1_->AddLengthDelimited(242, "cat"); + unknown2_->AddLengthDelimited(242, "dog"); + + EXPECT_EQ( + "modified: 240[0]: 122 -> 121\n" + "deleted: 241[0]: 0x00000001\n" + "added: 241[0]: 0x0000000000000002\n" + "modified: 242[0]: \"cat\" -> \"dog\"\n", + RunUn()); +} + +TEST_F(ComparisonTest, UnmatchedUnknownFieldTagTest) { + unknown1_->AddFixed32(243, 1); + unknown2_->AddVarint(244, 2); + unknown2_->AddVarint(244, 4); + + EXPECT_EQ( + "deleted: 243[0]: 0x00000001\n" + "added: 244[0]: 2\n" + "added: 244[1]: 4\n", + RunUn()); +} + +TEST_F(ComparisonTest, DifferentSizedUnknownFieldTest) { + unknown1_->AddVarint(240, 1); + unknown1_->AddVarint(240, 3); + unknown1_->AddVarint(240, 4); + unknown2_->AddVarint(240, 2); + unknown2_->AddVarint(240, 3); + unknown2_->AddVarint(240, 2); + unknown2_->AddVarint(240, 5); + + EXPECT_EQ( + "modified: 240[0]: 1 -> 2\n" + "modified: 240[2]: 4 -> 2\n" + "added: 240[3]: 5\n", + RunUn()); +} + +TEST_F(ComparisonTest, UnknownFieldsAll) { + unknown1_->AddVarint(243, 122); + unknown1_->AddFixed64(244, 0x0172356); + unknown1_->AddFixed64(244, 0x098); + unknown1_->AddGroup(245)->AddFixed32(248, 1); + unknown1_->mutable_field(3)->mutable_group()->AddFixed32(248, 2); + unknown1_->AddGroup(249)->AddFixed64(250, 1); + + unknown2_->AddVarint(243, 121); + unknown2_->AddLengthDelimited(73882, "test 123"); + unknown2_->AddGroup(245)->AddFixed32(248, 3); + unknown2_->AddGroup(247); + + EXPECT_EQ( + "modified: 243[0]: 122 -> 121\n" + "deleted: 244[0]: 0x0000000000172356\n" + "deleted: 244[1]: 0x0000000000000098\n" + "modified: 245[0].248[0]: 0x00000001 -> 0x00000003\n" + "deleted: 245[0].248[1]: 0x00000002\n" + "added: 247[0]: { ... }\n" + "deleted: 249[0]: { ... }\n" + "added: 73882[0]: \"test 123\"\n", + RunUn()); +} + +TEST_F(ComparisonTest, EquivalentIgnoresUnknown) { + unittest::ForeignMessage message1, message2; + + message1.set_c(5); + message1.mutable_unknown_fields()->AddVarint(123, 456); + message2.set_c(5); + message2.mutable_unknown_fields()->AddVarint(321, 654); + + EXPECT_FALSE(util::MessageDifferencer::Equals(message1, message2)); + EXPECT_TRUE(util::MessageDifferencer::Equivalent(message1, message2)); +} + +class MatchingTest : public testing::Test { + public: + typedef util::MessageDifferencer MessageDifferencer; + + protected: + MatchingTest() { + } + + ~MatchingTest() { + } + + string RunWithResult(MessageDifferencer* differencer, + const Message& msg1, const Message& msg2, + bool result) { + string output; + io::StringOutputStream output_stream(&output); + MessageDifferencer::StreamReporter reporter(&output_stream); + reporter.set_report_modified_aggregates(true); + differencer->set_report_matches(true); + differencer->ReportDifferencesTo(&reporter); + if (result) { + EXPECT_TRUE(differencer->Compare(msg1, msg2)); + } else { + EXPECT_FALSE(differencer->Compare(msg1, msg2)); + } + return output; + } + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MatchingTest); +}; + +TEST_F(MatchingTest, StreamReporterMatching) { + protobuf_unittest::TestField msg1, msg2; + msg1.set_c(72); + msg2.set_c(72); + msg1.add_rc(13); + msg2.add_rc(13); + msg1.add_rc(17); + msg2.add_rc(17); + string output; + MessageDifferencer differencer; + differencer.set_report_matches(true); + differencer.ReportDifferencesToString(&output); + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "matched: c : 72\n" + "matched: rc[0] : 13\n" + "matched: rc[1] : 17\n", + output); +} + +TEST_F(MatchingTest, DontReportMatchedWhenIgnoring) { + protobuf_unittest::TestField msg1, msg2; + msg1.set_c(72); + msg2.set_c(72); + msg1.add_rc(13); + msg2.add_rc(13); + msg1.add_rc(17); + msg2.add_rc(17); + string output; + MessageDifferencer differencer; + differencer.set_report_matches(true); + differencer.ReportDifferencesToString(&output); + + differencer.IgnoreField(msg1.GetDescriptor()->FindFieldByName("c")); + + EXPECT_TRUE(differencer.Compare(msg1, msg2)); + EXPECT_EQ( + "ignored: c\n" + "matched: rc[0] : 13\n" + "matched: rc[1] : 17\n", + output); +} + +TEST_F(MatchingTest, ReportMatchedForMovedFields) { + protobuf_unittest::TestDiffMessage msg1, msg2; + protobuf_unittest::TestDiffMessage::Item* item = msg1.add_item(); + item->set_a(53); + item->set_b("hello"); + item = msg2.add_item(); + item->set_a(27); + item = msg2.add_item(); + item->set_a(53); + item->set_b("hello"); + item = msg1.add_item(); + item->set_a(27); + MessageDifferencer differencer; + const FieldDescriptor* desc; + desc = msg1.GetDescriptor()->FindFieldByName("item"); + differencer.TreatAsSet(desc); + + EXPECT_EQ( + "matched: item[0].a -> item[1].a : 53\n" + "matched: item[0].b -> item[1].b : \"hello\"\n" + "moved: item[0] -> item[1] : { a: 53 b: \"hello\" }\n" + "matched: item[1].a -> item[0].a : 27\n" + "moved: item[1] -> item[0] : { a: 27 }\n", + RunWithResult(&differencer, msg1, msg2, true)); +} + +TEST_F(MatchingTest, MatchesAppearInPostTraversalOrderForMovedFields) { + protobuf_unittest::TestDiffMessage msg1, msg2; + protobuf_unittest::TestDiffMessage::Item* item; + protobuf_unittest::TestField* field; + + const FieldDescriptor* desc; + const FieldDescriptor* nested_desc; + const FieldDescriptor* double_nested_desc; + desc = msg1.GetDescriptor()->FindFieldByName("item"); + nested_desc = desc->message_type()->FindFieldByName("rm"); + double_nested_desc = nested_desc->message_type()->FindFieldByName("rc"); + MessageDifferencer differencer; + differencer.TreatAsSet(desc); + differencer.TreatAsSet(nested_desc); + differencer.TreatAsSet(double_nested_desc); + + item = msg1.add_item(); + field = item->add_rm(); + field->set_c(1); + field->add_rc(2); + field->add_rc(3); + field = item->add_rm(); + field->set_c(4); + field->add_rc(5); + field->add_rc(6); + field->add_rc(7); + item = msg2.add_item(); + field = item->add_rm(); + field->set_c(4); + field->add_rc(7); + field->add_rc(6); + field->add_rc(5); + field = item->add_rm(); + field->set_c(1); + field->add_rc(3); + field->add_rc(2); + item = msg1.add_item(); + field = item->add_rm(); + field->set_c(8); + field->add_rc(10); + field->add_rc(11); + field->add_rc(9); + item = msg2.add_item(); + field = item->add_rm(); + field->set_c(8); + field->add_rc(9); + field->add_rc(10); + field->add_rc(11); + + EXPECT_EQ( + "matched: item[0].rm[0].c -> item[0].rm[1].c : 1\n" + "moved: item[0].rm[0].rc[0] -> item[0].rm[1].rc[1] : 2\n" + "moved: item[0].rm[0].rc[1] -> item[0].rm[1].rc[0] : 3\n" + "moved: item[0].rm[0] -> item[0].rm[1] : { c: 1 rc: 2 rc: 3 }\n" + "matched: item[0].rm[1].c -> item[0].rm[0].c : 4\n" + "moved: item[0].rm[1].rc[0] -> item[0].rm[0].rc[2] : 5\n" + "matched: item[0].rm[1].rc[1] -> item[0].rm[0].rc[1] : 6\n" + "moved: item[0].rm[1].rc[2] -> item[0].rm[0].rc[0] : 7\n" + "moved: item[0].rm[1] -> item[0].rm[0] : { c: 4 rc: 5 rc: 6 rc: 7 }\n" + "matched: item[0] : { rm { c: 1 rc: 2 rc: 3 }" + " rm { c: 4 rc: 5 rc: 6 rc: 7 } }\n" + "matched: item[1].rm[0].c : 8\n" + "moved: item[1].rm[0].rc[0] -> item[1].rm[0].rc[1] : 10\n" + "moved: item[1].rm[0].rc[1] -> item[1].rm[0].rc[2] : 11\n" + "moved: item[1].rm[0].rc[2] -> item[1].rm[0].rc[0] : 9\n" + "matched: item[1].rm[0] : { c: 8 rc: 10 rc: 11 rc: 9 }\n" + "matched: item[1] : { rm { c: 8 rc: 10 rc: 11 rc: 9 } }\n", + RunWithResult(&differencer, msg1, msg2, true)); +} + +TEST_F(MatchingTest, MatchAndModifiedInterleaveProperly) { + protobuf_unittest::TestDiffMessage msg1, msg2; + protobuf_unittest::TestDiffMessage::Item* item; + protobuf_unittest::TestField* field; + + const FieldDescriptor* desc; + const FieldDescriptor* nested_key; + const FieldDescriptor* nested_desc; + const FieldDescriptor* double_nested_key; + const FieldDescriptor* double_nested_desc; + desc = msg1.GetDescriptor()->FindFieldByName("item"); + nested_key = desc->message_type()->FindFieldByName("a"); + nested_desc = desc->message_type()->FindFieldByName("rm"); + double_nested_key = nested_desc->message_type()->FindFieldByName("c"); + double_nested_desc = nested_desc->message_type()->FindFieldByName("rc"); + + MessageDifferencer differencer; + differencer.TreatAsMap(desc, nested_key); + differencer.TreatAsMap(nested_desc, double_nested_key); + differencer.TreatAsSet(double_nested_desc); + + item = msg1.add_item(); + item->set_a(1); + field = item->add_rm(); + field->set_c(2); + field->add_rc(3); + field->add_rc(4); + field = item->add_rm(); + field->set_c(5); + field->add_rc(6); + field->add_rc(7); + field->add_rc(8); + item = msg1.add_item(); + item->set_a(9); + field = item->add_rm(); + field->set_c(10); + field->add_rc(11); + field->add_rc(12); + field = item->add_rm(); + field->set_c(13); + + item = msg2.add_item(); + item->set_a(1); + field = item->add_rm(); + field->set_c(5); + field->add_rc(8); + field->add_rc(8); + field->add_rc(6); + field = item->add_rm(); + field->set_c(3); + field->add_rc(2); + field->add_rc(4); + item = msg2.add_item(); + item->set_a(9); + field = item->add_rm(); + field->set_c(10); + field->add_rc(12); + field->add_rc(11); + field = item->add_rm(); + field->set_c(13); + + EXPECT_EQ( + "matched: item[0].a : 1\n" + "matched: item[0].rm[1].c -> item[0].rm[0].c : 5\n" + "moved: item[0].rm[1].rc[0] -> item[0].rm[0].rc[2] : 6\n" + "moved: item[0].rm[1].rc[2] -> item[0].rm[0].rc[0] : 8\n" + "added: item[0].rm[0].rc[1]: 8\n" + "deleted: item[0].rm[1].rc[1]: 7\n" + "modified: item[0].rm[1] -> item[0].rm[0]: { c: 5 rc: 6 rc: 7 rc: 8 } ->" + " { c: 5 rc: 8 rc: 8 rc: 6 }\n" + "added: item[0].rm[1]: { c: 3 rc: 2 rc: 4 }\n" + "deleted: item[0].rm[0]: { c: 2 rc: 3 rc: 4 }\n" + "modified: item[0]: { a: 1 rm { c: 2 rc: 3 rc: 4 }" + " rm { c: 5 rc: 6 rc: 7 rc: 8 } } ->" + " { a: 1 rm { c: 5 rc: 8 rc: 8 rc: 6 }" + " rm { c: 3 rc: 2 rc: 4 } }\n" + "matched: item[1].a : 9\n" + "matched: item[1].rm[0].c : 10\n" + "moved: item[1].rm[0].rc[0] -> item[1].rm[0].rc[1] : 11\n" + "moved: item[1].rm[0].rc[1] -> item[1].rm[0].rc[0] : 12\n" + "matched: item[1].rm[0] : { c: 10 rc: 11 rc: 12 }\n" + "matched: item[1].rm[1].c : 13\n" + "matched: item[1].rm[1] : { c: 13 }\n" + "matched: item[1] : { a: 9 rm { c: 10 rc: 11 rc: 12 } rm { c: 13 } }\n", + RunWithResult(&differencer, msg1, msg2, false)); +} + +TEST_F(MatchingTest, MatchingWorksWithExtensions) { + protobuf_unittest::TestAllExtensions msg1, msg2; + protobuf_unittest::TestAllTypes::NestedMessage* nested; + using protobuf_unittest::repeated_nested_message_extension; + + const FileDescriptor* descriptor; + const FieldDescriptor* desc; + const FieldDescriptor* nested_key; + descriptor = msg1.GetDescriptor()->file(); + desc = descriptor->FindExtensionByName("repeated_nested_message_extension"); + ASSERT_FALSE(desc == NULL); + nested_key = desc->message_type()->FindFieldByName("bb"); + + MessageDifferencer differencer; + differencer.TreatAsMap(desc, nested_key); + + nested = msg1.AddExtension(repeated_nested_message_extension); + nested->set_bb(7); + nested = msg1.AddExtension(repeated_nested_message_extension); + nested->set_bb(13); + nested = msg1.AddExtension(repeated_nested_message_extension); + nested->set_bb(11); + nested = msg2.AddExtension(repeated_nested_message_extension); + nested->set_bb(11); + nested = msg2.AddExtension(repeated_nested_message_extension); + nested->set_bb(13); + nested = msg2.AddExtension(repeated_nested_message_extension); + nested->set_bb(7); + + EXPECT_EQ( + "matched: (protobuf_unittest.repeated_nested_message_extension)[0].bb ->" + " (protobuf_unittest.repeated_nested_message_extension)[2].bb : 7\n" + "moved: (protobuf_unittest.repeated_nested_message_extension)[0] ->" + " (protobuf_unittest.repeated_nested_message_extension)[2] :" + " { bb: 7 }\n" + "matched: (protobuf_unittest.repeated_nested_message_extension)[1].bb :" + " 13\n" + "matched: (protobuf_unittest.repeated_nested_message_extension)[1] :" + " { bb: 13 }\n" + "matched: (protobuf_unittest.repeated_nested_message_extension)[2].bb ->" + " (protobuf_unittest.repeated_nested_message_extension)[0].bb :" + " 11\n" + "moved: (protobuf_unittest.repeated_nested_message_extension)[2] ->" + " (protobuf_unittest.repeated_nested_message_extension)[0] :" + " { bb: 11 }\n", + RunWithResult(&differencer, msg1, msg2, true)); +} + +TEST(AnyTest, Simple) { + protobuf_unittest::TestField value1, value2; + value1.set_a(20); + value2.set_a(21); + + protobuf_unittest::TestAny m1, m2; + m1.mutable_any_value()->PackFrom(value1); + m2.mutable_any_value()->PackFrom(value2); + util::MessageDifferencer message_differencer; + string difference_string; + message_differencer.ReportDifferencesToString(&difference_string); + EXPECT_FALSE(message_differencer.Compare(m1, m2)); + EXPECT_EQ("modified: any_value.a: 20 -> 21\n", difference_string); +} + +TEST(Anytest, TreatAsSet) { + protobuf_unittest::TestField value1, value2; + value1.set_a(20); + value1.set_b(30); + value2.set_a(20); + value2.set_b(31); + + protobuf_unittest::TestAny m1, m2; + m1.add_repeated_any_value()->PackFrom(value1); + m1.add_repeated_any_value()->PackFrom(value2); + m2.add_repeated_any_value()->PackFrom(value2); + m2.add_repeated_any_value()->PackFrom(value1); + + util::MessageDifferencer message_differencer; + message_differencer.TreatAsSet(GetFieldDescriptor(m1, "repeated_any_value")); + EXPECT_TRUE(message_differencer.Compare(m1, m2)); +} + + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/util/message_differencer_unittest.proto b/src/google/protobuf/util/message_differencer_unittest.proto new file mode 100644 index 00000000..698775f1 --- /dev/null +++ b/src/google/protobuf/util/message_differencer_unittest.proto @@ -0,0 +1,74 @@ +// 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file contains messages for testing repeated field comparison + +syntax = "proto2"; +package protobuf_unittest; + +option optimize_for = SPEED; + +message TestField { + optional int32 a = 3; + optional int32 b = 4; + optional int32 c = 1; + repeated int32 rc = 2; + optional TestField m = 5; + + extend TestDiffMessage { + optional TestField tf = 100; + } +} + +message TestDiffMessage { + repeated group Item = 1 { + optional int32 a = 2; // Test basic repeated field comparison. + optional string b = 4; // Test basic repeated field comparison. + repeated int32 ra = 3; // Test SetOfSet Comparison. + repeated string rb = 5; // Test TreatAsMap when key is repeated + optional TestField m = 6; // Test TreatAsMap when key is a message + repeated TestField rm = 7; // Test TreatAsMap when key is a repeated + // message + } + + optional int32 v = 13 [deprecated = true]; + optional string w = 14; + optional TestField m = 15; + repeated int32 rv = 11; // Test for combinations + repeated string rw = 10; // Test for combinations + repeated TestField rm = 12 [deprecated = true]; // Test for combinations + + extensions 100 to 199; +} + diff --git a/src/google/protobuf/util/type_resolver.h b/src/google/protobuf/util/type_resolver.h new file mode 100644 index 00000000..77d4416a --- /dev/null +++ b/src/google/protobuf/util/type_resolver.h @@ -0,0 +1,75 @@ +// 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. + +#ifndef GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__ +#define GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__ + +#include + +#include +#include + + +namespace google { +namespace protobuf { +class Type; +class Enum; +} // namespace protobuf + + +namespace protobuf { +class DescriptorPool; +namespace util { + +// Abstract interface for a type resovler. +// +// Implementations of this interface must be thread-safe. +class LIBPROTOBUF_EXPORT TypeResolver { + public: + TypeResolver() {} + virtual ~TypeResolver() {} + + // Resolves a type url for a message type. + virtual util::Status ResolveMessageType( + const string& type_url, google::protobuf::Type* message_type) = 0; + + // Resolves a type url for an enum type. + virtual util::Status ResolveEnumType(const string& type_url, + google::protobuf::Enum* enum_type) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver); +}; + +} // namespace util +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__ diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc new file mode 100644 index 00000000..053a4ed7 --- /dev/null +++ b/src/google/protobuf/util/type_resolver_util.cc @@ -0,0 +1,212 @@ +// 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 + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace { +using google::protobuf::BoolValue; +using google::protobuf::Enum; +using google::protobuf::EnumValue; +using google::protobuf::Field; +using google::protobuf::Option; +using google::protobuf::Type; + +using util::Status; +using util::error::INVALID_ARGUMENT; +using util::error::NOT_FOUND; + +bool SplitTypeUrl(const string& type_url, + string* url_prefix, + string* message_name) { + size_t pos = type_url.find_last_of("/"); + if (pos == string::npos) { + return false; + } + *url_prefix = type_url.substr(0, pos); + *message_name = type_url.substr(pos + 1); + return true; +} + + +class DescriptorPoolTypeResolver : public TypeResolver { + public: + DescriptorPoolTypeResolver(const string& url_prefix, + const DescriptorPool* pool) + : url_prefix_(url_prefix), pool_(pool) { + } + + Status ResolveMessageType(const string& type_url, Type* type) { + string url_prefix, message_name; + if (!SplitTypeUrl(type_url, &url_prefix, &message_name) || + url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, "Failed to parse type url: " + type_url); + } + if (url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, + "Cannot resolve types from URL: " + url_prefix); + } + const Descriptor* descriptor = pool_->FindMessageTypeByName(message_name); + if (descriptor == NULL) { + return Status(NOT_FOUND, "Cannot found the type: " + message_name); + } + ConvertDescriptor(descriptor, type); + return Status(); + } + + Status ResolveEnumType(const string& type_url, Enum* enum_type) { + string url_prefix, type_name; + if (!SplitTypeUrl(type_url, &url_prefix, &type_name) || + url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, "Failed to parse type url: " + type_url); + } + if (url_prefix != url_prefix_) { + return Status(INVALID_ARGUMENT, + "Cannot resolve types from URL: " + url_prefix); + } + const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name); + if (descriptor == NULL) { + return Status(NOT_FOUND, "Cannot found the type: " + type_name); + } + ConvertEnumDescriptor(descriptor, enum_type); + return Status(); + } + + private: + void ConvertDescriptor(const Descriptor* descriptor, Type* type) { + type->Clear(); + type->set_name(descriptor->full_name()); + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = descriptor->field(i); + if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Group fields cannot be represented with Type. We discard them. + continue; + } + ConvertFieldDescriptor(descriptor->field(i), type->add_fields()); + } + for (int i = 0; i < descriptor->oneof_decl_count(); ++i) { + type->add_oneofs(descriptor->oneof_decl(i)->name()); + } + type->mutable_source_context()->set_file_name(descriptor->file()->name()); + ConvertMessageOptions(descriptor->options(), type->mutable_options()); + } + + void ConvertMessageOptions(const MessageOptions& options, + RepeatedPtrField