diff options
Diffstat (limited to 'src/google')
89 files changed, 2283 insertions, 1384 deletions
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc index c91faa08..ccccc9c1 100644 --- a/src/google/protobuf/any.pb.cc +++ b/src/google/protobuf/any.pb.cc @@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fany_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -61,6 +62,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fany_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -74,6 +76,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fany_2eproto() { delete Any_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fany_2eproto() { static bool already_here = false; if (already_here) return; @@ -101,16 +104,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fany_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2fany_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== void Any::PackFrom(const ::google::protobuf::Message& message) { @@ -334,7 +327,9 @@ int Any::ByteSize() const { void Any::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Any) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Any* source = ::google::protobuf::internal::DynamicCastToGenerated<const Any>( &from); @@ -349,7 +344,9 @@ void Any::MergeFrom(const ::google::protobuf::Message& from) { void Any::MergeFrom(const Any& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.type_url().size() > 0) { type_url_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.type_url_); diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc index d5dd8923..e8c2a178 100644 --- a/src/google/protobuf/api.pb.cc +++ b/src/google/protobuf/api.pb.cc @@ -35,6 +35,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -109,6 +110,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fapi_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -130,6 +132,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fapi_2eproto() { delete Mixin_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fapi_2eproto() { static bool already_here = false; if (already_here) return; @@ -175,16 +178,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fapi_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2fapi_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -601,7 +594,9 @@ int Api::ByteSize() const { void Api::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Api) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Api* source = ::google::protobuf::internal::DynamicCastToGenerated<const Api>( &from); @@ -616,7 +611,9 @@ void Api::MergeFrom(const ::google::protobuf::Message& from) { void Api::MergeFrom(const Api& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } methods_.MergeFrom(from.methods_); options_.MergeFrom(from.options_); mixins_.MergeFrom(from.mixins_); @@ -1008,7 +1005,7 @@ void Method::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -1345,7 +1342,9 @@ int Method::ByteSize() const { void Method::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Method) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Method* source = ::google::protobuf::internal::DynamicCastToGenerated<const Method>( &from); @@ -1360,7 +1359,9 @@ void Method::MergeFrom(const ::google::protobuf::Message& from) { void Method::MergeFrom(const Method& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } options_.MergeFrom(from.options_); if (from.name().size() > 0) { @@ -1858,7 +1859,9 @@ int Mixin::ByteSize() const { void Mixin::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Mixin) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Mixin* source = ::google::protobuf::internal::DynamicCastToGenerated<const Mixin>( &from); @@ -1873,7 +1876,9 @@ void Mixin::MergeFrom(const ::google::protobuf::Message& from) { void Mixin::MergeFrom(const Mixin& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.name().size() > 0) { name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 0ebf9b6a..dee438c6 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -719,6 +719,11 @@ TEST_F(CommandLineInterfaceTest, TrailingBackslash) { ExpectGenerated("test_generator", "", "foo.proto", "Foo"); } +TEST_F(CommandLineInterfaceTest, Win32ErrorMessage) { + EXPECT_EQ("The system cannot find the file specified.\r\n", + Subprocess::Win32ErrorMessage(ERROR_FILE_NOT_FOUND)); +} + #endif // defined(_WIN32) || defined(__CYGWIN__) TEST_F(CommandLineInterfaceTest, PathLookup) { diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 385b973e..b3eca660 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -336,19 +336,6 @@ void FileGenerator::GenerateSource(io::Printer* printer) { // Generate classes. for (int i = 0; i < file_->message_type_count(); i++) { - if (i == 0 && HasGeneratedMethods(file_, options_)) { - printer->Print( - "\n" - "namespace {\n" - "\n" - "static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD;\n" - "static void MergeFromFail(int line) {\n" - " GOOGLE_CHECK(false) << __FILE__ << \":\" << line;\n" - "}\n" - "\n" - "} // namespace\n" - "\n"); - } printer->Print("\n"); printer->Print(kThickSeparator); printer->Print("\n"); @@ -464,9 +451,10 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // and we only use AddDescriptors() to allocate default instances. if (HasDescriptorMethods(file_, options_)) { printer->Print( - "\n" - "void $assigndescriptorsname$() {\n", - "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); + "\n" + "void $assigndescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n" + "void $assigndescriptorsname$() {\n", + "assigndescriptorsname", GlobalAssignDescriptorsName(file_->name())); printer->Indent(); // Make sure the file has found its way into the pool. If a descriptor @@ -525,8 +513,9 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // protobuf_RegisterTypes(): Calls // MessageFactory::InternalRegisterGeneratedType() for each message type. printer->Print( - "void protobuf_RegisterTypes(const ::std::string&) {\n" - " protobuf_AssignDescriptorsOnce();\n"); + "void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD;\n" + "void protobuf_RegisterTypes(const ::std::string&) {\n" + " protobuf_AssignDescriptorsOnce();\n"); printer->Indent(); for (int i = 0; i < file_->message_type_count(); i++) { @@ -566,6 +555,7 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { // Note that we don't need any special synchronization in the following // code // because it is called at static init time before any threads exist. + "void $adddescriptorsname$() GOOGLE_ATTRIBUTE_COLD;\n" "void $adddescriptorsname$() {\n" " static bool already_here = false;\n" " if (already_here) return;\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc index dd9f1887..0588e34e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc @@ -251,117 +251,148 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { } } -void MapFieldGenerator:: -GenerateSerializeWithCachedSizes(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" - " it = this->$name$().begin();\n" - " it != this->$name$().end(); ++it) {\n"); +static void GenerateSerializationLoop(io::Printer* printer, + const map<string, string>& variables, + bool supports_arenas, + const string& utf8_check, + const string& loop_header, + const string& ptr, + bool loop_via_iterators) { + printer->Print(variables, + StrCat("::google::protobuf::scoped_ptr<$map_classname$> entry;\n", + loop_header, " {\n").c_str()); + printer->Indent(); + + printer->Print(variables, StrCat( + "entry.reset($name$_.New$wrapper$(\n" + " ", ptr, "->first, ", ptr, "->second));\n" + "$write_entry$;\n").c_str()); // 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"); + if (supports_arenas) { + printer->Print( + "if (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"); - - printer->Indent(); - printer->Indent(); - - const FieldDescriptor* key_field = - descriptor_->message_type()->FindFieldByName("key"); - const FieldDescriptor* value_field = - descriptor_->message_type()->FindFieldByName("value"); - if (key_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString(key_field, options_, false, variables_, - "it->first.data(), it->first.length(),\n", - printer); - } - if (value_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString(value_field, options_, false, variables_, - "it->second.data(), it->second.length(),\n", - printer); + if (!utf8_check.empty()) { + // If loop_via_iterators is true then ptr is actually an iterator, and we + // create a pointer by prefixing it with "&*". + printer->Print( + StrCat(utf8_check, "(", (loop_via_iterators ? "&*" : ""), ptr, ");\n") + .c_str()); } printer->Outdent(); - printer->Outdent(); - printer->Print( - " }\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"); - } + "}\n"); +} - printer->Print("}\n"); +void MapFieldGenerator:: +GenerateSerializeWithCachedSizes(io::Printer* printer) const { + map<string, string> variables(variables_); + variables["write_entry"] = "::google::protobuf::internal::WireFormatLite::Write" + + variables["stream_writer"] + "(\n " + + variables["number"] + ", *entry, output)"; + variables["deterministic"] = "output->IsSerializationDeterminstic()"; + GenerateSerializeWithCachedSizes(printer, variables); } void MapFieldGenerator:: GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { - printer->Print(variables_, - "{\n" - " ::google::protobuf::scoped_ptr<$map_classname$> entry;\n" - " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\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_)) { - 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" - " InternalWrite$declared_type$NoVirtualToArray(\n" - " $number$, *entry, false, target);\n"); + map<string, string> variables(variables_); + variables["write_entry"] = + "target = ::google::protobuf::internal::WireFormatLite::\n" + " InternalWrite" + variables["declared_type"] + + "NoVirtualToArray(\n " + variables["number"] + + ", *entry, deterministic, target);\n"; + variables["deterministic"] = "deterministic"; + GenerateSerializeWithCachedSizes(printer, variables); +} +void MapFieldGenerator::GenerateSerializeWithCachedSizes( + io::Printer* printer, const map<string, string>& variables) const { + printer->Print(variables, + "if (!this->$name$().empty()) {\n"); printer->Indent(); - printer->Indent(); - const FieldDescriptor* key_field = descriptor_->message_type()->FindFieldByName("key"); const FieldDescriptor* value_field = descriptor_->message_type()->FindFieldByName("value"); - if (key_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString(key_field, options_, false, variables_, - "it->first.data(), it->first.length(),\n", - printer); + const bool string_key = key_field->type() == FieldDescriptor::TYPE_STRING; + const bool string_value = value_field->type() == FieldDescriptor::TYPE_STRING; + + printer->Print(variables, + "typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_pointer\n" + " ConstPtr;\n"); + if (string_key) { + printer->Print(variables, + "typedef ConstPtr SortItem;\n" + "typedef ::google::protobuf::internal::" + "CompareByDerefFirst<SortItem> Less;\n"); + } else { + printer->Print(variables, + "typedef ::google::protobuf::internal::SortItem< $key_cpp$, ConstPtr > " + "SortItem;\n" + "typedef ::google::protobuf::internal::CompareByFirstField<SortItem> Less;\n"); } - if (value_field->type() == FieldDescriptor::TYPE_STRING) { - GenerateUtf8CheckCodeForString(value_field, options_, false, variables_, - "it->second.data(), it->second.length(),\n", - printer); + string utf8_check; + if (string_key || string_value) { + printer->Print( + "struct Utf8Check {\n" + " static void Check(ConstPtr p) {\n"); + printer->Indent(); + printer->Indent(); + if (string_key) { + GenerateUtf8CheckCodeForString(key_field, options_, false, variables, + "p->first.data(), p->first.length(),\n", + printer); + } + if (string_value) { + GenerateUtf8CheckCodeForString(value_field, options_, false, variables, + "p->second.data(), p->second.length(),\n", + printer); + } + printer->Outdent(); + printer->Outdent(); + printer->Print( + " }\n" + "};\n"); + utf8_check = "Utf8Check::Check"; } - printer->Outdent(); + printer->Print(variables, + "\n" + "if ($deterministic$ &&\n" + " this->$name$().size() > 1) {\n" + " ::google::protobuf::scoped_array<SortItem> items(\n" + " new SortItem[this->$name$().size()]);\n" + " typedef ::google::protobuf::Map< $key_cpp$, $val_cpp$ >::size_type size_type;\n" + " size_type n = 0;\n" + " for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " it = this->$name$().begin();\n" + " it != this->$name$().end(); ++it, ++n) {\n" + " items[n] = SortItem(&*it);\n" + " }\n" + " ::std::sort(&items[0], &items[n], Less());\n"); + printer->Indent(); + GenerateSerializationLoop(printer, variables, SupportsArenas(descriptor_), + utf8_check, "for (size_type i = 0; i < n; i++)", + string_key ? "items[i]" : "items[i].second", false); printer->Outdent(); printer->Print( - " }\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"); - } - + "} else {\n"); + printer->Indent(); + GenerateSerializationLoop( + printer, variables, SupportsArenas(descriptor_), utf8_check, + "for (::google::protobuf::Map< $key_cpp$, $val_cpp$ >::const_iterator\n" + " it = this->$name$().begin();\n" + " it != this->$name$().end(); ++it)", + "it", true); + printer->Outdent(); + printer->Print("}\n"); + printer->Outdent(); printer->Print("}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.h b/src/google/protobuf/compiler/cpp/cpp_map_field.h index 087dcde0..2930fe59 100644 --- a/src/google/protobuf/compiler/cpp/cpp_map_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_map_field.h @@ -61,6 +61,10 @@ class MapFieldGenerator : public FieldGenerator { void GenerateByteSize(io::Printer* printer) const; private: + // A helper for GenerateSerializeWithCachedSizes{,ToArray}. + void GenerateSerializeWithCachedSizes( + io::Printer* printer, const map<string, string>& variables) const; + const FieldDescriptor* descriptor_; const bool dependent_field_; map<string, string> variables_; diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 32f63152..69cd5f3c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -2419,7 +2419,7 @@ GenerateClear(io::Printer* printer) { " &reinterpret_cast<$classname$*>(16)->f)\n" "#endif\n\n" "#define ZR_(first, last) do {\\\n" - " ::memset(&first, 0,\\\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++) { @@ -2715,7 +2715,9 @@ GenerateMergeFrom(io::Printer* printer) { "void $classname$::MergeFrom(const ::google::protobuf::Message& from) {\n" "// @@protoc_insertion_point(generalized_merge_from_start:" "$full_name$)\n" - " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", + " if (GOOGLE_PREDICT_FALSE(&from == this)) {\n" + " ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);\n" + " }\n", "classname", classname_, "full_name", descriptor_->full_name()); printer->Indent(); @@ -2756,7 +2758,9 @@ GenerateMergeFrom(io::Printer* printer) { "void $classname$::MergeFrom(const $classname$& from) {\n" "// @@protoc_insertion_point(class_specific_merge_from_start:" "$full_name$)\n" - " if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__);\n", + " if (GOOGLE_PREDICT_FALSE(&from == this)) {\n" + " ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__);\n" + " }\n", "classname", classname_, "full_name", descriptor_->full_name()); printer->Indent(); @@ -2952,7 +2956,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // on the CodedOutputStream. printer->Print( " ::google::protobuf::io::LazyStringOutputStream unknown_fields_string(\n" - " ::google::protobuf::internal::NewPermanentCallback(\n" + " ::google::protobuf::NewPermanentCallback(\n" " &MutableUnknownFieldsFor$classname$, this));\n" " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" " &unknown_fields_string, false);\n", diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 5d82946d..b7b6039a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -1252,7 +1252,7 @@ class GeneratedServiceTest : public testing::Test { foo_(descriptor_->FindMethodByName("Foo")), bar_(descriptor_->FindMethodByName("Bar")), stub_(&mock_channel_), - done_(::google::protobuf::internal::NewPermanentCallback(&DoNothing)) {} + done_(NewPermanentCallback(&DoNothing)) {} virtual void SetUp() { ASSERT_TRUE(foo_ != NULL); diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc index 64381d0f..9e4da1ed 100644 --- a/src/google/protobuf/compiler/csharp/csharp_enum.cc +++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc @@ -68,9 +68,7 @@ void EnumGenerator::Generate(io::Printer* printer) { for (int i = 0; i < descriptor_->value_count(); i++) { WriteEnumValueDocComment(printer, descriptor_->value(i)); string original_name = descriptor_->value(i)->name(); - string name = options()->legacy_enum_values - ? descriptor_->value(i)->name() - : GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name()); + string name = GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name()); // Make sure we don't get any duplicate names due to prefix removal. while (!used_names.insert(name).second) { // It's possible we'll end up giving this warning multiple times, but that's better than not at all. diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.cc b/src/google/protobuf/compiler/csharp/csharp_generator.cc index d74e8c88..c13ed65b 100644 --- a/src/google/protobuf/compiler/csharp/csharp_generator.cc +++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc @@ -83,9 +83,6 @@ bool Generator::Generate( cli_options.base_namespace_specified = true; } else if (options[i].first == "internal_access") { cli_options.internal_access = true; - } else if (options[i].first == "legacy_enum_values") { - // TODO: Remove this before final release - cli_options.legacy_enum_values = true; } else { *error = "Unknown generator option: " + options[i].first; return false; diff --git a/src/google/protobuf/compiler/csharp/csharp_options.h b/src/google/protobuf/compiler/csharp/csharp_options.h index 4079bf7f..426fb3b5 100644 --- a/src/google/protobuf/compiler/csharp/csharp_options.h +++ b/src/google/protobuf/compiler/csharp/csharp_options.h @@ -45,8 +45,7 @@ struct Options { file_extension(".cs"), base_namespace(""), base_namespace_specified(false), - internal_access(false), - legacy_enum_values(false) { + internal_access(false) { } // Extension of the generated file. Defaults to ".cs" string file_extension; @@ -69,12 +68,6 @@ struct Options { // Whether the generated classes should have accessibility level of "internal". // Defaults to false that generates "public" classes. bool internal_access; - // By default, C# codegen now uses PascalCased enum values names, after - // removing the enum type name as a prefix (if it *is* a prefix of the value). - // Setting this option reverts to the previous behavior of just copying the - // value name specified in the .proto file, allowing gradual migration. - // This option will be removed before final release. - bool legacy_enum_values; }; } // namespace csharp diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index a06c5f6d..5e387285 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -266,9 +266,7 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print( "public static void registerAllExtensions(\n" - " com.google.protobuf.ExtensionRegistry$lite$ registry) {\n", - "lite", - HasDescriptorMethods(file_, context_->EnforceLite()) ? "" : "Lite"); + " com.google.protobuf.ExtensionRegistryLite registry) {\n"); printer->Indent(); @@ -283,6 +281,20 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Outdent(); printer->Print( "}\n"); + if (HasDescriptorMethods(file_, context_->EnforceLite())) { + // Overload registerAllExtensions for the non-lite usage to + // redundantly maintain the original signature (this is + // redundant because ExtensionRegistryLite now invokes + // ExtensionRegistry in the non-lite usage). Intent is + // to remove this in the future. + printer->Print( + "\n" + "public static void registerAllExtensions(\n" + " com.google.protobuf.ExtensionRegistry registry) {\n" + " registerAllExtensions(\n" + " (com.google.protobuf.ExtensionRegistryLite) registry);\n" + "}\n"); + } // ----------------------------------------------------------------- diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc index 3c545e15..b1ab4043 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -79,8 +79,6 @@ bool JavaGenerator::Generate(const FileDescriptor* file, file_options.generate_mutable_code = true; } else if (options[i].first == "shared") { file_options.generate_shared_code = true; - } else if (options[i].first == "lite") { - file_options.enforce_lite = true; } else if (options[i].first == "annotate_code") { file_options.annotate_code = true; } else if (options[i].first == "annotation_list_file") { diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index d55a9849..6c80d070 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -205,9 +205,10 @@ GenerateFieldAccessorTable(io::Printer* printer, int* bytecode_estimate) { } else { vars["final"] = ""; } + vars["ver"] = GeneratedCodeVersionSuffix(); printer->Print(vars, "$private$static $final$\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" " internal_$identifier$_fieldAccessorTable;\n"); // 6 bytes per field and oneof @@ -220,11 +221,11 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) { int bytecode_estimate = 10; printer->Print( "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" + " com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable(\n" " internal_$identifier$_descriptor,\n" " new java.lang.String[] { ", - "identifier", - UniqueFileScopeIdentifier(descriptor_)); + "identifier", UniqueFileScopeIdentifier(descriptor_), + "ver", GeneratedCodeVersionSuffix()); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); @@ -254,11 +255,11 @@ void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { printer->Print( "public interface $classname$OrBuilder$idend$ extends\n" " $extra_interfaces$\n" - " com.google.protobuf.GeneratedMessage.\n" + " com.google.protobuf.GeneratedMessage$ver$.\n" " ExtendableMessageOrBuilder<$classname$> {\n", "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name(), - "idend", ""); + "idend", "", "ver", GeneratedCodeVersionSuffix()); } else { printer->Print( "public interface $classname$OrBuilder$idend$ extends\n" @@ -302,6 +303,7 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { variables["static"] = is_own_file ? " " : " static "; variables["classname"] = descriptor_->name(); variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_); + variables["ver"] = GeneratedCodeVersionSuffix(); WriteMessageDocComment(printer, descriptor_); MaybePrintGeneratedAnnotation(context_, printer, descriptor_, @@ -315,22 +317,25 @@ void ImmutableMessageGenerator::Generate(io::Printer* printer) { printer->Annotate("classname", descriptor_); printer->Print( variables, - " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" + " com.google.protobuf.GeneratedMessage$ver$.ExtendableMessage<\n" " $classname$> implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n"); builder_type = strings::Substitute( - "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>", - name_resolver_->GetImmutableClassName(descriptor_)); + "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>", + name_resolver_->GetImmutableClassName(descriptor_), + GeneratedCodeVersionSuffix()); } else { printer->Print(variables, "public $static$final class $classname$ extends\n"); printer->Annotate("classname", descriptor_); printer->Print(variables, - " com.google.protobuf.GeneratedMessage implements\n" + " com.google.protobuf.GeneratedMessage$ver$ implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n"); - builder_type = "com.google.protobuf.GeneratedMessage.Builder<?>"; + builder_type = strings::Substitute( + "com.google.protobuf.GeneratedMessage$0.Builder<?>", + GeneratedCodeVersionSuffix()); } printer->Indent(); // Using builder_type, instead of Builder, prevents the Builder class from @@ -581,16 +586,18 @@ GenerateMessageSerializationMethods(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (descriptor_->options().message_set_wire_format()) { printer->Print( - "com.google.protobuf.GeneratedMessage\n" + "com.google.protobuf.GeneratedMessage$ver$\n" " .ExtendableMessage<$classname$>.ExtensionWriter\n" " extensionWriter = newMessageSetExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } else { printer->Print( - "com.google.protobuf.GeneratedMessage\n" + "com.google.protobuf.GeneratedMessage$ver$\n" " .ExtendableMessage<$classname$>.ExtensionWriter\n" " extensionWriter = newExtensionWriter();\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } } @@ -694,43 +701,44 @@ GenerateParseFromMethods(io::Printer* printer) { "}\n" "public static $classname$ parseFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" " .parseWithIOException(PARSER, 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 com.google.protobuf.GeneratedMessage\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" " .parseWithIOException(PARSER, input, extensionRegistry);\n" "}\n" "public static $classname$ parseDelimitedFrom(java.io.InputStream input)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" " .parseDelimitedWithIOException(PARSER, 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 com.google.protobuf.GeneratedMessage\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" " .parseDelimitedWithIOException(PARSER, input, extensionRegistry);\n" "}\n" "public static $classname$ parseFrom(\n" " com.google.protobuf.CodedInputStream input)\n" " throws java.io.IOException {\n" - " return com.google.protobuf.GeneratedMessage\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" " .parseWithIOException(PARSER, 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 com.google.protobuf.GeneratedMessage\n" + " return com.google.protobuf.GeneratedMessage$ver$\n" " .parseWithIOException(PARSER, input, extensionRegistry);\n" "}\n" "\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } void ImmutableMessageGenerator::GenerateSerializeOneField( @@ -769,10 +777,11 @@ void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "@java.lang.Override\n" "protected Builder newBuilderForType(\n" - " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" " Builder builder = new Builder(parent);\n" " return builder;\n" - "}\n"); + "}\n", + "ver", GeneratedCodeVersionSuffix()); MessageBuilderGenerator builderGenerator(descriptor_, context_); builderGenerator.Generate(printer); @@ -826,7 +835,7 @@ GenerateDescriptorMethods(io::Printer* printer) { "}\n"); } printer->Print( - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" " internalGetFieldAccessorTable() {\n" " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" " .ensureFieldAccessorsInitialized(\n" @@ -835,7 +844,8 @@ GenerateDescriptorMethods(io::Printer* printer) { "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + "identifier", UniqueFileScopeIdentifier(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } // =================================================================== diff --git a/src/google/protobuf/compiler/java/java_message_builder.cc b/src/google/protobuf/compiler/java/java_message_builder.cc index b3e9e986..42154694 100644 --- a/src/google/protobuf/compiler/java/java_message_builder.cc +++ b/src/google/protobuf/compiler/java/java_message_builder.cc @@ -94,20 +94,22 @@ Generate(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" + " com.google.protobuf.GeneratedMessage$ver$.ExtendableBuilder<\n" " $classname$, Builder> implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); + "extra_interfaces", ExtraBuilderInterfaces(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } else { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder<Builder> implements\n" + " com.google.protobuf.GeneratedMessage$ver$.Builder<Builder> implements\n" " $extra_interfaces$\n" " $classname$OrBuilder {\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), - "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); + "extra_interfaces", ExtraBuilderInterfaces(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } printer->Indent(); @@ -181,6 +183,18 @@ Generate(io::Printer* printer) { " return this;\n" "}\n" "\n"); + } else { + printer->Print( + "public final Builder setUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return super.setUnknownFields(unknownFields);\n" + "}\n" + "\n" + "public final Builder mergeUnknownFields(\n" + " final com.google.protobuf.UnknownFieldSet unknownFields) {\n" + " return super.mergeUnknownFields(unknownFields);\n" + "}\n" + "\n"); } printer->Print( @@ -268,7 +282,7 @@ GenerateDescriptorMethods(io::Printer* printer) { "}\n"); } printer->Print( - "protected com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + "protected com.google.protobuf.GeneratedMessage$ver$.FieldAccessorTable\n" " internalGetFieldAccessorTable() {\n" " return $fileclass$.internal_$identifier$_fieldAccessorTable\n" " .ensureFieldAccessorsInitialized(\n" @@ -277,7 +291,8 @@ GenerateDescriptorMethods(io::Printer* printer) { "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_), "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), - "identifier", UniqueFileScopeIdentifier(descriptor_)); + "identifier", UniqueFileScopeIdentifier(descriptor_), + "ver", GeneratedCodeVersionSuffix()); } // =================================================================== @@ -294,15 +309,18 @@ GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( "private Builder(\n" - " com.google.protobuf.GeneratedMessage.BuilderParent parent) {\n" + " com.google.protobuf.GeneratedMessage$ver$.BuilderParent parent) {\n" " super(parent);\n" " maybeForceBuilderInitialization();\n" "}\n", - "classname", name_resolver_->GetImmutableClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "ver", GeneratedCodeVersionSuffix()); printer->Print( "private void maybeForceBuilderInitialization() {\n" - " if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {\n"); + " if (com.google.protobuf.GeneratedMessage$ver$\n" + " .alwaysUseFieldBuilders) {\n", + "ver", GeneratedCodeVersionSuffix()); printer->Indent(); printer->Indent(); @@ -438,6 +456,62 @@ GenerateCommonBuilderMethods(io::Printer* printer) { "\n", "classname", name_resolver_->GetImmutableClassName(descriptor_)); + printer->Print( + "public Builder clone() {\n" + " return (Builder) super.clone();\n" + "}\n" + "public Builder setField(\n" + " com.google.protobuf.Descriptors.FieldDescriptor field,\n" + " Object value) {\n" + " return (Builder) super.setField(field, value);\n" + "}\n" + "public Builder clearField(\n" + " com.google.protobuf.Descriptors.FieldDescriptor field) {\n" + " return (Builder) super.clearField(field);\n" + "}\n" + "public Builder clearOneof(\n" + " com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n" + " return (Builder) super.clearOneof(oneof);\n" + "}\n" + "public Builder setRepeatedField(\n" + " com.google.protobuf.Descriptors.FieldDescriptor field,\n" + " int index, Object value) {\n" + " return (Builder) super.setRepeatedField(field, index, value);\n" + "}\n" + "public Builder addRepeatedField(\n" + " com.google.protobuf.Descriptors.FieldDescriptor field,\n" + " Object value) {\n" + " return (Builder) super.addRepeatedField(field, value);\n" + "}\n"); + + if (descriptor_->extension_range_count() > 0) { + printer->Print( + "public <Type> Builder setExtension(\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $classname$, Type> extension,\n" + " Type value) {\n" + " return (Builder) super.setExtension(extension, value);\n" + "}\n" + "public <Type> Builder setExtension(\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $classname$, java.util.List<Type>> extension,\n" + " int index, Type value) {\n" + " return (Builder) super.setExtension(extension, index, value);\n" + "}\n" + "public <Type> Builder addExtension(\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $classname$, java.util.List<Type>> extension,\n" + " Type value) {\n" + " return (Builder) super.addExtension(extension, value);\n" + "}\n" + "public <Type> Builder clearExtension(\n" + " com.google.protobuf.GeneratedMessage.GeneratedExtension<\n" + " $classname$, ?> extension) {\n" + " return (Builder) super.clearExtension(extension);\n" + "}\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } + // ----------------------------------------------------------------- if (context_->HasGeneratedMethods(descriptor_)) { @@ -522,6 +596,7 @@ GenerateCommonBuilderMethods(io::Printer* printer) { " return this;\n" "}\n" "\n"); + } } diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index cc627b5a..c9865dda 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -1203,7 +1203,7 @@ GenerateMergingCode(io::Printer* printer) const { " $name$_ = other.$name$_;\n" " $clear_mutable_bit_builder$;\n" " $name$Builder_ = \n" - " com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?\n" + " com.google.protobuf.GeneratedMessage$ver$.alwaysUseFieldBuilders ?\n" " get$capitalized_name$FieldBuilder() : null;\n" " } else {\n" " $name$Builder_.addAllMessages(other.$name$_);\n" diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index e1e5496a..ff1865b1 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -79,9 +79,11 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, " throw new NullPointerException();\n" " }\n"; (*variables)["writeString"] = - "com.google.protobuf.GeneratedMessage.writeString"; + "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() + + ".writeString"; (*variables)["computeStringSize"] = - "com.google.protobuf.GeneratedMessage.computeStringSize"; + "com.google.protobuf.GeneratedMessage" + GeneratedCodeVersionSuffix() + + ".computeStringSize"; // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported // by the proto compiler diff --git a/src/google/protobuf/compiler/js/js_generator.cc b/src/google/protobuf/compiler/js/js_generator.cc index 8a2633d7..58c77d00 100755 --- a/src/google/protobuf/compiler/js/js_generator.cc +++ b/src/google/protobuf/compiler/js/js_generator.cc @@ -768,7 +768,6 @@ string MaybeNumberString(const FieldDescriptor* field, const string& orig) { } string JSFieldDefault(const FieldDescriptor* field) { - assert(field->has_default_value()); switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: return MaybeNumberString( @@ -943,7 +942,7 @@ string JSFieldTypeAnnotation(const GeneratorOptions& options, } if (field->is_optional() && is_primitive && - (!field->has_default_value() || force_optional) && !force_present) { + force_optional && !force_present) { jstype += "?"; } else if (field->is_required() && !is_primitive && !force_optional) { jstype = "!" + jstype; @@ -1258,6 +1257,10 @@ string GetPivot(const Descriptor* desc) { // Returns true for fields that represent "null" as distinct from the default // value. See http://go/proto3#heading=h.kozewqqcqhuz for more information. bool HasFieldPresence(const FieldDescriptor* field) { + if (field->is_repeated()) { + return false; + } + return (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) || (field->containing_oneof() != NULL) || @@ -2031,9 +2034,8 @@ void Generator::GenerateClassFieldToObject(const GeneratorOptions& options, "getter", JSGetterName(options, field, BYTES_B64)); } else { if (field->has_default_value()) { - printer->Print("jspb.Message.getField(msg, $index$) == null ? " - "$defaultValue$ : ", - "index", JSFieldIndex(field), + printer->Print("!msg.has$name$() ? $defaultValue$ : ", + "name", JSGetterName(options, field), "defaultValue", JSFieldDefault(field)); } if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT || @@ -2253,25 +2255,6 @@ void Generator::GenerateClassField(const GeneratorOptions& options, " null"); } - if (options.binary) { - printer->Print(",\n" - " $keyWriterFn$,\n" - " $keyReaderFn$,\n" - " $valueWriterFn$,\n" - " $valueReaderFn$", - "keyWriterFn", JSBinaryWriterMethodName(options, key_field), - "keyReaderFn", JSBinaryReaderMethodName(options, key_field), - "valueWriterFn", JSBinaryWriterMethodName(options, value_field), - "valueReaderFn", JSBinaryReaderMethodName(options, value_field)); - - if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { - printer->Print(",\n" - " $messageType$.serializeBinaryToWriter,\n" - " $messageType$.deserializeBinaryFromReader", - "messageType", GetPath(options, value_field->message_type())); - } - } - printer->Print( "));\n"); @@ -2407,10 +2390,9 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "index", JSFieldIndex(field), "default", Proto3PrimitiveFieldDefault(field)); } else { - if (field->has_default_value()) { - printer->Print("jspb.Message.getField(this, $index$) == null ? " - "$defaultValue$ : ", - "index", JSFieldIndex(field), + if (!field->is_repeated()) { + printer->Print("!this.has$name$() ? $defaultValue$ : ", + "name", JSGetterName(options, field), "defaultValue", JSFieldDefault(field)); } if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT || @@ -2419,10 +2401,6 @@ void Generator::GenerateClassField(const GeneratorOptions& options, printer->Print("jspb.Message.getRepeatedFloatingPointField(" "this, $index$)", "index", JSFieldIndex(field)); - } else if (field->is_optional() && !field->has_default_value()) { - printer->Print("jspb.Message.getOptionalFloatingPointField(" - "this, $index$)", - "index", JSFieldIndex(field)); } else { // Convert "NaN" to NaN. printer->Print("+jspb.Message.getField(this, $index$)", @@ -2498,7 +2476,7 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "returndoc", JSReturnDoc(options, field)); } - if (HasFieldPresence(field)) { + if (HasFieldPresence(field) || field->is_repeated()) { printer->Print( "$class$.prototype.clear$name$ = function() {\n" " jspb.Message.set$oneoftag$Field(this, $index$$oneofgroup$, ", @@ -2517,6 +2495,22 @@ void Generator::GenerateClassField(const GeneratorOptions& options, "returnvalue", JSReturnClause(field)); } } + + if (HasFieldPresence(field)) { + printer->Print( + "/**\n" + " * Returns whether this field is set.\n" + " * @return{!boolean}\n" + " */\n" + "$class$.prototype.has$name$ = function() {\n" + " return jspb.Message.getField(this, $index$) != null;\n" + "};\n" + "\n" + "\n", + "class", GetPath(options, field->containing_type()), + "name", JSGetterName(options, field), + "index", JSFieldIndex(field)); + } } void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, @@ -2543,6 +2537,29 @@ void Generator::GenerateClassExtensionFieldInfo(const GeneratorOptions& options, "$class$.extensions = {};\n" "\n", "class", GetPath(options, desc)); + + if (options.binary) { + printer->Print( + "\n" + "/**\n" + " * The extensions registered with this message class. This is a " + "map of\n" + " * extension field number to fieldInfo object.\n" + " *\n" + " * For example:\n" + " * { 123: {fieldIndex: 123, fieldName: {my_field_name: 0}, " + "ctor: proto.example.MyMessage} }\n" + " *\n" + " * fieldName contains the JsCompiler renamed field name property " + "so that it\n" + " * works in OPTIMIZED mode.\n" + " *\n" + " * @type {!Object.<number, jspb.ExtensionFieldInfo>}\n" + " */\n" + "$class$.extensionsBinary = {};\n" + "\n", + "class", GetPath(options, desc)); + } } } @@ -2590,7 +2607,7 @@ void Generator::GenerateClassDeserializeBinary(const GeneratorOptions& options, " default:\n"); if (IsExtendable(desc)) { printer->Print( - " jspb.Message.readBinaryExtension(msg, reader, $extobj$,\n" + " jspb.Message.readBinaryExtension(msg, reader, $extobj$Binary,\n" " $class$.prototype.getExtension,\n" " $class$.prototype.setExtension);\n" " break;\n", @@ -2620,10 +2637,25 @@ void Generator::GenerateClassDeserializeBinaryField( "num", SimpleItoa(field->number())); if (field->is_map()) { + const FieldDescriptor* key_field = MapFieldKey(field); + const FieldDescriptor* value_field = MapFieldValue(field); printer->Print( " var value = msg.get$name$();\n" - " reader.readMessage(value, jspb.Map.deserializeBinary);\n", + " reader.readMessage(value, function(message, reader) {\n", "name", JSGetterName(options, field)); + + printer->Print(" jspb.Map.deserializeBinary(message, reader, " + "$keyReaderFn$, $valueReaderFn$", + "keyReaderFn", JSBinaryReaderMethodName(options, key_field), + "valueReaderFn", JSBinaryReaderMethodName(options, value_field)); + + if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { + printer->Print(", $messageType$.deserializeBinaryFromReader", + "messageType", GetPath(options, value_field->message_type())); + } + + printer->Print(");\n"); + printer->Print(" });\n"); } else { if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { printer->Print( @@ -2709,8 +2741,8 @@ void Generator::GenerateClassSerializeBinary(const GeneratorOptions& options, if (IsExtendable(desc)) { printer->Print( - " jspb.Message.serializeBinaryExtensions(this, writer, $extobj$,\n" - " $class$.prototype.getExtension);\n", + " jspb.Message.serializeBinaryExtensions(this, writer,\n" + " $extobj$Binary, $class$.prototype.getExtension);\n", "extobj", JSExtensionsObjectName(options, desc->file(), desc), "class", GetPath(options, desc)); } @@ -2725,11 +2757,18 @@ void Generator::GenerateClassSerializeBinaryField( const GeneratorOptions& options, io::Printer* printer, const FieldDescriptor* field) const { - printer->Print( - " f = this.get$name$($nolazy$);\n", - "name", JSGetterName(options, field, BYTES_U8), - // No lazy creation for maps containers -- fastpath the empty case. - "nolazy", (field->is_map()) ? "true" : ""); + if (HasFieldPresence(field) && + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { + printer->Print( + " f = jspb.Message.getField(this, $index$);\n", + "index", JSFieldIndex(field)); + } else { + printer->Print( + " f = this.get$name$($nolazy$);\n", + "name", JSGetterName(options, field, BYTES_U8), + // No lazy creation for maps containers -- fastpath the empty case. + "nolazy", (field->is_map()) ? "true" : ""); + } // Print an `if (condition)` statement that evaluates to true if the field @@ -2782,9 +2821,21 @@ void Generator::GenerateClassSerializeBinaryField( // Write the field on the wire. if (field->is_map()) { + const FieldDescriptor* key_field = MapFieldKey(field); + const FieldDescriptor* value_field = MapFieldValue(field); printer->Print( - " f.serializeBinary($index$, writer);\n", - "index", SimpleItoa(field->number())); + " f.serializeBinary($index$, writer, " + "$keyWriterFn$, $valueWriterFn$", + "index", SimpleItoa(field->number()), + "keyWriterFn", JSBinaryWriterMethodName(options, key_field), + "valueWriterFn", JSBinaryWriterMethodName(options, value_field)); + + if (value_field->type() == FieldDescriptor::TYPE_MESSAGE) { + printer->Print(", $messageType$.serializeBinaryToWriter", + "messageType", GetPath(options, value_field->message_type())); + } + + printer->Print(");\n"); } else { printer->Print( " writer.write$method$(\n" @@ -2866,7 +2917,7 @@ void Generator::GenerateExtension(const GeneratorOptions& options, " /** @type {?function((boolean|undefined),!jspb.Message=): " "!Object} */ (\n" " $toObject$),\n" - " $repeated$", + " $repeated$);\n", "index", SimpleItoa(field->number()), "name", JSObjectFieldName(options, field), "ctor", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ? @@ -2878,12 +2929,18 @@ void Generator::GenerateExtension(const GeneratorOptions& options, if (options.binary) { printer->Print( - ",\n" + "\n" + "$extendName$Binary[$index$] = new jspb.ExtensionFieldBinaryInfo(\n" + " $class$.$name$,\n" " $binaryReaderFn$,\n" " $binaryWriterFn$,\n" " $binaryMessageSerializeFn$,\n" - " $binaryMessageDeserializeFn$,\n" - " $isPacked$);\n", + " $binaryMessageDeserializeFn$,\n", + "extendName", JSExtensionsObjectName(options, field->file(), + field->containing_type()), + "index", SimpleItoa(field->number()), + "class", extension_scope, + "name", JSObjectFieldName(options, field), "binaryReaderFn", JSBinaryReaderMethodName(options, field), "binaryWriterFn", JSBinaryWriterMethodName(options, field), "binaryMessageSerializeFn", @@ -2893,10 +2950,11 @@ void Generator::GenerateExtension(const GeneratorOptions& options, "binaryMessageDeserializeFn", (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) ? (SubmessageTypeRef(options, field) + - ".deserializeBinaryFromReader") : "null", + ".deserializeBinaryFromReader") : "null"); + + printer->Print( + " $isPacked$);\n", "isPacked", (field->is_packed() ? "true" : "false")); - } else { - printer->Print(");\n"); } printer->Print( diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc index e76f8e99..34e17823 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc @@ -62,7 +62,7 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) { string enum_comments; SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { - enum_comments = BuildCommentsString(location); + enum_comments = BuildCommentsString(location, true); } else { enum_comments = ""; } @@ -81,16 +81,18 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) { if (HasPreservingUnknownEnumSemantics(descriptor_->file())) { // Include the unknown value. printer->Print( - "/// Value used if any message's field encounters a value that is not defined\n" - "/// by this enum. The message will also have C functions to get/set the rawValue\n" - "/// of the field.\n" + "/**\n" + " * Value used if any message's field encounters a value that is not defined\n" + " * by this enum. The message will also have C functions to get/set the rawValue\n" + " * of the field.\n" + " **/\n" "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n", "name", name_); } for (int i = 0; i < all_values_.size(); i++) { SourceLocation location; if (all_values_[i]->GetSourceLocation(&location)) { - string comments = BuildCommentsString(location).c_str(); + string comments = BuildCommentsString(location, true).c_str(); if (comments.length() > 0) { if (i > 0) { printer->Print("\n"); @@ -111,8 +113,10 @@ void EnumGenerator::GenerateHeader(io::Printer* printer) { "\n" "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n" "\n" - "/// Checks to see if the given value is defined by the enum or was not known at\n" - "/// the time this source was generated.\n" + "/**\n" + " * Checks to see if the given value is defined by the enum or was not known at\n" + " * the time this source was generated.\n" + " **/\n" "BOOL $name$_IsValidValue(int32_t value);\n" "\n", "name", name_); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc index b63bc0de..7a774a09 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc @@ -83,12 +83,16 @@ void EnumFieldGenerator::GenerateCFunctionDeclarations( printer->Print( variables_, - "/// Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n" - "/// if the value was not defined by the enum at the time the code was generated.\n" + "/**\n" + " * Fetches the raw value of a @c $owning_message_class$'s @c $name$ property, even\n" + " * if the value was not defined by the enum at the time the code was generated.\n" + " **/\n" "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n" - "/// Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n" - "/// it to be set to a value that was not defined by the enum at the time the code\n" - "/// was generated.\n" + "/**\n" + " * Sets the raw value of an @c $owning_message_class$'s @c $name$ property, allowing\n" + " * it to be set to a value that was not defined by the enum at the time the code\n" + " * was generated.\n" + " **/\n" "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n" "\n"); } diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc index 3f7ab9d3..d0de1eca 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc @@ -63,7 +63,7 @@ void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) { vars["method_name"] = method_name_; SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { - vars["comments"] = BuildCommentsString(location); + vars["comments"] = BuildCommentsString(location, true); } else { vars["comments"] = ""; } @@ -85,7 +85,7 @@ void ExtensionGenerator::GenerateStaticVariablesInitialization( if (descriptor_->containing_type()->options().message_set_wire_format()) options.push_back("GPBExtensionSetWireFormat"); - vars["options"] = BuildFlagsString(options); + vars["options"] = BuildFlagsString(FLAGTYPE_EXTENSION, options); ObjectiveCType objc_type = GetObjectiveCType(descriptor_); string singular_type; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc index 812b4a1c..527b7c0c 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc @@ -64,7 +64,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, SourceLocation location; if (descriptor->GetSourceLocation(&location)) { - (*variables)["comments"] = BuildCommentsString(location); + (*variables)["comments"] = BuildCommentsString(location, true); } else { (*variables)["comments"] = "\n"; } @@ -93,7 +93,7 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, field_flags.push_back("GPBFieldHasEnumDescriptor"); } - (*variables)["fieldflags"] = BuildFlagsString(field_flags); + (*variables)["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); (*variables)["default"] = DefaultValue(descriptor); (*variables)["default_name"] = GPBGenericValueFieldName(descriptor); @@ -335,7 +335,7 @@ void ObjCObjFieldGenerator::GeneratePropertyDeclaration( if (WantsHasProperty()) { printer->Print( variables_, - "/// Test to see if @c $name$ has been set.\n" + "/** Test to see if @c $name$ has been set. */\n" "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n"); } if (IsInitName(variables_.find("name")->second)) { @@ -387,7 +387,7 @@ void RepeatedFieldGenerator::GeneratePropertyDeclaration( "$comments$" "$array_comment$" "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n" - "/// The number of items in @c $name$ without causing the array to be created.\n" + "/** The number of items in @c $name$ without causing the array to be created. */\n" "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n"); if (IsInitName(variables_.find("name")->second)) { // If property name starts with init we need to annotate it to get past ARC. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc index cf8c34e1..878a3743 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc @@ -37,6 +37,7 @@ #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/stubs/stl_util.h> #include <google/protobuf/stubs/strutil.h> +#include <algorithm> // std::find() #include <iostream> #include <sstream> @@ -45,218 +46,122 @@ namespace google { namespace protobuf { - -// This is also found in GPBBootstrap.h, and needs to be kept in sync. It -// is the version check done to ensure generated code works with the current -// runtime being used. -const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30001; - namespace compiler { namespace objectivec { namespace { -class ImportWriter { - public: - ImportWriter(const Options& options) - : options_(options), - need_to_parse_mapping_file_(true) {} - - void AddFile(const FileGenerator* file); - void Print(io::Printer *printer) const; - - private: - class ProtoFrameworkCollector : public LineConsumer { - public: - ProtoFrameworkCollector(map<string, string>* inout_proto_file_to_framework_name) - : map_(inout_proto_file_to_framework_name) {} - - virtual bool ConsumeLine(const StringPiece& line, string* out_error); - - private: - map<string, string>* map_; - }; - - void ParseFrameworkMappings(); - - const Options options_; - map<string, string> proto_file_to_framework_name_; - bool need_to_parse_mapping_file_; - - vector<string> protobuf_framework_imports_; - vector<string> protobuf_non_framework_imports_; - vector<string> other_framework_imports_; - vector<string> other_imports_; -}; +// This is also found in GPBBootstrap.h, and needs to be kept in sync. It +// is the version check done to ensure generated code works with the current +// runtime being used. +const int32 GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30002; -void ImportWriter::AddFile(const FileGenerator* file) { - const FileDescriptor* file_descriptor = file->Descriptor(); - const string extension(".pbobjc.h"); +const char* kHeaderExtension = ".pbobjc.h"; - if (IsProtobufLibraryBundledProtoFile(file_descriptor)) { - protobuf_framework_imports_.push_back( - FilePathBasename(file_descriptor) + extension); - protobuf_non_framework_imports_.push_back(file->Path() + extension); - return; +// Checks if a message contains any extension definitions (on the message or +// a nested message under it). +bool MessageContainsExtensions(const Descriptor* message) { + if (message->extension_count() > 0) { + return true; } - - // Lazy parse any mappings. - if (need_to_parse_mapping_file_) { - ParseFrameworkMappings(); + for (int i = 0; i < message->nested_type_count(); i++) { + if (MessageContainsExtensions(message->nested_type(i))) { + return true; + } } + return false; +} - map<string, string>::iterator proto_lookup = - proto_file_to_framework_name_.find(file_descriptor->name()); - if (proto_lookup != proto_file_to_framework_name_.end()) { - other_framework_imports_.push_back( - proto_lookup->second + "/" + - FilePathBasename(file_descriptor) + extension); - return; +// Checks if the file contains any extensions definitions (at the root or +// nested under a message). +bool FileContainsExtensions(const FileDescriptor* file) { + if (file->extension_count() > 0) { + return true; } - - if (!options_.generate_for_named_framework.empty()) { - other_framework_imports_.push_back( - options_.generate_for_named_framework + "/" + - FilePathBasename(file_descriptor) + extension); - return; + for (int i = 0; i < file->message_type_count(); i++) { + if (MessageContainsExtensions(file->message_type(i))) { + return true; + } } - - other_imports_.push_back(file->Path() + extension); + return false; } -void ImportWriter::Print(io::Printer* printer) const { - assert(protobuf_non_framework_imports_.size() == - protobuf_framework_imports_.size()); - - bool add_blank_line = false; - - if (protobuf_framework_imports_.size() > 0) { - const string framework_name(ProtobufLibraryFrameworkName); - const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); - - printer->Print( - "#if $cpp_symbol$\n", - "cpp_symbol", cpp_symbol); - for (vector<string>::const_iterator iter = protobuf_framework_imports_.begin(); - iter != protobuf_framework_imports_.end(); ++iter) { - printer->Print( - " #import <$framework_name$/$header$>\n", - "framework_name", framework_name, - "header", *iter); - } - printer->Print( - "#else\n"); - for (vector<string>::const_iterator iter = protobuf_non_framework_imports_.begin(); - iter != protobuf_non_framework_imports_.end(); ++iter) { - printer->Print( - " #import \"$header$\"\n", - "header", *iter); - } - printer->Print( - "#endif\n"); - - add_blank_line = true; +// Helper for CollectMinimalFileDepsContainingExtensionsWorker that marks all +// deps as visited and prunes them from the needed files list. +void PruneFileAndDepsMarkingAsVisited( + const FileDescriptor* file, + vector<const FileDescriptor*>* files, + set<const FileDescriptor*>* files_visited) { + vector<const FileDescriptor*>::iterator iter = + std::find(files->begin(), files->end(), file); + if (iter != files->end()) { + files->erase(iter); } + files_visited->insert(file); + for (int i = 0; i < file->dependency_count(); i++) { + PruneFileAndDepsMarkingAsVisited(file->dependency(i), files, files_visited); + } +} - if (other_framework_imports_.size() > 0) { - if (add_blank_line) { - printer->Print("\n"); - } - - for (vector<string>::const_iterator iter = other_framework_imports_.begin(); - iter != other_framework_imports_.end(); ++iter) { - printer->Print( - " #import <$header$>\n", - "header", *iter); - } - - add_blank_line = true; +// Helper for CollectMinimalFileDepsContainingExtensions. +void CollectMinimalFileDepsContainingExtensionsWorker( + const FileDescriptor* file, + vector<const FileDescriptor*>* files, + set<const FileDescriptor*>* files_visited) { + if (files_visited->find(file) != files_visited->end()) { + return; } + files_visited->insert(file); - if (other_imports_.size() > 0) { - if (add_blank_line) { - printer->Print("\n"); + if (FileContainsExtensions(file)) { + files->push_back(file); + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + PruneFileAndDepsMarkingAsVisited(dep, files, files_visited); } - - for (vector<string>::const_iterator iter = other_imports_.begin(); - iter != other_imports_.end(); ++iter) { - printer->Print( - " #import \"$header$\"\n", - "header", *iter); + } else { + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + CollectMinimalFileDepsContainingExtensionsWorker(dep, files, + files_visited); } } } -void ImportWriter::ParseFrameworkMappings() { - need_to_parse_mapping_file_ = false; - if (options_.named_framework_to_proto_path_mappings_path.empty()) { - return; // Nothing to do. - } - - ProtoFrameworkCollector collector(&proto_file_to_framework_name_); - string parse_error; - if (!ParseSimpleFile(options_.named_framework_to_proto_path_mappings_path, - &collector, &parse_error)) { - cerr << "error parsing " << options_.named_framework_to_proto_path_mappings_path - << " : " << parse_error << endl; - cerr.flush(); +// Collect the deps of the given file that contain extensions. This can be used to +// create the chain of roots that need to be wired together. +// +// NOTE: If any changes are made to this and the supporting functions, you will +// need to manually validate what the generated code is for the test files: +// objectivec/Tests/unittest_extension_chain_*.proto +// There are comments about what the expected code should be line and limited +// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports +// specifically). +void CollectMinimalFileDepsContainingExtensions( + const FileDescriptor* file, + vector<const FileDescriptor*>* files) { + set<const FileDescriptor*> files_visited; + for (int i = 0; i < file->dependency_count(); i++) { + const FileDescriptor* dep = file->dependency(i); + CollectMinimalFileDepsContainingExtensionsWorker(dep, files, + &files_visited); } } -bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( - const StringPiece& line, string* out_error) { - int offset = line.find(':'); - if (offset == StringPiece::npos) { - *out_error = - string("Framework/proto file mapping line without colon sign: '") + - line.ToString() + "'."; - return false; - } - StringPiece framework_name(line, 0, offset); - StringPiece proto_file_list(line, offset + 1, line.length() - offset - 1); - StringPieceTrimWhitespace(&framework_name); - - int start = 0; - while (start < proto_file_list.length()) { - offset = proto_file_list.find(',', start); - if (offset == StringPiece::npos) { - offset = proto_file_list.length(); - } - - StringPiece proto_file(proto_file_list, start, offset); - StringPieceTrimWhitespace(&proto_file); - if (proto_file.size() != 0) { - map<string, string>::iterator existing_entry = - map_->find(proto_file.ToString()); - if (existing_entry != map_->end()) { - cerr << "warning: duplicate proto file reference, replacing framework entry for '" - << proto_file.ToString() << "' with '" << framework_name.ToString() - << "' (was '" << existing_entry->second << "')." << endl; - cerr.flush(); - } - - if (proto_file.find(' ') != StringPiece::npos) { - cerr << "note: framework mapping file had a proto file with a space in, hopefully that isn't a missing comma: '" - << proto_file.ToString() << "'" << endl; - cerr.flush(); - } - - (*map_)[proto_file.ToString()] = framework_name.ToString(); +bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) { + for (int i = 0; i < file->dependency_count(); i++) { + if (dep == file->dependency(i)) { + return true; } - - start = offset + 1; } - - return true; + return false; } } // namespace - FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) : file_(file), root_class_name_(FileClassName(file)), - is_public_dep_(false), options_(options) { for (int i = 0; i < file_->enum_type_count(); i++) { EnumGenerator *generator = new EnumGenerator(file_->enum_type(i)); @@ -275,8 +180,6 @@ FileGenerator::FileGenerator(const FileDescriptor *file, const Options& options) } FileGenerator::~FileGenerator() { - STLDeleteContainerPointers(dependency_generators_.begin(), - dependency_generators_.end()); STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end()); STLDeleteContainerPointers(message_generators_.begin(), message_generators_.end()); @@ -299,14 +202,12 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { // #import any headers for "public imports" in the proto file. { - ImportWriter import_writer(options_); - const vector<FileGenerator *> &dependency_generators = DependencyGenerators(); - for (vector<FileGenerator *>::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { - if ((*iter)->IsPublicDependency()) { - import_writer.AddFile(*iter); - } + ImportWriter import_writer( + options_.generate_for_named_framework, + options_.named_framework_to_proto_path_mappings_path); + const string header_extension(kHeaderExtension); + for (int i = 0; i < file_->public_dependency_count(); i++) { + import_writer.AddFile(file_->public_dependency(i), header_extension); } import_writer.Print(printer); } @@ -357,14 +258,16 @@ void FileGenerator::GenerateHeader(io::Printer *printer) { printer->Print( "#pragma mark - $root_class_name$\n" "\n" - "/// Exposes the extension registry for this file.\n" - "///\n" - "/// The base class provides:\n" - "/// @code\n" - "/// + (GPBExtensionRegistry *)extensionRegistry;\n" - "/// @endcode\n" - "/// which is a @c GPBExtensionRegistry that includes all the extensions defined by\n" - "/// this file and all files that it depends on.\n" + "/**\n" + " * Exposes the extension registry for this file.\n" + " *\n" + " * The base class provides:\n" + " * @code\n" + " * + (GPBExtensionRegistry *)extensionRegistry;\n" + " * @endcode\n" + " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n" + " * this file and all files that it depends on.\n" + " **/\n" "@interface $root_class_name$ : GPBRootObject\n" "@end\n" "\n", @@ -404,21 +307,41 @@ void FileGenerator::GenerateSource(io::Printer *printer) { // #import the runtime support. PrintFileRuntimePreamble(printer, "GPBProtocolBuffers_RuntimeSupport.h"); + vector<const FileDescriptor*> deps_with_extensions; + CollectMinimalFileDepsContainingExtensions(file_, &deps_with_extensions); + { - ImportWriter import_writer(options_); + ImportWriter import_writer( + options_.generate_for_named_framework, + options_.named_framework_to_proto_path_mappings_path); + const string header_extension(kHeaderExtension); // #import the header for this proto file. - import_writer.AddFile(this); + import_writer.AddFile(file_, header_extension); // #import the headers for anything that a plain dependency of this proto // file (that means they were just an include, not a "public" include). - const vector<FileGenerator *> &dependency_generators = - DependencyGenerators(); - for (vector<FileGenerator *>::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { - if (!(*iter)->IsPublicDependency()) { - import_writer.AddFile(*iter); + set<string> 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 FileDescriptor *dep = file_->dependency(i); + bool public_import = (public_import_names.count(dep->name()) != 0); + if (!public_import) { + import_writer.AddFile(dep, header_extension); + } + } + + // If any indirect dependency provided extensions, it needs to be directly + // imported so it can get merged into the root's extensions registry. + // See the Note by CollectMinimalFileDepsContainingExtensions before + // changing this. + for (vector<const FileDescriptor *>::iterator iter = + deps_with_extensions.begin(); + iter != deps_with_extensions.end(); ++iter) { + if (!IsDirectDependency(*iter, file_)) { + import_writer.AddFile(*iter, header_extension); } } @@ -458,29 +381,11 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "@implementation $root_class_name$\n\n", "root_class_name", root_class_name_); - // 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<ExtensionGenerator *>::iterator iter = - extension_generators_.begin(); - iter != extension_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); - } - for (vector<MessageGenerator *>::iterator iter = - message_generators_.begin(); - iter != message_generators_.end(); ++iter) { - (*iter)->GenerateStaticVariablesInitialization(&extensions_printer); - } - extensions_stringstream.flush(); - } + const bool file_contains_extensions = FileContainsExtensions(file_); // 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) { + if (file_contains_extensions || !deps_with_extensions.empty()) { printer->Print( "+ (GPBExtensionRegistry*)extensionRegistry {\n" " // This is called by +initialize so there is no need to worry\n" @@ -493,11 +398,20 @@ void FileGenerator::GenerateSource(io::Printer *printer) { printer->Indent(); printer->Indent(); - if (extensions_str.length() > 0) { + if (file_contains_extensions) { printer->Print( "static GPBExtensionDescription descriptions[] = {\n"); printer->Indent(); - printer->Print(extensions_str.c_str()); + for (vector<ExtensionGenerator *>::iterator iter = + extension_generators_.begin(); + iter != extension_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer); + } + for (vector<MessageGenerator *>::iterator iter = + message_generators_.begin(); + iter != message_generators_.end(); ++iter) { + (*iter)->GenerateStaticVariablesInitialization(printer); + } printer->Outdent(); printer->Print( "};\n" @@ -510,14 +424,21 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "}\n"); } - const vector<FileGenerator *> &dependency_generators = - DependencyGenerators(); - for (vector<FileGenerator *>::const_iterator iter = - dependency_generators.begin(); - iter != dependency_generators.end(); ++iter) { + if (deps_with_extensions.empty()) { printer->Print( - "[registry addExtensions:[$dependency$ extensionRegistry]];\n", - "dependency", (*iter)->RootClassName()); + "// None of the imports (direct or indirect) defined extensions, so no need to add\n" + "// them to this registry.\n"); + } else { + printer->Print( + "// Merge in the imports (direct or indirect) that defined extensions.\n"); + for (vector<const FileDescriptor *>::iterator iter = + deps_with_extensions.begin(); + iter != deps_with_extensions.end(); ++iter) { + const string root_class_name(FileClassName((*iter))); + printer->Print( + "[registry addExtensions:[$dependency$ extensionRegistry]];\n", + "dependency", root_class_name); + } } printer->Outdent(); @@ -526,27 +447,39 @@ void FileGenerator::GenerateSource(io::Printer *printer) { printer->Print( " }\n" " return registry;\n" - "}\n" - "\n"); + "}\n"); + } else { + if (file_->dependency_count() > 0) { + printer->Print( + "// No extensions in the file and none of the imports (direct or indirect)\n" + "// defined extensions, so no need to generate +extensionRegistry.\n"); + } else { + printer->Print( + "// No extensions in the file and no imports, so no need to generate\n" + "// +extensionRegistry.\n"); + } } - printer->Print("@end\n\n"); + printer->Print("\n@end\n\n"); // File descriptor only needed if there are messages to use it. if (message_generators_.size() > 0) { - string syntax; + map<string, string> vars; + vars["root_class_name"] = root_class_name_; + vars["package"] = file_->package(); + vars["objc_prefix"] = FileClassPrefix(file_); switch (file_->syntax()) { case FileDescriptor::SYNTAX_UNKNOWN: - syntax = "GPBFileSyntaxUnknown"; + vars["syntax"] = "GPBFileSyntaxUnknown"; break; case FileDescriptor::SYNTAX_PROTO2: - syntax = "GPBFileSyntaxProto2"; + vars["syntax"] = "GPBFileSyntaxProto2"; break; case FileDescriptor::SYNTAX_PROTO3: - syntax = "GPBFileSyntaxProto3"; + vars["syntax"] = "GPBFileSyntaxProto3"; break; } - printer->Print( + printer->Print(vars, "#pragma mark - $root_class_name$_FileDescriptor\n" "\n" "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n" @@ -554,16 +487,24 @@ void FileGenerator::GenerateSource(io::Printer *printer) { " // 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" + " GPBDebugCheckRuntimeVersion();\n"); + if (vars["objc_prefix"].size() > 0) { + printer->Print( + vars, + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " objcPrefix:@\"$objc_prefix$\"\n" + " syntax:$syntax$];\n"); + } else { + printer->Print( + vars, + " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n" + " syntax:$syntax$];\n"); + } + printer->Print( " }\n" " return descriptor;\n" "}\n" - "\n", - "root_class_name", root_class_name_, - "package", file_->package(), - "syntax", syntax); + "\n"); } for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin(); @@ -582,24 +523,6 @@ void FileGenerator::GenerateSource(io::Printer *printer) { "// @@protoc_insertion_point(global_scope)\n"); } -const vector<FileGenerator *> &FileGenerator::DependencyGenerators() { - if (file_->dependency_count() != dependency_generators_.size()) { - set<string> 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), options_); - 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_; -} - // Helper to print the import of the runtime support at the top of generated // files. This currently only supports the runtime coming from a framework // as defined by the official CocoaPod. diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h index 8e4388d8..a60a6885 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_file.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h @@ -62,32 +62,17 @@ class FileGenerator { void GenerateHeader(io::Printer* printer); const string& RootClassName() const { return root_class_name_; } - const string Path() const { return FilePath(file_); } - const FileDescriptor* Descriptor() const { return file_; } - - bool IsPublicDependency() const { return is_public_dep_; } - - protected: - void SetIsPublicDependency(bool is_public_dep) { - is_public_dep_ = is_public_dep; - } private: const FileDescriptor* file_; string root_class_name_; - // Access this field through the DependencyGenerators accessor call below. - // Do not reference it directly. - vector<FileGenerator*> dependency_generators_; - vector<EnumGenerator*> enum_generators_; vector<MessageGenerator*> message_generators_; vector<ExtensionGenerator*> extension_generators_; - bool is_public_dep_; const Options options_; - const vector<FileGenerator*>& DependencyGenerators(); void PrintFileRuntimePreamble( io::Printer* printer, const string& header_to_import) const; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc index 29a8765c..36407467 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc @@ -45,12 +45,29 @@ ObjectiveCGenerator::ObjectiveCGenerator() {} ObjectiveCGenerator::~ObjectiveCGenerator() {} +bool ObjectiveCGenerator::HasGenerateAll() const { + return true; +} + bool ObjectiveCGenerator::Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, + GeneratorContext* context, string* error) const { + *error = "Unimplemented Generate() method. Call GenerateAll() instead."; + return false; +} + +bool ObjectiveCGenerator::GenerateAll(const vector<const FileDescriptor*>& files, + const string& parameter, + GeneratorContext* context, + string* error) const { // ----------------------------------------------------------------- - // Parse generator options. + // Parse generator options. These options are passed to the compiler using the + // --objc_opt flag. The options are passed as a comma separated list of + // options along with their values. If the option appears multiple times, only + // the last value will be considered. + // + // e.g. protoc ... --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework Options generation_options; @@ -70,7 +87,7 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, // (i.e. - "package=prefix # comment") // // There is no validation that the prefixes are good prefixes, it is - // assume they are when you create the file. + // assumed that they are when you create the file. generation_options.expected_prefixes_path = options[i].second; } else if (options[i].first == "generate_for_named_framework") { // The name of the framework that protos are being generated for. This @@ -79,11 +96,12 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, // // NOTE: If this option is used with // named_framework_to_proto_path_mappings_path, then this is effectively - // the "default" to use for everything that wasn't mapped by the other. - generation_options.named_framework_to_proto_path_mappings_path = options[i].second; + // the "default" framework name used for everything that wasn't mapped by + // the mapping file. + generation_options.generate_for_named_framework = options[i].second; } else if (options[i].first == "named_framework_to_proto_path_mappings_path") { - // Path to find a file containing the listing of framework names and - // proto files. The generator uses this to decide if another proto file + // Path to find a file containing the list of framework names and proto + // files. The generator uses this to decide if a proto file // referenced should use a framework style import vs. a user level import // (#import <FRAMEWORK/file.pbobjc.h> vs #import "dir/file.pbobjc.h"). // @@ -97,8 +115,11 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, // with commas. // // There can be multiple lines listing the same frameworkName incase it - // has a lot of proto files included in it; and having multiple lines - // makes things easier to read. + // has a lot of proto files included in it; having multiple lines makes + // things easier to read. If a proto file is not configured in the + // mappings file, it will use the default framework name if one was passed + // with generate_for_named_framework, or the relative path to it's include + // path otherwise. generation_options.named_framework_to_proto_path_mappings_path = options[i].second; } else { *error = "error: Unknown generator option: " + options[i].first; @@ -108,29 +129,32 @@ bool ObjectiveCGenerator::Generate(const FileDescriptor* file, // ----------------------------------------------------------------- - // Validate the objc prefix/package pairing. - if (!ValidateObjCClassPrefix(file, generation_options, error)) { + // Validate the objc prefix/package pairings. + if (!ValidateObjCClassPrefixes(files, generation_options, error)) { // *error will have been filled in. return false; } - FileGenerator file_generator(file, generation_options); - string filepath = FilePath(file); + for (int i = 0; i < files.size(); i++) { + const FileDescriptor* file = files[i]; + FileGenerator file_generator(file, generation_options); + string filepath = FilePath(file); - // Generate header. - { - scoped_ptr<io::ZeroCopyOutputStream> output( - output_directory->Open(filepath + ".pbobjc.h")); - io::Printer printer(output.get(), '$'); - file_generator.GenerateHeader(&printer); - } + // Generate header. + { + scoped_ptr<io::ZeroCopyOutputStream> output( + context->Open(filepath + ".pbobjc.h")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateHeader(&printer); + } - // Generate m file. - { - scoped_ptr<io::ZeroCopyOutputStream> output( - output_directory->Open(filepath + ".pbobjc.m")); - io::Printer printer(output.get(), '$'); - file_generator.GenerateSource(&printer); + // Generate m file. + { + scoped_ptr<io::ZeroCopyOutputStream> output( + context->Open(filepath + ".pbobjc.m")); + io::Printer printer(output.get(), '$'); + file_generator.GenerateSource(&printer); + } } return true; diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h index 09266b04..9d801d51 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h @@ -47,8 +47,15 @@ class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator { ~ObjectiveCGenerator(); // implements CodeGenerator ---------------------------------------- - bool Generate(const FileDescriptor* file, const string& parameter, - OutputDirectory* output_directory, string* error) const; + bool HasGenerateAll() const; + bool Generate(const FileDescriptor* file, + const string& parameter, + GeneratorContext* context, + string* error) const; + bool GenerateAll(const vector<const FileDescriptor*>& files, + const string& parameter, + GeneratorContext* context, + string* error) const; private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator); diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc index 311bf35d..c7fd96ac 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc @@ -44,9 +44,10 @@ #include <google/protobuf/stubs/hash.h> #include <google/protobuf/compiler/objectivec/objectivec_helpers.h> +#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/io/coded_stream.h> +#include <google/protobuf/io/printer.h> #include <google/protobuf/io/zero_copy_stream_impl.h> -#include <google/protobuf/descriptor.pb.h> #include <google/protobuf/stubs/common.h> #include <google/protobuf/stubs/strutil.h> @@ -209,10 +210,14 @@ const char* const kReservedWordList[] = { hash_set<string> kReservedWords = MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList)); -string SanitizeNameForObjC(const string& input, const string& extension) { +string SanitizeNameForObjC(const string& input, + const string& extension, + string* out_suffix_added) { if (kReservedWords.count(input) > 0) { + if (out_suffix_added) *out_suffix_added = extension; return input + extension; } + if (out_suffix_added) out_suffix_added->clear(); return input; } @@ -261,6 +266,34 @@ bool IsSpecialName(const string& name, const string* special_names, return false; } +string GetZeroEnumNameForFlagType(const FlagType flag_type) { + switch(flag_type) { + case FLAGTYPE_DESCRIPTOR_INITIALIZATION: + return "GPBDescriptorInitializationFlag_None"; + case FLAGTYPE_EXTENSION: + return "GPBExtensionNone"; + case FLAGTYPE_FIELD: + return "GPBFieldNone"; + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + return "0"; + } +} + +string GetEnumNameForFlagType(const FlagType flag_type) { + switch(flag_type) { + case FLAGTYPE_DESCRIPTOR_INITIALIZATION: + return "GPBDescriptorInitializationFlags"; + case FLAGTYPE_EXTENSION: + return "GPBExtensionOptions"; + case FLAGTYPE_FIELD: + return "GPBFieldFlags"; + default: + GOOGLE_LOG(FATAL) << "Can't get here."; + return string(); + } +} + } // namespace // Escape C++ trigraphs by escaping question marks to \? @@ -307,6 +340,12 @@ string BaseFileName(const FileDescriptor* file) { return basename; } +string FileClassPrefix(const FileDescriptor* file) { + // Default is empty string, no need to check has_objc_class_prefix. + string result = file->options().objc_class_prefix(); + return result; +} + string FilePath(const FileDescriptor* file) { string output; string basename; @@ -337,19 +376,13 @@ string FilePathBasename(const FileDescriptor* file) { return output; } -string FileClassPrefix(const FileDescriptor* file) { - // Default is empty string, no need to check has_objc_class_prefix. - string result = file->options().objc_class_prefix(); - return result; -} - string FileClassName(const FileDescriptor* file) { string name = FileClassPrefix(file); name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true); name += "Root"; // There aren't really any reserved words that end in "Root", but playing // it safe and checking. - return SanitizeNameForObjC(name, "_RootClass"); + return SanitizeNameForObjC(name, "_RootClass", NULL); } string ClassNameWorker(const Descriptor* descriptor) { @@ -371,11 +404,15 @@ string ClassNameWorker(const EnumDescriptor* descriptor) { } string ClassName(const Descriptor* descriptor) { + return ClassName(descriptor, NULL); +} + +string ClassName(const Descriptor* descriptor, string* out_suffix_added) { // 1. Message names are used as is (style calls for CamelCase, trust it). // 2. Check for reserved word at the very end and then suffix things. string prefix = FileClassPrefix(descriptor->file()); string name = ClassNameWorker(descriptor); - return SanitizeNameForObjC(prefix + name, "_Class"); + return SanitizeNameForObjC(prefix + name, "_Class", out_suffix_added); } string EnumName(const EnumDescriptor* descriptor) { @@ -389,7 +426,7 @@ string EnumName(const EnumDescriptor* descriptor) { // yields Fixed_Class, Fixed_Size. string name = FileClassPrefix(descriptor->file()); name += ClassNameWorker(descriptor); - return SanitizeNameForObjC(name, "_Enum"); + return SanitizeNameForObjC(name, "_Enum", NULL); } string EnumValueName(const EnumValueDescriptor* descriptor) { @@ -404,7 +441,7 @@ string EnumValueName(const EnumValueDescriptor* descriptor) { const string& name = class_name + "_" + value_str; // There aren't really any reserved words with an underscore and a leading // capital letter, but playing it safe and checking. - return SanitizeNameForObjC(name, "_Value"); + return SanitizeNameForObjC(name, "_Value", NULL); } string EnumValueShortName(const EnumValueDescriptor* descriptor) { @@ -441,7 +478,7 @@ string UnCamelCaseEnumShortName(const string& name) { string ExtensionMethodName(const FieldDescriptor* descriptor) { const string& name = NameFromFieldDescriptor(descriptor); const string& result = UnderscoresToCamelCase(name, false); - return SanitizeNameForObjC(result, "_Extension"); + return SanitizeNameForObjC(result, "_Extension", NULL); } string FieldName(const FieldDescriptor* field) { @@ -456,7 +493,7 @@ string FieldName(const FieldDescriptor* field) { result += "_p"; } } - return SanitizeNameForObjC(result, "_p"); + return SanitizeNameForObjC(result, "_p", NULL); } string FieldNameCapitalized(const FieldDescriptor* field) { @@ -816,21 +853,26 @@ bool HasNonZeroDefaultValue(const FieldDescriptor* field) { return false; } -string BuildFlagsString(const vector<string>& strings) { +string BuildFlagsString(const FlagType flag_type, + const vector<string>& strings) { if (strings.size() == 0) { - return "0"; + return GetZeroEnumNameForFlagType(flag_type); + } else if (strings.size() == 1) { + return strings[0]; } - string string; + string string("(" + GetEnumNameForFlagType(flag_type) + ")("); for (size_t i = 0; i != strings.size(); ++i) { if (i > 0) { string.append(" | "); } string.append(strings[i]); } + string.append(")"); return string; } -string BuildCommentsString(const SourceLocation& location) { +string BuildCommentsString(const SourceLocation& location, + bool prefer_single_line) { const string& comments = location.leading_comments.empty() ? location.trailing_comments : location.leading_comments; @@ -839,15 +881,45 @@ string BuildCommentsString(const SourceLocation& location) { while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } - string prefix("///"); - string suffix("\n"); + // If there are no comments, just return an empty string. + if (lines.size() == 0) { + return ""; + } + + string prefix; + string suffix; string final_comments; - for (int i = 0; i < lines.size(); i++) { - // HeaderDoc uses '\' and '@' for markers; escape them. - const string line = StringReplace(lines[i], "\\", "\\\\", true); - final_comments += - prefix + StringReplace(line, "@", "\\@", true) + suffix; + string epilogue; + + bool add_leading_space = false; + + if (prefer_single_line && lines.size() == 1) { + prefix = "/** "; + suffix = " */\n"; + } else { + prefix = "* "; + suffix = "\n"; + final_comments += "/**\n"; + epilogue = " **/\n"; + add_leading_space = true; } + + for (int i = 0; i < lines.size(); i++) { + string line = StripPrefixString(lines[i], " "); + // HeaderDoc and appledoc use '\' and '@' for markers; escape them. + line = StringReplace(line, "\\", "\\\\", true); + line = StringReplace(line, "@", "\\@", true); + // Decouple / from * to not have inline comments inside comments. + line = StringReplace(line, "/*", "/\\*", true); + line = StringReplace(line, "*/", "*\\/", true); + line = prefix + line; + StripWhitespace(&line); + // If not a one line, need to add the first space before *, as + // StripWhitespace would have removed it. + line = (add_leading_space ? " " : "") + line; + final_comments += line + suffix; + } + final_comments += epilogue; return final_comments; } @@ -948,28 +1020,20 @@ bool LoadExpectedPackagePrefixes(const Options &generation_options, generation_options.expected_prefixes_path, &collector, out_error); } -} // namespace - -bool ValidateObjCClassPrefix(const FileDescriptor* file, - const Options& generation_options, - string* out_error) { +bool ValidateObjCClassPrefix( + const FileDescriptor* file, + const string& expected_prefixes_path, + const map<string, string>& expected_package_prefixes, + string* out_error) { const string prefix = file->options().objc_class_prefix(); const string package = file->package(); // 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 warnings. - // Load any expected package prefixes to validate against those. - map<string, string> expected_package_prefixes; - if (!LoadExpectedPackagePrefixes(generation_options, - &expected_package_prefixes, - out_error)) { - return false; - } - // Check: Error - See if there was an expected prefix for the package and // report if it doesn't match (wrong or missing). - map<string, string>::iterator package_match = + map<string, string>::const_iterator package_match = expected_package_prefixes.find(package); if (package_match != expected_package_prefixes.end()) { // There was an entry, and... @@ -990,27 +1054,11 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, } // If there was no prefix option, we're done at this point. - if (prefix.length() == 0) { + if (prefix.empty()) { // No prefix, nothing left to check. return true; } - // Check: Error - Make sure the prefix wasn't expected for a different - // package (overlap is allowed, but it has to be listed as an expected - // overlap). - for (map<string, string>::iterator i = expected_package_prefixes.begin(); - i != expected_package_prefixes.end(); ++i) { - if (i->second == prefix) { - *out_error = - "error: Found 'option objc_class_prefix = \"" + prefix + - "\";' in '" + file->name() + - "'; that prefix is already used for 'package " + i->first + - ";'. It can only be reused by listing it in the expected file (" + - generation_options.expected_prefixes_path + ")."; - return false; // Only report first usage of the prefix. - } - } - // Check: Warning - Make sure the prefix is is a reasonable value according // to Apple's rules (the checks above implicitly whitelist anything that // doesn't meet these rules). @@ -1032,6 +1080,56 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, cerr.flush(); } + // Look for any other package that uses the same prefix. + string other_package_for_prefix; + for (map<string, string>::const_iterator i = expected_package_prefixes.begin(); + i != expected_package_prefixes.end(); ++i) { + if (i->second == prefix) { + other_package_for_prefix = i->first; + break; + } + } + + // Check: Warning - If the file does not have a package, check whether + // the prefix declared is being used by another package or not. + if (package.empty()) { + // The file does not have a package and ... + if (other_package_for_prefix.empty()) { + // ... no other package has declared that prefix. + cerr << endl + << "protoc:0: warning: File '" << file->name() << "' has no " + << "package. Consider adding a new package to the proto and adding '" + << "new.package = " << prefix << "' to the expected prefixes file (" + << expected_prefixes_path << ")." << endl; + cerr.flush(); + } else { + // ... another package has declared the same prefix. + cerr << endl + << "protoc:0: warning: File '" << file->name() << "' has no package " + << "and package '" << other_package_for_prefix << "' already uses '" + << prefix << "' as its prefix. Consider either adding a new package " + << "to the proto, or reusing one of the packages already using this " + << "prefix in the expected prefixes file (" + << expected_prefixes_path << ")." << endl; + cerr.flush(); + } + return true; + } + + // Check: Error - Make sure the prefix wasn't expected for a different + // package (overlap is allowed, but it has to be listed as an expected + // overlap). + if (!other_package_for_prefix.empty()) { + *out_error = + "error: Found 'option objc_class_prefix = \"" + prefix + + "\";' in '" + file->name() + + "'; that prefix is already used for 'package " + + other_package_for_prefix + ";'. It can only be reused by listing " + + "it in the expected file (" + + expected_prefixes_path + ")."; + return false; // Only report first usage of the prefix. + } + // Check: Warning - If the given package/prefix pair wasn't expected, issue a // warning issue a warning suggesting it gets added to the file. if (!expected_package_prefixes.empty()) { @@ -1039,13 +1137,39 @@ bool ValidateObjCClassPrefix(const FileDescriptor* file, << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \"" << prefix << "\";' in '" << file->name() << "';" << " consider adding it to the expected prefixes file (" - << generation_options.expected_prefixes_path << ")." << endl; + << expected_prefixes_path << ")." << endl; cerr.flush(); } return true; } +} // namespace + +bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files, + const Options& generation_options, + string* out_error) { + // Load the expected package prefixes, if available, to validate against. + map<string, string> expected_package_prefixes; + if (!LoadExpectedPackagePrefixes(generation_options, + &expected_package_prefixes, + out_error)) { + return false; + } + + for (int i = 0; i < files.size(); i++) { + bool is_valid = + ValidateObjCClassPrefix(files[i], + generation_options.expected_prefixes_path, + expected_package_prefixes, + out_error); + if (!is_valid) { + return false; + } + } + return true; +} + TextFormatDecodeData::TextFormatDecodeData() { } TextFormatDecodeData::~TextFormatDecodeData() { } @@ -1306,7 +1430,8 @@ bool Parser::Finish() { return true; } // Force a newline onto the end to finish parsing. - p_ = StringPiece(leftover_ + "\n"); + leftover_ += "\n"; + p_ = StringPiece(leftover_); if (!ParseLoop()) { return false; } @@ -1367,6 +1492,178 @@ bool ParseSimpleFile( return parser.Finish(); } +ImportWriter::ImportWriter( + const string& generate_for_named_framework, + const string& named_framework_to_proto_path_mappings_path) + : generate_for_named_framework_(generate_for_named_framework), + named_framework_to_proto_path_mappings_path_( + named_framework_to_proto_path_mappings_path), + need_to_parse_mapping_file_(true) { +} + +ImportWriter::~ImportWriter() {} + +void ImportWriter::AddFile(const FileDescriptor* file, + const string& header_extension) { + const string file_path(FilePath(file)); + + if (IsProtobufLibraryBundledProtoFile(file)) { + protobuf_framework_imports_.push_back( + FilePathBasename(file) + header_extension); + protobuf_non_framework_imports_.push_back(file_path + header_extension); + return; + } + + // Lazy parse any mappings. + if (need_to_parse_mapping_file_) { + ParseFrameworkMappings(); + } + + map<string, string>::iterator proto_lookup = + proto_file_to_framework_name_.find(file->name()); + if (proto_lookup != proto_file_to_framework_name_.end()) { + other_framework_imports_.push_back( + proto_lookup->second + "/" + + FilePathBasename(file) + header_extension); + return; + } + + if (!generate_for_named_framework_.empty()) { + other_framework_imports_.push_back( + generate_for_named_framework_ + "/" + + FilePathBasename(file) + header_extension); + return; + } + + other_imports_.push_back(file_path + header_extension); +} + +void ImportWriter::Print(io::Printer* printer) const { + assert(protobuf_non_framework_imports_.size() == + protobuf_framework_imports_.size()); + + bool add_blank_line = false; + + if (protobuf_framework_imports_.size() > 0) { + const string framework_name(ProtobufLibraryFrameworkName); + const string cpp_symbol(ProtobufFrameworkImportSymbol(framework_name)); + + printer->Print( + "#if $cpp_symbol$\n", + "cpp_symbol", cpp_symbol); + for (vector<string>::const_iterator iter = protobuf_framework_imports_.begin(); + iter != protobuf_framework_imports_.end(); ++iter) { + printer->Print( + " #import <$framework_name$/$header$>\n", + "framework_name", framework_name, + "header", *iter); + } + printer->Print( + "#else\n"); + for (vector<string>::const_iterator iter = protobuf_non_framework_imports_.begin(); + iter != protobuf_non_framework_imports_.end(); ++iter) { + printer->Print( + " #import \"$header$\"\n", + "header", *iter); + } + printer->Print( + "#endif\n"); + + add_blank_line = true; + } + + if (other_framework_imports_.size() > 0) { + if (add_blank_line) { + printer->Print("\n"); + } + + for (vector<string>::const_iterator iter = other_framework_imports_.begin(); + iter != other_framework_imports_.end(); ++iter) { + printer->Print( + " #import <$header$>\n", + "header", *iter); + } + + add_blank_line = true; + } + + if (other_imports_.size() > 0) { + if (add_blank_line) { + printer->Print("\n"); + } + + for (vector<string>::const_iterator iter = other_imports_.begin(); + iter != other_imports_.end(); ++iter) { + printer->Print( + " #import \"$header$\"\n", + "header", *iter); + } + } +} + +void ImportWriter::ParseFrameworkMappings() { + need_to_parse_mapping_file_ = false; + if (named_framework_to_proto_path_mappings_path_.empty()) { + return; // Nothing to do. + } + + ProtoFrameworkCollector collector(&proto_file_to_framework_name_); + string parse_error; + if (!ParseSimpleFile(named_framework_to_proto_path_mappings_path_, + &collector, &parse_error)) { + cerr << "error parsing " << named_framework_to_proto_path_mappings_path_ + << " : " << parse_error << endl; + cerr.flush(); + } +} + +bool ImportWriter::ProtoFrameworkCollector::ConsumeLine( + const StringPiece& line, string* out_error) { + int offset = line.find(':'); + if (offset == StringPiece::npos) { + *out_error = + string("Framework/proto file mapping line without colon sign: '") + + line.ToString() + "'."; + return false; + } + StringPiece framework_name(line, 0, offset); + StringPiece proto_file_list(line, offset + 1, line.length() - offset - 1); + StringPieceTrimWhitespace(&framework_name); + + int start = 0; + while (start < proto_file_list.length()) { + offset = proto_file_list.find(',', start); + if (offset == StringPiece::npos) { + offset = proto_file_list.length(); + } + + StringPiece proto_file(proto_file_list, start, offset - start); + StringPieceTrimWhitespace(&proto_file); + if (proto_file.size() != 0) { + map<string, string>::iterator existing_entry = + map_->find(proto_file.ToString()); + if (existing_entry != map_->end()) { + cerr << "warning: duplicate proto file reference, replacing framework entry for '" + << proto_file.ToString() << "' with '" << framework_name.ToString() + << "' (was '" << existing_entry->second << "')." << endl; + cerr.flush(); + } + + if (proto_file.find(' ') != StringPiece::npos) { + cerr << "note: framework mapping file had a proto file with a space in, hopefully that isn't a missing comma: '" + << proto_file.ToString() << "'" << endl; + cerr.flush(); + } + + (*map_)[proto_file.ToString()] = framework_name.ToString(); + } + + start = offset + 1; + } + + return true; +} + } // namespace objectivec } // namespace compiler diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h index be20beee..d17d44aa 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h +++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h @@ -67,6 +67,9 @@ bool IsRetainedName(const string& name); // handling under ARC. bool IsInitName(const string& name); +// Gets the objc_class_prefix. +string FileClassPrefix(const FileDescriptor* file); + // Gets the path of the file we're going to generate (sans the .pb.h // extension). The path will be dependent on the objectivec package // declared in the proto package. @@ -83,6 +86,7 @@ string FileClassName(const FileDescriptor* file); // These return the fully-qualified class name corresponding to the given // descriptor. string ClassName(const Descriptor* descriptor); +string ClassName(const Descriptor* descriptor, string* out_suffix_added); string EnumName(const EnumDescriptor* descriptor); // Returns the fully-qualified name of the enum value corresponding to the @@ -137,6 +141,12 @@ enum ObjectiveCType { OBJECTIVECTYPE_MESSAGE }; +enum FlagType { + FLAGTYPE_DESCRIPTOR_INITIALIZATION, + FLAGTYPE_EXTENSION, + FLAGTYPE_FIELD +}; + template<class TDescriptor> string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor, bool preSpace = true, bool postNewline = false) { if (descriptor->options().deprecated()) { @@ -168,10 +178,12 @@ string GPBGenericValueFieldName(const FieldDescriptor* field); string DefaultValue(const FieldDescriptor* field); bool HasNonZeroDefaultValue(const FieldDescriptor* field); -string BuildFlagsString(const vector<string>& strings); +string BuildFlagsString(const FlagType type, const vector<string>& strings); -// Builds a HeaderDoc style comment out of the comments in the .proto file. -string BuildCommentsString(const SourceLocation& location); +// Builds HeaderDoc/appledoc style comments out of the comments in the .proto +// file. +string BuildCommentsString(const SourceLocation& location, + bool prefer_single_line); // The name the commonly used by the library when built as a framework. // This lines up to the name used in the CocoaPod. @@ -183,12 +195,12 @@ string ProtobufFrameworkImportSymbol(const string& framework_name); // Checks if the file is one of the proto's bundled with the library. bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file); -// Checks the prefix for a given file and outputs any warnings needed, if -// there are flat out errors, then out_error is filled in and the result is -// false. -bool ValidateObjCClassPrefix(const FileDescriptor* file, - const Options& generation_options, - string* out_error); +// Checks the prefix for the given files and outputs any warnings as needed. If +// there are flat out errors, then out_error is filled in with the first error +// and the result is false. +bool ValidateObjCClassPrefixes(const vector<const FileDescriptor*>& files, + const Options& generation_options, + string* out_error); // Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform // the input into the expected output. @@ -223,6 +235,43 @@ class LIBPROTOC_EXPORT LineConsumer { bool ParseSimpleFile( const string& path, LineConsumer* line_consumer, string* out_error); + +// Helper class for parsing framework import mappings and generating +// import statements. +class LIBPROTOC_EXPORT ImportWriter { + public: + ImportWriter(const string& generate_for_named_framework, + const string& named_framework_to_proto_path_mappings_path); + ~ImportWriter(); + + void AddFile(const FileDescriptor* file, const string& header_extension); + void Print(io::Printer *printer) const; + + private: + class ProtoFrameworkCollector : public LineConsumer { + public: + ProtoFrameworkCollector(map<string, string>* inout_proto_file_to_framework_name) + : map_(inout_proto_file_to_framework_name) {} + + virtual bool ConsumeLine(const StringPiece& line, string* out_error); + + private: + map<string, string>* map_; + }; + + void ParseFrameworkMappings(); + + const string generate_for_named_framework_; + const string named_framework_to_proto_path_mappings_path_; + map<string, string> proto_file_to_framework_name_; + bool need_to_parse_mapping_file_; + + vector<string> protobuf_framework_imports_; + vector<string> protobuf_non_framework_imports_; + vector<string> other_framework_imports_; + vector<string> other_imports_; +}; + } // namespace objectivec } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc index ac5d8aea..0bc9dc10 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc @@ -115,7 +115,7 @@ MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor, if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) { field_flags.push_back("GPBFieldHasEnumDescriptor"); } - variables_["fieldflags"] = BuildFlagsString(field_flags); + variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags); ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor); const bool value_is_object_type = diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc index e1a78619..4c6e1b55 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc @@ -331,7 +331,7 @@ void MessageGenerator::GenerateMessageHeader(io::Printer* printer) { string message_comments; SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { - message_comments = BuildCommentsString(location); + message_comments = BuildCommentsString(location, false); } else { message_comments = ""; } @@ -521,7 +521,8 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { if (descriptor_->options().message_set_wire_format()) { init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat"); } - vars["init_flags"] = BuildFlagsString(init_flags); + vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, + init_flags); printer->Print( vars, @@ -579,6 +580,19 @@ void MessageGenerator::GenerateSource(io::Printer* printer) { " [localDescriptor setupExtensionRanges:ranges\n" " count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n"); } + if (descriptor_->containing_type() != NULL) { + string parent_class_name = ClassName(descriptor_->containing_type()); + printer->Print( + " [localDescriptor setupContainingMessageClassName:GPBStringifySymbol($parent_name$)];\n", + "parent_name", parent_class_name); + } + string suffix_added; + ClassName(descriptor_, &suffix_added); + if (suffix_added.size() > 0) { + printer->Print( + " [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n", + "suffix", suffix_added); + } printer->Print( " NSAssert(descriptor == nil, @\"Startup recursed!\");\n" " descriptor = localDescriptor;\n" diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc index 44bafd7f..5531ae24 100644 --- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc +++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc @@ -53,7 +53,7 @@ OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor) string comments; SourceLocation location; if (descriptor_->GetSourceLocation(&location)) { - comments = BuildCommentsString(location); + comments = BuildCommentsString(location, true); } else { comments = ""; } @@ -104,7 +104,9 @@ void OneofGenerator::GeneratePublicCasePropertyDeclaration( void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) { printer->Print( variables_, - "/// Clears whatever value was set for the oneof '$name$'.\n" + "/**\n" + " * Clears whatever value was set for the oneof '$name$'.\n" + " **/\n" "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n"); } @@ -119,7 +121,7 @@ void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) { variables_, "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n" " GPBDescriptor *descriptor = [message descriptor];\n" - " GPBOneofDescriptor *oneof = descriptor->oneofs_[$raw_index$];\n" + " GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n" " GPBMaybeClearOneof(message, oneof, $index$, 0);\n" "}\n"); } diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 214d7c9c..519ed8fc 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -525,7 +525,6 @@ bool Parser::Parse(io::Tokenizer* input, FileDescriptorProto* file) { SourceCodeInfo source_code_info; source_code_info_ = &source_code_info; - vector<string> top_doc_comments; if (LookingAtType(io::Tokenizer::TYPE_START)) { // Advance to first token. input_->NextWithComments(NULL, &upcoming_detached_comments_, diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index c4d48fc6..9064c382 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -36,6 +36,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -102,6 +103,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -123,6 +125,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { delete CodeGeneratorResponse_File_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto() { static bool already_here = false; if (already_here) return; @@ -161,16 +164,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto } } static_descriptor_initializer_google_2fprotobuf_2fcompiler_2fplugin_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -451,7 +444,9 @@ int CodeGeneratorRequest::ByteSize() const { void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const CodeGeneratorRequest* source = ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorRequest>( &from); @@ -466,7 +461,9 @@ void CodeGeneratorRequest::MergeFrom(const ::google::protobuf::Message& from) { void CodeGeneratorRequest::MergeFrom(const CodeGeneratorRequest& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } file_to_generate_.MergeFrom(from.file_to_generate_); proto_file_.MergeFrom(from.proto_file_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { @@ -962,7 +959,9 @@ int CodeGeneratorResponse_File::ByteSize() const { void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const CodeGeneratorResponse_File* source = ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse_File>( &from); @@ -977,7 +976,9 @@ void CodeGeneratorResponse_File::MergeFrom(const ::google::protobuf::Message& fr void CodeGeneratorResponse_File::MergeFrom(const CodeGeneratorResponse_File& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { set_has_name(); @@ -1269,7 +1270,9 @@ int CodeGeneratorResponse::ByteSize() const { void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const CodeGeneratorResponse* source = ::google::protobuf::internal::DynamicCastToGenerated<const CodeGeneratorResponse>( &from); @@ -1284,7 +1287,9 @@ void CodeGeneratorResponse::MergeFrom(const ::google::protobuf::Message& from) { void CodeGeneratorResponse::MergeFrom(const CodeGeneratorResponse& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } file_.MergeFrom(from.file_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_error()) { diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index cc54a8ab..d5468a0c 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -44,6 +44,7 @@ // performance-minded Python code leverage the fast C++ implementation // directly. +#include <algorithm> #include <google/protobuf/stubs/hash.h> #include <limits> #include <map> @@ -107,20 +108,25 @@ string ModuleAlias(const string& filename) { return module_name; } - -// Returns an import statement of form "from X.Y.Z import T" for the given -// .proto filename. -string ModuleImportStatement(const string& filename) { - string module_name = ModuleName(filename); - int last_dot_pos = module_name.rfind('.'); - if (last_dot_pos == string::npos) { - // NOTE(petya): this is not tested as it would require a protocol buffer - // outside of any package, and I don't think that is easily achievable. - return "import " + module_name; - } else { - return "from " + module_name.substr(0, last_dot_pos) + " import " + - module_name.substr(last_dot_pos + 1); +// Keywords reserved by the Python language. +const char* const kKeywords[] = { + "False", "None", "True", "and", "as", "assert", "break", + "class", "continue", "def", "del", "elif", "else", "except", + "finally", "for", "from", "global", "if", "import", "in", + "is", "lambda", "nonlocal", "not", "or", "pass", "raise", + "return", "try", "while", "with", "yield", +}; +const char* const* kKeywordsEnd = + kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0])); + +bool ContainsPythonKeyword(const string& module_name) { + vector<string> tokens = Split(module_name, "."); + for (int i = 0; i < tokens.size(); ++i) { + if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) { + return true; + } } + return false; } @@ -359,10 +365,32 @@ bool Generator::Generate(const FileDescriptor* file, void Generator::PrintImports() const { for (int i = 0; i < file_->dependency_count(); ++i) { const string& filename = file_->dependency(i)->name(); - string import_statement = ModuleImportStatement(filename); + + string module_name = ModuleName(filename); string module_alias = ModuleAlias(filename); - printer_->Print("$statement$ as $alias$\n", "statement", - import_statement, "alias", module_alias); + if (ContainsPythonKeyword(module_name)) { + // If the module path contains a Python keyword, we have to quote the + // module name and import it using importlib. Otherwise the usual kind of + // import statement would result in a syntax error from the presence of + // the keyword. + printer_->Print("import importlib\n"); + printer_->Print("$alias$ = importlib.import_module('$name$')\n", "alias", + module_alias, "name", module_name); + } else { + int last_dot_pos = module_name.rfind('.'); + string import_statement; + if (last_dot_pos == string::npos) { + // NOTE(petya): this is not tested as it would require a protocol buffer + // outside of any package, and I don't think that is easily achievable. + import_statement = "import " + module_name; + } else { + import_statement = "from " + module_name.substr(0, last_dot_pos) + + " import " + module_name.substr(last_dot_pos + 1); + } + printer_->Print("$statement$ as $alias$\n", "statement", import_statement, + "alias", module_alias); + } + CopyPublicDependenciesAliases(module_alias, file_->dependency(i)); } printer_->Print("\n"); diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc index 23f2449c..34f857fd 100644 --- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -46,6 +46,7 @@ #include <google/protobuf/testing/file.h> #include <google/protobuf/testing/file.h> +#include <google/protobuf/stubs/strutil.h> #include <google/protobuf/testing/googletest.h> #include <gtest/gtest.h> @@ -115,6 +116,53 @@ TEST(PythonPluginTest, PluginTest) { EXPECT_EQ(0, cli.Run(5, argv)); } +// This test verifies that the generated Python output uses regular imports (as +// opposed to importlib) in the usual case where the .proto file paths do not +// not contain any Python keywords. +TEST(PythonPluginTest, ImportTest) { + // Create files test1.proto and test2.proto with the former importing the + // latter. + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test1.proto", + "syntax = \"proto3\";\n" + "package foo;\n" + "import \"test2.proto\";" + "message Message1 {\n" + " Message2 message_2 = 1;\n" + "}\n", + true)); + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test2.proto", + "syntax = \"proto3\";\n" + "package foo;\n" + "message Message2 {}\n", + true)); + + google::protobuf::compiler::CommandLineInterface cli; + cli.SetInputsAreProtoPathRelative(true); + python::Generator python_generator; + cli.RegisterGenerator("--python_out", &python_generator, ""); + string proto_path = "-I" + TestTempDir(); + string python_out = "--python_out=" + TestTempDir(); + const char* argv[] = {"protoc", proto_path.c_str(), "-I.", python_out.c_str(), + "test1.proto"}; + ASSERT_EQ(0, cli.Run(5, argv)); + + // Loop over the lines of the generated code and verify that we find an + // ordinary Python import but do not find the string "importlib". + string output; + GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/test1_pb2.py", &output, + true)); + std::vector<string> lines = Split(output, "\n"); + string expected_import = "import test2_pb2"; + bool found_expected_import = false; + for (int i = 0; i < lines.size(); ++i) { + if (lines[i].find(expected_import) != string::npos) { + found_expected_import = true; + } + EXPECT_EQ(string::npos, lines[i].find("importlib")); + } + EXPECT_TRUE(found_expected_import); +} + } // namespace } // namespace python } // namespace compiler diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb index 49b23fbe..49b23fbe 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generated_code.rb +++ b/src/google/protobuf/compiler/ruby/ruby_generated_code_pb.rb diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc index 92c76fb0..fbe3b4cb 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc @@ -48,7 +48,7 @@ namespace ruby { // Forward decls. std::string IntToString(int32 value); -std::string StripDotProto(const std::string& proto_file); +std::string GetRequireName(const std::string& proto_file); std::string LabelForField(google::protobuf::FieldDescriptor* field); std::string TypeName(google::protobuf::FieldDescriptor* field); void GenerateMessage(const google::protobuf::Descriptor* message, @@ -70,13 +70,13 @@ std::string IntToString(int32 value) { return os.str(); } -std::string StripDotProto(const std::string& proto_file) { +std::string GetRequireName(const std::string& proto_file) { int lastindex = proto_file.find_last_of("."); - return proto_file.substr(0, lastindex); + return proto_file.substr(0, lastindex) + "_pb"; } std::string GetOutputFilename(const std::string& proto_file) { - return StripDotProto(proto_file) + ".rb"; + return GetRequireName(proto_file) + ".rb"; } std::string LabelForField(const google::protobuf::FieldDescriptor* field) { @@ -237,15 +237,52 @@ void GenerateEnum(const google::protobuf::EnumDescriptor* en, "end\n"); } -// Module names, class names, and enum value names need to be Ruby constants, -// which must start with a capital letter. +// Locale-agnostic utility functions. +bool IsLower(char ch) { return ch >= 'a' && ch <= 'z'; } + +bool IsUpper(char ch) { return ch >= 'A' && ch <= 'Z'; } + +bool IsAlpha(char ch) { return IsLower(ch) || IsUpper(ch); } + +char ToUpper(char ch) { return IsLower(ch) ? (ch - 'a' + 'A') : ch; } + + +// Package names in protobuf are snake_case by convention, but Ruby module +// names must be PascalCased. +// +// foo_bar_baz -> FooBarBaz +std::string PackageToModule(const std::string& name) { + bool next_upper = true; + std::string result; + result.reserve(name.size()); + + for (int i = 0; i < name.size(); i++) { + if (name[i] == '_') { + next_upper = true; + } else { + if (next_upper) { + result.push_back(ToUpper(name[i])); + } else { + result.push_back(name[i]); + } + next_upper = false; + } + } + + return result; +} + +// Class and enum names in protobuf should be PascalCased by convention, but +// since there is nothing enforcing this we need to ensure that they are valid +// Ruby constants. That mainly means making sure that the first character is +// an upper-case letter. std::string RubifyConstant(const std::string& name) { std::string ret = name; if (!ret.empty()) { - if (ret[0] >= 'a' && ret[0] <= 'z') { + if (IsLower(ret[0])) { // If it starts with a lowercase letter, capitalize it. - ret[0] = ret[0] - 'a' + 'A'; - } else if (ret[0] < 'A' || ret[0] > 'Z') { + ret[0] = ToUpper(ret[0]); + } else if (!IsAlpha(ret[0])) { // Otherwise (e.g. if it begins with an underscore), we need to come up // with some prefix that starts with a capital letter. We could be smarter // here, e.g. try to strip leading underscores, but this may cause other @@ -254,6 +291,7 @@ std::string RubifyConstant(const std::string& name) { ret = "PB_" + ret; } } + return ret; } @@ -314,7 +352,7 @@ int GeneratePackageModules( component = package_name.substr(0, dot_index); package_name = package_name.substr(dot_index + 1); } - component = RubifyConstant(component); + component = PackageToModule(component); printer->Print( "module $name$\n", "name", component); @@ -391,7 +429,7 @@ bool MaybeEmitDependency(const FileDescriptor* import, return true; } else { printer->Print( - "require '$name$'\n", "name", StripDotProto(import->name())); + "require '$name$'\n", "name", GetRequireName(import->name())); return true; } } diff --git a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc index c0acb407..1aabe8aa 100644 --- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc +++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc @@ -91,12 +91,12 @@ TEST(RubyGeneratorTest, GeneratorTest) { // Load the generated output and compare to the expected result. string output; GOOGLE_CHECK_OK(File::GetContents( - TestTempDir() + "/ruby_generated_code.rb", + TestTempDir() + "/ruby_generated_code_pb.rb", &output, true)); string expected_output; GOOGLE_CHECK_OK(File::GetContents( - ruby_tests + "/ruby_generated_code.rb", + ruby_tests + "/ruby_generated_code_pb.rb", &expected_output, true)); EXPECT_EQ(expected_output, output); diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 6e258664..e929e4fb 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -261,12 +261,12 @@ string Subprocess::Win32ErrorMessage(DWORD error_code) { char* message; // WTF? - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, error_code, 0, - (LPTSTR)&message, // NOT A BUG! - 0, NULL); + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, error_code, 0, + (LPSTR)&message, // NOT A BUG! + 0, NULL); string result = message; LocalFree(message); diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index 4e2c9dcf..92c70c0d 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -106,6 +106,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -588,6 +589,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -697,6 +699,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() { delete GeneratedCodeInfo_Annotation_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { static bool already_here = false; if (already_here) return; @@ -834,9 +837,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { ".protobuf.GeneratedCodeInfo.Annotation\032O" "\n\nAnnotation\022\020\n\004path\030\001 \003(\005B\002\020\001\022\023\n\013source" "_file\030\002 \001(\t\022\r\n\005begin\030\003 \001(\005\022\013\n\003end\030\004 \001(\005B" - "X\n\023com.google.protobufB\020DescriptorProtos" - "H\001Z\ndescriptor\242\002\003GPB\252\002\032Google.Protobuf.R" - "eflection", 5289); + "[\n\023com.google.protobufB\020DescriptorProtos" + "H\001Z\ndescriptor\240\001\001\242\002\003GPB\252\002\032Google.Protobu" + "f.Reflection", 5292); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -899,16 +902,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fdescriptor_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2fdescriptor_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -1088,7 +1081,9 @@ int FileDescriptorSet::ByteSize() const { void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorSet) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const FileDescriptorSet* source = ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorSet>( &from); @@ -1103,7 +1098,9 @@ void FileDescriptorSet::MergeFrom(const ::google::protobuf::Message& from) { void FileDescriptorSet::MergeFrom(const FileDescriptorSet& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } file_.MergeFrom(from.file_); if (from._internal_metadata_.have_unknown_fields()) { mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -1856,7 +1853,9 @@ int FileDescriptorProto::ByteSize() const { void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const FileDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const FileDescriptorProto>( &from); @@ -1871,7 +1870,9 @@ void FileDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void FileDescriptorProto::MergeFrom(const FileDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } dependency_.MergeFrom(from.dependency_); public_dependency_.MergeFrom(from.public_dependency_); weak_dependency_.MergeFrom(from.weak_dependency_); @@ -2532,7 +2533,7 @@ void DescriptorProto_ExtensionRange::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -2682,7 +2683,9 @@ int DescriptorProto_ExtensionRange::ByteSize() const { void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const DescriptorProto_ExtensionRange* source = ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ExtensionRange>( &from); @@ -2697,7 +2700,9 @@ void DescriptorProto_ExtensionRange::MergeFrom(const ::google::protobuf::Message void DescriptorProto_ExtensionRange::MergeFrom(const DescriptorProto_ExtensionRange& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_start()) { set_start(from.start()); @@ -2831,7 +2836,7 @@ void DescriptorProto_ReservedRange::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -2981,7 +2986,9 @@ int DescriptorProto_ReservedRange::ByteSize() const { void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto.ReservedRange) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const DescriptorProto_ReservedRange* source = ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto_ReservedRange>( &from); @@ -2996,7 +3003,9 @@ void DescriptorProto_ReservedRange::MergeFrom(const ::google::protobuf::Message& void DescriptorProto_ReservedRange::MergeFrom(const DescriptorProto_ReservedRange& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_start()) { set_start(from.start()); @@ -3608,7 +3617,9 @@ int DescriptorProto::ByteSize() const { void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const DescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const DescriptorProto>( &from); @@ -3623,7 +3634,9 @@ void DescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void DescriptorProto::MergeFrom(const DescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } field_.MergeFrom(from.field_); extension_.MergeFrom(from.extension_); nested_type_.MergeFrom(from.nested_type_); @@ -4844,7 +4857,9 @@ int FieldDescriptorProto::ByteSize() const { void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const FieldDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const FieldDescriptorProto>( &from); @@ -4859,7 +4874,9 @@ void FieldDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { set_has_name(); @@ -5606,7 +5623,9 @@ int OneofDescriptorProto::ByteSize() const { void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const OneofDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const OneofDescriptorProto>( &from); @@ -5621,7 +5640,9 @@ void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { set_has_name(); @@ -6056,7 +6077,9 @@ int EnumDescriptorProto::ByteSize() const { void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const EnumDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumDescriptorProto>( &from); @@ -6071,7 +6094,9 @@ void EnumDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void EnumDescriptorProto::MergeFrom(const EnumDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } value_.MergeFrom(from.value_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { @@ -6534,7 +6559,9 @@ int EnumValueDescriptorProto::ByteSize() const { void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const EnumValueDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueDescriptorProto>( &from); @@ -6549,7 +6576,9 @@ void EnumValueDescriptorProto::MergeFrom(const ::google::protobuf::Message& from void EnumValueDescriptorProto::MergeFrom(const EnumValueDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { set_has_name(); @@ -7012,7 +7041,9 @@ int ServiceDescriptorProto::ByteSize() const { void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const ServiceDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const ServiceDescriptorProto>( &from); @@ -7027,7 +7058,9 @@ void ServiceDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) void ServiceDescriptorProto::MergeFrom(const ServiceDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } method_.MergeFrom(from.method_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { @@ -7314,7 +7347,7 @@ void MethodDescriptorProto::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -7642,7 +7675,9 @@ int MethodDescriptorProto::ByteSize() const { void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const MethodDescriptorProto* source = ::google::protobuf::internal::DynamicCastToGenerated<const MethodDescriptorProto>( &from); @@ -7657,7 +7692,9 @@ void MethodDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { void MethodDescriptorProto::MergeFrom(const MethodDescriptorProto& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { set_has_name(); @@ -8126,7 +8163,7 @@ void FileOptions::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -8792,7 +8829,9 @@ int FileOptions::ByteSize() const { void FileOptions::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FileOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const FileOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const FileOptions>( &from); @@ -8807,7 +8846,9 @@ void FileOptions::MergeFrom(const ::google::protobuf::Message& from) { void FileOptions::MergeFrom(const FileOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_java_package()) { @@ -9529,7 +9570,7 @@ void MessageOptions::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -9789,7 +9830,9 @@ int MessageOptions::ByteSize() const { void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MessageOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const MessageOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const MessageOptions>( &from); @@ -9804,7 +9847,9 @@ void MessageOptions::MergeFrom(const ::google::protobuf::Message& from) { void MessageOptions::MergeFrom(const MessageOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_message_set_wire_format()) { @@ -10138,7 +10183,7 @@ void FieldOptions::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -10477,7 +10522,9 @@ int FieldOptions::ByteSize() const { void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const FieldOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const FieldOptions>( &from); @@ -10492,7 +10539,9 @@ void FieldOptions::MergeFrom(const ::google::protobuf::Message& from) { void FieldOptions::MergeFrom(const FieldOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_ctype()) { @@ -10943,7 +10992,9 @@ int OneofOptions::ByteSize() const { void OneofOptions::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.OneofOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const OneofOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const OneofOptions>( &from); @@ -10958,7 +11009,9 @@ void OneofOptions::MergeFrom(const ::google::protobuf::Message& from) { void OneofOptions::MergeFrom(const OneofOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } uninterpreted_option_.MergeFrom(from.uninterpreted_option_); _extensions_.MergeFrom(from._extensions_); if (from._internal_metadata_.have_unknown_fields()) { @@ -11124,7 +11177,7 @@ void EnumOptions::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -11324,7 +11377,9 @@ int EnumOptions::ByteSize() const { void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const EnumOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumOptions>( &from); @@ -11339,7 +11394,9 @@ void EnumOptions::MergeFrom(const ::google::protobuf::Message& from) { void EnumOptions::MergeFrom(const EnumOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_allow_alias()) { @@ -11709,7 +11766,9 @@ int EnumValueOptions::ByteSize() const { void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValueOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const EnumValueOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumValueOptions>( &from); @@ -11724,7 +11783,9 @@ void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) { void EnumValueOptions::MergeFrom(const EnumValueOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_deprecated()) { @@ -12066,7 +12127,9 @@ int ServiceOptions::ByteSize() const { void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ServiceOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const ServiceOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const ServiceOptions>( &from); @@ -12081,7 +12144,9 @@ void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) { void ServiceOptions::MergeFrom(const ServiceOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_deprecated()) { @@ -12423,7 +12488,9 @@ int MethodOptions::ByteSize() const { void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.MethodOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const MethodOptions* source = ::google::protobuf::internal::DynamicCastToGenerated<const MethodOptions>( &from); @@ -12438,7 +12505,9 @@ void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) { void MethodOptions::MergeFrom(const MethodOptions& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } uninterpreted_option_.MergeFrom(from.uninterpreted_option_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_deprecated()) { @@ -12796,7 +12865,9 @@ int UninterpretedOption_NamePart::ByteSize() const { void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption.NamePart) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const UninterpretedOption_NamePart* source = ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption_NamePart>( &from); @@ -12811,7 +12882,9 @@ void UninterpretedOption_NamePart::MergeFrom(const ::google::protobuf::Message& void UninterpretedOption_NamePart::MergeFrom(const UninterpretedOption_NamePart& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name_part()) { set_has_name_part(); @@ -12960,7 +13033,7 @@ void UninterpretedOption::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -13313,7 +13386,9 @@ int UninterpretedOption::ByteSize() const { void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UninterpretedOption) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const UninterpretedOption* source = ::google::protobuf::internal::DynamicCastToGenerated<const UninterpretedOption>( &from); @@ -13328,7 +13403,9 @@ void UninterpretedOption::MergeFrom(const ::google::protobuf::Message& from) { void UninterpretedOption::MergeFrom(const UninterpretedOption& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } name_.MergeFrom(from.name_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { if (from.has_identifier_value()) { @@ -14170,7 +14247,9 @@ int SourceCodeInfo_Location::ByteSize() const { void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo.Location) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const SourceCodeInfo_Location* source = ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo_Location>( &from); @@ -14185,7 +14264,9 @@ void SourceCodeInfo_Location::MergeFrom(const ::google::protobuf::Message& from) void SourceCodeInfo_Location::MergeFrom(const SourceCodeInfo_Location& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } path_.MergeFrom(from.path_); span_.MergeFrom(from.span_); leading_detached_comments_.MergeFrom(from.leading_detached_comments_); @@ -14426,7 +14507,9 @@ int SourceCodeInfo::ByteSize() const { void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceCodeInfo) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const SourceCodeInfo* source = ::google::protobuf::internal::DynamicCastToGenerated<const SourceCodeInfo>( &from); @@ -14441,7 +14524,9 @@ void SourceCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { void SourceCodeInfo::MergeFrom(const SourceCodeInfo& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } location_.MergeFrom(from.location_); if (from._internal_metadata_.have_unknown_fields()) { mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -14833,7 +14918,7 @@ void GeneratedCodeInfo_Annotation::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -15093,7 +15178,9 @@ int GeneratedCodeInfo_Annotation::ByteSize() const { void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const GeneratedCodeInfo_Annotation* source = ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo_Annotation>( &from); @@ -15108,7 +15195,9 @@ void GeneratedCodeInfo_Annotation::MergeFrom(const ::google::protobuf::Message& void GeneratedCodeInfo_Annotation::MergeFrom(const GeneratedCodeInfo_Annotation& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } path_.MergeFrom(from.path_); if (from._has_bits_[1 / 32] & (0xffu << (1 % 32))) { if (from.has_source_file()) { @@ -15348,7 +15437,9 @@ int GeneratedCodeInfo::ByteSize() const { void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.GeneratedCodeInfo) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const GeneratedCodeInfo* source = ::google::protobuf::internal::DynamicCastToGenerated<const GeneratedCodeInfo>( &from); @@ -15363,7 +15454,9 @@ void GeneratedCodeInfo::MergeFrom(const ::google::protobuf::Message& from) { void GeneratedCodeInfo::MergeFrom(const GeneratedCodeInfo& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } annotation_.MergeFrom(from.annotation_); if (from._internal_metadata_.have_unknown_fields()) { mutable_unknown_fields()->MergeFrom(from.unknown_fields()); diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index da853dbc..28410d4a 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -45,6 +45,7 @@ option java_package = "com.google.protobuf"; option java_outer_classname = "DescriptorProtos"; option csharp_namespace = "Google.Protobuf.Reflection"; option objc_class_prefix = "GPB"; +option java_generate_equals_and_hash = true; // descriptor.proto must be optimized for speed because reflection-based // algorithms don't work during bootstrapping. diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc index b0c641bf..ed5cca4b 100644 --- a/src/google/protobuf/duration.pb.cc +++ b/src/google/protobuf/duration.pb.cc @@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -61,6 +62,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fduration_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -74,6 +76,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fduration_2eproto() { delete Duration_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fduration_2eproto() { static bool already_here = false; if (already_here) return; @@ -101,16 +104,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fduration_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2fduration_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -192,7 +185,7 @@ void Duration::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -322,7 +315,9 @@ int Duration::ByteSize() const { void Duration::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Duration) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Duration* source = ::google::protobuf::internal::DynamicCastToGenerated<const Duration>( &from); @@ -337,7 +332,9 @@ void Duration::MergeFrom(const ::google::protobuf::Message& from) { void Duration::MergeFrom(const Duration& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.seconds() != 0) { set_seconds(from.seconds()); } diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc index 8b461201..83775753 100644 --- a/src/google/protobuf/empty.pb.cc +++ b/src/google/protobuf/empty.pb.cc @@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -59,6 +60,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fempty_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -72,6 +74,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fempty_2eproto() { delete Empty_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fempty_2eproto() { static bool already_here = false; if (already_here) return; @@ -98,16 +101,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fempty_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2fempty_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -240,7 +233,9 @@ int Empty::ByteSize() const { void Empty::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Empty) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Empty* source = ::google::protobuf::internal::DynamicCastToGenerated<const Empty>( &from); @@ -255,7 +250,9 @@ void Empty::MergeFrom(const ::google::protobuf::Message& from) { void Empty::MergeFrom(const Empty& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Empty) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } } void Empty::CopyFrom(const ::google::protobuf::Message& from) { diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 5dd171ed..b26a246c 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -341,7 +341,7 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, int ExtensionSet::SpaceUsedExcludingSelf() const { int total_size = - extensions_.size() * sizeof(map<int, Extension>::value_type); + extensions_.size() * sizeof(ExtensionMap::value_type); for (ExtensionMap::const_iterator iter = extensions_.begin(), end = extensions_.end(); iter != end; diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc index d197b406..ed05fe57 100644 --- a/src/google/protobuf/field_mask.pb.cc +++ b/src/google/protobuf/field_mask.pb.cc @@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto() { protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -60,6 +61,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2ffield_5fmask_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -73,6 +75,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2ffield_5fmask_2eproto() { delete FieldMask_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2ffield_5fmask_2eproto() { static bool already_here = false; if (already_here) return; @@ -99,16 +102,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2ffield_5fmask_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2ffield_5fmask_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -281,7 +274,9 @@ int FieldMask::ByteSize() const { void FieldMask::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FieldMask) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const FieldMask* source = ::google::protobuf::internal::DynamicCastToGenerated<const FieldMask>( &from); @@ -296,7 +291,9 @@ void FieldMask::MergeFrom(const ::google::protobuf::Message& from) { void FieldMask::MergeFrom(const FieldMask& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } paths_.MergeFrom(from.paths_); } diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc index 7b813f8a..7ad6d61c 100644 --- a/src/google/protobuf/generated_message_util.cc +++ b/src/google/protobuf/generated_message_util.cc @@ -73,6 +73,12 @@ int StringSpaceUsedExcludingSelf(const string& str) { +void MergeFromFail(const char* file, int line) { + GOOGLE_CHECK(false) << file << ":" << line; + // Open-source GOOGLE_CHECK(false) is not NORETURN. + exit(1); +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/generated_message_util.h b/src/google/protobuf/generated_message_util.h index 56f5afd2..8967726e 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -41,8 +41,8 @@ #include <assert.h> #include <string> -#include <google/protobuf/stubs/once.h> #include <google/protobuf/stubs/common.h> +#include <google/protobuf/stubs/once.h> namespace google { @@ -112,8 +112,13 @@ class ArenaString; // 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); +LIBPROTOBUF_EXPORT ArenaString* ReadArenaString( + ::google::protobuf::io::CodedInputStream* input, + ::google::protobuf::Arena* arena); + +// Helper function to crash on merge failure. +// Moved out of generated code to reduce binary size. +LIBPROTOBUF_EXPORT void MergeFromFail(const char* file, int line) GOOGLE_ATTRIBUTE_NORETURN; } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 148eee0e..a5675e79 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -649,13 +649,16 @@ bool CodedInputStream::Refresh() { // CodedOutputStream ================================================= +bool CodedOutputStream::default_serialization_deterministic_ = false; + CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) : output_(output), buffer_(NULL), buffer_size_(0), total_bytes_(0), had_error_(false), - aliasing_enabled_(false) { + aliasing_enabled_(false), + serialization_deterministic_is_overridden_(false) { // Eagerly Refresh() so buffer space is immediately available. Refresh(); // The Refresh() may have failed. If the client doesn't write any data, @@ -671,7 +674,8 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output, buffer_size_(0), total_bytes_(0), had_error_(false), - aliasing_enabled_(false) { + aliasing_enabled_(false), + serialization_deterministic_is_overridden_(false) { if (do_eager_refresh) { // Eagerly Refresh() so buffer space is immediately available. Refresh(); diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index eb320745..316da765 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -813,6 +813,44 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // created. bool HadError() const { return had_error_; } + // Deterministic serialization, if requested, guarantees that for a given + // binary, equal messages will always be serialized to the same bytes. This + // implies: + // . repeated serialization of a message will return the same bytes + // . different processes of the same binary (which may be executing on + // different machines) will serialize equal messages to the same bytes. + // + // Note the deterministic serialization is NOT canonical across languages; it + // is also unstable across different builds with schema changes due to unknown + // fields. Users who need canonical serialization, e.g., persistent storage in + // a canonical form, fingerprinting, etc., should define their own + // canonicalization specification and implement the serializer using + // reflection APIs rather than relying on this API. + // + // If determinisitc serialization is requested, the serializer will + // sort map entries by keys in lexicographical order or numerical order. + // (This is an implementation detail and may subject to change.) + // + // There are two ways to determine whether serialization should be + // deterministic for this CodedOutputStream. If SetSerializationDeterministic + // has not yet been called, then the default comes from the global default, + // which is false, until SetDefaultSerializationDeterministic has been called. + // Otherwise, SetSerializationDeterministic has been called, and the last + // value passed to it is all that matters. + void SetSerializationDeterministic(bool value) { + serialization_deterministic_is_overridden_ = true; + serialization_deterministic_override_ = value; + } + // See above. Also, note that users of this CodedOutputStream may need to + // call IsSerializationDeterminstic() to serialize in the intended way. This + // CodedOutputStream cannot enforce a desire for deterministic serialization + // by itself. + bool IsSerializationDeterminstic() const { + return serialization_deterministic_is_overridden_ ? + serialization_deterministic_override_ : + default_serialization_deterministic_; + } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream); @@ -822,6 +860,10 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { int total_bytes_; // Sum of sizes of all buffers seen so far. bool had_error_; // Whether an error occurred during output. bool aliasing_enabled_; // See EnableAliasing(). + // See SetSerializationDeterministic() regarding these three fields. + bool serialization_deterministic_is_overridden_; + bool serialization_deterministic_override_; + static bool default_serialization_deterministic_; // Advance the buffer by a given number of bytes. void Advance(int amount); @@ -849,6 +891,11 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { uint64 value, uint8* target); static int VarintSize32Fallback(uint32 value); + + // See above. Other projects may use "friend" to allow them to call this. + static void SetDefaultSerializationDeterministic() { + default_serialization_deterministic_ = true; + } }; // inline methods ==================================================== diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h index 42bcfd94..1b9aa703 100644 --- a/src/google/protobuf/map.h +++ b/src/google/protobuf/map.h @@ -1250,7 +1250,7 @@ class Map { // Return whether table_[b] is a linked list that seems awfully long. // Requires table_[b] to point to a non-empty linked list. bool TableEntryIsTooLong(size_type b) { - const int kMaxLength = 8; + const size_type kMaxLength = 8; size_type count = 0; Node* node = static_cast<Node*>(table_[b]); do { diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h index 23ac7b8a..4dedfd57 100644 --- a/src/google/protobuf/map_entry_lite.h +++ b/src/google/protobuf/map_entry_lite.h @@ -535,6 +535,32 @@ class MapEntryLite : public MessageLite { GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite); }; +// Helpers for deterministic serialization ============================= + +// This struct can be used with any generic sorting algorithm. If the Key +// type is relatively small and easy to copy then copying Keys into an +// array of SortItems can be beneficial. Then all the data the sorting +// algorithm needs to touch is in that one array. +template <typename Key, typename PtrToKeyValuePair> struct SortItem { + SortItem() {} + explicit SortItem(PtrToKeyValuePair p) : first(p->first), second(p) {} + + Key first; + PtrToKeyValuePair second; +}; + +template <typename T> struct CompareByFirstField { + bool operator()(const T& a, const T& b) const { + return a.first < b.first; + } +}; + +template <typename T> struct CompareByDerefFirst { + bool operator()(const T& a, const T& b) const { + return a->first < b->first; + } +}; + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto index 916cc546..ddc2a582 100644 --- a/src/google/protobuf/map_proto2_unittest.proto +++ b/src/google/protobuf/map_proto2_unittest.proto @@ -64,3 +64,23 @@ message TestEnumMapPlusExtra { message TestImportEnumMap { map<int32, protobuf_unittest_import.ImportEnumForMap> import_enum_amp = 1; } + +message TestIntIntMap { + map<int32, int32> m = 1; +} + +// Test all key types: string, plus the non-floating-point scalars. +message TestMaps { + map<int32, TestIntIntMap> m_int32 = 1; + map<int64, TestIntIntMap> m_int64 = 2; + map<uint32, TestIntIntMap> m_uint32 = 3; + map<uint64, TestIntIntMap> m_uint64 = 4; + map<sint32, TestIntIntMap> m_sint32 = 5; + map<sint64, TestIntIntMap> m_sint64 = 6; + map<fixed32, TestIntIntMap> m_fixed32 = 7; + map<fixed64, TestIntIntMap> m_fixed64 = 8; + map<sfixed32, TestIntIntMap> m_sfixed32 = 9; + map<sfixed64, TestIntIntMap> m_sfixed64 = 10; + map<bool, TestIntIntMap> m_bool = 11; + map<string, TestIntIntMap> m_string = 12; +} diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc index cdd1ccd5..03954e75 100644 --- a/src/google/protobuf/map_test.cc +++ b/src/google/protobuf/map_test.cc @@ -74,6 +74,7 @@ #include <google/protobuf/io/tokenizer.h> #include <google/protobuf/io/zero_copy_stream_impl.h> #include <google/protobuf/util/time_util.h> +#include <google/protobuf/util/message_differencer.h> #include <google/protobuf/stubs/strutil.h> #include <google/protobuf/stubs/substitute.h> #include <gmock/gmock.h> @@ -2869,6 +2870,82 @@ TEST(WireFormatForMapFieldTest, MapParseHelpers) { } } +// Deterministic Serialization Test ========================================== + +template <typename T> +static string DeterministicSerialization(const T& t) { + const int size = t.ByteSize(); + string result(size, '\0'); + io::ArrayOutputStream array_stream(string_as_array(&result), size); + io::CodedOutputStream output_stream(&array_stream); + output_stream.SetSerializationDeterministic(true); + t.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + return result; +} + +// Helper to test the serialization of the first arg against a golden file. +static void TestDeterministicSerialization(const protobuf_unittest::TestMaps& t, + const string& filename) { + string expected; + GOOGLE_CHECK_OK(File::GetContents( + TestSourceDir() + "/google/protobuf/testdata/" + filename, + &expected, true)); + const string actual = DeterministicSerialization(t); + EXPECT_EQ(expected, actual); + protobuf_unittest::TestMaps u; + EXPECT_TRUE(u.ParseFromString(actual)); + EXPECT_TRUE(google::protobuf::util::MessageDifferencer::Equals(u, t)); +} + +// Helper for MapSerializationTest. Return a 7-bit ASCII string. +static string ConstructKey(uint64 n) { + string s(n % static_cast<uint64>(9), '\0'); + if (s.empty()) { + return StrCat(n); + } else { + while (n != 0) { + s[n % s.size()] = (n >> 10) & 0x7f; + n /= 888; + } + return s; + } +} + +TEST(MapSerializationTest, Deterministic) { + const int kIters = 25; + protobuf_unittest::TestMaps t; + protobuf_unittest::TestIntIntMap inner; + (*inner.mutable_m())[0] = (*inner.mutable_m())[10] = + (*inner.mutable_m())[-200] = 0; + uint64 frog = 9; + const uint64 multiplier = 0xa29cd16f; + for (int i = 0; i < kIters; i++) { + const int32 i32 = static_cast<int32>(frog & 0xffffffff); + const uint32 u32 = static_cast<uint32>(i32) * 91919; + const int64 i64 = static_cast<int64>(frog); + const uint64 u64 = frog * static_cast<uint64>(187321); + const bool b = i32 > 0; + const string s = ConstructKey(frog); + (*inner.mutable_m())[i] = i32; + (*t.mutable_m_int32())[i32] = (*t.mutable_m_sint32())[i32] = + (*t.mutable_m_sfixed32())[i32] = inner; + (*t.mutable_m_uint32())[u32] = (*t.mutable_m_fixed32())[u32] = inner; + (*t.mutable_m_int64())[i64] = (*t.mutable_m_sint64())[i64] = + (*t.mutable_m_sfixed64())[i64] = inner; + (*t.mutable_m_uint64())[u64] = (*t.mutable_m_fixed64())[u64] = inner; + (*t.mutable_m_bool())[b] = inner; + (*t.mutable_m_string())[s] = inner; + (*t.mutable_m_string())[s + string(1 << (u32 % static_cast<uint32>(9)), + b)] = inner; + inner.mutable_m()->erase(i); + frog = frog * multiplier + i; + frog ^= (frog >> 41); + } + TestDeterministicSerialization(t, "golden_message_maps"); +} + // Text Format Test ================================================= TEST(TextFormatMapTest, SerializeAndParse) { diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h index 74e8bb50..685a770f 100644 --- a/src/google/protobuf/map_type_handler.h +++ b/src/google/protobuf/map_type_handler.h @@ -166,10 +166,10 @@ class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> { io::CodedOutputStream* output); static inline uint8* InternalWriteToArray(int field, const MapEntryAccessorType& value, - bool deterministic, uint8* output); + bool deterministic, uint8* target); static inline uint8* WriteToArray(int field, const MapEntryAccessorType& value, - uint8* output); + uint8* target); // Functions to manipulate data on memory. ======================== static inline const Type& GetExternalReference(const Type* value); @@ -227,11 +227,11 @@ class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> { int field, \ const MapEntryAccessorType& value, \ bool deterministic, \ - uint8* output); \ + uint8* target); \ static inline uint8* WriteToArray(int field, \ const MapEntryAccessorType& value, \ - uint8* output) { \ - return InternalWriteToArray(field, value, false, output); \ + uint8* target) { \ + return InternalWriteToArray(field, value, false, target); \ } \ static inline const MapEntryAccessorType& GetExternalReference( \ const TypeOnMemory& value); \ @@ -374,9 +374,9 @@ template <typename Type> inline uint8* MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::InternalWriteToArray( int field, const MapEntryAccessorType& value, bool deterministic, - uint8* output) { + uint8* target) { return WireFormatLite::InternalWriteMessageToArray(field, value, - deterministic, output); + deterministic, target); } #define WRITE_METHOD(FieldType, DeclaredType) \ @@ -390,8 +390,8 @@ MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::InternalWriteToArray( inline uint8* \ MapTypeHandler<WireFormatLite::TYPE_##FieldType, \ Type>::InternalWriteToArray( \ - int field, const MapEntryAccessorType& value, bool, uint8* output) { \ - return WireFormatLite::Write##DeclaredType##ToArray(field, value, output); \ + int field, const MapEntryAccessorType& value, bool, uint8* target) { \ + return WireFormatLite::Write##DeclaredType##ToArray(field, value, target); \ } WRITE_METHOD(STRING , String) diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index d62ca79c..f18077dd 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -62,8 +62,6 @@ namespace protobuf { using internal::WireFormat; using internal::ReflectionOps; -Message::~Message() {} - void Message::MergeFrom(const Message& from) { const Descriptor* descriptor = GetDescriptor(); GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index dcdffe1c..9705e97e 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -179,7 +179,7 @@ struct Metadata { class LIBPROTOBUF_EXPORT Message : public MessageLite { public: inline Message() {} - virtual ~Message(); + virtual ~Message() {} // Basic Operations ------------------------------------------------ diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 3913be1b..ba56db95 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -46,8 +46,6 @@ namespace google { namespace protobuf { -MessageLite::~MessageLite() {} - string MessageLite::InitializationErrorString() const { return "(cannot determine missing fields for lite message)"; } diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index f606aeec..2bdfe496 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -81,7 +81,7 @@ namespace internal { class LIBPROTOBUF_EXPORT MessageLite { public: inline MessageLite() {} - virtual ~MessageLite(); + virtual ~MessageLite() {} // Basic Operations ------------------------------------------------ diff --git a/src/google/protobuf/repeated_field_reflection.h b/src/google/protobuf/repeated_field_reflection.h deleted file mode 100644 index 512c0f1d..00000000 --- a/src/google/protobuf/repeated_field_reflection.h +++ /dev/null @@ -1,337 +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 header file is protobuf internal. Users should not include this -// file directly. -#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__ -#define GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__ - -#include <memory> -#ifndef _SHARED_PTR_H -#include <google/protobuf/stubs/shared_ptr.h> -#endif - -#include <google/protobuf/generated_enum_reflection.h> - -namespace google { -namespace protobuf { -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<T>::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 beginning 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<typename T> - T Get(const Field* data, int index) const { - typedef typename RefTypeTraits<T>::AccessorValueType ActualType; - ActualType scratch_space; - return static_cast<T>( - *reinterpret_cast<const ActualType*>( - Get(data, index, static_cast<Value*>(&scratch_space)))); - } - - template<typename T, typename ValueType> - void Set(Field* data, int index, const ValueType& value) const { - typedef typename RefTypeTraits<T>::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<ActualType>(value); - Set(data, index, static_cast<const Value*>(&tmp)); - } - - template<typename T, typename ValueType> - void Add(Field* data, const ValueType& value) const { - typedef typename RefTypeTraits<T>::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<ActualType>(value); - Add(data, static_cast<const Value*>(&tmp)); - } -}; - -// Implement (Mutable)RepeatedFieldRef::iterator -template<typename T> -class RepeatedFieldRefIterator - : public std::iterator<std::forward_iterator_tag, T> { - typedef typename RefTypeTraits<T>::AccessorValueType AccessorValueType; - typedef typename RefTypeTraits<T>::IteratorValueType IteratorValueType; - typedef typename RefTypeTraits<T>::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<IteratorValueType>( - *static_cast<const AccessorValueType*>( - accessor_->GetIteratorValue( - data_, iterator_, scratch_space_.get()))); - } - IteratorPointerType operator->() const { - return static_cast<IteratorPointerType>( - 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<AccessorValueType> scratch_space_; -}; - -// TypeTraits that maps the type parameter T of RepeatedFieldRef or -// MutableRepeatedFieldRef to corresponding iterator type, -// RepeatedFieldAccessor type, etc. -template<typename T> -struct PrimitiveTraits { - static const bool is_primitive = false; -}; -#define DEFINE_PRIMITIVE(TYPE, type) \ - template<> struct PrimitiveTraits<type> { \ - 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<typename T> -struct RefTypeTraits< - T, typename internal::enable_if<PrimitiveTraits<T>::is_primitive>::type> { - typedef RepeatedFieldRefIterator<T> iterator; - typedef RepeatedFieldAccessor AccessorType; - typedef T AccessorValueType; - typedef T IteratorValueType; - typedef T* IteratorPointerType; - static const FieldDescriptor::CppType cpp_type = - PrimitiveTraits<T>::cpp_type; - static const Descriptor* GetMessageFieldDescriptor() { - return NULL; - } -}; - -template<typename T> -struct RefTypeTraits< - T, typename internal::enable_if<is_proto_enum<T>::value>::type> { - typedef RepeatedFieldRefIterator<T> 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<typename T> -struct RefTypeTraits< - T, typename internal::enable_if<internal::is_same<string, T>::value>::type> { - typedef RepeatedFieldRefIterator<T> 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<typename T> -struct MessageDescriptorGetter { - static const Descriptor* get() { - return T::default_instance().GetDescriptor(); - } -}; -template<> -struct MessageDescriptorGetter<Message> { - static const Descriptor* get() { - return NULL; - } -}; - -template<typename T> -struct RefTypeTraits< - T, typename internal::enable_if<internal::is_base_of<Message, T>::value>::type> { - typedef RepeatedFieldRefIterator<T> 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<T>::get(); - } -}; -} // namespace internal -} // namespace protobuf -} // namespace google -#endif // GOOGLE_PROTOBUF_REPEATED_FIELD_REFLECTION_H__ diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc index 4d8e77ce..5cc77bf3 100644 --- a/src/google/protobuf/source_context.pb.cc +++ b/src/google/protobuf/source_context.pb.cc @@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -60,6 +61,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fsource_5fcontext_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -73,6 +75,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fsource_5fcontext_2eproto() { delete SourceContext_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fsource_5fcontext_2eproto() { static bool already_here = false; if (already_here) return; @@ -99,16 +102,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fsource_5fcontext_2eproto } } static_descriptor_initializer_google_2fprotobuf_2fsource_5fcontext_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -281,7 +274,9 @@ int SourceContext::ByteSize() const { void SourceContext::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceContext) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const SourceContext* source = ::google::protobuf::internal::DynamicCastToGenerated<const SourceContext>( &from); @@ -296,7 +291,9 @@ void SourceContext::MergeFrom(const ::google::protobuf::Message& from) { void SourceContext::MergeFrom(const SourceContext& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.file_name().size() > 0) { file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_); diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc index dd6b78d1..a551384c 100644 --- a/src/google/protobuf/struct.pb.cc +++ b/src/google/protobuf/struct.pb.cc @@ -45,6 +45,7 @@ const ::google::protobuf::EnumDescriptor* NullValue_descriptor_ = NULL; } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -116,6 +117,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fstruct_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -147,6 +149,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fstruct_2eproto() { delete ListValue_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fstruct_2eproto() { static bool already_here = false; if (already_here) return; @@ -203,16 +206,6 @@ bool NullValue_IsValid(int value) { } -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -348,18 +341,51 @@ void Struct::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { // @@protoc_insertion_point(serialize_start:google.protobuf.Struct) // map<string, .google.protobuf.Value> fields = 1; - { - ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry; - for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - 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); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - it->first.data(), it->first.length(), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Struct.FieldsEntry.key"); + if (!this->fields().empty()) { + typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_pointer + ConstPtr; + typedef ConstPtr SortItem; + typedef ::google::protobuf::internal::CompareByDerefFirst<SortItem> Less; + struct Utf8Check { + static void Check(ConstPtr p) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + p->first.data(), p->first.length(), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Struct.FieldsEntry.key"); + } + }; + + if (output->IsSerializationDeterminstic() && + this->fields().size() > 1) { + ::google::protobuf::scoped_array<SortItem> items( + new SortItem[this->fields().size()]); + typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::size_type size_type; + size_type n = 0; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + it = this->fields().begin(); + it != this->fields().end(); ++it, ++n) { + items[n] = SortItem(&*it); + } + ::std::sort(&items[0], &items[n], Less()); + ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry; + for (size_type i = 0; i < n; i++) { + entry.reset(fields_.NewEntryWrapper( + items[i]->first, items[i]->second)); + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, *entry, output); + Utf8Check::Check(items[i]); + } + } else { + ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + 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); + Utf8Check::Check(&*it); + } } } @@ -370,19 +396,55 @@ void Struct::SerializeWithCachedSizes( bool deterministic, ::google::protobuf::uint8* target) const { // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct) // map<string, .google.protobuf.Value> fields = 1; - { - ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry; - for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator - it = this->fields().begin(); - it != this->fields().end(); ++it) { - entry.reset(fields_.NewEntryWrapper(it->first, it->second)); - target = ::google::protobuf::internal::WireFormatLite:: - InternalWriteMessageNoVirtualToArray( - 1, *entry, false, target); - ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( - it->first.data(), it->first.length(), - ::google::protobuf::internal::WireFormatLite::SERIALIZE, - "google.protobuf.Struct.FieldsEntry.key"); + if (!this->fields().empty()) { + typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_pointer + ConstPtr; + typedef ConstPtr SortItem; + typedef ::google::protobuf::internal::CompareByDerefFirst<SortItem> Less; + struct Utf8Check { + static void Check(ConstPtr p) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + p->first.data(), p->first.length(), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Struct.FieldsEntry.key"); + } + }; + + if (deterministic && + this->fields().size() > 1) { + ::google::protobuf::scoped_array<SortItem> items( + new SortItem[this->fields().size()]); + typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::size_type size_type; + size_type n = 0; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + it = this->fields().begin(); + it != this->fields().end(); ++it, ++n) { + items[n] = SortItem(&*it); + } + ::std::sort(&items[0], &items[n], Less()); + ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry; + for (size_type i = 0; i < n; i++) { + entry.reset(fields_.NewEntryWrapper( + items[i]->first, items[i]->second)); + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessageNoVirtualToArray( + 1, *entry, deterministic, target); +; + Utf8Check::Check(items[i]); + } + } else { + ::google::protobuf::scoped_ptr<Struct_FieldsEntry> entry; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + it = this->fields().begin(); + it != this->fields().end(); ++it) { + entry.reset(fields_.NewEntryWrapper( + it->first, it->second)); + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessageNoVirtualToArray( + 1, *entry, deterministic, target); +; + Utf8Check::Check(&*it); + } } } @@ -415,7 +477,9 @@ int Struct::ByteSize() const { void Struct::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Struct) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Struct* source = ::google::protobuf::internal::DynamicCastToGenerated<const Struct>( &from); @@ -430,7 +494,9 @@ void Struct::MergeFrom(const ::google::protobuf::Message& from) { void Struct::MergeFrom(const Struct& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } fields_.MergeFrom(from.fields_); } @@ -881,7 +947,9 @@ int Value::ByteSize() const { void Value::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const Value>( &from); @@ -896,7 +964,9 @@ void Value::MergeFrom(const ::google::protobuf::Message& from) { void Value::MergeFrom(const Value& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } switch (from.kind_case()) { case kNullValue: { set_null_value(from.null_value()); @@ -1406,7 +1476,9 @@ int ListValue::ByteSize() const { void ListValue::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ListValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const ListValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const ListValue>( &from); @@ -1421,7 +1493,9 @@ void ListValue::MergeFrom(const ::google::protobuf::Message& from) { void ListValue::MergeFrom(const ListValue& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } values_.MergeFrom(from.values_); } diff --git a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h index a0116a60..7314ee4f 100644 --- a/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h +++ b/src/google/protobuf/stubs/atomicops_internals_generic_gcc.h @@ -128,6 +128,24 @@ inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, return old_value; } +inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, + Atomic64 increment) { + return __atomic_add_fetch(ptr, increment, __ATOMIC_RELAXED); +} + +inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) { + __atomic_store_n(ptr, value, __ATOMIC_RELAXED); +} + +inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, + Atomic64 new_value) { + return __atomic_exchange_n(ptr, new_value, __ATOMIC_RELAXED); +} + +inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { + return __atomic_load_n(ptr, __ATOMIC_RELAXED); +} + #endif // defined(__LP64__) } // namespace internal diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h index 87271c5e..bbd507a8 100644 --- a/src/google/protobuf/stubs/callback.h +++ b/src/google/protobuf/stubs/callback.h @@ -381,6 +381,8 @@ class MethodResultCallback_5_2 : public ResultCallback2<R, A1, A2> { typename remove_reference<P5>::type p5_; }; +} // namespace internal + // See Closure. inline Closure* NewCallback(void (*function)()) { return new internal::FunctionClosure0(function, true); @@ -533,8 +535,6 @@ inline ResultCallback2<R, A1, A2>* NewPermanentCallback( p2, p3, p4, p5); } -} // namespace internal - // A function which does nothing. Useful for creating no-op callbacks, e.g.: // Closure* nothing = NewCallback(&DoNothing); void LIBPROTOBUF_EXPORT DoNothing(); diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc index 25bae9b0..f9e2cfd4 100644 --- a/src/google/protobuf/stubs/common_unittest.cc +++ b/src/google/protobuf/stubs/common_unittest.cc @@ -41,8 +41,6 @@ namespace google { namespace protobuf { -using internal::NewCallback; -using internal::NewPermanentCallback; namespace { // TODO(kenton): More tests. diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc index 3a36b4b1..a5090801 100644 --- a/src/google/protobuf/stubs/int128.cc +++ b/src/google/protobuf/stubs/int128.cc @@ -145,15 +145,15 @@ std::ostream& operator<<(std::ostream& o, const uint128& b) { std::streamsize div_base_log; switch (flags & std::ios::basefield) { case std::ios::hex: - div = GOOGLE_ULONGLONG(0x1000000000000000); // 16^15 + div = static_cast<uint64>(GOOGLE_ULONGLONG(0x1000000000000000)); // 16^15 div_base_log = 15; break; case std::ios::oct: - div = GOOGLE_ULONGLONG(01000000000000000000000); // 8^21 + div = static_cast<uint64>(GOOGLE_ULONGLONG(01000000000000000000000)); // 8^21 div_base_log = 21; break; default: // std::ios::dec - div = GOOGLE_ULONGLONG(10000000000000000000); // 10^19 + div = static_cast<uint64>(GOOGLE_ULONGLONG(10000000000000000000)); // 10^19 div_base_log = 19; break; } diff --git a/src/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h index 4cccbbed..887f12a6 100644 --- a/src/google/protobuf/stubs/map_util.h +++ b/src/google/protobuf/stubs/map_util.h @@ -208,7 +208,7 @@ typename Collection::value_type::second_type::element_type& FindLinkedPtrOrDie(const Collection& collection, const typename Collection::value_type::first_type& key) { typename Collection::const_iterator it = collection.find(key); - CHECK(it != collection.end()) << "key not found: " << key; + GOOGLE_CHECK(it != collection.end()) << "key not found: " << key; // Since linked_ptr::operator*() is a const member returning a non const, // we do not need a version of this function taking a non const collection. return *it->second; @@ -337,14 +337,15 @@ bool InsertIfNotPresent( template <class Collection> void InsertOrDie(Collection* const collection, const typename Collection::value_type& value) { - CHECK(InsertIfNotPresent(collection, value)) << "duplicate value: " << value; + GOOGLE_CHECK(InsertIfNotPresent(collection, value)) + << "duplicate value: " << value; } // Same as above except doesn't log the value on error. template <class Collection> void InsertOrDieNoPrint(Collection* const collection, const typename Collection::value_type& value) { - CHECK(InsertIfNotPresent(collection, value)) << "duplicate value."; + GOOGLE_CHECK(InsertIfNotPresent(collection, value)) << "duplicate value."; } // Inserts the key-value pair into the collection. Dies if key was already diff --git a/src/google/protobuf/stubs/once_unittest.cc b/src/google/protobuf/stubs/once_unittest.cc index 37def58d..d5f7779e 100644 --- a/src/google/protobuf/stubs/once_unittest.cc +++ b/src/google/protobuf/stubs/once_unittest.cc @@ -43,7 +43,6 @@ namespace google { namespace protobuf { -using internal::NewCallback; namespace { class OnceInitTest : public testing::Test { @@ -128,11 +127,11 @@ class OnceInitTest : public testing::Test { }; TestThread* RunInitOnceInNewThread() { - return new TestThread(internal::NewCallback(this, &OnceInitTest::InitOnce)); + return new TestThread(NewCallback(this, &OnceInitTest::InitOnce)); } TestThread* RunInitRecursiveOnceInNewThread() { return new TestThread( - internal::NewCallback(this, &OnceInitTest::InitRecursiveOnce)); + NewCallback(this, &OnceInitTest::InitRecursiveOnce)); } enum State { diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h index 328258b7..d7f93b4c 100644 --- a/src/google/protobuf/stubs/port.h +++ b/src/google/protobuf/stubs/port.h @@ -109,15 +109,15 @@ typedef unsigned __int16 uint16; typedef unsigned __int32 uint32; typedef unsigned __int64 uint64; #else -typedef signed char int8; -typedef short int16; -typedef int int32; -typedef long long int64; - -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; -typedef unsigned long long uint64; +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; #endif // long long macros to be used because gcc and vc++ use different suffixes, @@ -131,8 +131,10 @@ typedef unsigned long long uint64; #define GOOGLE_ULONGLONG(x) x##UI64 #define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...) #else +// By long long, we actually mean int64. #define GOOGLE_LONGLONG(x) x##LL #define GOOGLE_ULONGLONG(x) x##ULL +// Used to format real long long integers. #define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also. #endif diff --git a/src/google/protobuf/testdata/golden_message_maps b/src/google/protobuf/testdata/golden_message_maps Binary files differnew file mode 100644 index 00000000..c70a4d7c --- /dev/null +++ b/src/google/protobuf/testdata/golden_message_maps diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index 3d07b127..470512ed 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -91,6 +91,7 @@ bool File::WriteStringToFile(const string& contents, const string& name) { if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) { GOOGLE_LOG(ERROR) << "fwrite(" << name << "): " << strerror(errno); + fclose(file); return false; } @@ -140,12 +141,12 @@ void File::DeleteRecursively(const string& name, #ifdef _MSC_VER // This interface is so weird. - WIN32_FIND_DATA find_data; - HANDLE find_handle = FindFirstFile((name + "/*").c_str(), &find_data); + WIN32_FIND_DATAA find_data; + HANDLE find_handle = FindFirstFileA((name + "/*").c_str(), &find_data); if (find_handle == INVALID_HANDLE_VALUE) { // Just delete it, whatever it is. - DeleteFile(name.c_str()); - RemoveDirectory(name.c_str()); + DeleteFileA(name.c_str()); + RemoveDirectoryA(name.c_str()); return; } @@ -155,15 +156,15 @@ void File::DeleteRecursively(const string& name, string path = name + "/" + entry_name; if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { DeleteRecursively(path, NULL, NULL); - RemoveDirectory(path.c_str()); + RemoveDirectoryA(path.c_str()); } else { - DeleteFile(path.c_str()); + DeleteFileA(path.c_str()); } } - } while(FindNextFile(find_handle, &find_data)); + } while(FindNextFileA(find_handle, &find_data)); FindClose(find_handle); - RemoveDirectory(name.c_str()); + RemoveDirectoryA(name.c_str()); #else // Use opendir()! Yay! // lstat = Don't follow symbolic links. diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index d49d8588..66b2648b 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -759,6 +759,20 @@ class TextFormat::Parser::ParserImpl { } return true; } + if (TryConsume("[")) { + while (true) { + if (!LookingAt("{") && !LookingAt("<")) { + DO(SkipFieldValue()); + } else { + DO(SkipFieldMessage()); + } + if (TryConsume("]")) { + break; + } + DO(Consume(",")); + } + return true; + } // Possible field values other than string: // 12345 => TYPE_INTEGER // -12345 => TYPE_SYMBOL + TYPE_INTEGER diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc index 2ec4bc56..487e62b0 100644 --- a/src/google/protobuf/timestamp.pb.cc +++ b/src/google/protobuf/timestamp.pb.cc @@ -29,6 +29,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto() { protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -61,6 +62,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2ftimestamp_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -74,6 +76,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2ftimestamp_2eproto() { delete Timestamp_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2ftimestamp_2eproto() { static bool already_here = false; if (already_here) return; @@ -101,16 +104,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2ftimestamp_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2ftimestamp_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -206,7 +199,7 @@ void Timestamp::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -336,7 +329,9 @@ int Timestamp::ByteSize() const { void Timestamp::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Timestamp) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Timestamp* source = ::google::protobuf::internal::DynamicCastToGenerated<const Timestamp>( &from); @@ -351,7 +346,9 @@ void Timestamp::MergeFrom(const ::google::protobuf::Message& from) { void Timestamp::MergeFrom(const Timestamp& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.seconds() != 0) { set_seconds(from.seconds()); } diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc index f9182a75..a2a7f282 100644 --- a/src/google/protobuf/type.pb.cc +++ b/src/google/protobuf/type.pb.cc @@ -44,6 +44,7 @@ const ::google::protobuf::EnumDescriptor* Syntax_descriptor_ = NULL; } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto() { protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -159,6 +160,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2ftype_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -188,6 +190,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2ftype_2eproto() { delete Option_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2ftype_2eproto() { static bool already_here = false; if (already_here) return; @@ -272,16 +275,6 @@ bool Syntax_IsValid(int value) { } -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -658,7 +651,9 @@ int Type::ByteSize() const { void Type::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Type) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Type* source = ::google::protobuf::internal::DynamicCastToGenerated<const Type>( &from); @@ -673,7 +668,9 @@ void Type::MergeFrom(const ::google::protobuf::Message& from) { void Type::MergeFrom(const Type& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Type) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } fields_.MergeFrom(from.fields_); oneofs_.MergeFrom(from.oneofs_); options_.MergeFrom(from.options_); @@ -1128,7 +1125,7 @@ void Field::Clear() { #endif #define ZR_(first, last) do {\ - ::memset(&first, 0,\ + ::memset(&(first), 0,\ ZR_HELPER_(last) - ZR_HELPER_(first) + sizeof(last));\ } while (0) @@ -1581,7 +1578,9 @@ int Field::ByteSize() const { void Field::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Field) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Field* source = ::google::protobuf::internal::DynamicCastToGenerated<const Field>( &from); @@ -1596,7 +1595,9 @@ void Field::MergeFrom(const ::google::protobuf::Message& from) { void Field::MergeFrom(const Field& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Field) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } options_.MergeFrom(from.options_); if (from.kind() != 0) { set_kind(from.kind()); @@ -2285,7 +2286,9 @@ int Enum::ByteSize() const { void Enum::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Enum) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Enum* source = ::google::protobuf::internal::DynamicCastToGenerated<const Enum>( &from); @@ -2300,7 +2303,9 @@ void Enum::MergeFrom(const ::google::protobuf::Message& from) { void Enum::MergeFrom(const Enum& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Enum) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } enumvalue_.MergeFrom(from.enumvalue_); options_.MergeFrom(from.options_); if (from.name().size() > 0) { @@ -2764,7 +2769,9 @@ int EnumValue::ByteSize() const { void EnumValue::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.EnumValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const EnumValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const EnumValue>( &from); @@ -2779,7 +2786,9 @@ void EnumValue::MergeFrom(const ::google::protobuf::Message& from) { void EnumValue::MergeFrom(const EnumValue& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } options_.MergeFrom(from.options_); if (from.name().size() > 0) { @@ -3133,7 +3142,9 @@ int Option::ByteSize() const { void Option::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Option) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Option* source = ::google::protobuf::internal::DynamicCastToGenerated<const Option>( &from); @@ -3148,7 +3159,9 @@ void Option::MergeFrom(const ::google::protobuf::Message& from) { void Option::MergeFrom(const Option& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Option) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.name().size() > 0) { name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.name_); diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc index d4e383da..8ee99d48 100644 --- a/src/google/protobuf/unknown_field_set.cc +++ b/src/google/protobuf/unknown_field_set.cc @@ -69,28 +69,14 @@ const UnknownFieldSet* UnknownFieldSet::default_instance() { return default_unknown_field_set_instance_; } -UnknownFieldSet::UnknownFieldSet() - : fields_(NULL) {} - -UnknownFieldSet::~UnknownFieldSet() { - Clear(); - delete fields_; -} - void UnknownFieldSet::ClearFallback() { - if (fields_ != NULL) { - for (int i = 0; i < fields_->size(); i++) { - (*fields_)[i].Delete(); - } - delete fields_; - fields_ = NULL; - } -} - -void UnknownFieldSet::ClearAndFreeMemory() { - if (fields_ != NULL) { - Clear(); - } + GOOGLE_DCHECK(fields_ != NULL && fields_->size() > 0); + int n = fields_->size(); + do { + (*fields_)[--n].Delete(); + } while (n > 0); + delete fields_; + fields_ = NULL; } void UnknownFieldSet::InternalMergeFrom(const UnknownFieldSet& other) { diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h index 612a942a..aa752916 100644 --- a/src/google/protobuf/unknown_field_set.h +++ b/src/google/protobuf/unknown_field_set.h @@ -241,8 +241,14 @@ class LIBPROTOBUF_EXPORT UnknownField { // =================================================================== // inline implementations +inline UnknownFieldSet::UnknownFieldSet() : fields_(NULL) {} + +inline UnknownFieldSet::~UnknownFieldSet() { Clear(); } + +inline void UnknownFieldSet::ClearAndFreeMemory() { Clear(); } + inline void UnknownFieldSet::Clear() { - if (fields_) { + if (fields_ != NULL) { ClearFallback(); } } diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc index 21d7a2e4..fa31f763 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter.cc @@ -64,6 +64,7 @@ DefaultValueObjectWriter::DefaultValueObjectWriter( type_(type), current_(NULL), root_(NULL), + suppress_empty_list_(false), field_scrub_callback_(NULL), ow_(ow) {} @@ -164,7 +165,10 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes( if (current_ == NULL) { ow_->RenderBytes(name, value); } else { - RenderDataPiece(name, DataPiece(value, false, true)); + // 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(), false, true)); } return this; } @@ -184,12 +188,10 @@ void DefaultValueObjectWriter::RegisterFieldScrubCallBack( field_scrub_callback_.reset(field_scrub_callback.release()); } -DefaultValueObjectWriter::Node::Node(const string& name, - const google::protobuf::Type* type, - NodeKind kind, const DataPiece& data, - bool is_placeholder, - const vector<string>& path, - FieldScrubCallBack* field_scrub_callback) +DefaultValueObjectWriter::Node::Node( + const string& name, const google::protobuf::Type* type, NodeKind kind, + const DataPiece& data, bool is_placeholder, const vector<string>& path, + bool suppress_empty_list, FieldScrubCallBack* field_scrub_callback) : name_(name), type_(type), kind_(kind), @@ -197,6 +199,7 @@ DefaultValueObjectWriter::Node::Node(const string& name, data_(data), is_placeholder_(is_placeholder), path_(path), + suppress_empty_list_(suppress_empty_list), field_scrub_callback_(field_scrub_callback) {} DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild( @@ -230,6 +233,9 @@ void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) { // Write out lists. If we didn't have any list in response, write out empty // list. if (kind_ == LIST) { + // Suppress empty lists if requested. + if (suppress_empty_list_ && is_placeholder_) return; + ow->StartList(name_); WriteChildren(ow); ow->EndList(); @@ -366,7 +372,7 @@ void DefaultValueObjectWriter::Node::PopulateChildren( field.json_name(), field_type, kind, kind == PRIMITIVE ? CreateDefaultDataPieceForField(field, typeinfo) : DataPiece::NullData(), - true, path, field_scrub_callback_)); + true, path, suppress_empty_list_, field_scrub_callback_)); new_children.push_back(child.release()); } // Adds all leftover nodes in children_ to the beginning of new_child. @@ -462,7 +468,8 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( if (current_ == NULL) { vector<string> path; root_.reset(new Node(name.ToString(), &type_, OBJECT, DataPiece::NullData(), - false, path, field_scrub_callback_.get())); + false, path, suppress_empty_list_, + field_scrub_callback_.get())); root_->PopulateChildren(typeinfo_); current_ = root_.get(); return this; @@ -478,7 +485,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject( : NULL), OBJECT, DataPiece::NullData(), false, child == NULL ? current_->path() : child->path(), - field_scrub_callback_.get())); + suppress_empty_list_, field_scrub_callback_.get())); child = node.get(); current_->AddChild(node.release()); } @@ -509,7 +516,8 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( if (current_ == NULL) { vector<string> path; root_.reset(new Node(name.ToString(), &type_, LIST, DataPiece::NullData(), - false, path, field_scrub_callback_.get())); + false, path, suppress_empty_list_, + field_scrub_callback_.get())); current_ = root_.get(); return this; } @@ -519,7 +527,7 @@ DefaultValueObjectWriter* DefaultValueObjectWriter::StartList( google::protobuf::scoped_ptr<Node> node( new Node(name.ToString(), NULL, LIST, DataPiece::NullData(), false, child == NULL ? current_->path() : child->path(), - field_scrub_callback_.get())); + suppress_empty_list_, field_scrub_callback_.get())); child = node.get(); current_->AddChild(node.release()); } @@ -577,7 +585,7 @@ void DefaultValueObjectWriter::RenderDataPiece(StringPiece name, google::protobuf::scoped_ptr<Node> node( new Node(name.ToString(), NULL, PRIMITIVE, data, false, child == NULL ? current_->path() : child->path(), - field_scrub_callback_.get())); + suppress_empty_list_, field_scrub_callback_.get())); child = node.get(); current_->AddChild(node.release()); } else { diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h index 1d85bed8..5f3b25f3 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter.h +++ b/src/google/protobuf/util/internal/default_value_objectwriter.h @@ -122,6 +122,10 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // field_scrub_callback pointer is also transferred to this class void RegisterFieldScrubCallBack(FieldScrubCallBackPtr field_scrub_callback); + // If set to true, empty lists are suppressed from output when default values + // are written. + void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; } + private: enum NodeKind { PRIMITIVE = 0, @@ -136,7 +140,7 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { public: Node(const string& name, const google::protobuf::Type* type, NodeKind kind, const DataPiece& data, bool is_placeholder, const vector<string>& path, - FieldScrubCallBack* field_scrub_callback); + bool suppress_empty_list, FieldScrubCallBack* field_scrub_callback); virtual ~Node() { for (int i = 0; i < children_.size(); ++i) { delete children_[i]; @@ -212,6 +216,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // Path of the field of this node std::vector<string> path_; + // Whether to suppress empty list output. + bool suppress_empty_list_; + // Pointer to function for determining whether a field needs to be scrubbed // or not. This callback is owned by the creator of this node. FieldScrubCallBack* field_scrub_callback_; @@ -257,6 +264,9 @@ class LIBPROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter { // The stack to hold the path of Nodes from current_ to root_; std::stack<Node*> stack_; + // Whether to suppress output of empty lists. + bool suppress_empty_list_; + // Unique Pointer to function for determining whether a field needs to be // scrubbed or not. FieldScrubCallBackPtr field_scrub_callback_; diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc index 8254c0fa..e1dd697a 100644 --- a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc +++ b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc @@ -149,6 +149,39 @@ TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) { } +class DefaultValueObjectWriterSuppressListTest + : public BaseDefaultValueObjectWriterTest { + protected: + DefaultValueObjectWriterSuppressListTest() + : BaseDefaultValueObjectWriterTest(DefaultValueTest::descriptor()) { + testing_->set_suppress_empty_list(true); + } + ~DefaultValueObjectWriterSuppressListTest() {} +}; + +INSTANTIATE_TEST_CASE_P(DifferentTypeInfoSourceTest, + DefaultValueObjectWriterSuppressListTest, + ::testing::Values( + testing::USE_TYPE_RESOLVER)); + +TEST_P(DefaultValueObjectWriterSuppressListTest, Empty) { + // Set expectation. Emtpy lists should be suppressed. + expects_.StartObject("") + ->RenderDouble("doubleValue", 0.0) + ->RenderFloat("floatValue", 0.0) + ->RenderInt64("int64Value", 0) + ->RenderUint64("uint64Value", 0) + ->RenderInt32("int32Value", 0) + ->RenderUint32("uint32Value", 0) + ->RenderBool("boolValue", false) + ->RenderString("stringValue", "") + ->RenderBytes("bytesValue", "") + ->RenderString("enumValue", "ENUM_FIRST") + ->EndObject(); + + // Actual testing + testing_->StartObject("")->EndObject(); +} } // namespace testing } // namespace converter } // namespace util diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc index 7a1a6cbd..0c38aeb9 100644 --- a/src/google/protobuf/util/internal/proto_writer.cc +++ b/src/google/protobuf/util/internal/proto_writer.cc @@ -298,7 +298,9 @@ ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo, proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), type_(type), size_index_(-1), - array_index_(-1) { + array_index_(-1), + // oneof_indices_ values are 1-indexed (0 means not present). + oneof_indices_(type.oneofs_size() + 1) { if (!proto3_) { required_fields_ = GetRequiredFields(type_); } @@ -312,13 +314,15 @@ ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent, ow_(this->parent()->ow_), parent_field_(field), typeinfo_(this->parent()->typeinfo_), - proto3_(this->parent()->proto3_), + proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3), type_(type), size_index_( !is_list && field->kind() == google::protobuf::Field_Kind_TYPE_MESSAGE ? ow_->size_insert_.size() : -1), - array_index_(is_list ? 0 : -1) { + array_index_(is_list ? 0 : -1), + // oneof_indices_ values are 1-indexed (0 means not present). + oneof_indices_(type_.oneofs_size() + 1) { if (!is_list) { if (ow_->IsRepeated(*field)) { // Update array_index_ if it is an explicit list. @@ -411,11 +415,11 @@ string ProtoWriter::ProtoElement::ToString() const { } bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32 index) { - return ContainsKey(oneof_indices_, index); + return oneof_indices_[index]; } void ProtoWriter::ProtoElement::TakeOneofIndex(int32 index) { - InsertIfNotPresent(&oneof_indices_, index); + oneof_indices_[index] = true; } void ProtoWriter::InvalidName(StringPiece unknown_name, StringPiece message) { @@ -573,10 +577,19 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField( // 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, false)); + // + // For proto3, since there is no required field tracking, we only need to push + // ProtoElement for error cases. + if (!element_->proto3()) { + element_.reset(new ProtoElement(element_.release(), &field, type, false)); + } if (field.kind() == google::protobuf::Field_Kind_TYPE_UNKNOWN || field.kind() == google::protobuf::Field_Kind_TYPE_MESSAGE) { + // Push a ProtoElement for location reporting purposes. + if (element_->proto3()) { + element_.reset(new ProtoElement(element_.release(), &field, type, false)); + } InvalidValue(field.type_url().empty() ? google::protobuf::Field_Kind_Name(field.kind()) : field.type_url(), @@ -657,11 +670,18 @@ ProtoWriter* ProtoWriter::RenderPrimitiveField( } if (!status.ok()) { + // Push a ProtoElement for location reporting purposes. + if (element_->proto3()) { + element_.reset(new ProtoElement(element_.release(), &field, type, false)); + } InvalidValue(google::protobuf::Field_Kind_Name(field.kind()), status.error_message()); + element_.reset(element()->pop()); + return this; } - element_.reset(element()->pop()); + if (!element_->proto3()) element_.reset(element()->pop()); + return this; } diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h index 8b7c6c34..7f1108ab 100644 --- a/src/google/protobuf/util/internal/proto_writer.h +++ b/src/google/protobuf/util/internal/proto_writer.h @@ -32,8 +32,8 @@ #define GOOGLE_PROTOBUF_UTIL_CONVERTER_PROTO_WRITER_H__ #include <deque> -#include <google/protobuf/stubs/hash.h> #include <string> +#include <vector> #include <google/protobuf/stubs/common.h> #include <google/protobuf/io/coded_stream.h> @@ -45,6 +45,7 @@ #include <google/protobuf/util/internal/structured_objectwriter.h> #include <google/protobuf/util/type_resolver.h> #include <google/protobuf/stubs/bytestream.h> +#include <google/protobuf/stubs/hash.h> namespace google { namespace protobuf { @@ -191,6 +192,8 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // generate an error. void TakeOneofIndex(int32 index); + bool proto3() { return proto3_; } + private: // Used for access to variables of the enclosing instance of // ProtoWriter. @@ -203,7 +206,7 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // TypeInfo to lookup types. const TypeInfo* typeinfo_; - // Whether the root type is a proto3 or not. + // Whether the type_ is proto3 or not. bool proto3_; // Additional variables if this element is a message: @@ -221,7 +224,7 @@ class LIBPROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter { // Set of oneof indices already seen for the type_. Used to validate // incoming messages so no more than one oneof is set. - hash_set<int32> oneof_indices_; + std::vector<bool> oneof_indices_; GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement); }; diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc index 1825f556..73e05cfe 100644 --- a/src/google/protobuf/util/internal/protostream_objectwriter.cc +++ b/src/google/protobuf/util/internal/protostream_objectwriter.cc @@ -907,7 +907,7 @@ Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow, // conversions as much as possible. Because ToSnakeCase sometimes returns the // wrong value. google::protobuf::scoped_ptr<ResultCallback1<util::Status, StringPiece> > callback( - ::google::protobuf::internal::NewPermanentCallback(&RenderOneFieldPath, ow)); + NewPermanentCallback(&RenderOneFieldPath, ow)); return DecodeCompactFieldMaskPaths(data.str(), callback.get()); } diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc index 6d45a4f9..d7ac2dba 100644 --- a/src/google/protobuf/util/json_util.cc +++ b/src/google/protobuf/util/json_util.cc @@ -177,6 +177,66 @@ util::Status JsonToBinaryString(TypeResolver* resolver, resolver, type_url, &input_stream, &output_stream, options); } +namespace { +const char* kTypeUrlPrefix = "type.googleapis.com"; +TypeResolver* generated_type_resolver_ = NULL; +GOOGLE_PROTOBUF_DECLARE_ONCE(generated_type_resolver_init_); + +string GetTypeUrl(const Message& message) { + return string(kTypeUrlPrefix) + "/" + message.GetDescriptor()->full_name(); +} + +void DeleteGeneratedTypeResolver() { delete generated_type_resolver_; } + +void InitGeneratedTypeResolver() { + generated_type_resolver_ = NewTypeResolverForDescriptorPool( + kTypeUrlPrefix, DescriptorPool::generated_pool()); + ::google::protobuf::internal::OnShutdown(&DeleteGeneratedTypeResolver); +} + +TypeResolver* GetGeneratedTypeResolver() { + ::google::protobuf::GoogleOnceInit(&generated_type_resolver_init_, &InitGeneratedTypeResolver); + return generated_type_resolver_; +} +} // namespace + +util::Status MessageToJsonString(const Message& message, string* output, + const JsonOptions& options) { + const DescriptorPool* pool = message.GetDescriptor()->file()->pool(); + TypeResolver* resolver = + pool == DescriptorPool::generated_pool() + ? GetGeneratedTypeResolver() + : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool); + util::Status result = + BinaryToJsonString(resolver, GetTypeUrl(message), + message.SerializeAsString(), output, options); + if (pool != DescriptorPool::generated_pool()) { + delete resolver; + } + return result; +} + +util::Status JsonStringToMessage(const string& input, Message* message, + const JsonParseOptions& options) { + const DescriptorPool* pool = message->GetDescriptor()->file()->pool(); + TypeResolver* resolver = + pool == DescriptorPool::generated_pool() + ? GetGeneratedTypeResolver() + : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool); + string binary; + util::Status result = JsonToBinaryString( + resolver, GetTypeUrl(*message), input, &binary, options); + if (result.ok() && !message->ParseFromString(binary)) { + result = + util::Status(util::error::INVALID_ARGUMENT, + "JSON transcoder produced invalid protobuf output."); + } + if (pool != DescriptorPool::generated_pool()) { + delete resolver; + } + return result; +} + } // namespace util } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h index b4c2579b..6d3cee52 100644 --- a/src/google/protobuf/util/json_util.h +++ b/src/google/protobuf/util/json_util.h @@ -33,6 +33,7 @@ #ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ #define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__ +#include <google/protobuf/message.h> #include <google/protobuf/util/type_resolver.h> #include <google/protobuf/stubs/bytestream.h> @@ -69,13 +70,37 @@ struct JsonPrintOptions { // DEPRECATED. Use JsonPrintOptions instead. typedef JsonPrintOptions JsonOptions; +// Converts from protobuf message to JSON. This is a simple wrapper of +// BinaryToJsonString(). It will use the DescriptorPool of the passed-in +// message to resolve Any types. +LIBPROTOBUF_EXPORT util::Status MessageToJsonString(const Message& message, + string* output, + const JsonOptions& options); + +inline util::Status MessageToJsonString(const Message& message, + string* output) { + return MessageToJsonString(message, output, JsonOptions()); +} + +// Converts from JSON to protobuf message. This is a simple wrapper of +// JsonStringToBinary(). It will use the DescriptorPool of the passed-in +// message to resolve Any types. +LIBPROTOBUF_EXPORT util::Status JsonStringToMessage(const string& input, + Message* message, + const JsonParseOptions& options); + +inline util::Status JsonStringToMessage(const string& input, + Message* message) { + return JsonStringToMessage(input, message, JsonParseOptions()); +} + // 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( +LIBPROTOBUF_EXPORT util::Status BinaryToJsonStream( TypeResolver* resolver, const string& type_url, io::ZeroCopyInputStream* binary_input, @@ -110,7 +135,7 @@ inline util::Status BinaryToJsonString(TypeResolver* resolver, // 1. TypeResolver fails to resolve a type. // 2. input is not valid JSON format, or conflicts with the type // information returned by TypeResolver. -util::Status JsonToBinaryStream( +LIBPROTOBUF_EXPORT util::Status JsonToBinaryStream( TypeResolver* resolver, const string& type_url, io::ZeroCopyInputStream* json_input, diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc index c7d5c59e..24ff5fd6 100644 --- a/src/google/protobuf/util/json_util_test.cc +++ b/src/google/protobuf/util/json_util_test.cc @@ -34,6 +34,8 @@ #include <string> #include <google/protobuf/io/zero_copy_stream.h> +#include <google/protobuf/descriptor_database.h> +#include <google/protobuf/dynamic_message.h> #include <google/protobuf/util/json_format_proto3.pb.h> #include <google/protobuf/util/type_resolver.h> #include <google/protobuf/util/type_resolver_util.h> @@ -63,28 +65,21 @@ static string GetTypeUrl(const Descriptor* message) { class JsonUtilTest : public testing::Test { protected: JsonUtilTest() { - resolver_.reset(NewTypeResolverForDescriptorPool( - kTypeUrlPrefix, DescriptorPool::generated_pool())); } string ToJson(const Message& message, const JsonPrintOptions& options) { string result; - GOOGLE_CHECK_OK(BinaryToJsonString(resolver_.get(), - GetTypeUrl(message.GetDescriptor()), - message.SerializeAsString(), &result, options)); + GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options)); return result; } bool FromJson(const string& json, Message* message, const JsonParseOptions& options) { - string binary; - if (!JsonToBinaryString(resolver_.get(), - GetTypeUrl(message->GetDescriptor()), json, &binary, - options) - .ok()) { - return false; - } - return message->ParseFromString(binary); + return JsonStringToMessage(json, message, options).ok(); + } + + bool FromJson(const string& json, Message* message) { + return FromJson(json, message, JsonParseOptions()); } google::protobuf::scoped_ptr<TypeResolver> resolver_; @@ -133,6 +128,34 @@ TEST_F(JsonUtilTest, TestDefaultValues) { "\"repeatedMessageValue\":[]" "}", ToJson(m, options)); + + options.always_print_primitive_fields = true; + m.set_string_value("i am a test string value"); + m.set_bytes_value("i am a test bytes value"); + EXPECT_EQ( + "{\"boolValue\":false," + "\"int32Value\":0," + "\"int64Value\":\"0\"," + "\"uint32Value\":0," + "\"uint64Value\":\"0\"," + "\"floatValue\":0," + "\"doubleValue\":0," + "\"stringValue\":\"i am a test string value\"," + "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\"," + "\"enumValue\":\"FOO\"," + "\"repeatedBoolValue\":[]," + "\"repeatedInt32Value\":[]," + "\"repeatedInt64Value\":[]," + "\"repeatedUint32Value\":[]," + "\"repeatedUint64Value\":[]," + "\"repeatedFloatValue\":[]," + "\"repeatedDoubleValue\":[]," + "\"repeatedStringValue\":[]," + "\"repeatedBytesValue\":[]," + "\"repeatedEnumValue\":[]," + "\"repeatedMessageValue\":[]" + "}", + ToJson(m, options)); } TEST_F(JsonUtilTest, ParseMessage) { @@ -189,6 +212,45 @@ TEST_F(JsonUtilTest, TestParseErrors) { EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m, options)); } +TEST_F(JsonUtilTest, TestDynamicMessage) { + // Some random message but good enough to test the wrapper functions. + 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"; + + // Create a new DescriptorPool with the same protos as the generated one. + DescriptorPoolDatabase database(*DescriptorPool::generated_pool()); + DescriptorPool pool(&database); + // A dynamic version of the test proto. + DynamicMessageFactory factory; + google::protobuf::scoped_ptr<Message> message(factory.GetPrototype( + pool.FindMessageTypeByName("proto3.TestMessage"))->New()); + EXPECT_TRUE(FromJson(input, message.get())); + + // Convert to generated message for easy inspection. + TestMessage generated; + EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString())); + EXPECT_EQ(1024, generated.int32_value()); + ASSERT_EQ(2, generated.repeated_int32_value_size()); + EXPECT_EQ(1, generated.repeated_int32_value(0)); + EXPECT_EQ(2, generated.repeated_int32_value(1)); + EXPECT_EQ(2048, generated.message_value().value()); + ASSERT_EQ(2, generated.repeated_message_value_size()); + EXPECT_EQ(40, generated.repeated_message_value(0).value()); + EXPECT_EQ(96, generated.repeated_message_value(1).value()); + + JsonOptions options; + EXPECT_EQ(ToJson(generated, options), ToJson(*message, options)); +} + typedef pair<char*, int> Segment; // A ZeroCopyOutputStream that writes to multiple buffers. class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream { diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc index a6d0cb07..03a334b6 100644 --- a/src/google/protobuf/util/message_differencer.cc +++ b/src/google/protobuf/util/message_differencer.cc @@ -1389,8 +1389,7 @@ bool MessageDifferencer::MatchRepeatedFieldIndices( // doesn't necessarily 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 = - ::google::protobuf::internal::NewPermanentCallback( + MaximumMatcher::NodeMatchCallback* callback = NewPermanentCallback( this, &MessageDifferencer::IsMatch, repeated_field, key_comparator, &message1, &message2, parent_fields); diff --git a/src/google/protobuf/util/time_util.cc b/src/google/protobuf/util/time_util.cc index c782d691..031d019a 100644 --- a/src/google/protobuf/util/time_util.cc +++ b/src/google/protobuf/util/time_util.cc @@ -142,6 +142,13 @@ int64 RoundTowardZero(int64 value, int64 divider) { } } // namespace +// Actually define these static const integers. Required by C++ standard (but +// omitting them may still work with some compilers). +const int64 TimeUtil::kTimestampMinSeconds; +const int64 TimeUtil::kTimestampMaxSeconds; +const int64 TimeUtil::kDurationMaxSeconds; +const int64 TimeUtil::kDurationMinSeconds; + string TimeUtil::ToString(const Timestamp& timestamp) { return FormatTime(timestamp.seconds(), timestamp.nanos()); } @@ -174,7 +181,7 @@ string TimeUtil::ToString(const Duration& duration) { seconds = -seconds; nanos = -nanos; } - result += StringPrintf("%" GOOGLE_LL_FORMAT "d", seconds); + result += SimpleItoa(seconds); if (nanos != 0) { result += "." + FormatNanos(nanos); } diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc index f2517074..05cc0854 100644 --- a/src/google/protobuf/wire_format_lite.cc +++ b/src/google/protobuf/wire_format_lite.cc @@ -466,7 +466,8 @@ void WireFormatLite::WriteGroupMaybeToArray(int field_number, const int size = value.GetCachedSize(); uint8* target = output->GetDirectBufferForNBytesAndAdvance(size); if (target != NULL) { - uint8* end = value.SerializeWithCachedSizesToArray(target); + uint8* end = value.InternalSerializeWithCachedSizesToArray( + output->IsSerializationDeterminstic(), target); GOOGLE_DCHECK_EQ(end - target, size); } else { value.SerializeWithCachedSizes(output); @@ -482,7 +483,8 @@ void WireFormatLite::WriteMessageMaybeToArray(int field_number, output->WriteVarint32(size); uint8* target = output->GetDirectBufferForNBytesAndAdvance(size); if (target != NULL) { - uint8* end = value.SerializeWithCachedSizesToArray(target); + uint8* end = value.InternalSerializeWithCachedSizesToArray( + output->IsSerializationDeterminstic(), target); GOOGLE_DCHECK_EQ(end - target, size); } else { value.SerializeWithCachedSizes(output); diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h index ebd858ff..93d7c824 100644 --- a/src/google/protobuf/wire_format_lite_inl.h +++ b/src/google/protobuf/wire_format_lite_inl.h @@ -346,9 +346,9 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive( io::CodedInputStream* input, RepeatedField<CType>* values) { int length; if (!input->ReadVarintSizeAsInt(&length)) return false; - const uint32 old_entries = values->size(); - const uint32 new_entries = length / sizeof(CType); - const uint32 new_bytes = new_entries * sizeof(CType); + const int old_entries = values->size(); + const int new_entries = length / sizeof(CType); + const int new_bytes = new_entries * sizeof(CType); if (new_bytes != length) return false; // We would *like* to pre-allocate the buffer to write into (for // speed), but *must* avoid performing a very large allocation due @@ -382,7 +382,7 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive( #else values->Reserve(old_entries + new_entries); CType value; - for (uint32 i = 0; i < new_entries; ++i) { + for (int i = 0; i < new_entries; ++i) { if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; values->AddAlreadyReserved(value); } @@ -392,7 +392,7 @@ inline bool WireFormatLite::ReadPackedFixedSizePrimitive( // safely allocate. We read as much as we can into *values // without pre-allocating "length" bytes. CType value; - for (uint32 i = 0; i < new_entries; ++i) { + for (int i = 0; i < new_entries; ++i) { if (!ReadPrimitive<CType, DeclaredType>(input, &value)) return false; values->Add(value); } diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc index 08490f3f..33a69d3b 100644 --- a/src/google/protobuf/wrappers.pb.cc +++ b/src/google/protobuf/wrappers.pb.cc @@ -53,6 +53,7 @@ const ::google::protobuf::internal::GeneratedMessageReflection* } // namespace +void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto() { protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto(); const ::google::protobuf::FileDescriptor* file = @@ -204,6 +205,7 @@ inline void protobuf_AssignDescriptorsOnce() { &protobuf_AssignDesc_google_2fprotobuf_2fwrappers_2eproto); } +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_ATTRIBUTE_COLD; void protobuf_RegisterTypes(const ::std::string&) { protobuf_AssignDescriptorsOnce(); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -249,6 +251,7 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fwrappers_2eproto() { delete BytesValue_reflection_; } +void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() GOOGLE_ATTRIBUTE_COLD; void protobuf_AddDesc_google_2fprotobuf_2fwrappers_2eproto() { static bool already_here = false; if (already_here) return; @@ -298,16 +301,6 @@ struct StaticDescriptorInitializer_google_2fprotobuf_2fwrappers_2eproto { } } static_descriptor_initializer_google_2fprotobuf_2fwrappers_2eproto_; -namespace { - -static void MergeFromFail(int line) GOOGLE_ATTRIBUTE_COLD; -static void MergeFromFail(int line) { - GOOGLE_CHECK(false) << __FILE__ << ":" << line; -} - -} // namespace - - // =================================================================== #if !defined(_MSC_VER) || _MSC_VER >= 1900 @@ -477,7 +470,9 @@ int DoubleValue::ByteSize() const { void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.DoubleValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const DoubleValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const DoubleValue>( &from); @@ -492,7 +487,9 @@ void DoubleValue::MergeFrom(const ::google::protobuf::Message& from) { void DoubleValue::MergeFrom(const DoubleValue& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DoubleValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value() != 0) { set_value(from.value()); } @@ -735,7 +732,9 @@ int FloatValue::ByteSize() const { void FloatValue::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.FloatValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const FloatValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const FloatValue>( &from); @@ -750,7 +749,9 @@ void FloatValue::MergeFrom(const ::google::protobuf::Message& from) { void FloatValue::MergeFrom(const FloatValue& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FloatValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value() != 0) { set_value(from.value()); } @@ -995,7 +996,9 @@ int Int64Value::ByteSize() const { void Int64Value::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int64Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Int64Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const Int64Value>( &from); @@ -1010,7 +1013,9 @@ void Int64Value::MergeFrom(const ::google::protobuf::Message& from) { void Int64Value::MergeFrom(const Int64Value& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int64Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value() != 0) { set_value(from.value()); } @@ -1255,7 +1260,9 @@ int UInt64Value::ByteSize() const { void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt64Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const UInt64Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const UInt64Value>( &from); @@ -1270,7 +1277,9 @@ void UInt64Value::MergeFrom(const ::google::protobuf::Message& from) { void UInt64Value::MergeFrom(const UInt64Value& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt64Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value() != 0) { set_value(from.value()); } @@ -1515,7 +1524,9 @@ int Int32Value::ByteSize() const { void Int32Value::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Int32Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const Int32Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const Int32Value>( &from); @@ -1530,7 +1541,9 @@ void Int32Value::MergeFrom(const ::google::protobuf::Message& from) { void Int32Value::MergeFrom(const Int32Value& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int32Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value() != 0) { set_value(from.value()); } @@ -1775,7 +1788,9 @@ int UInt32Value::ByteSize() const { void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.UInt32Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const UInt32Value* source = ::google::protobuf::internal::DynamicCastToGenerated<const UInt32Value>( &from); @@ -1790,7 +1805,9 @@ void UInt32Value::MergeFrom(const ::google::protobuf::Message& from) { void UInt32Value::MergeFrom(const UInt32Value& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt32Value) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value() != 0) { set_value(from.value()); } @@ -2033,7 +2050,9 @@ int BoolValue::ByteSize() const { void BoolValue::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BoolValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const BoolValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const BoolValue>( &from); @@ -2048,7 +2067,9 @@ void BoolValue::MergeFrom(const ::google::protobuf::Message& from) { void BoolValue::MergeFrom(const BoolValue& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BoolValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value() != 0) { set_value(from.value()); } @@ -2308,7 +2329,9 @@ int StringValue::ByteSize() const { void StringValue::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.StringValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const StringValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const StringValue>( &from); @@ -2323,7 +2346,9 @@ void StringValue::MergeFrom(const ::google::protobuf::Message& from) { void StringValue::MergeFrom(const StringValue& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.StringValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value().size() > 0) { set_value(from.value()); } @@ -2623,7 +2648,9 @@ int BytesValue::ByteSize() const { void BytesValue::MergeFrom(const ::google::protobuf::Message& from) { // @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.BytesValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } const BytesValue* source = ::google::protobuf::internal::DynamicCastToGenerated<const BytesValue>( &from); @@ -2638,7 +2665,9 @@ void BytesValue::MergeFrom(const ::google::protobuf::Message& from) { void BytesValue::MergeFrom(const BytesValue& from) { // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BytesValue) - if (GOOGLE_PREDICT_FALSE(&from == this)) MergeFromFail(__LINE__); + if (GOOGLE_PREDICT_FALSE(&from == this)) { + ::google::protobuf::internal::MergeFromFail(__FILE__, __LINE__); + } if (from.value().size() > 0) { set_value(from.value()); } |