From 4de8f55113007fdc8e34107950e605fc0209d465 Mon Sep 17 00:00:00 2001 From: "jieluo@google.com" Date: Fri, 18 Jul 2014 00:47:59 +0000 Subject: down integrate to svn --- src/Makefile.am | 24 +- src/google/protobuf/compiler/code_generator.cc | 8 +- src/google/protobuf/compiler/code_generator.h | 3 + .../protobuf/compiler/command_line_interface.cc | 194 +- .../protobuf/compiler/command_line_interface.h | 29 +- .../compiler/command_line_interface_unittest.cc | 127 +- .../compiler/cpp/cpp_bootstrap_unittest.cc | 8 +- src/google/protobuf/compiler/cpp/cpp_enum.cc | 52 +- src/google/protobuf/compiler/cpp/cpp_enum.h | 2 + src/google/protobuf/compiler/cpp/cpp_enum_field.cc | 73 +- src/google/protobuf/compiler/cpp/cpp_enum_field.h | 19 +- src/google/protobuf/compiler/cpp/cpp_field.cc | 28 +- src/google/protobuf/compiler/cpp/cpp_field.h | 10 +- src/google/protobuf/compiler/cpp/cpp_file.cc | 61 +- src/google/protobuf/compiler/cpp/cpp_file.h | 2 +- src/google/protobuf/compiler/cpp/cpp_generator.cc | 5 +- src/google/protobuf/compiler/cpp/cpp_helpers.cc | 120 +- src/google/protobuf/compiler/cpp/cpp_helpers.h | 24 +- src/google/protobuf/compiler/cpp/cpp_message.cc | 985 ++++++-- src/google/protobuf/compiler/cpp/cpp_message.h | 6 +- .../protobuf/compiler/cpp/cpp_message_field.cc | 83 +- .../protobuf/compiler/cpp/cpp_message_field.h | 19 +- .../protobuf/compiler/cpp/cpp_plugin_unittest.cc | 18 +- .../protobuf/compiler/cpp/cpp_primitive_field.cc | 64 + .../protobuf/compiler/cpp/cpp_primitive_field.h | 20 +- src/google/protobuf/compiler/cpp/cpp_service.h | 1 - .../protobuf/compiler/cpp/cpp_string_field.cc | 183 +- .../protobuf/compiler/cpp/cpp_string_field.h | 21 +- .../compiler/cpp/cpp_test_bad_identifiers.proto | 9 + src/google/protobuf/compiler/cpp/cpp_unittest.cc | 732 +++++- src/google/protobuf/compiler/importer.cc | 39 +- src/google/protobuf/compiler/importer.h | 15 +- src/google/protobuf/compiler/importer_unittest.cc | 55 +- src/google/protobuf/compiler/java/java_context.cc | 195 ++ src/google/protobuf/compiler/java/java_context.h | 95 + .../protobuf/compiler/java/java_doc_comment.cc | 13 +- .../compiler/java/java_doc_comment_unittest.cc | 1 + src/google/protobuf/compiler/java/java_enum.cc | 80 +- src/google/protobuf/compiler/java/java_enum.h | 15 +- .../protobuf/compiler/java/java_enum_field.cc | 399 ++- .../protobuf/compiler/java/java_enum_field.h | 61 +- .../protobuf/compiler/java/java_extension.cc | 97 +- src/google/protobuf/compiler/java/java_extension.h | 46 +- src/google/protobuf/compiler/java/java_field.cc | 206 +- src/google/protobuf/compiler/java/java_field.h | 79 +- src/google/protobuf/compiler/java/java_file.cc | 306 ++- src/google/protobuf/compiler/java/java_file.h | 32 +- .../protobuf/compiler/java/java_generator.cc | 85 +- .../compiler/java/java_generator_factory.cc | 77 + .../compiler/java/java_generator_factory.h | 101 + src/google/protobuf/compiler/java/java_helpers.cc | 307 ++- src/google/protobuf/compiler/java/java_helpers.h | 128 +- .../compiler/java/java_lazy_message_field.cc | 826 +++++++ .../compiler/java/java_lazy_message_field.h | 121 + src/google/protobuf/compiler/java/java_message.cc | 763 ++++-- src/google/protobuf/compiler/java/java_message.h | 50 +- .../protobuf/compiler/java/java_message_field.cc | 631 ++++- .../protobuf/compiler/java/java_message_field.h | 69 +- .../protobuf/compiler/java/java_name_resolver.cc | 266 ++ .../protobuf/compiler/java/java_name_resolver.h | 124 + .../protobuf/compiler/java/java_plugin_unittest.cc | 24 +- .../protobuf/compiler/java/java_primitive_field.cc | 460 ++-- .../protobuf/compiler/java/java_primitive_field.h | 63 +- src/google/protobuf/compiler/java/java_service.cc | 74 +- src/google/protobuf/compiler/java/java_service.h | 38 +- .../compiler/java/java_shared_code_generator.cc | 223 ++ .../compiler/java/java_shared_code_generator.h | 91 + .../protobuf/compiler/java/java_string_field.cc | 574 ++++- .../protobuf/compiler/java/java_string_field.h | 64 +- .../protobuf/compiler/mock_code_generator.cc | 25 +- src/google/protobuf/compiler/parser.cc | 275 ++- src/google/protobuf/compiler/parser.h | 91 +- src/google/protobuf/compiler/parser_unittest.cc | 252 +- src/google/protobuf/compiler/plugin.pb.cc | 278 ++- src/google/protobuf/compiler/plugin.pb.h | 161 +- .../protobuf/compiler/python/python_generator.cc | 149 +- .../protobuf/compiler/python/python_generator.h | 9 +- .../compiler/python/python_plugin_unittest.cc | 18 +- src/google/protobuf/compiler/subprocess.cc | 2 +- src/google/protobuf/descriptor.cc | 737 +++++- src/google/protobuf/descriptor.h | 202 +- src/google/protobuf/descriptor.pb.cc | 2603 ++++++++++++++------ src/google/protobuf/descriptor.pb.h | 1435 ++++++++--- src/google/protobuf/descriptor.proto | 79 +- src/google/protobuf/descriptor_database.cc | 4 +- src/google/protobuf/descriptor_database.h | 2 + src/google/protobuf/descriptor_pb2_test.py | 54 + src/google/protobuf/descriptor_unittest.cc | 895 ++++++- src/google/protobuf/dynamic_message.cc | 231 +- src/google/protobuf/dynamic_message.h | 12 + src/google/protobuf/dynamic_message_unittest.cc | 64 + src/google/protobuf/extension_set.cc | 241 +- src/google/protobuf/extension_set.h | 263 +- src/google/protobuf/extension_set_heavy.cc | 65 +- src/google/protobuf/extension_set_unittest.cc | 379 ++- src/google/protobuf/generated_enum_reflection.h | 6 + .../protobuf/generated_message_reflection.cc | 542 +++- src/google/protobuf/generated_message_reflection.h | 93 +- .../generated_message_reflection_unittest.cc | 311 +++ src/google/protobuf/generated_message_util.cc | 6 +- src/google/protobuf/generated_message_util.h | 34 +- src/google/protobuf/io/coded_stream.cc | 101 +- src/google/protobuf/io/coded_stream.h | 94 +- src/google/protobuf/io/coded_stream_inl.h | 3 +- src/google/protobuf/io/coded_stream_unittest.cc | 193 ++ src/google/protobuf/io/gzip_stream.h | 2 +- src/google/protobuf/io/printer_unittest.cc | 2 +- src/google/protobuf/io/strtod.cc | 113 + src/google/protobuf/io/strtod.h | 50 + src/google/protobuf/io/tokenizer.cc | 44 +- src/google/protobuf/io/tokenizer.h | 17 + src/google/protobuf/io/tokenizer_unittest.cc | 24 +- src/google/protobuf/io/zero_copy_stream.cc | 9 + src/google/protobuf/io/zero_copy_stream.h | 10 + src/google/protobuf/io/zero_copy_stream_impl.cc | 8 +- src/google/protobuf/io/zero_copy_stream_impl.h | 1 + .../protobuf/io/zero_copy_stream_impl_lite.cc | 20 +- .../protobuf/io/zero_copy_stream_impl_lite.h | 14 + .../protobuf/io/zero_copy_stream_unittest.cc | 27 +- src/google/protobuf/lite_unittest.cc | 169 +- src/google/protobuf/message.cc | 10 +- src/google/protobuf/message.h | 61 +- src/google/protobuf/message_lite.cc | 3 +- src/google/protobuf/message_lite.h | 3 +- src/google/protobuf/message_unittest.cc | 77 +- src/google/protobuf/reflection_ops.cc | 4 +- src/google/protobuf/reflection_ops_unittest.cc | 72 +- src/google/protobuf/repeated_field.h | 95 +- src/google/protobuf/repeated_field_unittest.cc | 97 +- src/google/protobuf/stubs/common.h | 2 + src/google/protobuf/stubs/map-util.h | 143 -- src/google/protobuf/stubs/map_util.h | 771 ++++++ src/google/protobuf/stubs/once.h | 18 + src/google/protobuf/stubs/strutil.cc | 186 +- src/google/protobuf/stubs/strutil.h | 103 +- src/google/protobuf/stubs/strutil_unittest.cc | 10 - src/google/protobuf/test_util.cc | 298 +++ src/google/protobuf/test_util.h | 22 + src/google/protobuf/test_util_lite.cc | 37 + src/google/protobuf/testdata/bad_utf8_string | 1 + src/google/protobuf/testdata/golden_message | Bin 509 -> 531 bytes .../testdata/golden_message_oneof_implemented | Bin 0 -> 515 bytes .../testdata/text_format_unittest_data.txt | 6 + ...text_format_unittest_data_oneof_implemented.txt | 129 + .../testdata/text_format_unittest_data_pointy.txt | 134 + .../text_format_unittest_extensions_data.txt | 6 + ...text_format_unittest_extensions_data_pointy.txt | 134 + src/google/protobuf/testing/file.cc | 18 + src/google/protobuf/testing/file.h | 14 + src/google/protobuf/text_format.cc | 541 ++-- src/google/protobuf/text_format.h | 114 +- src/google/protobuf/text_format_unittest.cc | 259 +- src/google/protobuf/unittest.proto | 142 ++ src/google/protobuf/unittest_custom_options.proto | 6 + src/google/protobuf/unittest_lite.proto | 24 + src/google/protobuf/unittest_mset.proto | 11 + .../protobuf/unittest_no_generic_services.proto | 1 + src/google/protobuf/unittest_optimize_for.proto | 7 +- src/google/protobuf/unknown_field_set.cc | 25 +- src/google/protobuf/unknown_field_set.h | 41 +- src/google/protobuf/unknown_field_set_unittest.cc | 7 +- src/google/protobuf/wire_format.cc | 74 +- src/google/protobuf/wire_format.h | 36 +- src/google/protobuf/wire_format_lite.cc | 112 +- src/google/protobuf/wire_format_lite.h | 39 + src/google/protobuf/wire_format_lite_inl.h | 101 +- src/google/protobuf/wire_format_unittest.cc | 160 +- 167 files changed, 20324 insertions(+), 4072 deletions(-) create mode 100644 src/google/protobuf/compiler/java/java_context.cc create mode 100644 src/google/protobuf/compiler/java/java_context.h create mode 100644 src/google/protobuf/compiler/java/java_generator_factory.cc create mode 100644 src/google/protobuf/compiler/java/java_generator_factory.h create mode 100644 src/google/protobuf/compiler/java/java_lazy_message_field.cc create mode 100644 src/google/protobuf/compiler/java/java_lazy_message_field.h create mode 100644 src/google/protobuf/compiler/java/java_name_resolver.cc create mode 100644 src/google/protobuf/compiler/java/java_name_resolver.h create mode 100644 src/google/protobuf/compiler/java/java_shared_code_generator.cc create mode 100644 src/google/protobuf/compiler/java/java_shared_code_generator.h create mode 100644 src/google/protobuf/descriptor_pb2_test.py create mode 100644 src/google/protobuf/io/strtod.cc create mode 100644 src/google/protobuf/io/strtod.h delete mode 100644 src/google/protobuf/stubs/map-util.h create mode 100644 src/google/protobuf/stubs/map_util.h create mode 100644 src/google/protobuf/testdata/bad_utf8_string create mode 100644 src/google/protobuf/testdata/golden_message_oneof_implemented create mode 100644 src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt create mode 100644 src/google/protobuf/testdata/text_format_unittest_data_pointy.txt create mode 100644 src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index 40696035..ada36ad4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -40,11 +40,13 @@ MAINTAINERCLEANFILES = \ nobase_include_HEADERS = \ google/protobuf/stubs/atomicops.h \ google/protobuf/stubs/atomicops_internals_arm_gcc.h \ + google/protobuf/stubs/atomicops_internals_arm64_gcc.h \ google/protobuf/stubs/atomicops_internals_arm_qnx.h \ google/protobuf/stubs/atomicops_internals_atomicword_compat.h \ google/protobuf/stubs/atomicops_internals_macosx.h \ google/protobuf/stubs/atomicops_internals_mips_gcc.h \ google/protobuf/stubs/atomicops_internals_pnacl.h \ + google/protobuf/stubs/atomicops_internals_tsan.h \ google/protobuf/stubs/atomicops_internals_x86_gcc.h \ google/protobuf/stubs/atomicops_internals_x86_msvc.h \ google/protobuf/stubs/common.h \ @@ -73,6 +75,7 @@ nobase_include_HEADERS = \ google/protobuf/io/coded_stream.h \ $(GZHEADERS) \ google/protobuf/io/printer.h \ + google/protobuf/io/strtod.h \ google/protobuf/io/tokenizer.h \ google/protobuf/io/zero_copy_stream.h \ google/protobuf/io/zero_copy_stream_impl.h \ @@ -97,7 +100,7 @@ libprotobuf_lite_la_SOURCES = \ google/protobuf/stubs/common.cc \ google/protobuf/stubs/once.cc \ google/protobuf/stubs/hash.h \ - google/protobuf/stubs/map-util.h \ + google/protobuf/stubs/map_util.h \ google/protobuf/stubs/stl_util.h \ google/protobuf/stubs/stringprintf.cc \ google/protobuf/stubs/stringprintf.h \ @@ -134,6 +137,7 @@ libprotobuf_la_SOURCES = \ google/protobuf/wire_format.cc \ google/protobuf/io/gzip_stream.cc \ google/protobuf/io/printer.cc \ + google/protobuf/io/strtod.cc \ google/protobuf/io/tokenizer.cc \ google/protobuf/io/zero_copy_stream_impl.cc \ google/protobuf/compiler/importer.cc \ @@ -174,6 +178,8 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/cpp/cpp_service.h \ google/protobuf/compiler/cpp/cpp_string_field.cc \ google/protobuf/compiler/cpp/cpp_string_field.h \ + google/protobuf/compiler/java/java_context.cc \ + google/protobuf/compiler/java/java_context.h \ google/protobuf/compiler/java/java_enum.cc \ google/protobuf/compiler/java/java_enum.h \ google/protobuf/compiler/java/java_enum_field.cc \ @@ -185,14 +191,22 @@ libprotoc_la_SOURCES = \ google/protobuf/compiler/java/java_file.cc \ google/protobuf/compiler/java/java_file.h \ google/protobuf/compiler/java/java_generator.cc \ + google/protobuf/compiler/java/java_generator_factory.cc \ + google/protobuf/compiler/java/java_generator_factory.h \ google/protobuf/compiler/java/java_helpers.cc \ google/protobuf/compiler/java/java_helpers.h \ + google/protobuf/compiler/java/java_lazy_message_field.cc \ + google/protobuf/compiler/java/java_lazy_message_field.h \ google/protobuf/compiler/java/java_message.cc \ google/protobuf/compiler/java/java_message.h \ google/protobuf/compiler/java/java_message_field.cc \ google/protobuf/compiler/java/java_message_field.h \ + google/protobuf/compiler/java/java_name_resolver.cc \ + google/protobuf/compiler/java/java_name_resolver.h \ google/protobuf/compiler/java/java_primitive_field.cc \ google/protobuf/compiler/java/java_primitive_field.h \ + google/protobuf/compiler/java/java_shared_code_generator.cc \ + google/protobuf/compiler/java/java_shared_code_generator.h \ google/protobuf/compiler/java/java_service.cc \ google/protobuf/compiler/java/java_service.h \ google/protobuf/compiler/java/java_string_field.cc \ @@ -229,9 +243,10 @@ EXTRA_DIST = \ google/protobuf/io/gzip_stream.h \ google/protobuf/io/gzip_stream_unittest.sh \ google/protobuf/testdata/golden_message \ + google/protobuf/testdata/golden_message_oneof_implemented \ google/protobuf/testdata/golden_packed_fields_message \ - google/protobuf/testdata/text_format_unittest_data.txt \ - google/protobuf/testdata/text_format_unittest_extensions_data.txt \ + google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt \ + google/protobuf/testdata/text_format_unittest_extensions_data.txt \ google/protobuf/package_info.h \ google/protobuf/io/package_info.h \ google/protobuf/compiler/package_info.h \ @@ -352,7 +367,8 @@ nodist_protobuf_test_SOURCES = $(protoc_outputs) # Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined. protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \ - $(top_builddir)/gtest/lib/libgtest.la \ + libprotoc.la \ + $(top_builddir)/gtest/lib/libgtest.la \ $(top_builddir)/gtest/lib/libgtest_main.la protobuf_lazy_descriptor_test_CPPFLAGS = -I$(top_srcdir)/gtest/include \ -I$(top_builddir)/gtest/include \ diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc index 455c239a..bc4800a6 100644 --- a/src/google/protobuf/compiler/code_generator.cc +++ b/src/google/protobuf/compiler/code_generator.cc @@ -44,6 +44,11 @@ namespace compiler { CodeGenerator::~CodeGenerator() {} GeneratorContext::~GeneratorContext() {} +io::ZeroCopyOutputStream* +GeneratorContext::OpenForAppend(const string& filename) { + return NULL; +} + io::ZeroCopyOutputStream* GeneratorContext::OpenForInsert( const string& filename, const string& insertion_point) { GOOGLE_LOG(FATAL) << "This GeneratorContext does not support insertion."; @@ -58,8 +63,7 @@ void GeneratorContext::ListParsedFiles( // Parses a set of comma-delimited name/value pairs. void ParseGeneratorParameter(const string& text, vector >* output) { - vector parts; - SplitStringUsing(text, ",", &parts); + vector parts = Split(text, ",", true); for (int i = 0; i < parts.size(); i++) { string::size_type equals_pos = parts[i].find_first_of('='); diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h index 252f68d1..541f784c 100644 --- a/src/google/protobuf/compiler/code_generator.h +++ b/src/google/protobuf/compiler/code_generator.h @@ -104,6 +104,9 @@ class LIBPROTOC_EXPORT GeneratorContext { // contain "." or ".." components. virtual io::ZeroCopyOutputStream* Open(const string& filename) = 0; + // Similar to Open() but the output will be appended to the file if exists + virtual io::ZeroCopyOutputStream* OpenForAppend(const string& filename); + // Creates a ZeroCopyOutputStream which will insert code into the given file // at the given insertion point. See plugin.proto (plugin.pb.h) for more // information on insertion points. The default implementation diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc index b9293c97..358d6462 100644 --- a/src/google/protobuf/compiler/command_line_interface.cc +++ b/src/google/protobuf/compiler/command_line_interface.cc @@ -49,8 +49,10 @@ #include #include +#include #include +#include #include #include #include @@ -64,7 +66,7 @@ #include #include #include -#include +#include #include @@ -160,8 +162,7 @@ bool VerifyDirectoryExists(const string& path) { // directories listed in |filename|. bool TryCreateParentDirectory(const string& prefix, const string& filename) { // Recursively create parent directories to the output file. - vector parts; - SplitStringUsing(filename, "/", &parts); + vector parts = Split(filename, "/", true); string path_so_far = prefix; for (int i = 0; i < parts.size() - 1; i++) { path_so_far += parts[i]; @@ -252,6 +253,7 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { // implements GeneratorContext -------------------------------------- io::ZeroCopyOutputStream* Open(const string& filename); + io::ZeroCopyOutputStream* OpenForAppend(const string& filename); io::ZeroCopyOutputStream* OpenForInsert( const string& filename, const string& insertion_point); void ListParsedFiles(vector* output) { @@ -271,7 +273,8 @@ class CommandLineInterface::GeneratorContextImpl : public GeneratorContext { class CommandLineInterface::MemoryOutputStream : public io::ZeroCopyOutputStream { public: - MemoryOutputStream(GeneratorContextImpl* directory, const string& filename); + MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, + bool append_mode); MemoryOutputStream(GeneratorContextImpl* directory, const string& filename, const string& insertion_point); virtual ~MemoryOutputStream(); @@ -290,6 +293,9 @@ class CommandLineInterface::MemoryOutputStream // The string we're building. string data_; + // Whether we should append the output stream to the existing file. + bool append_mode_; + // StringOutputStream writing to data_. scoped_ptr inner_; }; @@ -434,7 +440,13 @@ void CommandLineInterface::GeneratorContextImpl::AddJarManifest() { io::ZeroCopyOutputStream* CommandLineInterface::GeneratorContextImpl::Open( const string& filename) { - return new MemoryOutputStream(this, filename); + return new MemoryOutputStream(this, filename, false); +} + +io::ZeroCopyOutputStream* +CommandLineInterface::GeneratorContextImpl::OpenForAppend( + const string& filename) { + return new MemoryOutputStream(this, filename, true); } io::ZeroCopyOutputStream* @@ -446,9 +458,10 @@ CommandLineInterface::GeneratorContextImpl::OpenForInsert( // ------------------------------------------------------------------- CommandLineInterface::MemoryOutputStream::MemoryOutputStream( - GeneratorContextImpl* directory, const string& filename) + GeneratorContextImpl* directory, const string& filename, bool append_mode) : directory_(directory), filename_(filename), + append_mode_(append_mode), inner_(new io::StringOutputStream(&data_)) { } @@ -471,8 +484,12 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { if (insertion_point_.empty()) { // This was just a regular Open(). if (*map_slot != NULL) { - cerr << filename_ << ": Tried to write the same file twice." << endl; - directory_->had_error_ = true; + if (append_mode_) { + (*map_slot)->append(data_); + } else { + cerr << filename_ << ": Tried to write the same file twice." << endl; + directory_->had_error_ = true; + } return; } @@ -565,6 +582,7 @@ CommandLineInterface::MemoryOutputStream::~MemoryOutputStream() { CommandLineInterface::CommandLineInterface() : mode_(MODE_COMPILE), + print_mode_(PRINT_NONE), error_format_(ERROR_FORMAT_GCC), imports_in_descriptor_set_(false), source_info_in_descriptor_set_(false), @@ -632,7 +650,9 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { // Parse each file. for (int i = 0; i < input_files_.size(); i++) { // Import the file. + importer.AddUnusedImportTrackFile(input_files_[i]); const FileDescriptor* parsed_file = importer.Import(input_files_[i]); + importer.ClearUnusedImportTrackFiles(); if (parsed_file == NULL) return 1; parsed_files.push_back(parsed_file); @@ -721,6 +741,25 @@ int CommandLineInterface::Run(int argc, const char* const argv[]) { } } + if (mode_ == MODE_PRINT) { + switch (print_mode_) { + case PRINT_FREE_FIELDS: + for (int i = 0; i < parsed_files.size(); ++i) { + const FileDescriptor* fd = parsed_files[i]; + for (int j = 0; j < fd->message_type_count(); ++j) { + PrintFreeFieldNumbers(fd->message_type(j)); + } + } + break; + case PRINT_NONE: + GOOGLE_LOG(ERROR) << "If the code reaches here, it usually means a bug of " + "flag parsing in the CommonadLineInterface."; + return 1; + + // Do not add a default case. + } + } + return 0; } @@ -735,6 +774,7 @@ void CommandLineInterface::Clear() { descriptor_set_name_.clear(); mode_ = MODE_COMPILE; + print_mode_ = PRINT_NONE; imports_in_descriptor_set_ = false; source_info_in_descriptor_set_ = false; disallow_services_ = false; @@ -889,7 +929,8 @@ bool CommandLineInterface::ParseArgument(const char* arg, *name == "--include_imports" || *name == "--include_source_info" || *name == "--version" || - *name == "--decode_raw") { + *name == "--decode_raw" || + *name == "--print_free_field_numbers") { // HACK: These are the only flags that don't take a value. // They probably should not be hard-coded like this but for now it's // not worth doing better. @@ -919,8 +960,8 @@ CommandLineInterface::InterpretArgument(const string& name, // Java's -classpath (and some other languages) delimits path components // with colons. Let's accept that syntax too just to make things more // intuitive. - vector parts; - SplitStringUsing(value, kPathSeparator, &parts); + vector parts = Split( + value, kPathSeparator, true); for (int i = 0; i < parts.size(); i++) { string virtual_path; @@ -1061,6 +1102,19 @@ CommandLineInterface::InterpretArgument(const string& name, plugins_[plugin_name] = path; + } else if (name == "--print_free_field_numbers") { + if (mode_ != MODE_COMPILE) { + cerr << "Cannot use " << name << " and use --encode, --decode or print " + << "other info at the same time." << endl; + return PARSE_ARGUMENT_FAIL; + } + if (!output_directives_.empty() || !descriptor_set_name_.empty()) { + cerr << "Cannot use " << name + << " and generate code or descriptors at the same time." << endl; + return PARSE_ARGUMENT_FAIL; + } + mode_ = MODE_PRINT; + print_mode_ = PRINT_FREE_FIELDS; } else { // Some other flag. Look it up in the generators list. const GeneratorInfo* generator_info = @@ -1082,8 +1136,8 @@ CommandLineInterface::InterpretArgument(const string& name, } else { // It's an output flag. Add it to the output directives. if (mode_ != MODE_COMPILE) { - cerr << "Cannot use --encode or --decode and generate code at the " - "same time." << endl; + cerr << "Cannot use --encode, --decode or print .proto info and " + "generate code at the same time." << endl; return PARSE_ARGUMENT_FAIL; } @@ -1151,7 +1205,12 @@ void CommandLineInterface::PrintHelpText() { " well as surrounding comments.\n" " --error_format=FORMAT Set the format in which to print errors.\n" " FORMAT may be 'gcc' (the default) or 'msvs'\n" -" (Microsoft Visual Studio format)." << endl; +" (Microsoft Visual Studio format).\n" +" --print_free_field_numbers Print the free field numbers of the messages\n" +" defined in the given proto files. Groups share\n" +" the same field number space with the parent \n" +" message. Extension ranges are counted as \n" +" occupied fields numbers." << endl; if (!plugin_prefix_.empty()) { cerr << " --plugin=EXECUTABLE Specifies a plugin executable to use.\n" @@ -1431,6 +1490,113 @@ void CommandLineInterface::GetTransitiveDependencies( } } +namespace { + +// Utility function for PrintFreeFieldNumbers. +// Stores occupied ranges into the ranges parameter, and next level of sub +// message types into the nested_messages parameter. The FieldRange is left +// inclusive, right exclusive. i.e. [a, b). +// +// Nested Messages: +// Note that it only stores the nested message type, iff the nested type is +// either a direct child of the given descriptor, or the nested type is a +// decendent of the given descriptor and all the nodes between the +// nested type and the given descriptor are group types. e.g. +// +// message Foo { +// message Bar { +// message NestedBar {} +// } +// group Baz = 1 { +// group NestedBazGroup = 2 { +// message Quz { +// message NestedQuz {} +// } +// } +// message NestedBaz {} +// } +// } +// +// In this case, Bar, Quz and NestedBaz will be added into the nested types. +// Since free field numbers of group types will not be printed, this makes sure +// the nested message types in groups will not be dropped. The nested_messages +// parameter will contain the direct children (when groups are ignored in the +// tree) of the given descriptor for the caller to traverse. The declaration +// order of the nested messages is also preserved. +typedef pair FieldRange; +void GatherOccupiedFieldRanges(const Descriptor* descriptor, + set* ranges, + vector* nested_messages) { + set groups; + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* fd = descriptor->field(i); + ranges->insert(FieldRange(fd->number(), fd->number() + 1)); + if (fd->type() == FieldDescriptor::TYPE_GROUP) { + groups.insert(fd->message_type()); + } + } + for (int i = 0; i < descriptor->extension_range_count(); ++i) { + ranges->insert(FieldRange(descriptor->extension_range(i)->start, + descriptor->extension_range(i)->end)); + } + // Handle the nested messages/groups in declaration order to make it + // post-order strict. + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + const Descriptor* nested_desc = descriptor->nested_type(i); + if (groups.find(nested_desc) != groups.end()) { + GatherOccupiedFieldRanges(nested_desc, ranges, nested_messages); + } else { + nested_messages->push_back(nested_desc); + } + } +} + +// Utility function for PrintFreeFieldNumbers. +// Actually prints the formatted free field numbers for given message name and +// occupied ranges. +void FormatFreeFieldNumbers(const string& name, + const set& ranges) { + string output; + StringAppendF(&output, "%-35s free:", name.c_str()); + int next_free_number = 1; + for (set::iterator i = ranges.begin(); + i != ranges.end(); ++i) { + // This happens when groups re-use parent field numbers, in which + // case we skip the FieldRange entirely. + if (next_free_number >= i->second) continue; + + if (next_free_number < i->first) { + if (next_free_number + 1 == i->first) { + // Singleton + StringAppendF(&output, " %d", next_free_number); + } else { + // Range + StringAppendF(&output, " %d-%d", next_free_number, i->first - 1); + } + } + next_free_number = i->second; + } + if (next_free_number <= FieldDescriptor::kMaxNumber) { + StringAppendF(&output, " %d-INF", next_free_number); + } + cout << output << endl; +} + +} // namespace + +void CommandLineInterface::PrintFreeFieldNumbers( + const Descriptor* descriptor) { + set ranges; + vector nested_messages; + GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages); + + for (int i = 0; i < nested_messages.size(); ++i) { + PrintFreeFieldNumbers(nested_messages[i]); + } + FormatFreeFieldNumbers(descriptor->full_name(), ranges); +} + + } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h index 86ea9bde..3b734150 100644 --- a/src/google/protobuf/compiler/command_line_interface.h +++ b/src/google/protobuf/compiler/command_line_interface.h @@ -48,8 +48,9 @@ namespace google { namespace protobuf { -class FileDescriptor; // descriptor.h +class Descriptor; // descriptor.h class DescriptorPool; // descriptor.h +class FileDescriptor; // descriptor.h class FileDescriptorProto; // descriptor.pb.h template class RepeatedPtrField; // repeated_field.h @@ -259,6 +260,22 @@ class LIBPROTOC_EXPORT CommandLineInterface { set* already_seen, RepeatedPtrField* output); + // Implements the --print_free_field_numbers. This function prints free field + // numbers into stdout for the message and it's nested message types in + // post-order, i.e. nested types first. Printed range are left-right + // inclusive, i.e. [a, b]. + // + // Groups: + // For historical reasons, groups are considered to share the same + // field number space with the parent message, thus it will not print free + // field numbers for groups. The field numbers used in the groups are + // excluded in the free field numbers of the parent message. + // + // Extension Ranges: + // Extension ranges are considered ocuppied field numbers and they will not be + // listed as free numbers in the output. + void PrintFreeFieldNumbers(const Descriptor* descriptor); + // ----------------------------------------------------------------- // The name of the executable as invoked (i.e. argv[0]). @@ -295,11 +312,19 @@ class LIBPROTOC_EXPORT CommandLineInterface { enum Mode { MODE_COMPILE, // Normal mode: parse .proto files and compile them. MODE_ENCODE, // --encode: read text from stdin, write binary to stdout. - MODE_DECODE // --decode: read binary from stdin, write text to stdout. + MODE_DECODE, // --decode: read binary from stdin, write text to stdout. + MODE_PRINT, // Print mode: print info of the given .proto files and exit. }; Mode mode_; + enum PrintMode { + PRINT_NONE, // Not in MODE_PRINT + PRINT_FREE_FIELDS, // --print_free_fields + }; + + PrintMode print_mode_; + enum ErrorFormat { ERROR_FORMAT_GCC, // GCC error output format (default). ERROR_FORMAT_MSVS // Visual Studio output (--error_format=msvs). diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc index 16559923..9e244da3 100644 --- a/src/google/protobuf/compiler/command_line_interface_unittest.cc +++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc @@ -40,6 +40,7 @@ #else #include #endif +#include #include #include @@ -126,6 +127,9 @@ class CommandLineInterfaceTest : public testing::Test { void ExpectErrorSubstringWithZeroReturnCode( const string& expected_substring); + // Checks that the captured stdout is the same as the expected_text. + void ExpectCapturedStdout(const string& expected_text); + // Returns true if ExpectErrorSubstring(expected_substring) would pass, but // does not fail otherwise. bool HasAlternateErrorSubstring(const string& expected_substring); @@ -182,6 +186,9 @@ class CommandLineInterfaceTest : public testing::Test { // The captured stderr output. string error_text_; + // The captured stdout. + string captured_stdout_; + // Pointers which need to be deleted later. vector mock_generators_to_delete_; @@ -224,7 +231,7 @@ void CommandLineInterfaceTest::SetUp() { } // Create the temp directory. - GOOGLE_CHECK(File::CreateDir(temp_directory_.c_str(), DEFAULT_FILE_MODE)); + GOOGLE_CHECK_OK(File::CreateDir(temp_directory_, 0777)); // Register generators. CodeGenerator* generator = new MockCodeGenerator("test_generator"); @@ -255,8 +262,7 @@ void CommandLineInterfaceTest::TearDown() { } void CommandLineInterfaceTest::Run(const string& command) { - vector args; - SplitStringUsing(command, " ", &args); + vector args = Split(command, " ", true); if (!disallow_plugins_) { cli_.AllowPlugins("prefix-"); @@ -295,18 +301,20 @@ void CommandLineInterfaceTest::Run(const string& command) { } } - scoped_array argv(new const char*[args.size()]); + scoped_array argv(new const char* [args.size()]); for (int i = 0; i < args.size(); i++) { args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true); argv[i] = args[i].c_str(); } + CaptureTestStdout(); CaptureTestStderr(); return_code_ = cli_.Run(args.size(), argv.get()); error_text_ = GetCapturedTestStderr(); + captured_stdout_ = GetCapturedTestStdout(); } // ------------------------------------------------------------------- @@ -318,16 +326,20 @@ void CommandLineInterfaceTest::CreateTempFile( string::size_type slash_pos = name.find_last_of('/'); if (slash_pos != string::npos) { string dir = name.substr(0, slash_pos); - File::RecursivelyCreateDir(temp_directory_ + "/" + dir, 0777); + if (!File::Exists(temp_directory_ + "/" + dir)) { + GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + dir, + 0777)); + } } // Write file. string full_name = temp_directory_ + "/" + name; - File::WriteStringToFileOrDie(contents, full_name); + GOOGLE_CHECK_OK(File::SetContents(full_name, contents, true)); } void CommandLineInterfaceTest::CreateTempDir(const string& name) { - File::RecursivelyCreateDir(temp_directory_ + "/" + name, 0777); + GOOGLE_CHECK_OK(File::RecursivelyCreateDir(temp_directory_ + "/" + name, + 0777)); } // ------------------------------------------------------------------- @@ -414,14 +426,18 @@ void CommandLineInterfaceTest::ReadDescriptorSet( const string& filename, FileDescriptorSet* descriptor_set) { string path = temp_directory_ + "/" + filename; string file_contents; - if (!File::ReadFileToString(path, &file_contents)) { - FAIL() << "File not found: " << path; - } + GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true)); + if (!descriptor_set->ParseFromString(file_contents)) { FAIL() << "Could not parse file contents: " << path; } } +void CommandLineInterfaceTest::ExpectCapturedStdout( + const string& expected_text) { + EXPECT_EQ(expected_text, captured_stdout_); +} + // =================================================================== TEST_F(CommandLineInterfaceTest, BasicOutput) { @@ -813,7 +829,7 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSet) { FileDescriptorSet descriptor_set; ReadDescriptorSet("descriptor_set", &descriptor_set); if (HasFatalFailure()) return; - ASSERT_EQ(1, descriptor_set.file_size()); + EXPECT_EQ(1, descriptor_set.file_size()); EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); // Descriptor set should not have source code info. EXPECT_FALSE(descriptor_set.file(0).has_source_code_info()); @@ -838,7 +854,7 @@ TEST_F(CommandLineInterfaceTest, WriteDescriptorSetWithSourceInfo) { FileDescriptorSet descriptor_set; ReadDescriptorSet("descriptor_set", &descriptor_set); if (HasFatalFailure()) return; - ASSERT_EQ(1, descriptor_set.file_size()); + EXPECT_EQ(1, descriptor_set.file_size()); EXPECT_EQ("bar.proto", descriptor_set.file(0).name()); // Source code info included. EXPECT_TRUE(descriptor_set.file(0).has_source_code_info()); @@ -863,7 +879,7 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSet) { FileDescriptorSet descriptor_set; ReadDescriptorSet("descriptor_set", &descriptor_set); if (HasFatalFailure()) return; - ASSERT_EQ(2, descriptor_set.file_size()); + EXPECT_EQ(2, descriptor_set.file_size()); if (descriptor_set.file(0).name() == "bar.proto") { std::swap(descriptor_set.mutable_file()->mutable_data()[0], descriptor_set.mutable_file()->mutable_data()[1]); @@ -894,7 +910,7 @@ TEST_F(CommandLineInterfaceTest, WriteTransitiveDescriptorSetWithSourceInfo) { FileDescriptorSet descriptor_set; ReadDescriptorSet("descriptor_set", &descriptor_set); if (HasFatalFailure()) return; - ASSERT_EQ(2, descriptor_set.file_size()); + EXPECT_EQ(2, descriptor_set.file_size()); if (descriptor_set.file(0).name() == "bar.proto") { std::swap(descriptor_set.mutable_file()->mutable_data()[0], descriptor_set.mutable_file()->mutable_data()[1]); @@ -1393,6 +1409,70 @@ TEST_F(CommandLineInterfaceTest, MissingValueAtEndError) { ExpectErrorText("Missing value for flag: --test_out\n"); } +TEST_F(CommandLineInterfaceTest, PrintFreeFieldNumbers) { + CreateTempFile( + "foo.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "message Foo {\n" + " optional int32 a = 2;\n" + " optional string b = 4;\n" + " optional string c = 5;\n" + " optional int64 d = 8;\n" + " optional double e = 10;\n" + "}\n"); + CreateTempFile( + "bar.proto", + "syntax = \"proto2\";\n" + "message Bar {\n" + " optional int32 a = 2;\n" + " extensions 4 to 5;\n" + " optional int64 d = 8;\n" + " extensions 10;\n" + "}\n"); + CreateTempFile( + "baz.proto", + "syntax = \"proto2\";\n" + "message Baz {\n" + " optional int32 a = 2;\n" + " optional int64 d = 8;\n" + " extensions 15 to max;\n" // unordered. + " extensions 13;\n" + " extensions 10 to 12;\n" + " extensions 5;\n" + " extensions 4;\n" + "}\n"); + CreateTempFile( + "quz.proto", + "syntax = \"proto2\";\n" + "message Quz {\n" + " message Foo {}\n" // nested message + " optional int32 a = 2;\n" + " optional group C = 4 {\n" + " optional int32 d = 5;\n" + " }\n" + " extensions 8 to 10;\n" + " optional group E = 11 {\n" + " optional int32 f = 9;\n" // explicitly reuse extension range 8-10 + " optional group G = 15 {\n" // nested group + " message Foo {}\n" // nested message inside nested group + " }\n" + " }\n" + "}\n"); + + Run("protocol_compiler --print_free_field_numbers --proto_path=$tmpdir " + "foo.proto bar.proto baz.proto quz.proto"); + + ExpectNoErrors(); + ExpectCapturedStdout( + "foo.Foo free: 1 3 6-7 9 11-INF\n" + "Bar free: 1 3 6-7 9 11-INF\n" + "Baz free: 1 3 6-7 9 14\n" + "Quz.Foo free: 1-INF\n" + "Quz.E.G.Foo free: 1-INF\n" + "Quz free: 1 3 6-7 12-14 16-INF\n"); +} + // =================================================================== // Test for --encode and --decode. Note that it would be easier to do this @@ -1412,7 +1492,7 @@ class EncodeDecodeTest : public testing::Test { void RedirectStdinFromText(const string& input) { string filename = TestTempDir() + "/test_stdin"; - File::WriteStringToFileOrDie(input, filename); + GOOGLE_CHECK_OK(File::SetContents(filename, input, true)); GOOGLE_CHECK(RedirectStdinFromFile(filename)); } @@ -1446,7 +1526,7 @@ class EncodeDecodeTest : public testing::Test { SplitStringUsing(command, " ", &args); args.push_back("--proto_path=" + TestSourceDir()); - scoped_array argv(new const char*[args.size()]); + scoped_array argv(new const char* [args.size()]); for (int i = 0; i < args.size(); i++) { argv[i] = args[i].c_str(); } @@ -1467,7 +1547,7 @@ class EncodeDecodeTest : public testing::Test { void ExpectStdoutMatchesBinaryFile(const string& filename) { string expected_output; - ASSERT_TRUE(File::ReadFileToString(filename, &expected_output)); + GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); // Don't use EXPECT_EQ because we don't want to print raw binary data to // stdout on failure. @@ -1476,7 +1556,7 @@ class EncodeDecodeTest : public testing::Test { void ExpectStdoutMatchesTextFile(const string& filename) { string expected_output; - ASSERT_TRUE(File::ReadFileToString(filename, &expected_output)); + GOOGLE_CHECK_OK(File::GetContents(filename, &expected_output, true)); ExpectStdoutMatchesText(expected_output); } @@ -1496,22 +1576,23 @@ class EncodeDecodeTest : public testing::Test { }; TEST_F(EncodeDecodeTest, Encode) { - RedirectStdinFromFile(TestSourceDir() + - "/google/protobuf/testdata/text_format_unittest_data.txt"); + RedirectStdinFromFile(TestSourceDir() + "/google/protobuf/" + "testdata/text_format_unittest_data_oneof_implemented.txt"); EXPECT_TRUE(Run("google/protobuf/unittest.proto " "--encode=protobuf_unittest.TestAllTypes")); ExpectStdoutMatchesBinaryFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message"); + "/google/protobuf/testdata/golden_message_oneof_implemented"); ExpectStderrMatchesText(""); } TEST_F(EncodeDecodeTest, Decode) { RedirectStdinFromFile(TestSourceDir() + - "/google/protobuf/testdata/golden_message"); + "/google/protobuf/testdata/golden_message_oneof_implemented"); EXPECT_TRUE(Run("google/protobuf/unittest.proto " "--decode=protobuf_unittest.TestAllTypes")); ExpectStdoutMatchesTextFile(TestSourceDir() + - "/google/protobuf/testdata/text_format_unittest_data.txt"); + "/google/protobuf/" + "testdata/text_format_unittest_data_oneof_implemented.txt"); ExpectStderrMatchesText(""); } diff --git a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc index b7c1766b..48da534c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_bootstrap_unittest.cc @@ -48,7 +48,7 @@ #include #include #include -#include +#include #include #include #include @@ -93,9 +93,9 @@ class MockGeneratorContext : public GeneratorContext { << "Generator failed to generate file: " << virtual_filename; string actual_contents; - File::ReadFileToStringOrDie( - TestSourceDir() + "/" + physical_filename, - &actual_contents); + GOOGLE_CHECK_OK( + File::GetContents(TestSourceDir() + "/" + physical_filename, + &actual_contents, true)); EXPECT_TRUE(actual_contents == *expected_contents) << physical_filename << " needs to be regenerated. Please run " "generate_descriptor_proto.sh and add this file " diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.cc b/src/google/protobuf/compiler/cpp/cpp_enum.cc index 67c12d7a..0c4796f6 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum.cc @@ -45,11 +45,27 @@ namespace protobuf { namespace compiler { namespace cpp { +namespace { +// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value +// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the +// generation of the GOOGLE_ARRAYSIZE constant. +bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) { + int32 max_value = descriptor->value(0)->number(); + for (int i = 0; i < descriptor->value_count(); i++) { + if (descriptor->value(i)->number() > max_value) { + max_value = descriptor->value(i)->number(); + } + } + return max_value != kint32max; +} +} // namespace + EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, const Options& options) : descriptor_(descriptor), classname_(ClassName(descriptor, false)), - options_(options) { + options_(options), + generate_array_size_(ShouldGenerateArraySize(descriptor)) { } EnumGenerator::~EnumGenerator() {} @@ -67,7 +83,10 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { for (int i = 0; i < descriptor_->value_count(); i++) { vars["name"] = descriptor_->value(i)->name(); - vars["number"] = SimpleItoa(descriptor_->value(i)->number()); + // In C++, an value of -2147483648 gets interpreted as the negative of + // 2147483648, and since 2147483648 can't fit in an integer, this produces a + // compiler warning. This works around that issue. + vars["number"] = Int32ToString(descriptor_->value(i)->number()); vars["prefix"] = (descriptor_->containing_type() == NULL) ? "" : classname_ + "_"; @@ -97,9 +116,13 @@ void EnumGenerator::GenerateDefinition(io::Printer* printer) { printer->Print(vars, "$dllexport$bool $classname$_IsValid(int value);\n" "const $classname$ $prefix$$short_name$_MIN = $prefix$$min_name$;\n" - "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n" - "const int $prefix$$short_name$_ARRAYSIZE = $prefix$$short_name$_MAX + 1;\n" - "\n"); + "const $classname$ $prefix$$short_name$_MAX = $prefix$$max_name$;\n"); + + if (generate_array_size_) { + printer->Print(vars, + "const int $prefix$$short_name$_ARRAYSIZE = " + "$prefix$$short_name$_MAX + 1;\n\n"); + } if (HasDescriptorMethods(descriptor_->file())) { printer->Print(vars, @@ -123,6 +146,7 @@ void EnumGenerator:: GenerateGetEnumDescriptorSpecializations(io::Printer* printer) { if (HasDescriptorMethods(descriptor_->file())) { printer->Print( + "template <> struct is_proto_enum< $classname$> : ::google::protobuf::internal::true_type {};\n" "template <>\n" "inline const EnumDescriptor* GetEnumDescriptor< $classname$>() {\n" " return $classname$_descriptor();\n" @@ -150,9 +174,12 @@ void EnumGenerator::GenerateSymbolImports(io::Printer* printer) { "static const $nested_name$ $nested_name$_MIN =\n" " $classname$_$nested_name$_MIN;\n" "static const $nested_name$ $nested_name$_MAX =\n" - " $classname$_$nested_name$_MAX;\n" - "static const int $nested_name$_ARRAYSIZE =\n" - " $classname$_$nested_name$_ARRAYSIZE;\n"); + " $classname$_$nested_name$_MAX;\n"); + if (generate_array_size_) { + printer->Print(vars, + "static const int $nested_name$_ARRAYSIZE =\n" + " $classname$_$nested_name$_ARRAYSIZE;\n"); + } if (HasDescriptorMethods(descriptor_->file())) { printer->Print(vars, @@ -218,7 +245,7 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { iter != numbers.end(); ++iter) { printer->Print( " case $number$:\n", - "number", SimpleItoa(*iter)); + "number", Int32ToString(*iter)); } printer->Print(vars, @@ -245,8 +272,11 @@ void EnumGenerator::GenerateMethods(io::Printer* printer) { } printer->Print(vars, "const $classname$ $parent$::$nested_name$_MIN;\n" - "const $classname$ $parent$::$nested_name$_MAX;\n" - "const int $parent$::$nested_name$_ARRAYSIZE;\n"); + "const $classname$ $parent$::$nested_name$_MAX;\n"); + if (generate_array_size_) { + printer->Print(vars, + "const int $parent$::$nested_name$_ARRAYSIZE;\n"); + } printer->Print("#endif // _MSC_VER\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum.h b/src/google/protobuf/compiler/cpp/cpp_enum.h index 2e85a0bd..98cbdf69 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum.h @@ -89,6 +89,8 @@ class EnumGenerator { const EnumDescriptor* descriptor_; string classname_; Options options_; + // whether to generate the *_ARRAYSIZE constant. + bool generate_array_size_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc index 6e1620d4..2723c04a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.cc @@ -51,7 +51,8 @@ void SetEnumVariables(const FieldDescriptor* descriptor, SetCommonFieldVariables(descriptor, variables, options); const EnumValueDescriptor* default_value = descriptor->default_value_enum(); (*variables)["type"] = ClassName(descriptor->enum_type(), true); - (*variables)["default"] = SimpleItoa(default_value->number()); + (*variables)["default"] = Int32ToString(default_value->number()); + (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -83,12 +84,14 @@ void EnumFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_);\n" "}\n" "inline void $classname$::set_$name$($type$ value) {\n" " assert($type$_IsValid(value));\n" " set_has_$name$();\n" " $name$_ = value;\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n"); } @@ -121,10 +124,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " input, &value)));\n" "if ($type$_IsValid(value)) {\n" " set_$name$(static_cast< $type$ >(value));\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print(variables_, "} else {\n" " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } else { + printer->Print( + "} else {\n" + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(value);\n"); } printer->Print(variables_, "}\n"); @@ -153,6 +161,52 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== +EnumOneofFieldGenerator:: +EnumOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : EnumFieldGenerator(descriptor, options) { + SetCommonOneofFieldVariables(descriptor, &variables_); +} + +EnumOneofFieldGenerator::~EnumOneofFieldGenerator() {} + +void EnumOneofFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $classname$::$name$() const {\n" + " if (has_$name$()) {\n" + " return static_cast< $type$ >($oneof_prefix$$name$_);\n" + " }\n" + " return static_cast< $type$ >($default$);\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + " assert($type$_IsValid(value));\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " }\n" + " $oneof_prefix$$name$_ = value;\n" + "}\n"); +} + +void EnumOneofFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); +} + +void EnumOneofFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + // Don't print any swapping code. Swapping the union will swap this field. +} + +void EnumOneofFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + printer->Print(variables_, + " $classname$_default_oneof_instance_->$name$_ = $default$;\n"); +} + +// =================================================================== + RepeatedEnumFieldGenerator:: RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options) @@ -166,7 +220,8 @@ void RepeatedEnumFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::google::protobuf::RepeatedField $name$_;\n"); - if (descriptor_->options().packed() && HasGeneratedMethods(descriptor_->file())) { + if (descriptor_->options().packed() + && HasGeneratedMethods(descriptor_->file())) { printer->Print(variables_, "mutable int _$name$_cached_byte_size_;\n"); } @@ -187,23 +242,28 @@ void RepeatedEnumFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return static_cast< $type$ >($name$_.Get(index));\n" "}\n" "inline void $classname$::set_$name$(int index, $type$ value) {\n" " assert($type$_IsValid(value));\n" " $name$_.Set(index, value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::add_$name$($type$ value) {\n" " assert($type$_IsValid(value));\n" " $name$_.Add(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedField&\n" "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedField*\n" "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } @@ -238,10 +298,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { " input, &value)));\n" "if ($type$_IsValid(value)) {\n" " add_$name$(static_cast< $type$ >(value));\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print(variables_, "} else {\n" " mutable_unknown_fields()->AddVarint($number$, value);\n"); + } else { + printer->Print( + "} else {\n" + " unknown_fields_stream.WriteVarint32(tag);\n" + " unknown_fields_stream.WriteVarint32(value);\n"); } printer->Print("}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_enum_field.h b/src/google/protobuf/compiler/cpp/cpp_enum_field.h index 65770083..1da1623a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_enum_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_enum_field.h @@ -63,13 +63,30 @@ class EnumFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); }; +class EnumOneofFieldGenerator : public EnumFieldGenerator { + public: + explicit EnumOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~EnumOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumOneofFieldGenerator); +}; + class RepeatedEnumFieldGenerator : public FieldGenerator { public: explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, diff --git a/src/google/protobuf/compiler/cpp/cpp_field.cc b/src/google/protobuf/compiler/cpp/cpp_field.cc index 0786176b..beea8bac 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_field.cc @@ -33,6 +33,8 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include + #include #include #include @@ -68,6 +70,12 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, (*variables)["cppget"] = "Get"; } +void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, + map* variables) { + (*variables)["oneof_prefix"] = descriptor->containing_oneof()->name() + "_."; + (*variables)["oneof_name"] = descriptor->containing_oneof()->name(); +} + FieldGenerator::~FieldGenerator() {} void FieldGenerator:: @@ -84,8 +92,9 @@ GenerateMergeFromCodedStreamWithPacking(io::Printer* printer) const { FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor, const Options& options) - : descriptor_(descriptor), - field_generators_(new scoped_ptr[descriptor->field_count()]) { + : descriptor_(descriptor), + field_generators_( + new scoped_ptr[descriptor->field_count()]) { // Construct all the FieldGenerators. for (int i = 0; i < descriptor->field_count(); i++) { field_generators_[i].reset(MakeGenerator(descriptor->field(i), options)); @@ -109,6 +118,21 @@ FieldGenerator* FieldGeneratorMap::MakeGenerator(const FieldDescriptor* field, default: return new RepeatedPrimitiveFieldGenerator(field, options); } + } else if (field->containing_oneof()) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + return new MessageOneofFieldGenerator(field, options); + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // StringOneofFieldGenerator handles unknown ctypes. + case FieldOptions::STRING: + return new StringOneofFieldGenerator(field, options); + } + case FieldDescriptor::CPPTYPE_ENUM: + return new EnumOneofFieldGenerator(field, options); + default: + return new PrimitiveOneofFieldGenerator(field, options); + } } else { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_MESSAGE: diff --git a/src/google/protobuf/compiler/cpp/cpp_field.h b/src/google/protobuf/compiler/cpp/cpp_field.h index f7d99b15..e4340672 100644 --- a/src/google/protobuf/compiler/cpp/cpp_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_field.h @@ -36,9 +36,9 @@ #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__ #include +#include #include -#include #include #include @@ -61,6 +61,9 @@ void SetCommonFieldVariables(const FieldDescriptor* descriptor, map* variables, const Options& options); +void SetCommonOneofFieldVariables(const FieldDescriptor* descriptor, + map* variables); + class FieldGenerator { public: FieldGenerator() {} @@ -71,6 +74,11 @@ class FieldGenerator { // class. virtual void GeneratePrivateMembers(io::Printer* printer) const = 0; + // Generate static default variable for this field. These are placed inside + // the message class. Most field types don't need this, so the default + // implementation is empty. + virtual void GenerateStaticMembers(io::Printer* printer) const {} + // Generate prototypes for all of the accessor functions related to this // field. These are placed inside the class definition. virtual void GenerateAccessorDeclarations(io::Printer* printer) const = 0; diff --git a/src/google/protobuf/compiler/cpp/cpp_file.cc b/src/google/protobuf/compiler/cpp/cpp_file.cc index 3d869a37..f7f2cdda 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.cc +++ b/src/google/protobuf/compiler/cpp/cpp_file.cc @@ -33,6 +33,9 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include +#include + #include #include #include @@ -50,18 +53,17 @@ namespace cpp { // =================================================================== -FileGenerator::FileGenerator(const FileDescriptor* file, - const Options& options) - : file_(file), - message_generators_( - new scoped_ptr[file->message_type_count()]), - enum_generators_( - new scoped_ptr[file->enum_type_count()]), - service_generators_( - new scoped_ptr[file->service_count()]), - extension_generators_( - new scoped_ptr[file->extension_count()]), - options_(options) { +FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options) + : file_(file), + message_generators_( + new scoped_ptr[file->message_type_count()]), + enum_generators_( + new scoped_ptr[file->enum_type_count()]), + service_generators_( + new scoped_ptr[file->service_count()]), + extension_generators_( + new scoped_ptr[file->extension_count()]), + options_(options) { for (int i = 0; i < file->message_type_count(); i++) { message_generators_[i].reset( @@ -153,19 +155,28 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { "#include \n"); } - if (HasUnknownFields(file_) && file_->message_type_count() > 0) { + if (UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { printer->Print( "#include \n"); } + set public_import_names; + for (int i = 0; i < file_->public_dependency_count(); i++) { + public_import_names.insert(file_->public_dependency(i)->name()); + } + for (int i = 0; i < file_->dependency_count(); i++) { + const string& name = file_->dependency(i)->name(); + bool public_import = (public_import_names.count(name) != 0); + + printer->Print( - "#include \"$dependency$.pb.h\"\n", - "dependency", StripProto(file_->dependency(i)->name())); + "#include \"$dependency$.pb.h\"$iwyu$\n", + "dependency", StripProto(name), + "iwyu", (public_import) ? " // IWYU pragma: export" : ""); } - printer->Print( "// @@protoc_insertion_point(includes)\n"); @@ -248,6 +259,7 @@ void FileGenerator::GenerateHeader(io::Printer* printer) { printer->Print(kThickSeparator); printer->Print("\n"); + // Generate class inline methods. for (int i = 0; i < file_->message_type_count(); i++) { if (i > 0) { @@ -317,6 +329,12 @@ void FileGenerator::GenerateSource(io::Printer* printer) { "filename", file_->name(), "basename", StripProto(file_->name())); + // Unknown fields implementation in lite mode uses StringOutputStream + if (!UseUnknownFieldSet(file_) && file_->message_type_count() > 0) { + printer->Print( + "#include \n"); + } + if (HasDescriptorMethods(file_)) { printer->Print( "#include \n" @@ -542,17 +560,12 @@ void FileGenerator::GenerateBuildDescriptors(io::Printer* printer) { for (int i = 0; i < file_->dependency_count(); i++) { const FileDescriptor* dependency = file_->dependency(i); // Print the namespace prefix for the dependency. - vector dependency_package_parts; - SplitStringUsing(dependency->package(), ".", &dependency_package_parts); - printer->Print("::"); - for (int j = 0; j < dependency_package_parts.size(); j++) { - printer->Print("$name$::", - "name", dependency_package_parts[j]); - } + string add_desc_name = QualifiedFileLevelSymbol( + dependency->package(), GlobalAddDescriptorsName(dependency->name())); // Call its AddDescriptors function. printer->Print( "$name$();\n", - "name", GlobalAddDescriptorsName(dependency->name())); + "name", add_desc_name); } if (HasDescriptorMethods(file_)) { diff --git a/src/google/protobuf/compiler/cpp/cpp_file.h b/src/google/protobuf/compiler/cpp/cpp_file.h index 2deefaa8..07970971 100644 --- a/src/google/protobuf/compiler/cpp/cpp_file.h +++ b/src/google/protobuf/compiler/cpp/cpp_file.h @@ -35,6 +35,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__ +#include #include #include #include @@ -85,7 +86,6 @@ class FileGenerator { // E.g. if the package is foo.bar, package_parts_ is {"foo", "bar"}. vector package_parts_; - const Options options_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.cc b/src/google/protobuf/compiler/cpp/cpp_generator.cc index 1813510b..a43e993b 100644 --- a/src/google/protobuf/compiler/cpp/cpp_generator.cc +++ b/src/google/protobuf/compiler/cpp/cpp_generator.cc @@ -35,6 +35,7 @@ #include #include +#include #include #include @@ -102,7 +103,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Generate header. { scoped_ptr output( - generator_context->Open(basename + ".h")); + generator_context->Open(basename + ".h")); io::Printer printer(output.get(), '$'); file_generator.GenerateHeader(&printer); } @@ -110,7 +111,7 @@ bool CppGenerator::Generate(const FileDescriptor* file, // Generate cc file. { scoped_ptr output( - generator_context->Open(basename + ".cc")); + generator_context->Open(basename + ".cc")); io::Printer printer(output.get(), '$'); file_generator.GenerateSource(&printer); } diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc index 28911ab0..2c94b3a9 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc @@ -82,6 +82,22 @@ hash_set MakeKeywordsMap() { hash_set kKeywords = MakeKeywordsMap(); +// Returns whether the provided descriptor has an extension. This includes its +// nested types. +bool HasExtension(const Descriptor* descriptor) { + if (descriptor->extension_count() > 0) { + return true; + } + for (int i = 0; i < descriptor->nested_type_count(); ++i) { + if (HasExtension(descriptor->nested_type(i))) { + return true; + } + } + return false; +} + +} // namespace + string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { string result; // Note: I distrust ctype.h due to locales. @@ -107,22 +123,6 @@ string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { return result; } -// Returns whether the provided descriptor has an extension. This includes its -// nested types. -bool HasExtension(const Descriptor* descriptor) { - if (descriptor->extension_count() > 0) { - return true; - } - for (int i = 0; i < descriptor->nested_type_count(); ++i) { - if (HasExtension(descriptor->nested_type(i))) { - return true; - } - } - return false; -} - -} // namespace - const char kThickSeparator[] = "// ===================================================================\n"; const char kThinSeparator[] = @@ -256,27 +256,35 @@ const char* DeclaredTypeMethodName(FieldDescriptor::Type type) { return ""; } +string Int32ToString(int number) { + // gcc rejects the decimal form of kint32min. + if (number == kint32min) { + GOOGLE_COMPILE_ASSERT(kint32min == (~0x7fffffff), kint32min_value_error); + return "(~0x7fffffff)"; + } else { + return SimpleItoa(number); + } +} + +string Int64ToString(int64 number) { + // gcc rejects the decimal form of kint64min + if (number == kint64min) { + // Make sure we are in a 2's complement system. + GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(-0x8000000000000000), + kint64min_value_error); + return "GOOGLE_LONGLONG(-0x8000000000000000)"; + } + return "GOOGLE_LONGLONG(" + SimpleItoa(number) + ")"; +} + string DefaultValue(const FieldDescriptor* field) { switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32: - // gcc rejects the decimal form of kint32min and kint64min. - if (field->default_value_int32() == kint32min) { - // Make sure we are in a 2's complement system. - GOOGLE_COMPILE_ASSERT(kint32min == -0x80000000, kint32min_value_error); - return "-0x80000000"; - } - return SimpleItoa(field->default_value_int32()); + return Int32ToString(field->default_value_int32()); case FieldDescriptor::CPPTYPE_UINT32: return SimpleItoa(field->default_value_uint32()) + "u"; case FieldDescriptor::CPPTYPE_INT64: - // See the comments for CPPTYPE_INT32. - if (field->default_value_int64() == kint64min) { - // Make sure we are in a 2's complement system. - GOOGLE_COMPILE_ASSERT(kint64min == GOOGLE_LONGLONG(-0x8000000000000000), - kint64min_value_error); - return "GOOGLE_LONGLONG(-0x8000000000000000)"; - } - return "GOOGLE_LONGLONG(" + SimpleItoa(field->default_value_int64()) + ")"; + return Int64ToString(field->default_value_int64()); case FieldDescriptor::CPPTYPE_UINT64: return "GOOGLE_ULONGLONG(" + SimpleItoa(field->default_value_uint64())+ ")"; case FieldDescriptor::CPPTYPE_DOUBLE: { @@ -319,7 +327,7 @@ string DefaultValue(const FieldDescriptor* field) { return strings::Substitute( "static_cast< $0 >($1)", ClassName(field->enum_type(), true), - field->default_value_enum()->number()); + Int32ToString(field->default_value_enum()->number())); case FieldDescriptor::CPPTYPE_STRING: return "\"" + EscapeTrigraphs( CEscape(field->default_value_string())) + @@ -366,11 +374,39 @@ string GlobalShutdownFileName(const string& filename) { return "protobuf_ShutdownFile_" + FilenameIdentifier(filename); } +// Return the qualified C++ name for a file level symbol. +string QualifiedFileLevelSymbol(const string& package, const string& name) { + if (package.empty()) { + return StrCat("::", name); + } + return StrCat("::", DotsToColons(package), "::", name); +} + // Escape C++ trigraphs by escaping question marks to \? string EscapeTrigraphs(const string& to_escape) { return StringReplace(to_escape, "?", "\\?", true); } +// Escaped function name to eliminate naming conflict. +string SafeFunctionName(const Descriptor* descriptor, + const FieldDescriptor* field, + const string& prefix) { + // Do not use FieldName() since it will escape keywords. + string name = field->name(); + LowerString(&name); + string function_name = prefix + name; + if (descriptor->FindFieldByName(function_name)) { + // Single underscore will also make it conflicting with the private data + // member. We use double underscore to escape function names. + function_name.append("__"); + } else if (kKeywords.count(name) > 0) { + // If the field name is a keyword, we append the underscore back to keep it + // consistent with other function names. + function_name.append("_"); + } + return function_name; +} + bool StaticInitializersForced(const FileDescriptor* file) { if (HasDescriptorMethods(file) || file->extension_count() > 0) { return true; @@ -432,6 +468,26 @@ bool HasEnumDefinitions(const FileDescriptor* file) { return false; } +bool IsStringOrMessage(const FieldDescriptor* field) { + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_INT32: + case FieldDescriptor::CPPTYPE_INT64: + case FieldDescriptor::CPPTYPE_UINT32: + case FieldDescriptor::CPPTYPE_UINT64: + case FieldDescriptor::CPPTYPE_DOUBLE: + case FieldDescriptor::CPPTYPE_FLOAT: + case FieldDescriptor::CPPTYPE_BOOL: + case FieldDescriptor::CPPTYPE_ENUM: + return false; + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + return true; + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h index 526e19cc..27444d5a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_helpers.h +++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h @@ -103,6 +103,12 @@ const char* PrimitiveTypeName(FieldDescriptor::CppType type); // methods of WireFormat. For example, TYPE_INT32 becomes "Int32". const char* DeclaredTypeMethodName(FieldDescriptor::Type type); +// Return the code that evaluates to the number when compiled. +string Int32ToString(int number); + +// Return the code that evaluates to the number when compiled. +string Int64ToString(int64 number); + // Get code that evaluates to the field's default value. string DefaultValue(const FieldDescriptor* field); @@ -115,14 +121,23 @@ string GlobalAddDescriptorsName(const string& filename); // Return the name of the AssignDescriptors() function for a given file. string GlobalAssignDescriptorsName(const string& filename); +// Return the qualified C++ name for a file level symbol. +string QualifiedFileLevelSymbol(const string& package, const string& name); + // Return the name of the ShutdownFile() function for a given file. string GlobalShutdownFileName(const string& filename); // Escape C++ trigraphs by escaping question marks to \? string EscapeTrigraphs(const string& to_escape); -// Do message classes in this file keep track of unknown fields? -inline bool HasUnknownFields(const FileDescriptor* file) { +// Escaped function name to eliminate naming conflict. +string SafeFunctionName(const Descriptor* descriptor, + const FieldDescriptor* field, + const string& prefix); + +// Do message classes in this file use UnknownFieldSet? +// Otherwise, messages will store unknown fields in a string +inline bool UseUnknownFieldSet(const FileDescriptor* file) { return file->options().optimize_for() != FileOptions::LITE_RUNTIME; } @@ -178,6 +193,11 @@ void PrintHandlingOptionalStaticInitializers( const char* without_static_init); +// Returns true if the field's CPPTYPE is string or message. +bool IsStringOrMessage(const FieldDescriptor* field); + +string UnderscoresToCamelCase(const string& input, bool cap_next_letter); + } // namespace cpp } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/cpp/cpp_message.cc b/src/google/protobuf/compiler/cpp/cpp_message.cc index 1ea4f13d..962ff535 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message.cc @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include #include #include @@ -74,15 +76,6 @@ struct FieldOrderingByNumber { } }; -const char* kWireTypeNames[] = { - "VARINT", - "FIXED64", - "LENGTH_DELIMITED", - "START_GROUP", - "END_GROUP", - "FIXED32", -}; - // Sort the fields of the given Descriptor by number into a new[]'d array // and return it. const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { @@ -255,8 +248,9 @@ void OptimizePadding(vector* fields) { aligned_to_4.push_back(field_group); } // Sort by preferred location to keep fields as close to their original - // location as possible. - sort(aligned_to_4.begin(), aligned_to_4.end()); + // location as possible. Using stable_sort ensures that the output is + // consistent across runs. + stable_sort(aligned_to_4.begin(), aligned_to_4.end()); // Now group fields aligned to 4 bytes (or the 4-field groups created above) // into pairs, and treat those like a single field aligned to 8 bytes. @@ -271,9 +265,8 @@ void OptimizePadding(vector* fields) { } aligned_to_8.push_back(field_group); } - // Sort by preferred location to keep fields as close to their original - // location as possible. - sort(aligned_to_8.begin(), aligned_to_8.end()); + // Sort by preferred location. + stable_sort(aligned_to_8.begin(), aligned_to_8.end()); // Now pull out all the FieldDescriptors in order. fields->clear(); @@ -284,22 +277,26 @@ void OptimizePadding(vector* fields) { } } +string MessageTypeProtoName(const FieldDescriptor* field) { + return field->message_type()->full_name(); +} + } // =================================================================== MessageGenerator::MessageGenerator(const Descriptor* descriptor, const Options& options) - : descriptor_(descriptor), - classname_(ClassName(descriptor, false)), - options_(options), - field_generators_(descriptor, options), - nested_generators_(new scoped_ptr[ - descriptor->nested_type_count()]), - enum_generators_(new scoped_ptr[ - descriptor->enum_type_count()]), - extension_generators_(new scoped_ptr[ - descriptor->extension_count()]) { + : descriptor_(descriptor), + classname_(ClassName(descriptor, false)), + options_(options), + field_generators_(descriptor, options), + nested_generators_(new scoped_ptr< + MessageGenerator>[descriptor->nested_type_count()]), + enum_generators_( + new scoped_ptr[descriptor->enum_type_count()]), + extension_generators_(new scoped_ptr< + ExtensionGenerator>[descriptor->extension_count()]) { for (int i = 0; i < descriptor->nested_type_count(); i++) { nested_generators_[i].reset( @@ -383,6 +380,14 @@ GenerateFieldAccessorDeclarations(io::Printer* printer) { "GOOGLE_PROTOBUF_EXTENSION_ACCESSORS($classname$)\n", "classname", classname_); } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "inline $camel_oneof_name$Case $oneof_name$_case() const;\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true), + "oneof_name", descriptor_->oneof_decl(i)->name()); + } } void MessageGenerator:: @@ -403,6 +408,18 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { "inline int $classname$::$name$_size() const {\n" " return $name$_.size();\n" "}\n"); + } else if (field->containing_oneof()) { + // Singular field in a oneof + vars["field_name"] = UnderscoresToCamelCase(field->name(), true); + vars["oneof_name"] = field->containing_oneof()->name(); + vars["oneof_index"] = SimpleItoa(field->containing_oneof()->index()); + printer->Print(vars, + "inline bool $classname$::has_$name$() const {\n" + " return $oneof_name$_case() == k$field_name$;\n" + "}\n" + "inline void $classname$::set_has_$name$() {\n" + " _oneof_case_[$oneof_index$] = k$field_name$;\n" + "}\n"); } else { // Singular field. char buffer[kFastToBufferSize]; @@ -426,14 +443,27 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { "inline void $classname$::clear_$name$() {\n"); printer->Indent(); - field_generators_.get(field).GenerateClearingCode(printer); - printer->Outdent(); - if (!field->is_repeated()) { + if (field->containing_oneof()) { + // Clear this field only if it is the active field in this oneof, + // otherwise ignore printer->Print(vars, - " clear_has_$name$();\n"); + "if (has_$name$()) {\n"); + printer->Indent(); + field_generators_.get(field).GenerateClearingCode(printer); + printer->Print(vars, + "clear_has_$oneof_name$();\n"); + printer->Outdent(); + printer->Print("}\n"); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + if (!field->is_repeated()) { + printer->Print(vars, + "clear_has_$name$();\n"); + } } + printer->Outdent(); printer->Print("}\n"); // Generate type-specific accessors. @@ -441,6 +471,49 @@ GenerateFieldAccessorDefinitions(io::Printer* printer) { printer->Print("\n"); } + + // Generate has_$name$() and clear_has_$name$() functions for oneofs + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + map vars; + vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + vars["cap_oneof_name"] = + ToUpper(descriptor_->oneof_decl(i)->name()); + vars["classname"] = classname_; + printer->Print( + vars, + "inline bool $classname$::has_$oneof_name$() {\n" + " return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n" + "}\n" + "inline void $classname$::clear_has_$oneof_name$() {\n" + " _oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n" + "}\n"); + } +} + +// Helper for the code that emits the Clear() method. +static bool CanClearByZeroing(const FieldDescriptor* field) { + if (field->is_repeated() || field->is_extension()) return false; + switch (field->cpp_type()) { + case internal::WireFormatLite::CPPTYPE_ENUM: + return field->default_value_enum()->number() == 0; + case internal::WireFormatLite::CPPTYPE_INT32: + return field->default_value_int32() == 0; + case internal::WireFormatLite::CPPTYPE_INT64: + return field->default_value_int64() == 0; + case internal::WireFormatLite::CPPTYPE_UINT32: + return field->default_value_uint32() == 0; + case internal::WireFormatLite::CPPTYPE_UINT64: + return field->default_value_uint64() == 0; + case internal::WireFormatLite::CPPTYPE_FLOAT: + return field->default_value_float() == 0; + case internal::WireFormatLite::CPPTYPE_DOUBLE: + return field->default_value_double() == 0; + case internal::WireFormatLite::CPPTYPE_BOOL: + return field->default_value_bool() == false; + default: + return false; + } } void MessageGenerator:: @@ -455,6 +528,7 @@ GenerateClassDefinition(io::Printer* printer) { map vars; vars["classname"] = classname_; vars["field_count"] = SimpleItoa(descriptor_->field_count()); + vars["oneof_decl_count"] = SimpleItoa(descriptor_->oneof_decl_count()); if (options_.dllexport_decl.empty()) { vars["dllexport"] = ""; } else { @@ -479,7 +553,7 @@ GenerateClassDefinition(io::Printer* printer) { "}\n" "\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {\n" " return _unknown_fields_;\n" @@ -489,6 +563,16 @@ GenerateClassDefinition(io::Printer* printer) { " return &_unknown_fields_;\n" "}\n" "\n"); + } else { + printer->Print( + "inline const ::std::string& unknown_fields() const {\n" + " return _unknown_fields_;\n" + "}\n" + "\n" + "inline ::std::string* mutable_unknown_fields() {\n" + " return &_unknown_fields_;\n" + "}\n" + "\n"); } // Only generate this member if it's not disabled. @@ -502,6 +586,33 @@ GenerateClassDefinition(io::Printer* printer) { "static const $classname$& default_instance();\n" "\n"); + // Generate enum values for every field in oneofs. One list is generated for + // each oneof with an additional *_NOT_SET value. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "enum $camel_oneof_name$Case {\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + printer->Print( + "k$field_name$ = $field_number$,\n", + "field_name", + UnderscoresToCamelCase( + descriptor_->oneof_decl(i)->field(j)->name(), true), + "field_number", + SimpleItoa(descriptor_->oneof_decl(i)->field(j)->number())); + } + printer->Print( + "$cap_oneof_name$_NOT_SET = 0,\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "};\n" + "\n"); + } + if (!StaticInitializersForced(descriptor_->file())) { printer->Print(vars, "#ifdef GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER\n" @@ -545,20 +656,50 @@ GenerateClassDefinition(io::Printer* printer) { " ::google::protobuf::io::CodedInputStream* input);\n" "void SerializeWithCachedSizes(\n" " ::google::protobuf::io::CodedOutputStream* output) const;\n"); + // DiscardUnknownFields() is implemented in message.cc using reflections. We + // need to implement this function in generated code for messages. + if (!UseUnknownFieldSet(descriptor_->file())) { + printer->Print( + "void DiscardUnknownFields();\n"); + } if (HasFastArraySerialization(descriptor_->file())) { printer->Print( "::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;\n"); } } - printer->Print(vars, + // Check all FieldDescriptors including those in oneofs to estimate + // whether ::std::string is likely to be used, and depending on that + // estimate, set uses_string_ to true or false. That contols + // whether to force initialization of empty_string_ in SharedCtor(). + // It's often advantageous to do so to keep "is empty_string_ + // inited?" code from appearing all over the place. + vector descriptors; + for (int i = 0; i < descriptor_->field_count(); i++) { + descriptors.push_back(descriptor_->field(i)); + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + descriptors.push_back(descriptor_->oneof_decl(i)->field(j)); + } + } + uses_string_ = false; + for (int i = 0; i < descriptors.size(); i++) { + const FieldDescriptor* field = descriptors[i]; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: uses_string_ = true; break; + } + } + } + + printer->Print( "int GetCachedSize() const { return _cached_size_; }\n" "private:\n" "void SharedCtor();\n" "void SharedDtor();\n" "void SetCachedSize(int size) const;\n" - "public:\n" - "\n"); + "public:\n"); if (HasDescriptorMethods(descriptor_->file())) { printer->Print( @@ -621,13 +762,44 @@ GenerateClassDefinition(io::Printer* printer) { printer->Print( "inline void set_has_$name$();\n", "name", FieldName(descriptor_->field(i))); - printer->Print( - "inline void clear_has_$name$();\n", - "name", FieldName(descriptor_->field(i))); + if (!descriptor_->field(i)->containing_oneof()) { + printer->Print( + "inline void clear_has_$name$();\n", + "name", FieldName(descriptor_->field(i))); + } } } printer->Print("\n"); + // Generate oneof function declarations + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "inline bool has_$oneof_name$();\n" + "void clear_$oneof_name$();\n" + "inline void clear_has_$oneof_name$();\n\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + // Prepare decls for _cached_size_ and _has_bits_. Their position in the + // output will be determined later. + + bool need_to_emit_cached_size = true; + // TODO(kenton): Make _cached_size_ an atomic when C++ supports it. + const string cached_size_decl = "mutable int _cached_size_;\n"; + + // TODO(jieluo) - Optimize _has_bits_ for repeated and oneof fields. + size_t sizeof_has_bits = (descriptor_->field_count() + 31) / 32 * 4; + if (descriptor_->field_count() == 0) { + // Zero-size arrays aren't technically allowed, and MSVC in particular + // doesn't like them. We still need to declare these arrays to make + // other code compile. Since this is an uncommon case, we'll just declare + // them with size 1 and waste some space. Oh well. + sizeof_has_bits = 4; + } + const string has_bits_decl = sizeof_has_bits == 0 ? "" : + "::google::protobuf::uint32 _has_bits_[" + SimpleItoa(sizeof_has_bits / 4) + "];\n"; + + // To minimize padding, data members are divided into three sections: // (1) members assumed to align to 8 bytes // (2) members corresponding to message fields, re-ordered to optimize @@ -642,42 +814,92 @@ GenerateClassDefinition(io::Printer* printer) { "\n"); } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "::google::protobuf::UnknownFieldSet _unknown_fields_;\n" "\n"); + } else { + printer->Print( + "::std::string _unknown_fields_;\n" + "\n"); + } + + // _has_bits_ is frequently accessed, so to reduce code size and improve + // speed, it should be close to the start of the object. But, try not to + // waste space:_has_bits_ by itself always makes sense if its size is a + // multiple of 8, but, otherwise, maybe _has_bits_ and cached_size_ together + // will work well. + printer->Print(has_bits_decl.c_str()); + if ((sizeof_has_bits % 8) != 0) { + printer->Print(cached_size_decl.c_str()); + need_to_emit_cached_size = false; } // Field members: + // List fields which doesn't belong to any oneof vector fields; + hash_map fieldname_to_chunk; for (int i = 0; i < descriptor_->field_count(); i++) { - fields.push_back(descriptor_->field(i)); + if (!descriptor_->field(i)->containing_oneof()) { + const FieldDescriptor* field = descriptor_->field(i); + fields.push_back(field); + fieldname_to_chunk[FieldName(field)] = i / 8; + } } OptimizePadding(&fields); + // Emit some private and static members + runs_of_fields_ = vector< vector >(1); for (int i = 0; i < fields.size(); ++i) { - field_generators_.get(fields[i]).GeneratePrivateMembers(printer); + const FieldDescriptor* field = fields[i]; + const FieldGenerator& generator = field_generators_.get(field); + generator.GenerateStaticMembers(printer); + generator.GeneratePrivateMembers(printer); + if (CanClearByZeroing(field)) { + const string& fieldname = FieldName(field); + if (!runs_of_fields_.back().empty() && + (fieldname_to_chunk[runs_of_fields_.back().back()] != + fieldname_to_chunk[fieldname])) { + runs_of_fields_.push_back(vector()); + } + runs_of_fields_.back().push_back(fieldname); + } else if (!runs_of_fields_.back().empty()) { + runs_of_fields_.push_back(vector()); + } + } + + // For each oneof generate a union + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "union $camel_oneof_name$Union {\n", + "camel_oneof_name", + UnderscoresToCamelCase(descriptor_->oneof_decl(i)->name(), true)); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + field_generators_.get(descriptor_->oneof_decl(i)-> + field(j)).GeneratePrivateMembers(printer); + } + printer->Outdent(); + printer->Print( + "} $oneof_name$_;\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + field_generators_.get(descriptor_->oneof_decl(i)-> + field(j)).GenerateStaticMembers(printer); + } } // Members assumed to align to 4 bytes: - // TODO(kenton): Make _cached_size_ an atomic when C++ supports it. - printer->Print( - "\n" - "mutable int _cached_size_;\n"); + if (need_to_emit_cached_size) { + printer->Print(cached_size_decl.c_str()); + need_to_emit_cached_size = false; + } - // Generate _has_bits_. - if (descriptor_->field_count() > 0) { + // Generate _oneof_case_. + if (descriptor_->oneof_decl_count() > 0) { printer->Print(vars, - "::google::protobuf::uint32 _has_bits_[($field_count$ + 31) / 32];\n" - "\n"); - } else { - // Zero-size arrays aren't technically allowed, and MSVC in particular - // doesn't like them. We still need to declare these arrays to make - // other code compile. Since this is an uncommon case, we'll just declare - // them with size 1 and waste some space. Oh well. - printer->Print( - "::google::protobuf::uint32 _has_bits_[1];\n" + "::google::protobuf::uint32 _oneof_case_[$oneof_decl_count$];\n" "\n"); } @@ -710,6 +932,7 @@ GenerateClassDefinition(io::Printer* printer) { printer->Outdent(); printer->Print(vars, "};"); + GOOGLE_DCHECK(!need_to_emit_cached_size); } void MessageGenerator:: @@ -721,6 +944,23 @@ GenerateInlineMethods(io::Printer* printer) { } GenerateFieldAccessorDefinitions(printer); + + // Generate oneof_case() functions. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + map vars; + vars["class_name"] = classname_; + vars["camel_oneof_name"] = UnderscoresToCamelCase( + descriptor_->oneof_decl(i)->name(), true); + vars["oneof_name"] = descriptor_->oneof_decl(i)->name(); + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + printer->Print( + vars, + "inline $class_name$::$camel_oneof_name$Case $class_name$::" + "$oneof_name$_case() const {\n" + " return $class_name$::$camel_oneof_name$Case(" + "_oneof_case_[$oneof_index$]);\n" + "}\n"); + } } void MessageGenerator:: @@ -731,6 +971,25 @@ GenerateDescriptorDeclarations(io::Printer* printer) { " $name$_reflection_ = NULL;\n", "name", classname_); + // Generate oneof default instance for reflection usage. + if (descriptor_->oneof_decl_count() > 0) { + printer->Print("struct $name$OneofInstance {\n", + "name", classname_); + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print(" "); + if (IsStringOrMessage(field)) { + printer->Print("const "); + } + field_generators_.get(field).GeneratePrivateMembers(printer); + } + } + + printer->Print("}* $name$_default_oneof_instance_ = NULL;\n", + "name", classname_); + } + for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateDescriptorDeclarations(printer); } @@ -783,6 +1042,14 @@ GenerateDescriptorInitializer(io::Printer* printer, int index) { printer->Print(vars, " -1,\n"); } + + if (descriptor_->oneof_decl_count() > 0) { + printer->Print(vars, + " $classname$_default_oneof_instance_,\n" + " GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(" + "$classname$, _oneof_case_[0]),\n"); + } + printer->Print( " ::google::protobuf::DescriptorPool::generated_pool(),\n"); printer->Print(vars, @@ -830,6 +1097,13 @@ GenerateDefaultInstanceAllocator(io::Printer* printer) { "$classname$::default_instance_ = new $classname$();\n", "classname", classname_); + if ((descriptor_->oneof_decl_count() > 0) && + HasDescriptorMethods(descriptor_->file())) { + printer->Print( + "$classname$_default_oneof_instance_ = new $classname$OneofInstance;\n", + "classname", classname_); + } + // Handle nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { nested_generators_[i]->GenerateDefaultInstanceAllocator(printer); @@ -861,6 +1135,11 @@ GenerateShutdownCode(io::Printer* printer) { "classname", classname_); if (HasDescriptorMethods(descriptor_->file())) { + if (descriptor_->oneof_decl_count() > 0) { + printer->Print( + "delete $classname$_default_oneof_instance_;\n", + "classname", classname_); + } printer->Print( "delete $classname$_reflection_;\n", "classname", classname_); @@ -918,6 +1197,11 @@ GenerateClassMethods(io::Printer* printer) { GenerateStructors(printer); printer->Print("\n"); + if (descriptor_->oneof_decl_count() > 0) { + GenerateOneofClear(printer); + printer->Print("\n"); + } + if (HasGeneratedMethods(descriptor_->file())) { GenerateClear(printer); printer->Print("\n"); @@ -977,15 +1261,33 @@ GenerateOffsets(io::Printer* printer) { printer->Print( "static const int $classname$_offsets_[$field_count$] = {\n", "classname", classname_, - "field_count", SimpleItoa(max(1, descriptor_->field_count()))); + "field_count", SimpleItoa(max( + 1, descriptor_->field_count() + descriptor_->oneof_decl_count()))); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + if (field->containing_oneof()) { + printer->Print( + "PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(" + "$classname$_default_oneof_instance_, $name$_),\n", + "classname", classname_, + "name", FieldName(field)); + } else { + printer->Print( + "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, " + "$name$_),\n", + "classname", classname_, + "name", FieldName(field)); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); printer->Print( "GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET($classname$, $name$_),\n", "classname", classname_, - "name", FieldName(field)); + "name", oneof->name()); } printer->Outdent(); @@ -999,17 +1301,26 @@ GenerateSharedConstructorCode(io::Printer* printer) { "classname", classname_); printer->Indent(); - printer->Print( - "_cached_size_ = 0;\n"); + printer->Print(StrCat( + uses_string_ ? "::google::protobuf::internal::GetEmptyString();\n" : "", + "_cached_size_ = 0;\n").c_str()); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateConstructorCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateConstructorCode(printer); + } } printer->Print( "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "clear_has_$oneof_name$();\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + printer->Outdent(); printer->Print("}\n\n"); } @@ -1020,10 +1331,21 @@ GenerateSharedDestructorCode(io::Printer* printer) { "void $classname$::SharedDtor() {\n", "classname", classname_); printer->Indent(); - // Write the destructors for each field. + // Write the destructors for each field except oneof members. for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateDestructorCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateDestructorCode(printer); + } + } + + // Generate code to destruct oneofs. Clearing should do the work. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "if (has_$oneof_name$()) {\n" + " clear_$oneof_name$();\n" + "}\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); } PrintHandlingOptionalStaticInitializers( @@ -1042,8 +1364,12 @@ GenerateSharedDestructorCode(io::Printer* printer) { if (!field->is_repeated() && field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - printer->Print(" delete $name$_;\n", - "name", FieldName(field)); + // Skip oneof members + if (!field->containing_oneof()) { + printer->Print( + " delete $name$_;\n", + "name", FieldName(field)); + } } } @@ -1063,9 +1389,11 @@ GenerateStructors(io::Printer* printer) { "$classname$::$classname$()\n" " : $superclass$() {\n" " SharedCtor();\n" + " // @@protoc_insertion_point(constructor:$full_name$)\n" "}\n", "classname", classname_, - "superclass", superclass); + "superclass", superclass, + "full_name", descriptor_->full_name()); printer->Print( "\n" @@ -1082,7 +1410,14 @@ GenerateStructors(io::Printer* printer) { const FieldDescriptor* field = descriptor_->field(i); if (!field->is_repeated() && - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && + (field->containing_oneof() == NULL || + HasDescriptorMethods(descriptor_->file()))) { + string name; + if (field->containing_oneof()) { + name = classname_ + "_default_oneof_instance_->"; + } + name += FieldName(field); PrintHandlingOptionalStaticInitializers( descriptor_->file(), printer, // With static initializers. @@ -1091,8 +1426,12 @@ GenerateStructors(io::Printer* printer) { " $name$_ = const_cast< $type$*>(\n" " $type$::internal_default_instance());\n", // Vars. - "name", FieldName(field), + "name", name, "type", FieldMessageTypeName(field)); + } else if (field->containing_oneof() && + HasDescriptorMethods(descriptor_->file())) { + field_generators_.get(descriptor_->field(i)) + .GenerateConstructorCode(printer); } } printer->Print( @@ -1105,10 +1444,12 @@ GenerateStructors(io::Printer* printer) { " : $superclass$() {\n" " SharedCtor();\n" " MergeFrom(from);\n" + " // @@protoc_insertion_point(copy_constructor:$full_name$)\n" "}\n" "\n", "classname", classname_, - "superclass", superclass); + "superclass", superclass, + "full_name", descriptor_->full_name()); // Generate the shared constructor code. GenerateSharedConstructorCode(printer); @@ -1116,10 +1457,12 @@ GenerateStructors(io::Printer* printer) { // Generate the destructor. printer->Print( "$classname$::~$classname$() {\n" + " // @@protoc_insertion_point(destructor:$full_name$)\n" " SharedDtor();\n" "}\n" "\n", - "classname", classname_); + "classname", classname_, + "full_name", descriptor_->full_name()); // Generate the shared destructor code. GenerateSharedDestructorCode(printer); @@ -1166,13 +1509,25 @@ GenerateStructors(io::Printer* printer) { "}\n" "\n" "$classname$* $classname$::default_instance_ = NULL;\n" - "\n" + "\n", + "classname", classname_); + + printer->Print( "$classname$* $classname$::New() const {\n" " return new $classname$;\n" "}\n", - "classname", classname_, - "adddescriptorsname", - GlobalAddDescriptorsName(descriptor_->file()->name())); + "classname", classname_); + +} + +// Return the number of bits set in n, a non-negative integer. +static int popcnt(uint32 n) { + int result = 0; + while (n != 0) { + result += (n & 1); + n = n / 2; + } + return result; } void MessageGenerator:: @@ -1181,64 +1536,133 @@ GenerateClear(io::Printer* printer) { "classname", classname_); printer->Indent(); - int last_index = -1; - + // Step 1: Extensions if (descriptor_->extension_range_count() > 0) { printer->Print("_extensions_.Clear();\n"); } + // Step 2: Everything but extensions, repeateds, unions. + // These are handled in chunks of 8. The first chunk is + // the non-extensions-non-repeateds-non-unions in + // descriptor_->field(0), descriptor_->field(1), ... descriptor_->field(7), + // and the second chunk is the same for + // descriptor_->field(8), descriptor_->field(9), ... descriptor_->field(15), + // etc. + set step2_indices; + hash_map fieldname_to_chunk; + hash_map memsets_for_chunk; + hash_map memset_field_count_for_chunk; + hash_set handled; // fields that appear anywhere in memsets_for_chunk + hash_map fields_mask_for_chunk; for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + if (!field->is_repeated() && !field->containing_oneof()) { + step2_indices.insert(i); + int chunk = i / 8; + fieldname_to_chunk[FieldName(field)] = chunk; + fields_mask_for_chunk[chunk] |= static_cast(1) << (i % 32); + } + } - if (!field->is_repeated()) { - // We can use the fact that _has_bits_ is a giant bitfield to our - // advantage: We can check up to 32 bits at a time for equality to - // zero, and skip the whole range if so. This can improve the speed - // of Clear() for messages which contain a very large number of - // optional fields of which only a few are used at a time. Here, - // we've chosen to check 8 bits at a time rather than 32. - if (i / 8 != last_index / 8 || last_index < 0) { - if (last_index >= 0) { - printer->Outdent(); - printer->Print("}\n"); - } - printer->Print( - "if (_has_bits_[$index$ / 32] & (0xffu << ($index$ % 32))) {\n", - "index", SimpleItoa(field->index())); - printer->Indent(); + // Step 2a: Greedily seek runs of fields that can be cleared by memset-to-0. + // The generated code uses two macros to help it clear runs of fields: + // OFFSET_OF_FIELD_ computes the offset (in bytes) of a field in the Message. + // ZR_ zeroes a non-empty range of fields via memset. + const char* macros = + "#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \\\n" + " &reinterpret_cast<$classname$*>(16)->f) - \\\n" + " reinterpret_cast(16))\n\n" + "#define ZR_(first, last) do { \\\n" + " size_t f = OFFSET_OF_FIELD_(first); \\\n" + " size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \\\n" + " ::memset(&first, 0, n); \\\n" + " } while (0)\n\n"; + for (int i = 0; i < runs_of_fields_.size(); i++) { + const vector& run = runs_of_fields_[i]; + if (run.size() < 2) continue; + const string& first_field_name = run[0]; + const string& last_field_name = run.back(); + int chunk = fieldname_to_chunk[run[0]]; + memsets_for_chunk[chunk].append( + "ZR_(" + first_field_name + "_, " + last_field_name + "_);\n"); + for (int j = 0; j < run.size(); j++) { + GOOGLE_DCHECK_EQ(chunk, fieldname_to_chunk[run[j]]); + handled.insert(run[j]); + } + memset_field_count_for_chunk[chunk] += run.size(); + } + const bool macros_are_needed = handled.size() > 0; + if (macros_are_needed) { + printer->Outdent(); + printer->Print(macros, + "classname", classname_); + printer->Indent(); + } + // Step 2b: Finish step 2, ignoring fields handled in step 2a. + int last_index = -1; + bool chunk_block_in_progress = false; + for (int i = 0; i < descriptor_->field_count(); i++) { + if (step2_indices.count(i) == 0) continue; + const FieldDescriptor* field = descriptor_->field(i); + const string fieldname = FieldName(field); + if (i / 8 != last_index / 8 || last_index < 0) { + // End previous chunk, if there was one. + if (chunk_block_in_progress) { + printer->Outdent(); + printer->Print("}\n"); + chunk_block_in_progress = false; } - last_index = i; - - // It's faster to just overwrite primitive types, but we should - // only clear strings and messages if they were set. - // TODO(kenton): Let the CppFieldGenerator decide this somehow. - bool should_check_bit = - field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || - field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; - - if (should_check_bit) { + // Start chunk. + const string& memsets = memsets_for_chunk[i / 8]; + uint32 mask = fields_mask_for_chunk[i / 8]; + int count = popcnt(mask); + if (count == 1 || + (count <= 4 && count == memset_field_count_for_chunk[i / 8])) { + // No "if" here because the chunk is trivial. + } else { printer->Print( - "if (has_$name$()) {\n", - "name", FieldName(field)); + "if (_has_bits_[$index$ / 32] & $mask$) {\n", + "index", SimpleItoa(i / 8 * 8), + "mask", SimpleItoa(mask)); printer->Indent(); + chunk_block_in_progress = true; } + printer->Print(memsets.c_str()); + } + last_index = i; + if (handled.count(fieldname) > 0) continue; + + // It's faster to just overwrite primitive types, but we should + // only clear strings and messages if they were set. + // TODO(kenton): Let the CppFieldGenerator decide this somehow. + bool should_check_bit = + field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE || + field->cpp_type() == FieldDescriptor::CPPTYPE_STRING; + + if (should_check_bit) { + printer->Print("if (has_$name$()) {\n", "name", fieldname); + printer->Indent(); + } - field_generators_.get(field).GenerateClearingCode(printer); + field_generators_.get(field).GenerateClearingCode(printer); - if (should_check_bit) { - printer->Outdent(); - printer->Print("}\n"); - } + if (should_check_bit) { + printer->Outdent(); + printer->Print("}\n"); } } - if (last_index >= 0) { + if (chunk_block_in_progress) { printer->Outdent(); printer->Print("}\n"); } + if (macros_are_needed) { + printer->Outdent(); + printer->Print("\n#undef OFFSET_OF_FIELD_\n#undef ZR_\n\n"); + printer->Indent(); + } - // Repeated fields don't use _has_bits_ so we clear them in a separate - // pass. + // Step 3: Repeated fields don't use _has_bits_; emit code to clear them here. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); @@ -1247,18 +1671,81 @@ GenerateClear(io::Printer* printer) { } } + // Step 4: Unions. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "clear_$oneof_name$();\n", + "oneof_name", descriptor_->oneof_decl(i)->name()); + } + + // Step 5: Everything else. printer->Print( "::memset(_has_bits_, 0, sizeof(_has_bits_));\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "mutable_unknown_fields()->Clear();\n"); + } else { + printer->Print( + "mutable_unknown_fields()->clear();\n"); } printer->Outdent(); printer->Print("}\n"); } +void MessageGenerator:: +GenerateOneofClear(io::Printer* printer) { + // Generated function clears the active field and union case (e.g. foo_case_). + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "void $classname$::clear_$oneofname$() {\n", + "classname", classname_, + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + printer->Print( + "switch($oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + // We clear only allocated objects in oneofs + if (!IsStringOrMessage(field)) { + printer->Print( + "// No need to clear\n"); + } else { + field_generators_.get(field).GenerateClearingCode(printer); + } + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n" + "_oneof_case_[$oneof_index$] = $cap_oneof_name$_NOT_SET;\n", + "oneof_index", SimpleItoa(i), + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n" + "\n"); + } +} + void MessageGenerator:: GenerateSwap(io::Printer* printer) { // Generate the Swap member function. @@ -1274,13 +1761,23 @@ GenerateSwap(io::Printer* printer) { field_generators_.get(field).GenerateSwappingCode(printer); } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "std::swap($oneof_name$_, other->$oneof_name$_);\n" + "std::swap(_oneof_case_[$i$], other->_oneof_case_[$i$]);\n", + "oneof_name", descriptor_->oneof_decl(i)->name(), + "i", SimpleItoa(i)); + } + for (int i = 0; i < (descriptor_->field_count() + 31) / 32; ++i) { printer->Print("std::swap(_has_bits_[$i$], other->_has_bits_[$i$]);\n", "i", SimpleItoa(i)); } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print("_unknown_fields_.Swap(&other->_unknown_fields_);\n"); + } else { + printer->Print("_unknown_fields_.swap(other->_unknown_fields_);\n"); } printer->Print("std::swap(_cached_size_, other->_cached_size_);\n"); if (descriptor_->extension_range_count() > 0) { @@ -1352,13 +1849,43 @@ GenerateMergeFrom(io::Printer* printer) { } } + // Merge oneof fields. Oneof field requires oneof case check. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + printer->Print( + "switch (from.$oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n"); + } + // Merge Optional and Required fields (after a _has_bit check). int last_index = -1; for (int i = 0; i < descriptor_->field_count(); ++i) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated()) { + if (!field->is_repeated() && !field->containing_oneof()) { // See above in GenerateClear for an explanation of this. if (i / 8 != last_index / 8 || last_index < 0) { if (last_index >= 0) { @@ -1394,9 +1921,12 @@ GenerateMergeFrom(io::Printer* printer) { printer->Print("_extensions_.MergeFrom(from._extensions_);\n"); } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "mutable_unknown_fields()->MergeFrom(from.unknown_fields());\n"); + } else { + printer->Print( + "mutable_unknown_fields()->append(from.unknown_fields());\n"); } printer->Outdent(); @@ -1465,14 +1995,39 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print( "bool $classname$::MergePartialFromCodedStream(\n" " ::google::protobuf::io::CodedInputStream* input) {\n" - "#define DO_(EXPRESSION) if (!(EXPRESSION)) return false\n" - " ::google::protobuf::uint32 tag;\n" - " while ((tag = input->ReadTag()) != 0) {\n", + "#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure\n" + " ::google::protobuf::uint32 tag;\n", "classname", classname_); + if (!UseUnknownFieldSet(descriptor_->file())) { + printer->Print( + " ::google::protobuf::io::StringOutputStream unknown_fields_string(\n" + " mutable_unknown_fields());\n" + " ::google::protobuf::io::CodedOutputStream unknown_fields_stream(\n" + " &unknown_fields_string);\n"); + } + + printer->Print( + " // @@protoc_insertion_point(parse_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + printer->Indent(); + printer->Print("for (;;) {\n"); printer->Indent(); + scoped_array ordered_fields( + SortFieldsByNumber(descriptor_)); + uint32 maxtag = descriptor_->field_count() == 0 ? 0 : + WireFormat::MakeTag(ordered_fields[descriptor_->field_count() - 1]); + const int kCutoff0 = 127; // fits in 1-byte varint + const int kCutoff1 = (127 << 7) + 127; // fits in 2-byte varint + printer->Print("::std::pair< ::google::protobuf::uint32, bool> p = " + "input->ReadTagWithCutoff($max$);\n" + "tag = p.first;\n" + "if (!p.second) goto handle_unusual;\n", + "max", SimpleItoa(maxtag <= kCutoff0 ? kCutoff0 : + (maxtag <= kCutoff1 ? kCutoff1 : + maxtag))); if (descriptor_->field_count() > 0) { // We don't even want to print the switch() if we have no fields because // MSVC dislikes switch() statements that contain only a default value. @@ -1482,14 +2037,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // of each case. However, this is actually a bit slower in practice as it // creates a jump table that is 8x larger and sparser, and meanwhile the // if()s are highly predictable. - printer->Print( - "switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {\n"); + printer->Print("switch (::google::protobuf::internal::WireFormatLite::" + "GetTagFieldNumber(tag)) {\n"); printer->Indent(); - scoped_array ordered_fields( - SortFieldsByNumber(descriptor_)); - for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = ordered_fields[i]; @@ -1502,10 +2054,8 @@ GenerateMergeFromCodedStream(io::Printer* printer) { const FieldGenerator& field_generator = field_generators_.get(field); // Emit code to parse the common, expected case. - printer->Print( - "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" - " ::google::protobuf::internal::WireFormatLite::WIRETYPE_$wiretype$) {\n", - "wiretype", kWireTypeNames[WireFormat::WireTypeForField(field)]); + printer->Print("if (tag == $commontag$) {\n", + "commontag", SimpleItoa(WireFormat::MakeTag(field))); if (i > 0 || (field->is_repeated() && !field->options().packed())) { printer->Print( @@ -1523,20 +2073,22 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Emit code to parse unexpectedly packed or unpacked values. if (field->is_packable() && field->options().packed()) { - printer->Print( - "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n" - " == ::google::protobuf::internal::WireFormatLite::\n" - " WIRETYPE_$wiretype$) {\n", - "wiretype", - kWireTypeNames[WireFormat::WireTypeForFieldType(field->type())]); + internal::WireFormatLite::WireType wiretype = + WireFormat::WireTypeForFieldType(field->type()); + printer->Print("} else if (tag == $uncommontag$) {\n", + "uncommontag", SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), wiretype))); printer->Indent(); field_generator.GenerateMergeFromCodedStream(printer); printer->Outdent(); } else if (field->is_packable() && !field->options().packed()) { - printer->Print( - "} else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag)\n" - " == ::google::protobuf::internal::WireFormatLite::\n" - " WIRETYPE_LENGTH_DELIMITED) {\n"); + internal::WireFormatLite::WireType wiretype = + internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED; + printer->Print("} else if (tag == $uncommontag$) {\n", + "uncommontag", SimpleItoa( + internal::WireFormatLite::MakeTag( + field->number(), wiretype))); printer->Indent(); field_generator.GenerateMergeFromCodedStreamWithPacking(printer); printer->Outdent(); @@ -1544,7 +2096,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print( "} else {\n" - " goto handle_uninterpreted;\n" + " goto handle_unusual;\n" "}\n"); // switch() is slow since it can't be predicted well. Insert some if()s @@ -1568,7 +2120,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { // Expect EOF. // TODO(kenton): Expect group end-tag? printer->Print( - "if (input->ExpectAtEnd()) return true;\n"); + "if (input->ExpectAtEnd()) goto success;\n"); } printer->Print( @@ -1578,17 +2130,19 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Print("}\n\n"); } - printer->Print( - "default: {\n" - "handle_uninterpreted:\n"); + printer->Print("default: {\n"); printer->Indent(); } - // Is this an end-group tag? If so, this must be the end of the message. + printer->Outdent(); + printer->Print("handle_unusual:\n"); + printer->Indent(); + // If tag is 0 or an end-group tag then this must be the end of the message. printer->Print( - "if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" + "if (tag == 0 ||\n" + " ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==\n" " ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {\n" - " return true;\n" + " goto success;\n" "}\n"); // Handle extension ranges. @@ -1617,7 +2171,7 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } } printer->Print(") {\n"); - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { PrintHandlingOptionalStaticInitializers( descriptor_->file(), printer, // With static initializers. @@ -1630,9 +2184,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) { PrintHandlingOptionalStaticInitializers( descriptor_->file(), printer, // With static initializers. - " DO_(_extensions_.ParseField(tag, input, default_instance_));\n", + " DO_(_extensions_.ParseField(tag, input, default_instance_,\n" + " &unknown_fields_stream));\n", // Without. - " DO_(_extensions_.ParseField(tag, input, &default_instance()));\n"); + " DO_(_extensions_.ParseField(tag, input, &default_instance(),\n" + " &unknown_fields_stream));\n"); } printer->Print( " continue;\n" @@ -1640,13 +2196,14 @@ GenerateMergeFromCodedStream(io::Printer* printer) { } // We really don't recognize this tag. Skip it. - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print( "DO_(::google::protobuf::internal::WireFormat::SkipField(\n" " input, tag, mutable_unknown_fields()));\n"); } else { printer->Print( - "DO_(::google::protobuf::internal::WireFormatLite::SkipField(input, tag));\n"); + "DO_(::google::protobuf::internal::WireFormatLite::SkipField(\n" + " input, tag, &unknown_fields_stream));\n"); } if (descriptor_->field_count() > 0) { @@ -1660,10 +2217,15 @@ GenerateMergeFromCodedStream(io::Printer* printer) { printer->Outdent(); printer->Outdent(); printer->Print( - " }\n" // while + " }\n" // for (;;) + "success:\n" + " // @@protoc_insertion_point(parse_success:$full_name$)\n" " return true;\n" + "failure:\n" + " // @@protoc_insertion_point(parse_failure:$full_name$)\n" + " return false;\n" "#undef DO_\n" - "}\n"); + "}\n", "full_name", descriptor_->full_name()); } void MessageGenerator::GenerateSerializeOneField( @@ -1719,11 +2281,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { " ::google::protobuf::io::CodedOutputStream* output) const {\n" " _extensions_.SerializeMessageSetWithCachedSizes(output);\n", "classname", classname_); - if (HasUnknownFields(descriptor_->file())) { - printer->Print( - " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" - " unknown_fields(), output);\n"); - } + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + printer->Print( + " ::google::protobuf::internal::WireFormat::SerializeUnknownMessageSetItems(\n" + " unknown_fields(), output);\n"); printer->Print( "}\n"); return; @@ -1735,8 +2296,16 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) { "classname", classname_); printer->Indent(); + printer->Print( + "// @@protoc_insertion_point(serialize_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + GenerateSerializeWithCachedSizesBody(printer, false); + printer->Print( + "// @@protoc_insertion_point(serialize_end:$full_name$)\n", + "full_name", descriptor_->full_name()); + printer->Outdent(); printer->Print( "}\n"); @@ -1752,12 +2321,11 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { " target =\n" " _extensions_.SerializeMessageSetWithCachedSizesToArray(target);\n", "classname", classname_); - if (HasUnknownFields(descriptor_->file())) { - printer->Print( - " target = ::google::protobuf::internal::WireFormat::\n" - " SerializeUnknownMessageSetItemsToArray(\n" - " unknown_fields(), target);\n"); - } + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + printer->Print( + " target = ::google::protobuf::internal::WireFormat::\n" + " SerializeUnknownMessageSetItemsToArray(\n" + " unknown_fields(), target);\n"); printer->Print( " return target;\n" "}\n"); @@ -1770,8 +2338,16 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { "classname", classname_); printer->Indent(); + printer->Print( + "// @@protoc_insertion_point(serialize_to_array_start:$full_name$)\n", + "full_name", descriptor_->full_name()); + GenerateSerializeWithCachedSizesBody(printer, true); + printer->Print( + "// @@protoc_insertion_point(serialize_to_array_end:$full_name$)\n", + "full_name", descriptor_->full_name()); + printer->Outdent(); printer->Print( " return target;\n" @@ -1781,7 +2357,7 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) { void MessageGenerator:: GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { scoped_array ordered_fields( - SortFieldsByNumber(descriptor_)); + SortFieldsByNumber(descriptor_)); vector sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { @@ -1810,7 +2386,7 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { } } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print("if (!unknown_fields().empty()) {\n"); printer->Indent(); if (to_array) { @@ -1827,6 +2403,10 @@ GenerateSerializeWithCachedSizesBody(io::Printer* printer, bool to_array) { printer->Print( "}\n"); + } else { + printer->Print( + "output->WriteRaw(unknown_fields().data(),\n" + " unknown_fields().size());\n"); } } @@ -1838,11 +2418,10 @@ GenerateByteSize(io::Printer* printer) { "int $classname$::ByteSize() const {\n" " int total_size = _extensions_.MessageSetByteSize();\n", "classname", classname_); - if (HasUnknownFields(descriptor_->file())) { - printer->Print( - " total_size += ::google::protobuf::internal::WireFormat::\n" - " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); - } + GOOGLE_CHECK(UseUnknownFieldSet(descriptor_->file())); + printer->Print( + " total_size += ::google::protobuf::internal::WireFormat::\n" + " ComputeUnknownMessageSetItemsSize(unknown_fields());\n"); printer->Print( " GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN();\n" " _cached_size_ = total_size;\n" @@ -1865,7 +2444,7 @@ GenerateByteSize(io::Printer* printer) { for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated()) { + if (!field->is_repeated() && !field->containing_oneof()) { // See above in GenerateClear for an explanation of this. // TODO(kenton): Share code? Unclear how to do so without // over-engineering. @@ -1915,13 +2494,45 @@ GenerateByteSize(io::Printer* printer) { } } + // Fields inside a oneof don't use _has_bits_ so we count them in a separate + // pass. + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "switch ($oneofname$_case()) {\n", + "oneofname", descriptor_->oneof_decl(i)->name()); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + PrintFieldComment(printer, field); + printer->Print( + "case k$field_name$: {\n", + "field_name", UnderscoresToCamelCase(field->name(), true)); + printer->Indent(); + field_generators_.get(field).GenerateByteSize(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(descriptor_->oneof_decl(i)->name())); + printer->Outdent(); + printer->Print( + "}\n"); + } + if (descriptor_->extension_range_count() > 0) { printer->Print( "total_size += _extensions_.ByteSize();\n" "\n"); } - if (HasUnknownFields(descriptor_->file())) { + if (UseUnknownFieldSet(descriptor_->file())) { printer->Print("if (!unknown_fields().empty()) {\n"); printer->Indent(); printer->Print( @@ -1930,6 +2541,10 @@ GenerateByteSize(io::Printer* printer) { " unknown_fields());\n"); printer->Outdent(); printer->Print("}\n"); + } else { + printer->Print( + "total_size += unknown_fields().size();\n" + "\n"); } // We update _cached_size_ even though this is a const method. In theory, @@ -1987,16 +2602,26 @@ GenerateIsInitialized(io::Printer* printer) { HasRequiredFields(field->message_type())) { if (field->is_repeated()) { printer->Print( - "for (int i = 0; i < $name$_size(); i++) {\n" - " if (!this->$name$(i).IsInitialized()) return false;\n" - "}\n", + "if (!::google::protobuf::internal::AllAreInitialized(this->$name$()))" + " return false;\n", "name", FieldName(field)); } else { - printer->Print( - "if (has_$name$()) {\n" - " if (!this->$name$().IsInitialized()) return false;\n" - "}\n", - "name", FieldName(field)); + if (field->options().weak()) { + // For weak fields, use the data member (google::protobuf::Message*) instead + // of the getter to avoid a link dependency on the weak message type + // which is only forward declared. + printer->Print( + "if (has_$name$()) {\n" + " if (!this->$name$_->IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); + } else { + printer->Print( + "if (has_$name$()) {\n" + " if (!this->$name$().IsInitialized()) return false;\n" + "}\n", + "name", FieldName(field)); + } } } } diff --git a/src/google/protobuf/compiler/cpp/cpp_message.h b/src/google/protobuf/compiler/cpp/cpp_message.h index a7e43d9c..3b4085dc 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message.h +++ b/src/google/protobuf/compiler/cpp/cpp_message.h @@ -35,8 +35,9 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__ +#include #include -#include +#include #include #include @@ -132,6 +133,7 @@ class MessageGenerator { // Generate standard Message methods. void GenerateClear(io::Printer* printer); + void GenerateOneofClear(io::Printer* printer); void GenerateMergeFromCodedStream(io::Printer* printer); void GenerateSerializeWithCachedSizes(io::Printer* printer); void GenerateSerializeWithCachedSizesToArray(io::Printer* printer); @@ -156,9 +158,11 @@ class MessageGenerator { string classname_; Options options_; FieldGeneratorMap field_generators_; + vector< vector > runs_of_fields_; // that might be trivially cleared scoped_array > nested_generators_; scoped_array > enum_generators_; scoped_array > extension_generators_; + bool uses_string_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); }; diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.cc b/src/google/protobuf/compiler/cpp/cpp_message_field.cc index 447f975f..08a4f257 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.cc @@ -53,6 +53,12 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (HasFastArraySerialization(descriptor->message_type()->file()) ? "MaybeToArray" : ""); + // NOTE: Escaped here to unblock proto1->proto2 migration. + // TODO(liujisi): Extend this to apply for other conflicting methods. + (*variables)["release_name"] = + SafeFunctionName(descriptor->containing_type(), + descriptor, "release_"); + (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -78,14 +84,15 @@ GenerateAccessorDeclarations(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $name$() const$deprecation$;\n" "inline $type$* mutable_$name$()$deprecation$;\n" - "inline $type$* release_$name$()$deprecation$;\n" + "inline $type$* $release_name$()$deprecation$;\n" "inline void set_allocated_$name$($type$* $name$)$deprecation$;\n"); } void MessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, - "inline const $type$& $classname$::$name$() const {\n"); + "inline const $type$& $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n"); PrintHandlingOptionalStaticInitializers( variables_, descriptor_->file(), printer, @@ -99,9 +106,10 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { "inline $type$* $classname$::mutable_$name$() {\n" " set_has_$name$();\n" " if ($name$_ == NULL) $name$_ = new $type$;\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" "}\n" - "inline $type$* $classname$::release_$name$() {\n" + "inline $type$* $classname$::$release_name$() {\n" " clear_has_$name$();\n" " $type$* temp = $name$_;\n" " $name$_ = NULL;\n" @@ -115,6 +123,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " } else {\n" " clear_has_$name$();\n" " }\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); } @@ -178,6 +187,69 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== +MessageOneofFieldGenerator:: +MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : MessageFieldGenerator(descriptor, options) { + SetCommonOneofFieldVariables(descriptor, &variables_); +} + +MessageOneofFieldGenerator::~MessageOneofFieldGenerator() {} + +void MessageOneofFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline const $type$& $classname$::$name$() const {\n" + " return has_$name$() ? *$oneof_prefix$$name$_\n" + " : $type$::default_instance();\n" + "}\n" + "inline $type$* $classname$::mutable_$name$() {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = new $type$;\n" + " }\n" + " return $oneof_prefix$$name$_;\n" + "}\n" + "inline $type$* $classname$::$release_name$() {\n" + " if (has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " $type$* temp = $oneof_prefix$$name$_;\n" + " $oneof_prefix$$name$_ = NULL;\n" + " return temp;\n" + " } else {\n" + " return NULL;\n" + " }\n" + "}\n" + "inline void $classname$::set_allocated_$name$($type$* $name$) {\n" + " clear_$oneof_name$();\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = $name$;\n" + " }\n" + "}\n"); +} + +void MessageOneofFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + // if it is the active field, it cannot be NULL. + printer->Print(variables_, + "delete $oneof_prefix$$name$_;\n"); +} + +void MessageOneofFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + // Don't print any swapping code. Swapping the union will swap this field. +} + +void MessageOneofFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + // Don't print any constructor code. The field is in a union. We allocate + // space only when this field is used. +} + +// =================================================================== + RepeatedMessageFieldGenerator:: RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, const Options& options) @@ -210,21 +282,26 @@ void RepeatedMessageFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const $type$& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.$cppget$(index);\n" "}\n" "inline $type$* $classname$::mutable_$name$(int index) {\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" "inline $type$* $classname$::add_$name$() {\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" " return $name$_.Add();\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedPtrField< $type$ >&\n" "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedPtrField< $type$ >*\n" "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_message_field.h b/src/google/protobuf/compiler/cpp/cpp_message_field.h index a5ed68a5..4c01795c 100644 --- a/src/google/protobuf/compiler/cpp/cpp_message_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_message_field.h @@ -63,13 +63,30 @@ class MessageFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); }; +class MessageOneofFieldGenerator : public MessageFieldGenerator { + public: + explicit MessageOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~MessageOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator); +}; + class RepeatedMessageFieldGenerator : public FieldGenerator { public: explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, diff --git a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc index 5c4aa4fb..697b95f0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_plugin_unittest.cc @@ -34,6 +34,8 @@ // It seemed like parameterizing it would add more complexity than it is // worth. +#include + #include #include #include @@ -73,7 +75,7 @@ class TestGenerator : public CodeGenerator { void TryInsert(const string& filename, const string& insertion_point, GeneratorContext* context) const { scoped_ptr output( - context->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -83,13 +85,13 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(CppPluginTest, PluginTest) { - File::WriteStringToFileOrDie( - "syntax = \"proto2\";\n" - "package foo;\n" - "message Bar {\n" - " message Baz {}\n" - "}\n", - TestTempDir() + "/test.proto"); + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "message Bar {\n" + " message Baz {}\n" + "}\n", + true)); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc index 1c35fefa..cb72fb1d 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.cc @@ -93,6 +93,7 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["wire_format_field_type"] = "::google::protobuf::internal::WireFormatLite::" + FieldDescriptorProto_Type_Name( static_cast(descriptor->type())); + (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -124,11 +125,13 @@ void PrimitiveFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_;\n" "}\n" "inline void $classname$::set_$name$($type$ value) {\n" " set_has_$name$();\n" " $name$_ = value;\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n"); } @@ -191,6 +194,62 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== +PrimitiveOneofFieldGenerator:: +PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : PrimitiveFieldGenerator(descriptor, options) { + SetCommonOneofFieldVariables(descriptor, &variables_); +} + +PrimitiveOneofFieldGenerator::~PrimitiveOneofFieldGenerator() {} + +void PrimitiveOneofFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline $type$ $classname$::$name$() const {\n" + " if (has_$name$()) {\n" + " return $oneof_prefix$$name$_;\n" + " }\n" + " return $default$;\n" + "}\n" + "inline void $classname$::set_$name$($type$ value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " }\n" + " $oneof_prefix$$name$_ = value;\n" + "}\n"); +} + +void PrimitiveOneofFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, "$oneof_prefix$$name$_ = $default$;\n"); +} + +void PrimitiveOneofFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + // Don't print any swapping code. Swapping the union will swap this field. +} + +void PrimitiveOneofFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + printer->Print( + variables_, + " $classname$_default_oneof_instance_->$name$_ = $default$;\n"); +} + +void PrimitiveOneofFieldGenerator:: +GenerateMergeFromCodedStream(io::Printer* printer) const { + printer->Print(variables_, + "clear_$oneof_name$();\n" + "DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive<\n" + " $type$, $wire_format_field_type$>(\n" + " input, &$oneof_prefix$$name$_)));\n" + "set_has_$name$();\n"); +} + +// =================================================================== + RepeatedPrimitiveFieldGenerator:: RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, const Options& options) @@ -235,21 +294,26 @@ void RepeatedPrimitiveFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline $type$ $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.Get(index);\n" "}\n" "inline void $classname$::set_$name$(int index, $type$ value) {\n" " $name$_.Set(index, value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::add_$name$($type$ value) {\n" " $name$_.Add(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedField< $type$ >&\n" "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedField< $type$ >*\n" "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } diff --git a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h index 48249c40..1f66c9df 100644 --- a/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_primitive_field.h @@ -63,13 +63,31 @@ class PrimitiveFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); }; +class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator { + public: + explicit PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~PrimitiveOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateMergeFromCodedStream(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveOneofFieldGenerator); +}; + class RepeatedPrimitiveFieldGenerator : public FieldGenerator { public: explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, diff --git a/src/google/protobuf/compiler/cpp/cpp_service.h b/src/google/protobuf/compiler/cpp/cpp_service.h index 820f9f5f..493f314a 100644 --- a/src/google/protobuf/compiler/cpp/cpp_service.h +++ b/src/google/protobuf/compiler/cpp/cpp_service.h @@ -37,7 +37,6 @@ #include #include -#include #include #include diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc index 0b58b981..d41b5bcd 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc @@ -53,10 +53,16 @@ void SetStringVariables(const FieldDescriptor* descriptor, (*variables)["default_length"] = SimpleItoa(descriptor->default_value_string().length()); (*variables)["default_variable"] = descriptor->default_value_string().empty() - ? "&::google::protobuf::internal::GetEmptyString()" + ? "&::google::protobuf::internal::GetEmptyStringAlreadyInited()" : "_default_" + FieldName(descriptor) + "_"; (*variables)["pointer_type"] = descriptor->type() == FieldDescriptor::TYPE_BYTES ? "void" : "char"; + // NOTE: Escaped here to unblock proto1->proto2 migration. + // TODO(liujisi): Extend this to apply for other conflicting methods. + (*variables)["release_name"] = + SafeFunctionName(descriptor->containing_type(), + descriptor, "release_"); + (*variables)["full_name"] = descriptor->full_name(); } } // namespace @@ -75,6 +81,10 @@ StringFieldGenerator::~StringFieldGenerator() {} void StringFieldGenerator:: GeneratePrivateMembers(io::Printer* printer) const { printer->Print(variables_, "::std::string* $name$_;\n"); +} + +void StringFieldGenerator:: +GenerateStaticMembers(io::Printer* printer) const { if (!descriptor_->default_value_string().empty()) { printer->Print(variables_, "static ::std::string* $default_variable$;\n"); } @@ -113,7 +123,7 @@ GenerateAccessorDeclarations(io::Printer* printer) const { "inline void set_$name$(const $pointer_type$* value, size_t size)" "$deprecation$;\n" "inline ::std::string* mutable_$name$()$deprecation$;\n" - "inline ::std::string* release_$name$()$deprecation$;\n" + "inline ::std::string* $release_name$()$deprecation$;\n" "inline void set_allocated_$name$(::std::string* $name$)$deprecation$;\n"); @@ -128,6 +138,7 @@ void StringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const ::std::string& $classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return *$name$_;\n" "}\n" "inline void $classname$::set_$name$(const ::std::string& value) {\n" @@ -136,6 +147,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" "}\n" "inline void $classname$::set_$name$(const char* value) {\n" " set_has_$name$();\n" @@ -143,6 +155,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(value);\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" "inline " "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" @@ -151,6 +164,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " $name$_ = new ::std::string;\n" " }\n" " $name$_->assign(reinterpret_cast(value), size);\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" "inline ::std::string* $classname$::mutable_$name$() {\n" " set_has_$name$();\n" @@ -164,9 +178,10 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { } printer->Print(variables_, " }\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_;\n" "}\n" - "inline ::std::string* $classname$::release_$name$() {\n" + "inline ::std::string* $classname$::$release_name$() {\n" " clear_has_$name$();\n" " if ($name$_ == $default_variable$) {\n" " return NULL;\n" @@ -187,6 +202,7 @@ GenerateInlineAccessorDefinitions(io::Printer* printer) const { " clear_has_$name$();\n" " $name$_ = const_cast< ::std::string*>($default_variable$);\n" " }\n" + " // @@protoc_insertion_point(field_set_allocated:$full_name$)\n" "}\n"); } @@ -263,9 +279,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::PARSE);\n"); + " ::google::protobuf::internal::WireFormat::PARSE,\n" + " \"$name$\");\n"); } } @@ -274,12 +291,13 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" + " \"$name$\");\n"); } printer->Print(variables_, - "::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" + "::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n" " $number$, this->$name$(), output);\n"); } @@ -288,9 +306,10 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$().data(), this->$name$().length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" + " \"$name$\");\n"); } printer->Print(variables_, "target =\n" @@ -308,6 +327,125 @@ GenerateByteSize(io::Printer* printer) const { // =================================================================== +StringOneofFieldGenerator:: +StringOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options) + : StringFieldGenerator(descriptor, options) { + SetCommonOneofFieldVariables(descriptor, &variables_); +} + +StringOneofFieldGenerator::~StringOneofFieldGenerator() {} + +void StringOneofFieldGenerator:: +GenerateInlineAccessorDefinitions(io::Printer* printer) const { + printer->Print(variables_, + "inline const ::std::string& $classname$::$name$() const {\n" + " if (has_$name$()) {\n" + " return *$oneof_prefix$$name$_;\n" + " }\n"); + if (descriptor_->default_value_string().empty()) { + printer->Print(variables_, + " return ::google::protobuf::internal::GetEmptyStringAlreadyInited();\n"); + } else { + printer->Print(variables_, + " return *$default_variable$;\n"); + } + printer->Print(variables_, + "}\n" + "inline void $classname$::set_$name$(const ::std::string& value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = new ::std::string;\n" + " }\n" + " $oneof_prefix$$name$_->assign(value);\n" + "}\n" + "inline void $classname$::set_$name$(const char* value) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = new ::std::string;\n" + " }\n" + " $oneof_prefix$$name$_->assign(value);\n" + "}\n" + "inline " + "void $classname$::set_$name$(const $pointer_type$* value, size_t size) {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = new ::std::string;\n" + " }\n" + " $oneof_prefix$$name$_->assign(\n" + " reinterpret_cast(value), size);\n" + "}\n" + "inline ::std::string* $classname$::mutable_$name$() {\n" + " if (!has_$name$()) {\n" + " clear_$oneof_name$();\n" + " set_has_$name$();\n"); + if (descriptor_->default_value_string().empty()) { + printer->Print(variables_, + " $oneof_prefix$$name$_ = new ::std::string;\n"); + } else { + printer->Print(variables_, + " $oneof_prefix$$name$_ = new ::std::string(*$default_variable$);\n"); + } + printer->Print(variables_, + " }\n" + " return $oneof_prefix$$name$_;\n" + "}\n" + "inline ::std::string* $classname$::$release_name$() {\n" + " if (has_$name$()) {\n" + " clear_has_$oneof_name$();\n" + " ::std::string* temp = $oneof_prefix$$name$_;\n" + " $oneof_prefix$$name$_ = NULL;\n" + " return temp;\n" + " } else {\n" + " return NULL;\n" + " }\n" + "}\n" + "inline void $classname$::set_allocated_$name$(::std::string* $name$) {\n" + " clear_$oneof_name$();\n" + " if ($name$) {\n" + " set_has_$name$();\n" + " $oneof_prefix$$name$_ = $name$;\n" + " }\n" + "}\n"); +} + +void StringOneofFieldGenerator:: +GenerateClearingCode(io::Printer* printer) const { + printer->Print(variables_, + "delete $oneof_prefix$$name$_;\n"); +} + +void StringOneofFieldGenerator:: +GenerateSwappingCode(io::Printer* printer) const { + // Don't print any swapping code. Swapping the union will swap this field. +} + +void StringOneofFieldGenerator:: +GenerateConstructorCode(io::Printer* printer) const { + if (!descriptor_->default_value_string().empty()) { + printer->Print(variables_, + " $classname$_default_oneof_instance_->$name$_ = " + "$classname$::$default_variable$;\n"); + } else { + printer->Print(variables_, + " $classname$_default_oneof_instance_->$name$_ = " + "$default_variable$;\n"); + } +} + +void StringOneofFieldGenerator:: +GenerateDestructorCode(io::Printer* printer) const { + printer->Print(variables_, + "if (has_$name$()) {\n" + " delete $oneof_prefix$$name$_;\n" + "}\n"); +} + +// =================================================================== + RepeatedStringFieldGenerator:: RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, const Options& options) @@ -365,43 +503,53 @@ void RepeatedStringFieldGenerator:: GenerateInlineAccessorDefinitions(io::Printer* printer) const { printer->Print(variables_, "inline const ::std::string& $classname$::$name$(int index) const {\n" + " // @@protoc_insertion_point(field_get:$full_name$)\n" " return $name$_.$cppget$(index);\n" "}\n" "inline ::std::string* $classname$::mutable_$name$(int index) {\n" + " // @@protoc_insertion_point(field_mutable:$full_name$)\n" " return $name$_.Mutable(index);\n" "}\n" "inline void $classname$::set_$name$(int index, const ::std::string& value) {\n" + " // @@protoc_insertion_point(field_set:$full_name$)\n" " $name$_.Mutable(index)->assign(value);\n" "}\n" "inline void $classname$::set_$name$(int index, const char* value) {\n" " $name$_.Mutable(index)->assign(value);\n" + " // @@protoc_insertion_point(field_set_char:$full_name$)\n" "}\n" "inline void " "$classname$::set_$name$" "(int index, const $pointer_type$* value, size_t size) {\n" " $name$_.Mutable(index)->assign(\n" " reinterpret_cast(value), size);\n" + " // @@protoc_insertion_point(field_set_pointer:$full_name$)\n" "}\n" "inline ::std::string* $classname$::add_$name$() {\n" " return $name$_.Add();\n" "}\n" "inline void $classname$::add_$name$(const ::std::string& value) {\n" " $name$_.Add()->assign(value);\n" + " // @@protoc_insertion_point(field_add:$full_name$)\n" "}\n" "inline void $classname$::add_$name$(const char* value) {\n" " $name$_.Add()->assign(value);\n" + " // @@protoc_insertion_point(field_add_char:$full_name$)\n" "}\n" "inline void " "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n" " $name$_.Add()->assign(reinterpret_cast(value), size);\n" + " // @@protoc_insertion_point(field_add_pointer:$full_name$)\n" "}\n"); printer->Print(variables_, "inline const ::google::protobuf::RepeatedPtrField< ::std::string>&\n" "$classname$::$name$() const {\n" + " // @@protoc_insertion_point(field_list:$full_name$)\n" " return $name$_;\n" "}\n" "inline ::google::protobuf::RepeatedPtrField< ::std::string>*\n" "$classname$::mutable_$name$() {\n" + " // @@protoc_insertion_point(field_mutable_list:$full_name$)\n" " return &$name$_;\n" "}\n"); } @@ -434,10 +582,11 @@ GenerateMergeFromCodedStream(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$(this->$name$_size() - 1).data(),\n" " this->$name$(this->$name$_size() - 1).length(),\n" - " ::google::protobuf::internal::WireFormat::PARSE);\n"); + " ::google::protobuf::internal::WireFormat::PARSE,\n" + " \"$name$\");\n"); } } @@ -448,9 +597,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - "::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$(i).data(), this->$name$(i).length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" + " \"$name$\");\n"); } printer->Print(variables_, " ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n" @@ -465,9 +615,10 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const { if (HasUtf8Verification(descriptor_->file()) && descriptor_->type() == FieldDescriptor::TYPE_STRING) { printer->Print(variables_, - " ::google::protobuf::internal::WireFormat::VerifyUTF8String(\n" + " ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n" " this->$name$(i).data(), this->$name$(i).length(),\n" - " ::google::protobuf::internal::WireFormat::SERIALIZE);\n"); + " ::google::protobuf::internal::WireFormat::SERIALIZE,\n" + " \"$name$\");\n"); } printer->Print(variables_, " target = ::google::protobuf::internal::WireFormatLite::\n" diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.h b/src/google/protobuf/compiler/cpp/cpp_string_field.h index 3264134a..65f605c0 100644 --- a/src/google/protobuf/compiler/cpp/cpp_string_field.h +++ b/src/google/protobuf/compiler/cpp/cpp_string_field.h @@ -52,6 +52,7 @@ class StringFieldGenerator : public FieldGenerator { // implements FieldGenerator --------------------------------------- void GeneratePrivateMembers(io::Printer* printer) const; + void GenerateStaticMembers(io::Printer* printer) const; void GenerateAccessorDeclarations(io::Printer* printer) const; void GenerateInlineAccessorDefinitions(io::Printer* printer) const; void GenerateNonInlineAccessorDefinitions(io::Printer* printer) const; @@ -67,13 +68,31 @@ class StringFieldGenerator : public FieldGenerator { void GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const; void GenerateByteSize(io::Printer* printer) const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); }; +class StringOneofFieldGenerator : public StringFieldGenerator { + public: + explicit StringOneofFieldGenerator(const FieldDescriptor* descriptor, + const Options& options); + ~StringOneofFieldGenerator(); + + // implements FieldGenerator --------------------------------------- + void GenerateInlineAccessorDefinitions(io::Printer* printer) const; + void GenerateClearingCode(io::Printer* printer) const; + void GenerateSwappingCode(io::Printer* printer) const; + void GenerateConstructorCode(io::Printer* printer) const; + void GenerateDestructorCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOneofFieldGenerator); +}; + class RepeatedStringFieldGenerator : public FieldGenerator { public: explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, diff --git a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto index e14a818c..8b9ff5ae 100644 --- a/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto +++ b/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.proto @@ -98,6 +98,7 @@ message TestConflictingSymbolNames { // Some keywords. optional uint32 int = 30; optional uint32 friend = 31; + optional uint32 class = 37; // The generator used to #define a macro called "DO" inside the .cc file. message DO {} @@ -107,6 +108,14 @@ message TestConflictingSymbolNames { optional int32 field_type = 33; optional bool is_packed = 34; + // test conflicting release_$name$. "length" and "do" field in this message + // must remain string or message fields to make the test valid. + optional string release_length = 35; + // A more extreme case, the field name "do" here is a keyword, which will be + // escaped to "do_" already. Test there is no conflict even with escaped field + // names. + optional DO release_do = 36; + extensions 1000 to max; } diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc index 1eae29b5..4ef1da1e 100644 --- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc +++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc @@ -46,6 +46,7 @@ #include +#include #include #include @@ -53,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -148,6 +150,19 @@ TEST(GeneratedMessageTest, Defaults) { &message.optional_import_message()); } +TEST(GeneratedMessageTest, Int32StringConversion) { + EXPECT_EQ("971", Int32ToString(971)); + EXPECT_EQ("(~0x7fffffff)", Int32ToString(kint32min)); + EXPECT_EQ("2147483647", Int32ToString(kint32max)); +} + +TEST(GeneratedMessageTest, Int64StringConversion) { + EXPECT_EQ("GOOGLE_LONGLONG(971)", Int64ToString(971)); + EXPECT_EQ("GOOGLE_LONGLONG(-2147483648)", Int64ToString(kint32min)); + EXPECT_EQ("GOOGLE_LONGLONG(-0x8000000000000000)", Int64ToString(kint64min)); + EXPECT_EQ("GOOGLE_LONGLONG(9223372036854775807)", Int64ToString(kint64max)); +} + TEST(GeneratedMessageTest, FloatingPointDefaults) { const unittest::TestExtremeDefaultValues& extreme_default = unittest::TestExtremeDefaultValues::default_instance(); @@ -233,11 +248,10 @@ TEST(GeneratedMessageTest, ReleaseString) { message.set_default_string("blah"); EXPECT_TRUE(message.has_default_string()); - string* str = message.release_default_string(); + scoped_ptr str(message.release_default_string()); EXPECT_FALSE(message.has_default_string()); ASSERT_TRUE(str != NULL); EXPECT_EQ("blah", *str); - delete str; EXPECT_EQ(NULL, message.release_default_string()); EXPECT_FALSE(message.has_default_string()); @@ -253,12 +267,11 @@ TEST(GeneratedMessageTest, ReleaseMessage) { EXPECT_FALSE(message.has_optional_nested_message()); message.mutable_optional_nested_message()->set_bb(1); - unittest::TestAllTypes::NestedMessage* nest = - message.release_optional_nested_message(); + scoped_ptr nest( + message.release_optional_nested_message()); EXPECT_FALSE(message.has_optional_nested_message()); ASSERT_TRUE(nest != NULL); EXPECT_EQ(1, nest->bb()); - delete nest; EXPECT_EQ(NULL, message.release_optional_nested_message()); EXPECT_FALSE(message.has_optional_nested_message()); @@ -381,6 +394,7 @@ TEST(GeneratedMessageTest, StringCharStarLength) { EXPECT_EQ("wx", message.repeated_string(0)); } + TEST(GeneratedMessageTest, CopyFrom) { unittest::TestAllTypes message1, message2; @@ -393,6 +407,7 @@ TEST(GeneratedMessageTest, CopyFrom) { TestUtil::ExpectAllFieldsSet(message2); } + TEST(GeneratedMessageTest, SwapWithEmpty) { unittest::TestAllTypes message1, message2; TestUtil::SetAllFields(&message1); @@ -763,6 +778,9 @@ TEST(GeneratedMessageTest, TestConflictingSymbolNames) { message.set_friend_(5); EXPECT_EQ(5, message.friend_()); + message.set_class_(6); + EXPECT_EQ(6, message.class_()); + // Instantiate extension template functions to test conflicting template // parameter names. typedef protobuf_unittest::TestConflictingSymbolNamesExtension ExtensionMessage; @@ -840,6 +858,40 @@ TEST(GeneratedMessageTest, TestSpaceUsed) { message1.SpaceUsed()); } +TEST(GeneratedMessageTest, TestOneofSpaceUsed) { + unittest::TestOneof2 message1; + EXPECT_LE(sizeof(unittest::TestOneof2), message1.SpaceUsed()); + + const int empty_message_size = message1.SpaceUsed(); + // Setting primitive types shouldn't affect the space used. + message1.set_foo_int(123); + message1.set_bar_int(12345); + EXPECT_EQ(empty_message_size, message1.SpaceUsed()); + + // Setting a string in oneof to a small value should only increase SpaceUsed() + // by the size of a string object. + message1.set_foo_string("abc"); + EXPECT_LE(empty_message_size + sizeof(string), message1.SpaceUsed()); + + // Setting a string in oneof to a value larger than the string object itself + // should increase SpaceUsed(), because it cannot store the value internally. + message1.set_foo_string(string(sizeof(string) + 1, 'x')); + int min_expected_increase = message1.foo_string().capacity() + + sizeof(string); + EXPECT_LE(empty_message_size + min_expected_increase, + message1.SpaceUsed()); + + // Setting a message in oneof should delete the other fields and increase the + // size by the size of the nested message type. NestedMessage is simple enough + // that it is equal to sizeof(NestedMessage) + message1.mutable_foo_message(); + ASSERT_EQ(sizeof(unittest::TestOneof2::NestedMessage), + message1.foo_message().SpaceUsed()); + EXPECT_EQ(empty_message_size + + sizeof(unittest::TestOneof2::NestedMessage), + message1.SpaceUsed()); +} + #endif // !PROTOBUF_TEST_NO_DESCRIPTORS @@ -887,6 +939,9 @@ TEST(GeneratedEnumTest, EnumValuesAsSwitchCases) { case unittest::TestAllTypes::BAZ: i = 3; break; + case unittest::TestAllTypes::NEG: + i = -1; + break; // no default case: We want to make sure the compiler recognizes that // all cases are covered. (GCC warns if you do not cover all cases of // an enum in a switch.) @@ -915,7 +970,7 @@ TEST(GeneratedEnumTest, IsValidValue) { } TEST(GeneratedEnumTest, MinAndMax) { - EXPECT_EQ(unittest::TestAllTypes::FOO, + EXPECT_EQ(unittest::TestAllTypes::NEG, unittest::TestAllTypes::NestedEnum_MIN); EXPECT_EQ(unittest::TestAllTypes::BAZ, unittest::TestAllTypes::NestedEnum_MAX); @@ -989,6 +1044,20 @@ TEST(GeneratedEnumTest, GetEnumDescriptor) { GetEnumDescriptor()); } +enum NonProtoEnum { + kFoo = 1, +}; + +TEST(GeneratedEnumTest, IsProtoEnumTypeTrait) { + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + EXPECT_TRUE(is_proto_enum::value); + + EXPECT_FALSE(is_proto_enum::value); + EXPECT_FALSE(is_proto_enum::value); +} + #endif // PROTOBUF_TEST_NO_DESCRIPTORS // =================================================================== @@ -1288,6 +1357,657 @@ TEST_F(GeneratedServiceTest, NotImplemented) { EXPECT_TRUE(controller.called_); } +// =================================================================== + +class OneofTest : public testing::Test { + protected: + virtual void SetUp() { + } + + void ExpectEnumCasesWork(const unittest::TestOneof2 &message) { + switch (message.foo_case()) { + case unittest::TestOneof2::kFooInt: + EXPECT_TRUE(message.has_foo_int()); + break; + case unittest::TestOneof2::kFooString: + EXPECT_TRUE(message.has_foo_string()); + break; + case unittest::TestOneof2::kFooBytes: + EXPECT_TRUE(message.has_foo_bytes()); + break; + case unittest::TestOneof2::kFooEnum: + EXPECT_TRUE(message.has_foo_enum()); + break; + case unittest::TestOneof2::kFooMessage: + EXPECT_TRUE(message.has_foo_message()); + break; + case unittest::TestOneof2::kFoogroup: + EXPECT_TRUE(message.has_foogroup()); + break; + case unittest::TestOneof2::FOO_NOT_SET: + break; + } + } +}; + +TEST_F(OneofTest, SettingOneFieldClearsOthers) { + unittest::TestOneof2 message; + + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.set_foo_string("foo"); + EXPECT_TRUE(message.has_foo_string()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + + message.set_foo_bytes("qux"); + EXPECT_TRUE(message.has_foo_bytes()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.set_foo_enum(unittest::TestOneof2::FOO); + EXPECT_TRUE(message.has_foo_enum()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.mutable_foo_message()->set_qux_int(234); + EXPECT_TRUE(message.has_foo_message()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + message.mutable_foogroup()->set_a(345); + EXPECT_TRUE(message.has_foogroup()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); + + + // we repeat this because we didn't test if this properly clears other fields + // at the beginning. + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + TestUtil::ExpectAtMostOneFieldSetInOneof(message); +} + +TEST_F(OneofTest, EnumCases) { + unittest::TestOneof2 message; + + message.set_foo_int(123); + ExpectEnumCasesWork(message); + message.set_foo_string("foo"); + ExpectEnumCasesWork(message); + message.set_foo_bytes("qux"); + ExpectEnumCasesWork(message); + message.set_foo_enum(unittest::TestOneof2::FOO); + ExpectEnumCasesWork(message); + message.mutable_foo_message()->set_qux_int(234); + ExpectEnumCasesWork(message); + message.mutable_foogroup()->set_a(345); + ExpectEnumCasesWork(message); +} + +TEST_F(OneofTest, PrimitiveType) { + unittest::TestOneof2 message; + // Unset field returns default value + EXPECT_EQ(message.foo_int(), 0); + + message.set_foo_int(123); + EXPECT_TRUE(message.has_foo_int()); + EXPECT_EQ(message.foo_int(), 123); + message.clear_foo_int(); + EXPECT_FALSE(message.has_foo_int()); +} + +TEST_F(OneofTest, EnumType) { + unittest::TestOneof2 message; + // Unset field returns default value + EXPECT_EQ(message.foo_enum(), 1); + + message.set_foo_enum(unittest::TestOneof2::FOO); + EXPECT_TRUE(message.has_foo_enum()); + EXPECT_EQ(message.foo_enum(), unittest::TestOneof2::FOO); + message.clear_foo_enum(); + EXPECT_FALSE(message.has_foo_enum()); +} + +TEST_F(OneofTest, SetString) { + // Check that setting a string field in various ways works + unittest::TestOneof2 message; + + // Unset field returns default value + EXPECT_EQ(message.foo_string(), ""); + + message.set_foo_string("foo"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "foo"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string(string("bar")); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "bar"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + + message.set_foo_string("qux", 3); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "qux"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.mutable_foo_string()->assign("quux"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "quux"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string("corge"); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "corge"); + message.clear_foo_string(); + EXPECT_FALSE(message.has_foo_string()); +} + +TEST_F(OneofTest, ReleaseString) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestOneof2 message; + + EXPECT_EQ(NULL, message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); + + message.set_foo_string("blah"); + EXPECT_TRUE(message.has_foo_string()); + scoped_ptr str(message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); + ASSERT_TRUE(str != NULL); + EXPECT_EQ("blah", *str); + + EXPECT_EQ(NULL, message.release_foo_string()); + EXPECT_FALSE(message.has_foo_string()); +} + +TEST_F(OneofTest, SetAllocatedString) { + // Check that set_allocated_foo() works for strings. + unittest::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_string()); + const string kHello("hello"); + message.set_foo_string(kHello); + EXPECT_TRUE(message.has_foo_string()); + + message.set_allocated_foo_string(NULL); + EXPECT_FALSE(message.has_foo_string()); + EXPECT_EQ("", message.foo_string()); + + message.set_allocated_foo_string(new string(kHello)); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(kHello, message.foo_string()); +} + + +TEST_F(OneofTest, SetMessage) { + // Check that setting a message field works + unittest::TestOneof2 message; + + // Unset field returns default instance + EXPECT_EQ(&message.foo_message(), + &unittest::TestOneof2_NestedMessage::default_instance()); + EXPECT_EQ(message.foo_message().qux_int(), 0); + + message.mutable_foo_message()->set_qux_int(234); + EXPECT_TRUE(message.has_foo_message()); + EXPECT_EQ(message.foo_message().qux_int(), 234); + message.clear_foo_message(); + EXPECT_FALSE(message.has_foo_message()); +} + +TEST_F(OneofTest, ReleaseMessage) { + // Check that release_foo() starts out NULL, and gives us a value + // that we can delete after it's been set. + unittest::TestOneof2 message; + + EXPECT_EQ(NULL, message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); + + message.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message.has_foo_message()); + scoped_ptr mes( + message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); + ASSERT_TRUE(mes != NULL); + EXPECT_EQ(1, mes->qux_int()); + + EXPECT_EQ(NULL, message.release_foo_message()); + EXPECT_FALSE(message.has_foo_message()); +} + +TEST_F(OneofTest, SetAllocatedMessage) { + // Check that set_allocated_foo() works for messages. + unittest::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_message()); + + message.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message.has_foo_message()); + + message.set_allocated_foo_message(NULL); + EXPECT_FALSE(message.has_foo_message()); + EXPECT_EQ(&message.foo_message(), + &unittest::TestOneof2_NestedMessage::default_instance()); + + message.mutable_foo_message()->set_qux_int(1); + unittest::TestOneof2_NestedMessage* mes = message.release_foo_message(); + ASSERT_TRUE(mes != NULL); + EXPECT_FALSE(message.has_foo_message()); + + message.set_allocated_foo_message(mes); + EXPECT_TRUE(message.has_foo_message()); + EXPECT_EQ(1, message.foo_message().qux_int()); +} + + +TEST_F(OneofTest, Clear) { + unittest::TestOneof2 message; + + message.set_foo_int(1); + EXPECT_TRUE(message.has_foo_int()); + message.clear_foo_int(); + EXPECT_FALSE(message.has_foo_int()); +} + +TEST_F(OneofTest, Defaults) { + unittest::TestOneof2 message; + + EXPECT_FALSE(message.has_foo_int()); + EXPECT_EQ(message.foo_int(), 0); + + EXPECT_FALSE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), ""); + + + EXPECT_FALSE(message.has_foo_bytes()); + EXPECT_EQ(message.foo_bytes(), ""); + + EXPECT_FALSE(message.has_foo_enum()); + EXPECT_EQ(message.foo_enum(), 1); + + EXPECT_FALSE(message.has_foo_message()); + EXPECT_EQ(message.foo_message().qux_int(), 0); + + EXPECT_FALSE(message.has_foogroup()); + EXPECT_EQ(message.foogroup().a(), 0); + + + EXPECT_FALSE(message.has_bar_int()); + EXPECT_EQ(message.bar_int(), 5); + + EXPECT_FALSE(message.has_bar_string()); + EXPECT_EQ(message.bar_string(), "STRING"); + + + EXPECT_FALSE(message.has_bar_bytes()); + EXPECT_EQ(message.bar_bytes(), "BYTES"); + + EXPECT_FALSE(message.has_bar_enum()); + EXPECT_EQ(message.bar_enum(), 2); +} + +TEST_F(OneofTest, SwapWithEmpty) { + unittest::TestOneof2 message1, message2; + message1.set_foo_string("FOO"); + EXPECT_TRUE(message1.has_foo_string()); + message1.Swap(&message2); + EXPECT_FALSE(message1.has_foo_string()); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "FOO"); +} + +TEST_F(OneofTest, SwapWithSelf) { + unittest::TestOneof2 message; + message.set_foo_string("FOO"); + EXPECT_TRUE(message.has_foo_string()); + message.Swap(&message); + EXPECT_TRUE(message.has_foo_string()); + EXPECT_EQ(message.foo_string(), "FOO"); +} + +TEST_F(OneofTest, SwapBothHasFields) { + unittest::TestOneof2 message1, message2; + + message1.set_foo_string("FOO"); + EXPECT_TRUE(message1.has_foo_string()); + message2.mutable_foo_message()->set_qux_int(1); + EXPECT_TRUE(message2.has_foo_message()); + + message1.Swap(&message2); + EXPECT_FALSE(message1.has_foo_string()); + EXPECT_FALSE(message2.has_foo_message()); + EXPECT_TRUE(message1.has_foo_message()); + EXPECT_EQ(message1.foo_message().qux_int(), 1); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "FOO"); +} + +TEST_F(OneofTest, CopyContructor) { + unittest::TestOneof2 message1; + message1.set_foo_bytes("FOO"); + + unittest::TestOneof2 message2(message1); + EXPECT_TRUE(message2.has_foo_bytes()); + EXPECT_EQ(message2.foo_bytes(), "FOO"); +} + +TEST_F(OneofTest, CopyFrom) { + unittest::TestOneof2 message1, message2; + message1.set_foo_enum(unittest::TestOneof2::BAR); + EXPECT_TRUE(message1.has_foo_enum()); + + message2.CopyFrom(message1); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR); + + // Copying from self should be a no-op. + message2.CopyFrom(message2); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::BAR); +} + +TEST_F(OneofTest, CopyAssignmentOperator) { + unittest::TestOneof2 message1; + message1.mutable_foo_message()->set_qux_int(123); + EXPECT_TRUE(message1.has_foo_message()); + + unittest::TestOneof2 message2; + message2 = message1; + EXPECT_EQ(message2.foo_message().qux_int(), 123); + + // Make sure that self-assignment does something sane. + message2 = message2; + EXPECT_EQ(message2.foo_message().qux_int(), 123); +} + +TEST_F(OneofTest, UpcastCopyFrom) { + // Test the CopyFrom method that takes in the generic const Message& + // parameter. + unittest::TestOneof2 message1, message2; + message1.mutable_foogroup()->set_a(123); + EXPECT_TRUE(message1.has_foogroup()); + + const Message* source = implicit_cast(&message1); + message2.CopyFrom(*source); + + EXPECT_TRUE(message2.has_foogroup()); + EXPECT_EQ(message2.foogroup().a(), 123); +} + +// Test the generated SerializeWithCachedSizesToArray(), +// This indirectly tests MergePartialFromCodedStream() +// We have to test each field type separately because we cannot set them at the +// same time +TEST_F(OneofTest, SerializationToArray) { + // Primitive type + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_int(123); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_int(), 123); + } + + // String + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_string("foo"); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_string(), "foo"); + } + + + // Bytes + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_bytes("qux"); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_bytes(), "qux"); + } + + // Enum + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_enum(unittest::TestOneof2::FOO); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); + } + + // Message + { + unittest::TestOneof2 message1, message2; + string data; + message1.mutable_foo_message()->set_qux_int(234); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + } + + // Group + { + unittest::TestOneof2 message1, message2; + string data; + message1.mutable_foogroup()->set_a(345); + int size = message1.ByteSize(); + data.resize(size); + uint8* start = reinterpret_cast(string_as_array(&data)); + uint8* end = message1.SerializeWithCachedSizesToArray(start); + EXPECT_EQ(size, end - start); + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foogroup().a(), 345); + } + +} + +// Test the generated SerializeWithCachedSizes() by forcing the buffer to write +// one byte at a time. +// This indirectly tests MergePartialFromCodedStream() +// We have to test each field type separately because we cannot set them at the +// same time +TEST_F(OneofTest, SerializationToStream) { + // Primitive type + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_int(123); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_int(), 123); + } + + // String + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_string("foo"); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_string(), "foo"); + } + + + // Bytes + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_bytes("qux"); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_bytes(), "qux"); + } + + // Enum + { + unittest::TestOneof2 message1, message2; + string data; + message1.set_foo_enum(unittest::TestOneof2::FOO); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); + } + + // Message + { + unittest::TestOneof2 message1, message2; + string data; + message1.mutable_foo_message()->set_qux_int(234); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + } + + // Group + { + unittest::TestOneof2 message1, message2; + string data; + message1.mutable_foogroup()->set_a(345); + int size = message1.ByteSize(); + data.resize(size); + + { + // Allow the output stream to buffer only one byte at a time. + io::ArrayOutputStream array_stream(string_as_array(&data), size, 1); + io::CodedOutputStream output_stream(&array_stream); + message1.SerializeWithCachedSizes(&output_stream); + EXPECT_FALSE(output_stream.HadError()); + EXPECT_EQ(size, output_stream.ByteCount()); + } + + EXPECT_TRUE(message2.ParseFromString(data)); + EXPECT_EQ(message2.foogroup().a(), 345); + } + +} + +TEST_F(OneofTest, MergeFrom) { + unittest::TestOneof2 message1, message2; + + message1.set_foo_int(123); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_int()); + EXPECT_EQ(message2.foo_int(), 123); + + message1.set_foo_string("foo"); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_string()); + EXPECT_EQ(message2.foo_string(), "foo"); + + + message1.set_foo_bytes("qux"); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_bytes()); + EXPECT_EQ(message2.foo_bytes(), "qux"); + + message1.set_foo_enum(unittest::TestOneof2::FOO); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_enum()); + EXPECT_EQ(message2.foo_enum(), unittest::TestOneof2::FOO); + + message1.mutable_foo_message()->set_qux_int(234); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foo_message()); + EXPECT_EQ(message2.foo_message().qux_int(), 234); + + message1.mutable_foogroup()->set_a(345); + message2.MergeFrom(message1); + TestUtil::ExpectAtMostOneFieldSetInOneof(message2); + EXPECT_TRUE(message2.has_foogroup()); + EXPECT_EQ(message2.foogroup().a(), 345); + +} + } // namespace cpp_unittest } // namespace cpp } // namespace compiler diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc index 422f759f..701ac483 100644 --- a/src/google/protobuf/compiler/importer.cc +++ b/src/google/protobuf/compiler/importer.cc @@ -43,6 +43,7 @@ #include #include +#include #include @@ -124,7 +125,8 @@ bool SourceTreeDescriptorDatabase::FindFileByName( scoped_ptr input(source_tree_->Open(filename)); if (input == NULL) { if (error_collector_ != NULL) { - error_collector_->AddError(filename, -1, 0, "File not found."); + error_collector_->AddError(filename, -1, 0, + source_tree_->GetLastErrorMessage()); } return false; } @@ -186,6 +188,7 @@ Importer::Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector) : database_(source_tree), pool_(&database_, database_.GetValidationErrorCollector()) { + pool_.EnforceWeakDependencies(true); database_.RecordErrorsTo(error_collector); } @@ -195,10 +198,22 @@ const FileDescriptor* Importer::Import(const string& filename) { return pool_.FindFileByName(filename); } +void Importer::AddUnusedImportTrackFile(const string& file_name) { + pool_.AddUnusedImportTrackFile(file_name); +} + +void Importer::ClearUnusedImportTrackFiles() { + pool_.ClearUnusedImportTrackFiles(); +} + // =================================================================== SourceTree::~SourceTree() {} +string SourceTree::GetLastErrorMessage() { + return "File not found."; +} + DiskSourceTree::DiskSourceTree() {} DiskSourceTree::~DiskSourceTree() {} @@ -239,9 +254,9 @@ static string CanonicalizePath(string path) { } #endif - vector parts; vector canonical_parts; - SplitStringUsing(path, "/", &parts); // Note: Removes empty parts. + vector parts = Split( + path, "/", true); // Note: Removes empty parts. for (int i = 0; i < parts.size(); i++) { if (parts[i] == ".") { // Ignore. @@ -249,7 +264,7 @@ static string CanonicalizePath(string path) { canonical_parts.push_back(parts[i]); } } - string result = JoinStrings(canonical_parts, "/"); + string result = Join(canonical_parts, "/"); if (!path.empty() && path[0] == '/') { // Restore leading slash. result = '/' + result; @@ -395,8 +410,8 @@ DiskSourceTree::DiskFileToVirtualFile( bool DiskSourceTree::VirtualFileToDiskFile(const string& virtual_file, string* disk_file) { - scoped_ptr stream(OpenVirtualFile(virtual_file, - disk_file)); + scoped_ptr stream( + OpenVirtualFile(virtual_file, disk_file)); return stream != NULL; } @@ -404,6 +419,10 @@ io::ZeroCopyInputStream* DiskSourceTree::Open(const string& filename) { return OpenVirtualFile(filename, NULL); } +string DiskSourceTree::GetLastErrorMessage() { + return last_error_message_; +} + io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( const string& virtual_file, string* disk_file) { @@ -412,6 +431,8 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( // We do not allow importing of paths containing things like ".." or // consecutive slashes since the compiler expects files to be uniquely // identified by file name. + last_error_message_ = "Backslashes, consecutive slashes, \".\", or \"..\" " + "are not allowed in the virtual path"; return NULL; } @@ -429,13 +450,13 @@ io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile( if (errno == EACCES) { // The file exists but is not readable. - // TODO(kenton): Find a way to report this more nicely. - GOOGLE_LOG(WARNING) << "Read access is denied for file: " << temp_disk_file; + last_error_message_ = "Read access is denied for file: " + + temp_disk_file; return NULL; } } } - + last_error_message_ = "File not found."; return NULL; } diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h index 7a62fa0e..0171d2fa 100644 --- a/src/google/protobuf/compiler/importer.h +++ b/src/google/protobuf/compiler/importer.h @@ -166,6 +166,9 @@ class LIBPROTOBUF_EXPORT Importer { return &pool_; } + void AddUnusedImportTrackFile(const string& file_name); + void ClearUnusedImportTrackFiles(); + private: SourceTreeDescriptorDatabase database_; DescriptorPool pool_; @@ -204,6 +207,13 @@ class LIBPROTOBUF_EXPORT SourceTree { // contain "." or ".." components. virtual io::ZeroCopyInputStream* Open(const string& filename) = 0; + // If Open() returns NULL, calling this method immediately will return an + // description of the error. + // Subclasses should implement this method and return a meaningful value for + // better error reporting. + // TODO(xiaofeng): change this to a pure virtual function. + virtual string GetLastErrorMessage(); + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree); }; @@ -273,7 +283,9 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { bool VirtualFileToDiskFile(const string& virtual_file, string* disk_file); // implements SourceTree ------------------------------------------- - io::ZeroCopyInputStream* Open(const string& filename); + virtual io::ZeroCopyInputStream* Open(const string& filename); + + virtual string GetLastErrorMessage(); private: struct Mapping { @@ -285,6 +297,7 @@ class LIBPROTOBUF_EXPORT DiskSourceTree : public SourceTree { : virtual_path(virtual_path_param), disk_path(disk_path_param) {} }; vector mappings_; + string last_error_message_; // Like Open(), but returns the on-disk path in disk_file if disk_file is // non-NULL and the file could be successfully opened. diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc index 56fad56e..b54d9b73 100644 --- a/src/google/protobuf/compiler/importer_unittest.cc +++ b/src/google/protobuf/compiler/importer_unittest.cc @@ -33,12 +33,13 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include #include #include #include -#include +#include #include #include #include @@ -92,6 +93,10 @@ class MockSourceTree : public SourceTree { } } + string GetLastErrorMessage() { + return "File not found."; + } + private: hash_map files_; }; @@ -324,6 +329,7 @@ TEST_F(ImporterTest, MapFieldKeyNotScalar) { EXPECT_SUBSTRING("must name a scalar or string", error()); } + // =================================================================== class DiskSourceTreeTest : public testing::Test { @@ -336,7 +342,7 @@ class DiskSourceTreeTest : public testing::Test { if (File::Exists(dirnames_[i])) { File::DeleteRecursively(dirnames_[i], NULL, NULL); } - GOOGLE_CHECK(File::CreateDir(dirnames_[i].c_str(), DEFAULT_FILE_MODE)); + GOOGLE_CHECK_OK(File::CreateDir(dirnames_[i], 0777)); } } @@ -347,11 +353,11 @@ class DiskSourceTreeTest : public testing::Test { } void AddFile(const string& filename, const char* contents) { - File::WriteStringToFileOrDie(contents, filename); + GOOGLE_CHECK_OK(File::SetContents(filename, contents, true)); } void AddSubdir(const string& dirname) { - GOOGLE_CHECK(File::CreateDir(dirname.c_str(), DEFAULT_FILE_MODE)); + GOOGLE_CHECK_OK(File::CreateDir(dirname, 0777)); } void ExpectFileContents(const string& filename, @@ -371,9 +377,11 @@ class DiskSourceTreeTest : public testing::Test { EXPECT_EQ(expected_contents, file_contents); } - void ExpectFileNotFound(const string& filename) { + void ExpectCannotOpenFile(const string& filename, + const string& error_message) { scoped_ptr input(source_tree_.Open(filename)); EXPECT_TRUE(input == NULL); + EXPECT_EQ(error_message, source_tree_.GetLastErrorMessage()); } DiskSourceTree source_tree_; @@ -389,7 +397,7 @@ TEST_F(DiskSourceTreeTest, MapRoot) { source_tree_.MapPath("", dirnames_[0]); ExpectFileContents("foo", "Hello World!"); - ExpectFileNotFound("bar"); + ExpectCannotOpenFile("bar", "File not found."); } TEST_F(DiskSourceTreeTest, MapDirectory) { @@ -400,15 +408,21 @@ TEST_F(DiskSourceTreeTest, MapDirectory) { source_tree_.MapPath("baz", dirnames_[0]); ExpectFileContents("baz/foo", "Hello World!"); - ExpectFileNotFound("baz/bar"); - ExpectFileNotFound("foo"); - ExpectFileNotFound("bar"); + ExpectCannotOpenFile("baz/bar", "File not found."); + ExpectCannotOpenFile("foo", "File not found."); + ExpectCannotOpenFile("bar", "File not found."); // Non-canonical file names should not work. - ExpectFileNotFound("baz//foo"); - ExpectFileNotFound("baz/../baz/foo"); - ExpectFileNotFound("baz/./foo"); - ExpectFileNotFound("baz/foo/"); + ExpectCannotOpenFile("baz//foo", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); + ExpectCannotOpenFile("baz/../baz/foo", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); + ExpectCannotOpenFile("baz/./foo", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); + ExpectCannotOpenFile("baz/foo/", "File not found."); } TEST_F(DiskSourceTreeTest, NoParent) { @@ -420,8 +434,12 @@ TEST_F(DiskSourceTreeTest, NoParent) { source_tree_.MapPath("", dirnames_[0] + "/bar"); ExpectFileContents("baz", "Blah."); - ExpectFileNotFound("../foo"); - ExpectFileNotFound("../bar/baz"); + ExpectCannotOpenFile("../foo", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); + ExpectCannotOpenFile("../bar/baz", + "Backslashes, consecutive slashes, \".\", or \"..\" are " + "not allowed in the virtual path"); } TEST_F(DiskSourceTreeTest, MapFile) { @@ -431,7 +449,7 @@ TEST_F(DiskSourceTreeTest, MapFile) { source_tree_.MapPath("foo", dirnames_[0] + "/foo"); ExpectFileContents("foo", "Hello World!"); - ExpectFileNotFound("bar"); + ExpectCannotOpenFile("bar", "File not found."); } TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) { @@ -445,7 +463,7 @@ TEST_F(DiskSourceTreeTest, SearchMultipleDirectories) { ExpectFileContents("foo", "Hello World!"); ExpectFileContents("bar", "Goodbye World!"); - ExpectFileNotFound("baz"); + ExpectCannotOpenFile("baz", "File not found."); } TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) { @@ -453,8 +471,7 @@ TEST_F(DiskSourceTreeTest, OrderingTrumpsSpecificity) { // directory is more-specific than a former one. // Create the "bar" directory so we can put a file in it. - ASSERT_TRUE(File::CreateDir((dirnames_[0] + "/bar").c_str(), - DEFAULT_FILE_MODE)); + GOOGLE_CHECK_OK(File::CreateDir(dirnames_[0] + "/bar", 0777)); // Add files and map paths. AddFile(dirnames_[0] + "/bar/foo", "Hello World!"); diff --git a/src/google/protobuf/compiler/java/java_context.cc b/src/google/protobuf/compiler/java/java_context.cc new file mode 100644 index 00000000..67ac0ef3 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_context.cc @@ -0,0 +1,195 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +Context::Context(const FileDescriptor* file) + : name_resolver_(new ClassNameResolver) { + InitializeFieldGeneratorInfo(file); +} + +Context::~Context() { +} + +ClassNameResolver* Context::GetNameResolver() { + return name_resolver_.get(); +} + +namespace { +// Whether two fields have conflicting accessors (assuming name1 and name2 +// are different). name1 and name2 are field1 and field2's camel-case name +// respectively. +bool IsConflicting(const FieldDescriptor* field1, const string& name1, + const FieldDescriptor* field2, const string& name2, + string* info) { + if (field1->is_repeated()) { + if (field2->is_repeated()) { + // Both fields are repeated. + return false; + } else { + // field1 is repeated, and field2 is not. + if (name1 + "Count" == name2) { + *info = "both repeated field \"" + field1->name() + "\" and singular " + + "field \"" + field2->name() + "\" generates the method \"" + + "get" + name1 + "Count()\""; + return true; + } + if (name1 + "List" == name2) { + *info = "both repeated field \"" + field1->name() + "\" and singular " + + "field \"" + field2->name() + "\" generates the method \"" + + "get" + name1 + "List()\""; + return true; + } + // Well, there are obviously many more conflicting cases, but it probably + // doesn't worth the effort to exhaust all of them because they rarely + // happen and as we are continuing adding new methods/changing existing + // methods the number of different conflicting cases will keep growing. + // We can just add more cases here when they are found in the real world. + return false; + } + } else { + if (field2->is_repeated()) { + return IsConflicting(field2, name2, field1, name1, info); + } else { + // None of the two fields are repeated. + return false; + } + } +} +} // namespace + +void Context::InitializeFieldGeneratorInfo(const FileDescriptor* file) { + for (int i = 0; i < file->message_type_count(); ++i) { + InitializeFieldGeneratorInfoForMessage(file->message_type(i)); + } +} + +void Context::InitializeFieldGeneratorInfoForMessage( + const Descriptor* message) { + for (int i = 0; i < message->nested_type_count(); ++i) { + InitializeFieldGeneratorInfoForMessage(message->nested_type(i)); + } + vector fields; + for (int i = 0; i < message->field_count(); ++i) { + fields.push_back(message->field(i)); + } + InitializeFieldGeneratorInfoForFields(fields); + + for (int i = 0; i < message->oneof_decl_count(); ++i) { + const OneofDescriptor* oneof = message->oneof_decl(i); + OneofGeneratorInfo info; + info.name = UnderscoresToCamelCase(oneof->name(), false); + info.capitalized_name = UnderscoresToCamelCase(oneof->name(), true); + oneof_generator_info_map_[oneof] = info; + } +} + +void Context::InitializeFieldGeneratorInfoForFields( + const vector& fields) { + // Find out all fields that conflict with some other field in the same + // message. + vector is_conflict(fields.size()); + vector conflict_reason(fields.size()); + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + const string& name = UnderscoresToCapitalizedCamelCase(field); + for (int j = i + 1; j < fields.size(); ++j) { + const FieldDescriptor* other = fields[j]; + const string& other_name = UnderscoresToCapitalizedCamelCase(other); + if (name == other_name) { + is_conflict[i] = is_conflict[j] = true; + conflict_reason[i] = conflict_reason[j] = + "capitalized name of field \"" + field->name() + + "\" conflicts with field \"" + other->name() + "\""; + } else if (IsConflicting(field, name, other, other_name, + &conflict_reason[j])) { + is_conflict[i] = is_conflict[j] = true; + conflict_reason[i] = conflict_reason[j]; + } + } + if (is_conflict[i]) { + GOOGLE_LOG(WARNING) << "field \"" << field->full_name() << "\" is conflicting " + << "with another field: " << conflict_reason[i]; + } + } + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + FieldGeneratorInfo info; + info.name = UnderscoresToCamelCase(field); + info.capitalized_name = UnderscoresToCapitalizedCamelCase(field); + // For fields conflicting with some other fields, we append the field + // number to their field names in generated code to avoid conflicts. + if (is_conflict[i]) { + info.name += SimpleItoa(field->number()); + info.capitalized_name += SimpleItoa(field->number()); + info.disambiguated_reason = conflict_reason[i]; + } + field_generator_info_map_[field] = info; + } +} + +const FieldGeneratorInfo* Context::GetFieldGeneratorInfo( + const FieldDescriptor* field) const { + const FieldGeneratorInfo* result = + FindOrNull(field_generator_info_map_, field); + if (result == NULL) { + GOOGLE_LOG(FATAL) << "Can not find FieldGeneratorInfo for field: " + << field->full_name(); + } + return result; +} + +const OneofGeneratorInfo* Context::GetOneofGeneratorInfo( + const OneofDescriptor* oneof) const { + const OneofGeneratorInfo* result = + FindOrNull(oneof_generator_info_map_, oneof); + if (result == NULL) { + GOOGLE_LOG(FATAL) << "Can not find OneofGeneratorInfo for oneof: " + << oneof->name(); + } + return result; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_context.h b/src/google/protobuf/compiler/java/java_context.h new file mode 100644 index 00000000..c622b319 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_context.h @@ -0,0 +1,95 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { + class FileDescriptor; + class FieldDescriptor; + class OneofDescriptor; + class Descriptor; + namespace compiler { + namespace java { + class ClassNameResolver; // name_resolver.h + } + } +} // namespace protobuf + +namespace protobuf { +namespace compiler { +namespace java { + +struct FieldGeneratorInfo; +struct OneofGeneratorInfo; +// A context object holds the information that is shared among all code +// generators. +class Context { + public: + explicit Context(const FileDescriptor* file); + ~Context(); + + // Get the name resolver associated with this context. The resolver + // can be used to map descriptors to Java class names. + ClassNameResolver* GetNameResolver(); + + // Get the FieldGeneratorInfo for a given field. + const FieldGeneratorInfo* GetFieldGeneratorInfo( + const FieldDescriptor* field) const; + + // Get the OneofGeneratorInfo for a given oneof. + const OneofGeneratorInfo* GetOneofGeneratorInfo( + const OneofDescriptor* oneof) const; + + private: + void InitializeFieldGeneratorInfo(const FileDescriptor* file); + void InitializeFieldGeneratorInfoForMessage(const Descriptor* message); + void InitializeFieldGeneratorInfoForFields( + const vector& fields); + + scoped_ptr name_resolver_; + map field_generator_info_map_; + map oneof_generator_info_map_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__ diff --git a/src/google/protobuf/compiler/java/java_doc_comment.cc b/src/google/protobuf/compiler/java/java_doc_comment.cc index 60b4f2ac..23127b7f 100644 --- a/src/google/protobuf/compiler/java/java_doc_comment.cc +++ b/src/google/protobuf/compiler/java/java_doc_comment.cc @@ -70,12 +70,10 @@ string EscapeJavadoc(const string& input) { } break; case '@': - // "{@" starts Javadoc markup. - if (prev == '{') { - result.append("@"); - } else { - result.push_back(c); - } + // '@' starts javadoc tags including the @deprecated tag, which will + // cause a compile-time error if inserted before a declaration that + // does not have a corresponding @Deprecated annotation. + result.append("@"); break; case '<': // Avoid interpretation as HTML. @@ -117,8 +115,7 @@ static void WriteDocCommentBodyForLocation( // HTML-escape them so that they don't accidentally close the doc comment. comments = EscapeJavadoc(comments); - vector lines; - SplitStringAllowEmpty(comments, "\n", &lines); + vector lines = Split(comments, "\n"); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); } diff --git a/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc b/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc index 28b6d8b4..41ea9f42 100644 --- a/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc +++ b/src/google/protobuf/compiler/java/java_doc_comment_unittest.cc @@ -46,6 +46,7 @@ TEST(JavaDocCommentTest, Escaping) { EXPECT_EQ("{@foo}", EscapeJavadoc("{@foo}")); EXPECT_EQ("<i>&</i>", EscapeJavadoc("&")); EXPECT_EQ("foo\u1234bar", EscapeJavadoc("foo\\u1234bar")); + EXPECT_EQ("@deprecated", EscapeJavadoc("@deprecated")); } // TODO(kenton): It's hard to write a robust test of the doc comments -- we diff --git a/src/google/protobuf/compiler/java/java_enum.cc b/src/google/protobuf/compiler/java/java_enum.cc index cfed815f..6bebe213 100644 --- a/src/google/protobuf/compiler/java/java_enum.cc +++ b/src/google/protobuf/compiler/java/java_enum.cc @@ -35,9 +35,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -47,8 +49,22 @@ namespace protobuf { namespace compiler { namespace java { -EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor) - : descriptor_(descriptor) { +namespace { +bool EnumHasCustomOptions(const EnumDescriptor* descriptor) { + if (descriptor->options().unknown_fields().field_count() > 0) return true; + for (int i = 0; i < descriptor->value_count(); ++i) { + const EnumValueDescriptor* value = descriptor->value(i); + if (value->options().unknown_fields().field_count() > 0) return true; + } + return false; +} +} // namespace + +EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor, + bool immutable_api, + Context* context) + : descriptor_(descriptor), immutable_api_(immutable_api), + name_resolver_(context->GetNameResolver()) { for (int i = 0; i < descriptor_->value_count(); i++) { const EnumValueDescriptor* value = descriptor_->value(i); const EnumValueDescriptor* canonical_value = @@ -88,6 +104,9 @@ void EnumGenerator::Generate(io::Printer* printer) { vars["index"] = SimpleItoa(canonical_values_[i]->index()); vars["number"] = SimpleItoa(canonical_values_[i]->number()); WriteEnumValueDocComment(printer, canonical_values_[i]); + if (canonical_values_[i]->options().deprecated()) { + printer->Print("@java.lang.Deprecated\n"); + } printer->Print(vars, "$name$($index$, $number$),\n"); } @@ -178,15 +197,58 @@ void EnumGenerator::Generate(io::Printer* printer) { // at module init time because it wouldn't work with descriptor.proto, but // we can cache the value the first time getDescriptor() is called. if (descriptor_->containing_type() == NULL) { - printer->Print( - " return $file$.getDescriptor().getEnumTypes().get($index$);\n", - "file", ClassName(descriptor_->file()), - "index", SimpleItoa(descriptor_->index())); + if (!MultipleJavaFiles(descriptor_->file(), immutable_api_)) { + printer->Print( + " return $file$.getDescriptor().getEnumTypes().get($index$);\n", + "file", name_resolver_->GetClassName(descriptor_->file(), + immutable_api_), + "index", SimpleItoa(descriptor_->index())); + } else { + printer->Indent(); + if (EnumHasCustomOptions(descriptor_)) { + // We need to load the immutable classes in order to parse custom + // options. However, since file level enums (no outer class) are + // shared by immutable code and mutable code, the immutable classes + // may not exist. So we try to use Java reflection to retrieve the + // descriptor from immutable classes. + printer->Print( + "try {\n" + " java.lang.Class immutableFileClass =\n" + " java.lang.Class.forName(\"$immutable_file_class_name$\");\n" + " @java.lang.SuppressWarnings(\"unchecked\")\n" + " java.lang.reflect.Method m =\n" + " immutableFileClass.getMethod(\"getDescriptor\");\n" + " com.google.protobuf.Descriptors.FileDescriptor file =\n" + " (com.google.protobuf.Descriptors.FileDescriptor)\n" + " m.invoke(immutableFileClass);\n" + " return file.getEnumTypes().get($index$);\n" + "} catch (Exception e) {\n" + // Immutable classes cannot be found. Proceed as if custom options + // don't exist. + "}\n", + "immutable_file_class_name", + name_resolver_->GetImmutableClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); + } + printer->Print( + "return $immutable_package$.$descriptor_class$.descriptor\n" + " .getEnumTypes().get($index$);\n", + "immutable_package", FileJavaPackage(descriptor_->file(), true), + "descriptor_class", + name_resolver_->GetDescriptorClassName(descriptor_->file()), + "index", SimpleItoa(descriptor_->index())); + printer->Outdent(); + } } else { printer->Print( - " return $parent$.getDescriptor().getEnumTypes().get($index$);\n", - "parent", ClassName(descriptor_->containing_type()), - "index", SimpleItoa(descriptor_->index())); + " return $parent$.$descriptor$.getEnumTypes().get($index$);\n", + "parent", name_resolver_->GetClassName(descriptor_->containing_type(), + immutable_api_), + "descriptor", descriptor_->containing_type()->options() + .no_standard_descriptor_accessor() + ? "getDefaultInstance().getDescriptorForType()" + : "getDescriptor()", + "index", SimpleItoa(descriptor_->index())); } printer->Print( diff --git a/src/google/protobuf/compiler/java/java_enum.h b/src/google/protobuf/compiler/java/java_enum.h index 9a9e5742..af0cd15d 100644 --- a/src/google/protobuf/compiler/java/java_enum.h +++ b/src/google/protobuf/compiler/java/java_enum.h @@ -41,6 +41,12 @@ namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { class Printer; // printer.h } @@ -52,7 +58,9 @@ namespace java { class EnumGenerator { public: - explicit EnumGenerator(const EnumDescriptor* descriptor); + explicit EnumGenerator(const EnumDescriptor* descriptor, + bool immutable_api, + Context* context); ~EnumGenerator(); void Generate(io::Printer* printer); @@ -73,6 +81,11 @@ class EnumGenerator { }; vector aliases_; + bool immutable_api_; + + Context* context_; + ClassNameResolver* name_resolver_; + bool CanUseEnumValues(); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator); diff --git a/src/google/protobuf/compiler/java/java_enum_field.cc b/src/google/protobuf/compiler/java/java_enum_field.cc index ec0b067e..cab9bd0e 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.cc +++ b/src/google/protobuf/compiler/java/java_enum_field.cc @@ -35,10 +35,12 @@ #include #include -#include -#include #include +#include +#include +#include #include +#include #include #include #include @@ -50,20 +52,19 @@ namespace java { namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, map* variables) { - (*variables)["name"] = - UnderscoresToCamelCase(descriptor); - (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); - (*variables)["constant_name"] = FieldConstantName(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = ClassName(descriptor->enum_type()); - (*variables)["default"] = DefaultValue(descriptor); + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["type"] = + name_resolver->GetImmutableClassName(descriptor->enum_type()); + (*variables)["mutable_type"] = + name_resolver->GetMutableClassName(descriptor->enum_type()); + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); (*variables)["tag"] = SimpleItoa(internal::WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor))); @@ -74,14 +75,28 @@ void SetEnumVariables(const FieldDescriptor* descriptor, (*variables)["on_changed"] = HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; - // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["set_has_field_bit_builder"] = + GenerateSetBit(builderBitIndex) + ";"; + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_builder"] = ""; + (*variables)["clear_has_field_bit_builder"] = ""; - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex); + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != " + (*variables)["default"]; + } // For repated builders, one bit is used for whether the array is immutable. (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -105,44 +120,53 @@ void SetEnumVariables(const FieldDescriptor* descriptor, // =================================================================== -EnumFieldGenerator:: -EnumFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex) +ImmutableEnumFieldGenerator:: +ImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_); + builderBitIndex_(builderBitIndex), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -EnumFieldGenerator::~EnumFieldGenerator() {} +ImmutableEnumFieldGenerator::~ImmutableEnumFieldGenerator() {} -int EnumFieldGenerator::GetNumBitsForMessage() const { +int ImmutableEnumFieldGenerator::GetNumBitsForMessage() const { return 1; } -int EnumFieldGenerator::GetNumBitsForBuilder() const { +int ImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private $type$ $name$_;\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$ get$capitalized_name$() {\n" @@ -150,15 +174,17 @@ GenerateMembers(io::Printer* printer) const { "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, "private $type$ $name$_ = $default$;\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$ get$capitalized_name$() {\n" @@ -170,7 +196,7 @@ GenerateBuilderMembers(io::Printer* printer) const { " if (value == null) {\n" " throw new NullPointerException();\n" " }\n" - " $set_has_field_bit_builder$;\n" + " $set_has_field_bit_builder$\n" " $name$_ = value;\n" " $on_changed$\n" " return this;\n" @@ -178,129 +204,274 @@ GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public Builder clear$capitalized_name$() {\n" - " $clear_has_field_bit_builder$;\n" + " $clear_has_field_bit_builder$\n" " $name$_ = $default$;\n" " $on_changed$\n" " return this;\n" "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for enums } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print(variables_, - "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$;\n"); + "$name$_ = $default$;\n" + "$clear_has_field_bit_builder$\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } else { + printer->Print(variables_, + "if (other.get$capitalized_name$() != $default$) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n" "result.$name$_ = $name$_;\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n"); - if (HasUnknownFields(descriptor_->containing_type())) { + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (UseUnknownFieldSet(descriptor_->containing_type())) { printer->Print(variables_, - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n"); + " unknownFields.mergeVarintField($number$, rawValue);\n"); } else { printer->Print(variables_, - "if (value != null) {\n"); + " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" + " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); } printer->Print(variables_, - " $set_has_field_bit_message$;\n" + "} else {\n" + " $set_has_field_bit_message$\n" " $name$_ = value;\n" "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { // noop for enums } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " output.writeEnum($number$, $name$_.getNumber());\n" "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" " .computeEnumSize($number$, $name$_.getNumber());\n" "}\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "result = result &&\n" " (get$capitalized_name$() == other.get$capitalized_name$());\n"); } -void EnumFieldGenerator:: +void ImmutableEnumFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n" - "hash = (53 * hash) + hashEnum(get$capitalized_name$());\n"); + "hash = (53 * hash) + com.google.protobuf.Internal.hashEnum(\n" + " get$capitalized_name$());\n"); +} + +string ImmutableEnumFieldGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); +} + +// =================================================================== + +ImmutableEnumOneofFieldGenerator:: +ImmutableEnumOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableEnumFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutableEnumOneofFieldGenerator:: +~ImmutableEnumOneofFieldGenerator() {} + +void ImmutableEnumOneofFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); } -string EnumFieldGenerator::GetBoxedType() const { - return ClassName(descriptor_->enum_type()); +void ImmutableEnumOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + " if (value == null) {\n" + " throw new NullPointerException();\n" + " }\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); +} + +void ImmutableEnumOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); +} + +void ImmutableEnumOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "set$capitalized_name$(other.get$capitalized_name$());\n"); +} + +void ImmutableEnumOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "int rawValue = input.readEnum();\n" + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (UseUnknownFieldSet(descriptor_->containing_type())) { + printer->Print(variables_, + " unknownFields.mergeVarintField($number$, rawValue);\n"); + } else { + printer->Print(variables_, + " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" + " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); + } + printer->Print(variables_, + "} else {\n" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + "}\n"); +} + +void ImmutableEnumOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeEnum($number$, (($type$) $oneof_name$_).getNumber());\n" + "}\n"); +} + +void ImmutableEnumOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeEnumSize($number$, (($type$) $oneof_name$_).getNumber());\n" + "}\n"); } // =================================================================== -RepeatedEnumFieldGenerator:: -RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex) +RepeatedImmutableEnumFieldGenerator:: +RepeatedImmutableEnumFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex) { - SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, &variables_); + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetEnumVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {} +RepeatedImmutableEnumFieldGenerator::~RepeatedImmutableEnumFieldGenerator() {} -int RepeatedEnumFieldGenerator::GetNumBitsForMessage() const { +int RepeatedImmutableEnumFieldGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedEnumFieldGenerator::GetNumBitsForBuilder() const { +int RepeatedImmutableEnumFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -313,10 +484,11 @@ GenerateInterfaceMembers(io::Printer* printer) const { "$deprecation$$type$ get$capitalized_name$(int index);\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private java.util.List<$type$> $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" @@ -340,7 +512,7 @@ GenerateMembers(io::Printer* printer) const { } } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, // One field is the list and the other field keeps track of whether the @@ -409,7 +581,8 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$public Builder addAll$capitalized_name$(\n" " java.lang.Iterable values) {\n" " ensure$capitalized_name$IsMutable();\n" - " super.addAll(values, $name$_);\n" + " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -423,24 +596,24 @@ GenerateBuilderMembers(io::Printer* printer) const { "}\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for enums } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n" "$clear_mutable_bit_builder$;\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { // The code below does two optimizations: // 1. If the other list is empty, there's nothing to do. This ensures we @@ -460,7 +633,7 @@ GenerateMergingCode(io::Printer* printer) const { "}\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { // The code below ensures that the result has an immutable list. If our // list is immutable, we can just reuse it. If not, we make it immutable. @@ -472,22 +645,23 @@ GenerateBuildingCode(io::Printer* printer) const { "result.$name$_ = $name$_;\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { // Read and store the enum printer->Print(variables_, "int rawValue = input.readEnum();\n" - "$type$ value = $type$.valueOf(rawValue);\n"); - if (HasUnknownFields(descriptor_->containing_type())) { + "$type$ value = $type$.valueOf(rawValue);\n" + "if (value == null) {\n"); + if (UseUnknownFieldSet(descriptor_->containing_type())) { printer->Print(variables_, - "if (value == null) {\n" - " unknownFields.mergeVarintField($number$, rawValue);\n" - "} else {\n"); + " unknownFields.mergeVarintField($number$, rawValue);\n"); } else { printer->Print(variables_, - "if (value != null) {\n"); + " unknownFieldsCodedOutput.writeRawVarint32(tag);\n" + " unknownFieldsCodedOutput.writeRawVarint32(rawValue);\n"); } printer->Print(variables_, + " } else {\n" " if (!$get_mutable_bit_parser$) {\n" " $name$_ = new java.util.ArrayList<$type$>();\n" " $set_mutable_bit_parser$;\n" @@ -496,7 +670,7 @@ GenerateParsingCode(io::Printer* printer) const { "}\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { // Wrap GenerateParsingCode's contents with a while loop. @@ -514,7 +688,7 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { "input.popLimit(oldLimit);\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { printer->Print(variables_, "if ($get_mutable_bit_parser$) {\n" @@ -522,7 +696,7 @@ GenerateParsingDoneCode(io::Printer* printer) const { "}\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, @@ -541,7 +715,7 @@ GenerateSerializationCode(io::Printer* printer) const { } } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "{\n" @@ -577,24 +751,25 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "result = result && get$capitalized_name$List()\n" " .equals(other.get$capitalized_name$List());\n"); } -void RepeatedEnumFieldGenerator:: +void RepeatedImmutableEnumFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, "if (get$capitalized_name$Count() > 0) {\n" " hash = (37 * hash) + $constant_name$;\n" - " hash = (53 * hash) + hashEnumList(get$capitalized_name$List());\n" + " hash = (53 * hash) + com.google.protobuf.Internal.hashEnumList(\n" + " get$capitalized_name$List());\n" "}\n"); } -string RepeatedEnumFieldGenerator::GetBoxedType() const { - return ClassName(descriptor_->enum_type()); +string RepeatedImmutableEnumFieldGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->enum_type()); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_enum_field.h b/src/google/protobuf/compiler/java/java_enum_field.h index 90fae639..a3afb160 100644 --- a/src/google/protobuf/compiler/java/java_enum_field.h +++ b/src/google/protobuf/compiler/java/java_enum_field.h @@ -40,17 +40,27 @@ #include namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + namespace protobuf { namespace compiler { namespace java { -class EnumFieldGenerator : public FieldGenerator { +class ImmutableEnumFieldGenerator : public ImmutableFieldGenerator { public: - explicit EnumFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex); - ~EnumFieldGenerator(); + explicit ImmutableEnumFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableEnumFieldGenerator(); - // implements FieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -70,22 +80,45 @@ class EnumFieldGenerator : public FieldGenerator { string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; const int messageBitIndex_; const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator); + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldGenerator); +}; + +class ImmutableEnumOneofFieldGenerator : public ImmutableEnumFieldGenerator { + public: + ImmutableEnumOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableEnumOneofFieldGenerator(); + + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldGenerator); }; -class RepeatedEnumFieldGenerator : public FieldGenerator { +class RepeatedImmutableEnumFieldGenerator : public ImmutableFieldGenerator { public: - explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex); - ~RepeatedEnumFieldGenerator(); + explicit RepeatedImmutableEnumFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableEnumFieldGenerator(); - // implements FieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -111,8 +144,10 @@ class RepeatedEnumFieldGenerator : public FieldGenerator { map variables_; const int messageBitIndex_; const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc index 921fe658..c62dbfaf 100644 --- a/src/google/protobuf/compiler/java/java_extension.cc +++ b/src/google/protobuf/compiler/java/java_extension.cc @@ -33,74 +33,50 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include #include #include -#include +#include #include +#include namespace google { namespace protobuf { namespace compiler { namespace java { -namespace { - -const char* TypeName(FieldDescriptor::Type field_type) { - switch (field_type) { - case FieldDescriptor::TYPE_INT32 : return "INT32"; - case FieldDescriptor::TYPE_UINT32 : return "UINT32"; - case FieldDescriptor::TYPE_SINT32 : return "SINT32"; - case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; - case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; - case FieldDescriptor::TYPE_INT64 : return "INT64"; - case FieldDescriptor::TYPE_UINT64 : return "UINT64"; - case FieldDescriptor::TYPE_SINT64 : return "SINT64"; - case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; - case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; - case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; - case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; - case FieldDescriptor::TYPE_BOOL : return "BOOL"; - case FieldDescriptor::TYPE_STRING : return "STRING"; - case FieldDescriptor::TYPE_BYTES : return "BYTES"; - case FieldDescriptor::TYPE_ENUM : return "ENUM"; - case FieldDescriptor::TYPE_GROUP : return "GROUP"; - case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; -} - -} - -ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor) - : descriptor_(descriptor) { +ImmutableExtensionGenerator::ImmutableExtensionGenerator( + const FieldDescriptor* descriptor, Context* context) + : descriptor_(descriptor), context_(context), + name_resolver_(context->GetNameResolver()) { if (descriptor_->extension_scope() != NULL) { - scope_ = ClassName(descriptor_->extension_scope()); + scope_ = name_resolver_->GetImmutableClassName( + descriptor_->extension_scope()); } else { - scope_ = ClassName(descriptor_->file()); + scope_ = name_resolver_->GetImmutableClassName(descriptor_->file()); } } -ExtensionGenerator::~ExtensionGenerator() {} +ImmutableExtensionGenerator::~ImmutableExtensionGenerator() {} // Initializes the vars referenced in the generated code templates. -void InitTemplateVars(const FieldDescriptor* descriptor, - const string& scope, - map* vars_pointer) { +void ExtensionGenerator::InitTemplateVars(const FieldDescriptor* descriptor, + const string& scope, + bool immutable, + ClassNameResolver* name_resolver, + map* vars_pointer) { map &vars = *vars_pointer; vars["scope"] = scope; vars["name"] = UnderscoresToCamelCase(descriptor); - vars["containing_type"] = ClassName(descriptor->containing_type()); + vars["containing_type"] = + name_resolver->GetClassName(descriptor->containing_type(), immutable); vars["number"] = SimpleItoa(descriptor->number()); vars["constant_name"] = FieldConstantName(descriptor); vars["index"] = SimpleItoa(descriptor->index()); - vars["default"] = - descriptor->is_repeated() ? "" : DefaultValue(descriptor); - vars["type_constant"] = TypeName(GetType(descriptor)); + vars["default"] = descriptor->is_repeated() ? + "" : DefaultValue(descriptor, immutable, name_resolver); + vars["type_constant"] = FieldTypeName(GetType(descriptor)); vars["packed"] = descriptor->options().packed() ? "true" : "false"; vars["enum_map"] = "null"; vars["prototype"] = "null"; @@ -109,13 +85,21 @@ void InitTemplateVars(const FieldDescriptor* descriptor, string singular_type; switch (java_type) { case JAVATYPE_MESSAGE: - singular_type = ClassName(descriptor->message_type()); + singular_type = name_resolver->GetClassName(descriptor->message_type(), + immutable); vars["prototype"] = singular_type + ".getDefaultInstance()"; break; case JAVATYPE_ENUM: - singular_type = ClassName(descriptor->enum_type()); + singular_type = name_resolver->GetClassName(descriptor->enum_type(), + immutable); vars["enum_map"] = singular_type + ".internalGetValueMap()"; break; + case JAVATYPE_STRING: + singular_type = "java.lang.String"; + break; + case JAVATYPE_BYTES: + singular_type = immutable ? "com.google.protobuf.ByteString" : "byte[]"; + break; default: singular_type = BoxedPrimitiveTypeName(java_type); break; @@ -125,9 +109,11 @@ void InitTemplateVars(const FieldDescriptor* descriptor, vars["singular_type"] = singular_type; } -void ExtensionGenerator::Generate(io::Printer* printer) { +void ImmutableExtensionGenerator::Generate(io::Printer* printer) { map vars; - InitTemplateVars(descriptor_, scope_, &vars); + const bool kUseImmutableNames = true; + InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_, + &vars); printer->Print(vars, "public static final int $constant_name$ = $number$;\n"); @@ -174,7 +160,8 @@ void ExtensionGenerator::Generate(io::Printer* printer) { " $enum_map$,\n" " $number$,\n" " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" - " $packed$);\n"); + " $packed$,\n" + " $singular_type$.class);\n"); } else { printer->Print( vars, @@ -188,12 +175,13 @@ void ExtensionGenerator::Generate(io::Printer* printer) { " $prototype$,\n" " $enum_map$,\n" " $number$,\n" - " com.google.protobuf.WireFormat.FieldType.$type_constant$);\n"); + " com.google.protobuf.WireFormat.FieldType.$type_constant$,\n" + " $singular_type$.class);\n"); } } } -void ExtensionGenerator::GenerateNonNestedInitializationCode( +void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode( io::Printer* printer) { if (descriptor_->extension_scope() == NULL && HasDescriptorMethods(descriptor_->file())) { @@ -205,7 +193,8 @@ void ExtensionGenerator::GenerateNonNestedInitializationCode( } } -void ExtensionGenerator::GenerateRegistrationCode(io::Printer* printer) { +void ImmutableExtensionGenerator::GenerateRegistrationCode( + io::Printer* printer) { printer->Print( "registry.add($scope$.$name$);\n", "scope", scope_, diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h index 009ed9ff..69686ef2 100644 --- a/src/google/protobuf/compiler/java/java_extension.h +++ b/src/google/protobuf/compiler/java/java_extension.h @@ -35,6 +35,7 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ +#include #include #include @@ -42,6 +43,12 @@ namespace google { namespace protobuf { class FieldDescriptor; // descriptor.h + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { class Printer; // printer.h } @@ -56,17 +63,42 @@ namespace java { // since extensions are just simple identifiers with interesting types. class ExtensionGenerator { public: - explicit ExtensionGenerator(const FieldDescriptor* descriptor); - ~ExtensionGenerator(); + explicit ExtensionGenerator() {} + virtual ~ExtensionGenerator() {} + + virtual void Generate(io::Printer* printer) = 0; + virtual void GenerateNonNestedInitializationCode(io::Printer* printer) = 0; + virtual void GenerateRegistrationCode(io::Printer* printer) = 0; - void Generate(io::Printer* printer); - void GenerateNonNestedInitializationCode(io::Printer* printer); - void GenerateRegistrationCode(io::Printer* printer); + protected: + static void InitTemplateVars(const FieldDescriptor* descriptor, + const string& scope, + bool immutable, + ClassNameResolver* name_resolver, + map* vars_pointer); private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); +}; + +class ImmutableExtensionGenerator : public ExtensionGenerator { + public: + explicit ImmutableExtensionGenerator(const FieldDescriptor* descriptor, + Context* context); + virtual ~ImmutableExtensionGenerator(); + + virtual void Generate(io::Printer* printer); + virtual void GenerateNonNestedInitializationCode(io::Printer* printer); + virtual void GenerateRegistrationCode(io::Printer* printer); + + protected: const FieldDescriptor* descriptor_; + Context* context_; + ClassNameResolver* name_resolver_; string scope_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator); }; } // namespace java @@ -74,4 +106,4 @@ class ExtensionGenerator { } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__ diff --git a/src/google/protobuf/compiler/java/java_field.cc b/src/google/protobuf/compiler/java/java_field.cc index c7d433c8..f670477c 100644 --- a/src/google/protobuf/compiler/java/java_field.cc +++ b/src/google/protobuf/compiler/java/java_field.cc @@ -33,102 +33,178 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include -#include -#include + +#include + +#include +#include #include +#include +#include #include +#include #include -#include +#include +#include +#include namespace google { namespace protobuf { namespace compiler { namespace java { -FieldGenerator::~FieldGenerator() {} +namespace { + +ImmutableFieldGenerator* MakeImmutableGenerator( + const FieldDescriptor* field, int messageBitIndex, int builderBitIndex, + Context* context) { + if (field->is_repeated()) { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + if (IsLazy(field)) { + return new RepeatedImmutableLazyMessageFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new RepeatedImmutableMessageFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + case JAVATYPE_ENUM: + return new RepeatedImmutableEnumFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new RepeatedImmutableStringFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + default: + return new RepeatedImmutablePrimitiveFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + } else { + if (field->containing_oneof()) { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + if (IsLazy(field)) { + return new ImmutableLazyMessageOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new ImmutableMessageOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + case JAVATYPE_ENUM: + return new ImmutableEnumOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new ImmutableStringOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + default: + return new ImmutablePrimitiveOneofFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + } else { + switch (GetJavaType(field)) { + case JAVATYPE_MESSAGE: + if (IsLazy(field)) { + return new ImmutableLazyMessageFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } else { + return new ImmutableMessageFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + case JAVATYPE_ENUM: + return new ImmutableEnumFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + case JAVATYPE_STRING: + return new ImmutableStringFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + default: + return new ImmutablePrimitiveFieldGenerator( + field, messageBitIndex, builderBitIndex, context); + } + } + } +} + -void FieldGenerator::GenerateParsingCodeFromPacked(io::Printer* printer) const { +static inline void ReportUnexpectedPackedFieldsCall(io::Printer* printer) { // Reaching here indicates a bug. Cases are: - // - This FieldGenerator should support packing, but this method should be - // overridden. - // - This FieldGenerator doesn't support packing, and this method should - // never have been called. + // - This FieldGenerator should support packing, + // but this method should be overridden. + // - This FieldGenerator doesn't support packing, and this method + // should never have been called. GOOGLE_LOG(FATAL) << "GenerateParsingCodeFromPacked() " << "called on field generator that does not support packing."; } -FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor) - : descriptor_(descriptor), - field_generators_( - new scoped_ptr[descriptor->field_count()]), - extension_generators_( - new scoped_ptr[descriptor->extension_count()]) { +} // namespace + +ImmutableFieldGenerator::~ImmutableFieldGenerator() {} + +void ImmutableFieldGenerator:: +GenerateParsingCodeFromPacked(io::Printer* printer) const { + ReportUnexpectedPackedFieldsCall(printer); +} + +// =================================================================== + +template <> +FieldGeneratorMap::FieldGeneratorMap( + const Descriptor* descriptor, Context* context) + : descriptor_(descriptor), + field_generators_(new scoped_ptr< + ImmutableFieldGenerator>[descriptor->field_count()]) { // Construct all the FieldGenerators and assign them bit indices for their // bit fields. int messageBitIndex = 0; int builderBitIndex = 0; for (int i = 0; i < descriptor->field_count(); i++) { - FieldGenerator* generator = MakeGenerator(descriptor->field(i), - messageBitIndex, builderBitIndex); + ImmutableFieldGenerator* generator = MakeImmutableGenerator( + descriptor->field(i), messageBitIndex, builderBitIndex, context); field_generators_[i].reset(generator); messageBitIndex += generator->GetNumBitsForMessage(); builderBitIndex += generator->GetNumBitsForBuilder(); } - for (int i = 0; i < descriptor->extension_count(); i++) { - FieldGenerator* generator = MakeGenerator(descriptor->extension(i), - messageBitIndex, builderBitIndex); - extension_generators_[i].reset(generator); - messageBitIndex += generator->GetNumBitsForMessage(); - builderBitIndex += generator->GetNumBitsForBuilder(); - } } -FieldGenerator* FieldGeneratorMap::MakeGenerator( - const FieldDescriptor* field, int messageBitIndex, int builderBitIndex) { - if (field->is_repeated()) { - switch (GetJavaType(field)) { - case JAVATYPE_MESSAGE: - return new RepeatedMessageFieldGenerator( - field, messageBitIndex, builderBitIndex); - case JAVATYPE_ENUM: - return new RepeatedEnumFieldGenerator( - field, messageBitIndex, builderBitIndex); - case JAVATYPE_STRING: - return new RepeatedStringFieldGenerator( - field, messageBitIndex, builderBitIndex); - default: - return new RepeatedPrimitiveFieldGenerator( - field, messageBitIndex, builderBitIndex); - } - } else { - switch (GetJavaType(field)) { - case JAVATYPE_MESSAGE: - return new MessageFieldGenerator( - field, messageBitIndex, builderBitIndex); - case JAVATYPE_ENUM: - return new EnumFieldGenerator( - field, messageBitIndex, builderBitIndex); - case JAVATYPE_STRING: - return new StringFieldGenerator( - field, messageBitIndex, builderBitIndex); - default: - return new PrimitiveFieldGenerator( - field, messageBitIndex, builderBitIndex); - } - } -} +template<> +FieldGeneratorMap::~FieldGeneratorMap() {} -FieldGeneratorMap::~FieldGeneratorMap() {} -const FieldGenerator& FieldGeneratorMap::get( - const FieldDescriptor* field) const { - GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); - return *field_generators_[field->index()]; +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + const FieldGeneratorInfo* info, + map* variables) { + (*variables)["field_name"] = descriptor->name(); + (*variables)["name"] = info->name; + (*variables)["capitalized_name"] = info->capitalized_name; + (*variables)["disambiguated_reason"] = info->disambiguated_reason; + (*variables)["constant_name"] = FieldConstantName(descriptor); + (*variables)["number"] = SimpleItoa(descriptor->number()); } -const FieldGenerator& FieldGeneratorMap::get_extension(int index) const { - return *extension_generators_[index]; +void SetCommonOneofVariables(const FieldDescriptor* descriptor, + const OneofGeneratorInfo* info, + map* variables) { + (*variables)["oneof_name"] = info->name; + (*variables)["oneof_capitalized_name"] = info->capitalized_name; + (*variables)["oneof_index"] = + SimpleItoa(descriptor->containing_oneof()->index()); + (*variables)["set_oneof_case_message"] = info->name + + "Case_ = " + SimpleItoa(descriptor->number()); + (*variables)["clear_oneof_case_message"] = info->name + + "Case_ = 0"; + (*variables)["has_oneof_case_message"] = info->name + + "Case_ == " + SimpleItoa(descriptor->number()); +} + +void PrintExtraFieldInfo(const map& variables, + io::Printer* printer) { + const map::const_iterator it = + variables.find("disambiguated_reason"); + if (it != variables.end() && !it->second.empty()) { + printer->Print( + variables, + "// An alternative name is used for field \"$field_name$\" because:\n" + "// $disambiguated_reason$\n"); + } } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_field.h b/src/google/protobuf/compiler/java/java_field.h index 4dd0efd6..a4aa3bce 100644 --- a/src/google/protobuf/compiler/java/java_field.h +++ b/src/google/protobuf/compiler/java/java_field.h @@ -35,14 +35,23 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__ +#include +#include #include + #include #include namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { - class Printer; // printer.h + class Printer; // printer.h } } @@ -50,10 +59,10 @@ namespace protobuf { namespace compiler { namespace java { -class FieldGenerator { +class ImmutableFieldGenerator { public: - FieldGenerator() {} - virtual ~FieldGenerator(); + ImmutableFieldGenerator() {} + virtual ~ImmutableFieldGenerator(); virtual int GetNumBitsForMessage() const = 0; virtual int GetNumBitsForBuilder() const = 0; @@ -78,29 +87,73 @@ class FieldGenerator { virtual string GetBoxedType() const = 0; private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator); }; + // Convenience class which constructs FieldGenerators for a Descriptor. +template class FieldGeneratorMap { public: - explicit FieldGeneratorMap(const Descriptor* descriptor); + explicit FieldGeneratorMap(const Descriptor* descriptor, + Context* context); ~FieldGeneratorMap(); - const FieldGenerator& get(const FieldDescriptor* field) const; - const FieldGenerator& get_extension(int index) const; + const FieldGeneratorType& get(const FieldDescriptor* field) const; private: const Descriptor* descriptor_; - scoped_array > field_generators_; - scoped_array > extension_generators_; - - static FieldGenerator* MakeGenerator(const FieldDescriptor* field, - int messageBitIndex, int builderBitIndex); + Context* context_; + ClassNameResolver* name_resolver_; + scoped_array > field_generators_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap); }; +template +inline const FieldGeneratorType& +FieldGeneratorMap::get(const FieldDescriptor* field) const { + GOOGLE_CHECK_EQ(field->containing_type(), descriptor_); + return *field_generators_[field->index()]; +} + +// Instantiate template for mutable and immutable maps. +template<> +FieldGeneratorMap:: +FieldGeneratorMap(const Descriptor* descriptor, + Context* context); + +template<> +FieldGeneratorMap::~FieldGeneratorMap(); + + +// Field information used in FieldGeneartors. +struct FieldGeneratorInfo { + string name; + string capitalized_name; + string disambiguated_reason; +}; + +// Oneof information used in OneofFieldGeneartors. +struct OneofGeneratorInfo { + string name; + string capitalized_name; +}; + +// Set some common variables used in variable FieldGenerators. +void SetCommonFieldVariables(const FieldDescriptor* descriptor, + const FieldGeneratorInfo* info, + map* variables); + +// Set some common oneof variables used in OneofFieldGenerators. +void SetCommonOneofVariables(const FieldDescriptor* descriptor, + const OneofGeneratorInfo* info, + map* variables); + +// Print useful comments before a field's accessors. +void PrintExtraFieldInfo(const map& variables, + io::Printer* printer); + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc index f43e5500..deec0e71 100644 --- a/src/google/protobuf/compiler/java/java_file.cc +++ b/src/google/protobuf/compiler/java/java_file.cc @@ -33,11 +33,17 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include + +#include #include -#include #include +#include #include #include +#include +#include #include #include #include @@ -132,10 +138,27 @@ void CollectExtensions(const FileDescriptorProto& file_proto, } // namespace -FileGenerator::FileGenerator(const FileDescriptor* file) - : file_(file), - java_package_(FileJavaPackage(file)), - classname_(FileClassName(file)) { +FileGenerator::FileGenerator(const FileDescriptor* file, bool immutable_api) + : file_(file), + java_package_(FileJavaPackage(file, immutable_api)), + message_generators_( + new scoped_ptr[file->message_type_count()]), + extension_generators_( + new scoped_ptr[file->extension_count()]), + context_(new Context(file)), + name_resolver_(context_->GetNameResolver()), + immutable_api_(immutable_api) { + classname_ = name_resolver_->GetFileClassName(file, immutable_api); + generator_factory_.reset( + new ImmutableGeneratorFactory(context_.get())); + for (int i = 0; i < file_->message_type_count(); ++i) { + message_generators_[i].reset( + generator_factory_->NewMessageGenerator(file_->message_type(i))); + } + for (int i = 0; i < file_->extension_count(); ++i) { + extension_generators_[i].reset( + generator_factory_->NewExtensionGenerator(file_->extension(i))); + } } FileGenerator::~FileGenerator() {} @@ -145,25 +168,7 @@ bool FileGenerator::Validate(string* error) { // problem that leads to Java compile errors that can be hard to understand. // It's especially bad when using the java_multiple_files, since we would // end up overwriting the outer class with one of the inner ones. - - bool found_conflict = false; - for (int i = 0; i < file_->enum_type_count() && !found_conflict; i++) { - if (file_->enum_type(i)->name() == classname_) { - found_conflict = true; - } - } - for (int i = 0; i < file_->message_type_count() && !found_conflict; i++) { - if (file_->message_type(i)->name() == classname_) { - found_conflict = true; - } - } - for (int i = 0; i < file_->service_count() && !found_conflict; i++) { - if (file_->service(i)->name() == classname_) { - found_conflict = true; - } - } - - if (found_conflict) { + if (name_resolver_->HasConflictingClassName(file_, classname_)) { error->assign(file_->name()); error->append( ": Cannot generate Java output because the file's outer class name, \""); @@ -174,7 +179,29 @@ bool FileGenerator::Validate(string* error) { "option to specify a different outer class name for the .proto file."); return false; } - + // If java_outer_classname option is not set and the default outer class name + // conflicts with a type defined in the message, we will append a suffix to + // avoid the conflict. This allows proto1 API protos to be dual-compiled into + // proto2 API without code change. When this happens we'd like to issue an + // warning to let the user know that the outer class name has been changed. + // Although we only do this automatic naming fix for immutable API, mutable + // outer class name will also be affected as it's contructed from immutable + // outer class name with an additional "Mutable" prefix. Since the naming + // change in mutable API is not caused by a naming conflict, we generate the + // warning for immutable API only. + if (immutable_api_ && !file_->options().has_java_outer_classname()) { + string default_classname = + name_resolver_->GetFileDefaultImmutableClassName(file_); + if (default_classname != classname_) { + GOOGLE_LOG(WARNING) << file_->name() << ": The default outer class name, \"" + << default_classname << "\", conflicts with a type " + << "declared in the proto file and an alternative outer " + << "class name is used: \"" << classname_ << "\". To avoid " + << "this warning, please use the java_outer_classname " + << "option to specify a different outer class name for " + << "the .proto file."; + } + } return true; } @@ -208,12 +235,11 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Indent(); for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator(file_->extension(i)).GenerateRegistrationCode(printer); + extension_generators_[i]->GenerateRegistrationCode(printer); } for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator(file_->message_type(i)) - .GenerateExtensionRegistrationCode(printer); + message_generators_[i]->GenerateExtensionRegistrationCode(printer); } printer->Outdent(); @@ -222,18 +248,20 @@ void FileGenerator::Generate(io::Printer* printer) { // ----------------------------------------------------------------- - if (!file_->options().java_multiple_files()) { + if (!MultipleJavaFiles(file_, immutable_api_)) { for (int i = 0; i < file_->enum_type_count(); i++) { - EnumGenerator(file_->enum_type(i)).Generate(printer); + EnumGenerator(file_->enum_type(i), immutable_api_, context_.get()) + .Generate(printer); } for (int i = 0; i < file_->message_type_count(); i++) { - MessageGenerator messageGenerator(file_->message_type(i)); - messageGenerator.GenerateInterface(printer); - messageGenerator.Generate(printer); + message_generators_[i]->GenerateInterface(printer); + message_generators_[i]->Generate(printer); } if (HasGenericServices(file_)) { for (int i = 0; i < file_->service_count(); i++) { - ServiceGenerator(file_->service(i)).Generate(printer); + scoped_ptr generator( + generator_factory_->NewServiceGenerator(file_->service(i))); + generator->Generate(printer); } } } @@ -241,28 +269,29 @@ void FileGenerator::Generate(io::Printer* printer) { // Extensions must be generated in the outer class since they are values, // not classes. for (int i = 0; i < file_->extension_count(); i++) { - ExtensionGenerator(file_->extension(i)).Generate(printer); + extension_generators_[i]->Generate(printer); } // Static variables. for (int i = 0; i < file_->message_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(file_->message_type(i)).GenerateStaticVariables(printer); + message_generators_[i]->GenerateStaticVariables(printer); } printer->Print("\n"); if (HasDescriptorMethods(file_)) { - GenerateEmbeddedDescriptor(printer); + if (immutable_api_) { + GenerateDescriptorInitializationCodeForImmutable(printer); + } else { + GenerateDescriptorInitializationCodeForMutable(printer); + } } else { printer->Print( "static {\n"); printer->Indent(); for (int i = 0; i < file_->message_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(file_->message_type(i)) - .GenerateStaticVariableInitializers(printer); + message_generators_[i]->GenerateStaticVariableInitializers(printer); } printer->Outdent(); @@ -278,23 +307,8 @@ void FileGenerator::Generate(io::Printer* printer) { printer->Print("}\n"); } -void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { - // Embed the descriptor. We simply serialize the entire FileDescriptorProto - // and embed it as a string literal, which is parsed and built into real - // descriptors at initialization time. We unfortunately have to put it in - // a string literal, not a byte array, because apparently using a literal - // byte array causes the Java compiler to generate *instructions* to - // initialize each and every byte of the array, e.g. as if you typed: - // b[0] = 123; b[1] = 456; b[2] = 789; - // This makes huge bytecode files and can easily hit the compiler's internal - // code size limits (error "code to large"). String literals are apparently - // embedded raw, which is what we want. - FileDescriptorProto file_proto; - file_->CopyTo(&file_proto); - - string file_data; - file_proto.SerializeToString(&file_data); - +void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( + io::Printer* printer) { printer->Print( "public static com.google.protobuf.Descriptors.FileDescriptor\n" " getDescriptor() {\n" @@ -302,55 +316,18 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { "}\n" "private static com.google.protobuf.Descriptors.FileDescriptor\n" " descriptor;\n" - "static {\n" - " java.lang.String[] descriptorData = {\n"); + "static {\n"); printer->Indent(); - printer->Indent(); - - // Only write 40 bytes per line. - static const int kBytesPerLine = 40; - for (int i = 0; i < file_data.size(); i += kBytesPerLine) { - if (i > 0) { - // Every 400 lines, start a new string literal, in order to avoid the - // 64k length limit. - if (i % 400 == 0) { - printer->Print(",\n"); - } else { - printer->Print(" +\n"); - } - } - printer->Print("\"$data$\"", - "data", CEscape(file_data.substr(i, kBytesPerLine))); - } - - printer->Outdent(); - printer->Print("\n};\n"); - - // ----------------------------------------------------------------- - // Create the InternalDescriptorAssigner. printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor." - "InternalDescriptorAssigner assigner =\n" - " new com.google.protobuf.Descriptors.FileDescriptor." - "InternalDescriptorAssigner() {\n" - " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n" - " com.google.protobuf.Descriptors.FileDescriptor root) {\n" - " descriptor = root;\n"); - - printer->Indent(); - printer->Indent(); - printer->Indent(); + "descriptor = $descriptor_classname$.descriptor;\n", + "descriptor_classname", name_resolver_->GetDescriptorClassName(file_)); for (int i = 0; i < file_->message_type_count(); i++) { - // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(file_->message_type(i)) - .GenerateStaticVariableInitializers(printer); + message_generators_[i]->GenerateStaticVariableInitializers(printer); } for (int i = 0; i < file_->extension_count(); i++) { - // TODO(kenton): Reuse ExtensionGenerator objects? - ExtensionGenerator(file_->extension(i)) - .GenerateNonNestedInitializationCode(printer); + extension_generators_[i]->GenerateNonNestedInitializationCode(printer); } // Proto compiler builds a DescriptorPool, which holds all the descriptors to @@ -368,52 +345,107 @@ void FileGenerator::GenerateEmbeddedDescriptor(io::Printer* printer) { // To find those extensions, we need to parse the data into a dynamic message // of the FileDescriptor based on the builder-pool, then we can use // reflections to find all extension fields + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + string file_data; + file_proto.SerializeToString(&file_data); vector extensions; CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); if (extensions.size() > 0) { // Must construct an ExtensionRegistry containing all existing extensions - // and return it. + // and use it to parse the descriptor data again to recognize extensions. printer->Print( "com.google.protobuf.ExtensionRegistry registry =\n" - " com.google.protobuf.ExtensionRegistry.newInstance();\n"); + " com.google.protobuf.ExtensionRegistry.newInstance();\n"); for (int i = 0; i < extensions.size(); i++) { - ExtensionGenerator(extensions[i]).GenerateRegistrationCode(printer); + scoped_ptr generator( + generator_factory_->NewExtensionGenerator(extensions[i])); + generator->GenerateRegistrationCode(printer); } printer->Print( - "return registry;\n"); - } else { - printer->Print( - "return null;\n"); + "com.google.protobuf.Descriptors.FileDescriptor\n" + " .internalUpdateFileDescriptor(descriptor, registry);\n"); } - printer->Outdent(); - printer->Outdent(); - printer->Outdent(); + // Force descriptor initialization of all dependencies. + for (int i = 0; i < file_->dependency_count(); i++) { + if (ShouldIncludeDependency(file_->dependency(i), true)) { + string dependency = + name_resolver_->GetImmutableClassName(file_->dependency(i)); + printer->Print( + "$dependency$.getDescriptor();\n", + "dependency", dependency); + } + } + printer->Outdent(); printer->Print( - " }\n" - " };\n"); + "}\n"); +} - // ----------------------------------------------------------------- - // Invoke internalBuildGeneratedFileFrom() to build the file. +void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer* printer) { + printer->Print( + "public static com.google.protobuf.Descriptors.FileDescriptor\n" + " getDescriptor() {\n" + " return descriptor;\n" + "}\n" + "private static com.google.protobuf.Descriptors.FileDescriptor\n" + " descriptor;\n" + "static {\n"); + printer->Indent(); printer->Print( - "com.google.protobuf.Descriptors.FileDescriptor\n" - " .internalBuildGeneratedFileFrom(descriptorData,\n" - " new com.google.protobuf.Descriptors.FileDescriptor[] {\n"); + "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n", + "immutable_package", FileJavaPackage(file_, true), + "descriptor_classname", name_resolver_->GetDescriptorClassName(file_)); + for (int i = 0; i < file_->message_type_count(); i++) { + message_generators_[i]->GenerateStaticVariableInitializers(printer); + } + for (int i = 0; i < file_->extension_count(); i++) { + extension_generators_[i]->GenerateNonNestedInitializationCode(printer); + } + + // Check if custom options exist. If any, try to load immutable classes since + // custom options are only represented with immutable messages. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + string file_data; + file_proto.SerializeToString(&file_data); + vector extensions; + CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); + + if (extensions.size() > 0) { + // Try to load immutable messages' outer class. Its initialization code + // will take care of interpreting custom options. + printer->Print( + "try {\n" + // Note that we have to load the immutable class dynamically here as + // we want the mutable code to be independent from the immutable code + // at compile time. It is required to implement dual-compile for + // mutable and immutable API in blaze. + " java.lang.Class immutableClass = java.lang.Class.forName(\n" + " \"$immutable_classname$\");\n" + "} catch (java.lang.ClassNotFoundException e) {\n" + // The immutable class can not be found. Custom options are left + // as unknown fields. + // TODO(xiaofeng): inform the user with a warning? + "}\n", + "immutable_classname", name_resolver_->GetImmutableClassName(file_)); + } + + // Force descriptor initialization of all dependencies. for (int i = 0; i < file_->dependency_count(); i++) { - if (ShouldIncludeDependency(file_->dependency(i))) { + if (ShouldIncludeDependency(file_->dependency(i), false)) { + string dependency = name_resolver_->GetMutableClassName( + file_->dependency(i)); printer->Print( - " $dependency$.getDescriptor(),\n", - "dependency", ClassName(file_->dependency(i))); + "$dependency$.getDescriptor();\n", + "dependency", dependency); } } - printer->Print( - " }, assigner);\n"); - printer->Outdent(); printer->Print( "}\n"); @@ -426,6 +458,7 @@ static void GenerateSibling(const string& package_dir, GeneratorContext* context, vector* file_list, const string& name_suffix, + GeneratorClass* generator, void (GeneratorClass::*pfn)(io::Printer* printer)) { string filename = package_dir + descriptor->name() + name_suffix + ".java"; file_list->push_back(filename); @@ -445,42 +478,53 @@ static void GenerateSibling(const string& package_dir, "package", java_package); } - GeneratorClass generator(descriptor); - (generator.*pfn)(&printer); + (generator->*pfn)(&printer); } void FileGenerator::GenerateSiblings(const string& package_dir, GeneratorContext* context, vector* file_list) { - if (file_->options().java_multiple_files()) { + if (MultipleJavaFiles(file_, immutable_api_)) { for (int i = 0; i < file_->enum_type_count(); i++) { + EnumGenerator generator(file_->enum_type(i), immutable_api_, + context_.get()); GenerateSibling(package_dir, java_package_, file_->enum_type(i), context, file_list, "", + &generator, &EnumGenerator::Generate); } for (int i = 0; i < file_->message_type_count(); i++) { - GenerateSibling(package_dir, java_package_, - file_->message_type(i), - context, file_list, "OrBuilder", - &MessageGenerator::GenerateInterface); + if (immutable_api_) { + GenerateSibling(package_dir, java_package_, + file_->message_type(i), + context, file_list, + "OrBuilder", + message_generators_[i].get(), + &MessageGenerator::GenerateInterface); + } GenerateSibling(package_dir, java_package_, file_->message_type(i), context, file_list, "", + message_generators_[i].get(), &MessageGenerator::Generate); } if (HasGenericServices(file_)) { for (int i = 0; i < file_->service_count(); i++) { + scoped_ptr generator( + generator_factory_->NewServiceGenerator(file_->service(i))); GenerateSibling(package_dir, java_package_, file_->service(i), context, file_list, "", + generator.get(), &ServiceGenerator::Generate); } } } } -bool FileGenerator::ShouldIncludeDependency(const FileDescriptor* descriptor) { +bool FileGenerator::ShouldIncludeDependency( + const FileDescriptor* descriptor, bool immutable_api) { return true; } diff --git a/src/google/protobuf/compiler/java/java_file.h b/src/google/protobuf/compiler/java/java_file.h index 59911462..7f289491 100644 --- a/src/google/protobuf/compiler/java/java_file.h +++ b/src/google/protobuf/compiler/java/java_file.h @@ -35,18 +35,26 @@ #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ #define GOOGLE_PROTOBUF_COMPILER_JAVA_FILE_H__ +#include #include #include #include namespace google { namespace protobuf { - class FileDescriptor; // descriptor.h + class FileDescriptor; // descriptor.h namespace io { - class Printer; // printer.h + class Printer; // printer.h } namespace compiler { - class GeneratorContext; // code_generator.h + class GeneratorContext; // code_generator.h + namespace java { + class Context; // context.h + class MessageGenerator; // message.h + class GeneratorFactory; // generator_factory.h + class ExtensionGenerator; // extension.h + class ClassNameResolver; // name_resolver.h + } } } @@ -56,7 +64,7 @@ namespace java { class FileGenerator { public: - explicit FileGenerator(const FileDescriptor* file); + FileGenerator(const FileDescriptor* file, bool immutable_api = true); ~FileGenerator(); // Checks for problems that would otherwise lead to cryptic compile errors. @@ -78,17 +86,23 @@ class FileGenerator { private: - // Returns whether the dependency should be included in the output file. - // Always returns true for opensource, but used internally at Google to help - // improve compatibility with version 1 of protocol buffers. - bool ShouldIncludeDependency(const FileDescriptor* descriptor); + void GenerateDescriptorInitializationCodeForImmutable(io::Printer* printer); + void GenerateDescriptorInitializationCodeForMutable(io::Printer* printer); + + bool ShouldIncludeDependency(const FileDescriptor* descriptor, + bool immutable_api_); const FileDescriptor* file_; string java_package_; string classname_; + scoped_array > message_generators_; + scoped_array > extension_generators_; + scoped_ptr generator_factory_; + scoped_ptr context_; + ClassNameResolver* name_resolver_; + bool immutable_api_; - void GenerateEmbeddedDescriptor(io::Printer* printer); GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator); }; diff --git a/src/google/protobuf/compiler/java/java_generator.cc b/src/google/protobuf/compiler/java/java_generator.cc index e6c79abc..b713797b 100644 --- a/src/google/protobuf/compiler/java/java_generator.cc +++ b/src/google/protobuf/compiler/java/java_generator.cc @@ -33,8 +33,13 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include + #include +#include #include +#include #include #include #include @@ -64,55 +69,89 @@ bool JavaGenerator::Generate(const FileDescriptor* file, vector > options; ParseGeneratorParameter(parameter, &options); + bool generate_immutable_code = false; + bool generate_mutable_code = false; + bool generate_shared_code = false; for (int i = 0; i < options.size(); i++) { if (options[i].first == "output_list_file") { output_list_file = options[i].second; + } else if (options[i].first == "immutable") { + generate_immutable_code = true; + } else if (options[i].first == "mutable") { + generate_mutable_code = true; + } else if (options[i].first == "shared") { + generate_shared_code = true; } else { *error = "Unknown generator option: " + options[i].first; return false; } } + // By default we generate immutable code and shared code for immutable API. + if (!generate_immutable_code && !generate_mutable_code && + !generate_shared_code) { + generate_immutable_code = true; + generate_shared_code = true; + } + // ----------------------------------------------------------------- - if (file->options().optimize_for() == FileOptions::LITE_RUNTIME && - file->options().java_generate_equals_and_hash()) { - *error = "The \"java_generate_equals_and_hash\" option is incompatible " - "with \"optimize_for = LITE_RUNTIME\". You must optimize for " - "SPEED or CODE_SIZE if you want to use this option."; - return false; + vector all_files; + + if (generate_shared_code) { + // Generate code shared between immutable and mutable API. + SharedCodeGenerator shared_code_generator(file); + shared_code_generator.Generate(context, &all_files); } - FileGenerator file_generator(file); - if (!file_generator.Validate(error)) { - return false; + vector file_generators; + if (generate_immutable_code) { + file_generators.push_back(new FileGenerator(file, /* immutable = */ true)); + } + if (generate_mutable_code) { + file_generators.push_back(new FileGenerator(file, /* mutable = */ false)); + } + for (int i = 0; i < file_generators.size(); ++i) { + if (!file_generators[i]->Validate(error)) { + for (int j = 0; j < file_generators.size(); ++j) { + delete file_generators[j]; + } + return false; + } } - string package_dir = JavaPackageToDir(file_generator.java_package()); + for (int i = 0; i < file_generators.size(); ++i) { + FileGenerator* file_generator = file_generators[i]; - vector all_files; + string package_dir = JavaPackageToDir(file_generator->java_package()); - string java_filename = package_dir; - java_filename += file_generator.classname(); - java_filename += ".java"; - all_files.push_back(java_filename); + string java_filename = package_dir; + java_filename += file_generator->classname(); + java_filename += ".java"; + all_files.push_back(java_filename); - // Generate main java file. - scoped_ptr output( - context->Open(java_filename)); - io::Printer printer(output.get(), '$'); - file_generator.Generate(&printer); + // Generate main java file. + scoped_ptr output( + context->Open(java_filename)); + io::Printer printer(output.get(), '$'); + file_generator->Generate(&printer); - // Generate sibling files. - file_generator.GenerateSiblings(package_dir, context, &all_files); + // Generate sibling files. + file_generator->GenerateSiblings(package_dir, context, &all_files); + } + + for (int i = 0; i < file_generators.size(); ++i) { + delete file_generators[i]; + } + file_generators.clear(); // Generate output list if requested. if (!output_list_file.empty()) { // Generate output list. This is just a simple text file placed in a // deterministic location which lists the .java files being generated. scoped_ptr srclist_raw_output( - context->Open(output_list_file)); + context->Open(output_list_file)); io::Printer srclist_printer(srclist_raw_output.get(), '$'); for (int i = 0; i < all_files.size(); i++) { srclist_printer.Print("$filename$\n", "filename", all_files[i]); diff --git a/src/google/protobuf/compiler/java/java_generator_factory.cc b/src/google/protobuf/compiler/java/java_generator_factory.cc new file mode 100644 index 00000000..ce71d436 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_generator_factory.cc @@ -0,0 +1,77 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: liujisi@google.com (Pherl Liu) + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +GeneratorFactory::GeneratorFactory() {} +GeneratorFactory::~GeneratorFactory() {} + +// =================================================================== + +ImmutableGeneratorFactory::ImmutableGeneratorFactory( + Context* context) : context_(context) { +} +ImmutableGeneratorFactory::~ImmutableGeneratorFactory() {} + +MessageGenerator* ImmutableGeneratorFactory::NewMessageGenerator( + const Descriptor* descriptor) const { + return new ImmutableMessageGenerator(descriptor, context_); +} + +ExtensionGenerator* ImmutableGeneratorFactory::NewExtensionGenerator( + const FieldDescriptor* descriptor) const { + return new ImmutableExtensionGenerator(descriptor, context_); +} + +ServiceGenerator* ImmutableGeneratorFactory::NewServiceGenerator( + const ServiceDescriptor* descriptor) const { + return new ImmutableServiceGenerator(descriptor, context_); +} + + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_generator_factory.h b/src/google/protobuf/compiler/java/java_generator_factory.h new file mode 100644 index 00000000..abf894f6 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_generator_factory.h @@ -0,0 +1,101 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: liujisi@google.com (Pherl Liu) + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ + +#include + +namespace google { +namespace protobuf { + class FieldDescriptor; // descriptor.h + class Descriptor; // descriptor.h + class ServiceDescriptor; // descriptor.h + namespace compiler { + namespace java { + class MessageGenerator; // message.h + class ExtensionGenerator; // extension.h + class ServiceGenerator; // service.h + class Context; // context.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class GeneratorFactory { + public: + GeneratorFactory(); + virtual ~GeneratorFactory(); + + virtual MessageGenerator* NewMessageGenerator( + const Descriptor* descriptor) const = 0; + + virtual ExtensionGenerator* NewExtensionGenerator( + const FieldDescriptor* descriptor) const = 0; + + virtual ServiceGenerator* NewServiceGenerator( + const ServiceDescriptor* descriptor) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorFactory); +}; + +// Factory that creates generators for immutable-default messages. +class ImmutableGeneratorFactory : public GeneratorFactory { + public: + ImmutableGeneratorFactory(Context* context); + virtual ~ImmutableGeneratorFactory(); + + virtual MessageGenerator* NewMessageGenerator( + const Descriptor* descriptor) const; + + virtual ExtensionGenerator* NewExtensionGenerator( + const FieldDescriptor* descriptor) const; + + virtual ServiceGenerator* NewServiceGenerator( + const ServiceDescriptor* descriptor) const; + + private: + Context* context_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableGeneratorFactory); +}; + + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__ diff --git a/src/google/protobuf/compiler/java/java_helpers.cc b/src/google/protobuf/compiler/java/java_helpers.cc index cf241b8a..fdd4e5e5 100644 --- a/src/google/protobuf/compiler/java/java_helpers.cc +++ b/src/google/protobuf/compiler/java/java_helpers.cc @@ -32,11 +32,15 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include +#include #include #include #include +#include #include +#include #include #include @@ -45,6 +49,9 @@ namespace protobuf { namespace compiler { namespace java { +using internal::WireFormat; +using internal::WireFormatLite; + const char kThickSeparator[] = "// ===================================================================\n"; const char kThinSeparator[] = @@ -54,18 +61,47 @@ namespace { const char* kDefaultPackage = ""; -const string& FieldName(const FieldDescriptor* field) { +// Names that should be avoided as field names. +// Using them will cause the compiler to generate accessors whose names are +// colliding with methods defined in base classes. +const char* kForbiddenWordList[] = { + // message base class: + "cached_size", "serialized_size", + // java.lang.Object: + "class", +}; + +bool IsForbidden(const string& field_name) { + for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) { + if (field_name == kForbiddenWordList[i]) { + return true; + } + } + return false; +} + +string FieldName(const FieldDescriptor* field) { + string field_name; // Groups are hacky: The name of the field is just the lower-cased name // of the group type. In Java, though, we would like to retain the original // capitalization of the type name. if (GetType(field) == FieldDescriptor::TYPE_GROUP) { - return field->message_type()->name(); + field_name = field->message_type()->name(); } else { - return field->name(); + field_name = field->name(); + } + if (IsForbidden(field_name)) { + // Append a trailing "#" to indicate that the name should be decorated to + // avoid collision with other names. + field_name += "#"; } + return field_name; } -string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { + +} // namespace + +string UnderscoresToCamelCase(const string& input, bool cap_next_letter) { string result; // Note: I distrust ctype.h due to locales. for (int i = 0; i < input.size(); i++) { @@ -93,21 +129,27 @@ string UnderscoresToCamelCaseImpl(const string& input, bool cap_next_letter) { cap_next_letter = true; } } + // Add a trailing "_" if the name should be altered. + if (input[input.size() - 1] == '#') { + result += '_'; + } return result; } -} // namespace - string UnderscoresToCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCaseImpl(FieldName(field), false); + return UnderscoresToCamelCase(FieldName(field), false); } string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) { - return UnderscoresToCamelCaseImpl(FieldName(field), true); + return UnderscoresToCamelCase(FieldName(field), true); } string UnderscoresToCamelCase(const MethodDescriptor* method) { - return UnderscoresToCamelCaseImpl(method->name(), false); + return UnderscoresToCamelCase(method->name(), false); +} + +string UniqueFileScopeIdentifier(const Descriptor* descriptor) { + return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); } string StripProto(const string& filename) { @@ -118,22 +160,12 @@ string StripProto(const string& filename) { } } -string FileClassName(const FileDescriptor* file) { - if (file->options().has_java_outer_classname()) { - return file->options().java_outer_classname(); - } else { - string basename; - string::size_type last_slash = file->name().find_last_of('/'); - if (last_slash == string::npos) { - basename = file->name(); - } else { - basename = file->name().substr(last_slash + 1); - } - return UnderscoresToCamelCaseImpl(StripProto(basename), true); - } +string FileClassName(const FileDescriptor* file, bool immutable) { + ClassNameResolver name_resolver; + return name_resolver.GetFileClassName(file, immutable); } -string FileJavaPackage(const FileDescriptor* file) { +string FileJavaPackage(const FileDescriptor* file, bool immutable) { string result; if (file->options().has_java_package()) { @@ -146,7 +178,6 @@ string FileJavaPackage(const FileDescriptor* file) { } } - return result; } @@ -157,7 +188,10 @@ string JavaPackageToDir(string package_name) { return package_dir; } -string ToJavaName(const string& full_name, const FileDescriptor* file) { +// TODO(xiaofeng): This function is only kept for it's publicly referenced. +// It should be removed after mutable API up-integration. +string ToJavaName(const string& full_name, + const FileDescriptor* file) { string result; if (file->options().java_multiple_files()) { result = FileJavaPackage(file); @@ -178,22 +212,42 @@ string ToJavaName(const string& full_name, const FileDescriptor* file) { } string ClassName(const Descriptor* descriptor) { - return ToJavaName(descriptor->full_name(), descriptor->file()); + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); } string ClassName(const EnumDescriptor* descriptor) { - return ToJavaName(descriptor->full_name(), descriptor->file()); + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); } string ClassName(const ServiceDescriptor* descriptor) { - return ToJavaName(descriptor->full_name(), descriptor->file()); + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); } string ClassName(const FileDescriptor* descriptor) { - string result = FileJavaPackage(descriptor); - if (!result.empty()) result += '.'; - result += FileClassName(descriptor); - return result; + ClassNameResolver name_resolver; + return name_resolver.GetClassName(descriptor, true); +} + +string ExtraMessageInterfaces(const Descriptor* descriptor) { + string interfaces = "// @@protoc_insertion_point(message_implements:" + + descriptor->full_name() + ")"; + return interfaces; +} + + +string ExtraBuilderInterfaces(const Descriptor* descriptor) { + string interfaces = "// @@protoc_insertion_point(builder_implements:" + + descriptor->full_name() + ")"; + return interfaces; +} + +string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor) { + string interfaces = "// @@protoc_insertion_point(interface_extends:" + + descriptor->full_name() + ")"; + return interfaces; } string FieldConstantName(const FieldDescriptor *field) { @@ -272,6 +326,35 @@ const char* BoxedPrimitiveTypeName(JavaType type) { return NULL; } +const char* FieldTypeName(FieldDescriptor::Type field_type) { + switch (field_type) { + case FieldDescriptor::TYPE_INT32 : return "INT32"; + case FieldDescriptor::TYPE_UINT32 : return "UINT32"; + case FieldDescriptor::TYPE_SINT32 : return "SINT32"; + case FieldDescriptor::TYPE_FIXED32 : return "FIXED32"; + case FieldDescriptor::TYPE_SFIXED32: return "SFIXED32"; + case FieldDescriptor::TYPE_INT64 : return "INT64"; + case FieldDescriptor::TYPE_UINT64 : return "UINT64"; + case FieldDescriptor::TYPE_SINT64 : return "SINT64"; + case FieldDescriptor::TYPE_FIXED64 : return "FIXED64"; + case FieldDescriptor::TYPE_SFIXED64: return "SFIXED64"; + case FieldDescriptor::TYPE_FLOAT : return "FLOAT"; + case FieldDescriptor::TYPE_DOUBLE : return "DOUBLE"; + case FieldDescriptor::TYPE_BOOL : return "BOOL"; + case FieldDescriptor::TYPE_STRING : return "STRING"; + case FieldDescriptor::TYPE_BYTES : return "BYTES"; + case FieldDescriptor::TYPE_ENUM : return "ENUM"; + case FieldDescriptor::TYPE_GROUP : return "GROUP"; + case FieldDescriptor::TYPE_MESSAGE : return "MESSAGE"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + bool AllAscii(const string& text) { for (int i = 0; i < text.size(); i++) { if ((text[i] & 0x80) != 0) { @@ -281,7 +364,8 @@ bool AllAscii(const string& text) { return true; } -string DefaultValue(const FieldDescriptor* field) { +string DefaultValue(const FieldDescriptor* field, bool immutable, + ClassNameResolver* name_resolver) { // Switch on CppType since we need to know which default_value_* method // of FieldDescriptor to call. switch (field->cpp_type()) { @@ -344,11 +428,12 @@ string DefaultValue(const FieldDescriptor* field) { } case FieldDescriptor::CPPTYPE_ENUM: - return ClassName(field->enum_type()) + "." + + return name_resolver->GetClassName(field->enum_type(), immutable) + "." + field->default_value_enum()->name(); case FieldDescriptor::CPPTYPE_MESSAGE: - return ClassName(field->message_type()) + ".getDefaultInstance()"; + return name_resolver->GetClassName(field->message_type(), immutable) + + ".getDefaultInstance()"; // No default because we want the compiler to complain if any new // types are added. @@ -494,6 +579,158 @@ string GenerateSetBitMutableLocal(int bitIndex) { return GenerateSetBitInternal("mutable_", bitIndex); } +bool IsReferenceType(JavaType type) { + switch (type) { + case JAVATYPE_INT : return false; + case JAVATYPE_LONG : return false; + case JAVATYPE_FLOAT : return false; + case JAVATYPE_DOUBLE : return false; + case JAVATYPE_BOOLEAN: return false; + case JAVATYPE_STRING : return true; + case JAVATYPE_BYTES : return true; + case JAVATYPE_ENUM : return true; + case JAVATYPE_MESSAGE: return true; + + // No default because we want the compiler to complain if any new + // JavaTypes are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return false; +} + +const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) { + switch (GetType(field)) { + case FieldDescriptor::TYPE_INT32 : return "Int32"; + case FieldDescriptor::TYPE_UINT32 : return "UInt32"; + case FieldDescriptor::TYPE_SINT32 : return "SInt32"; + case FieldDescriptor::TYPE_FIXED32 : return "Fixed32"; + case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; + case FieldDescriptor::TYPE_INT64 : return "Int64"; + case FieldDescriptor::TYPE_UINT64 : return "UInt64"; + case FieldDescriptor::TYPE_SINT64 : return "SInt64"; + case FieldDescriptor::TYPE_FIXED64 : return "Fixed64"; + case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; + case FieldDescriptor::TYPE_FLOAT : return "Float"; + case FieldDescriptor::TYPE_DOUBLE : return "Double"; + case FieldDescriptor::TYPE_BOOL : return "Bool"; + case FieldDescriptor::TYPE_STRING : return "String"; + case FieldDescriptor::TYPE_BYTES : { + return "Bytes"; + } + case FieldDescriptor::TYPE_ENUM : return "Enum"; + case FieldDescriptor::TYPE_GROUP : return "Group"; + case FieldDescriptor::TYPE_MESSAGE : return "Message"; + + // No default because we want the compiler to complain if any new + // types are added. + } + + GOOGLE_LOG(FATAL) << "Can't get here."; + return NULL; +} + +// For encodings with fixed sizes, returns that size in bytes. Otherwise +// returns -1. +int FixedSize(FieldDescriptor::Type type) { + switch (type) { + case FieldDescriptor::TYPE_INT32 : return -1; + case FieldDescriptor::TYPE_INT64 : return -1; + case FieldDescriptor::TYPE_UINT32 : return -1; + case FieldDescriptor::TYPE_UINT64 : return -1; + case FieldDescriptor::TYPE_SINT32 : return -1; + case FieldDescriptor::TYPE_SINT64 : return -1; + case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; + case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; + case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; + case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; + case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; + case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; + + case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; + case FieldDescriptor::TYPE_ENUM : return -1; + + case FieldDescriptor::TYPE_STRING : return -1; + case FieldDescriptor::TYPE_BYTES : return -1; + case FieldDescriptor::TYPE_GROUP : return -1; + case FieldDescriptor::TYPE_MESSAGE : return -1; + + // No default because we want the compiler to complain if any new + // types are added. + } + GOOGLE_LOG(FATAL) << "Can't get here."; + return -1; +} + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. The caller should delete the returned array. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { + const FieldDescriptor** fields = + new const FieldDescriptor*[descriptor->field_count()]; + for (int i = 0; i < descriptor->field_count(); i++) { + fields[i] = descriptor->field(i); + } + sort(fields, fields + descriptor->field_count(), + FieldOrderingByNumber()); + return fields; +} + +// Returns true if the message type has any required fields. If it doesn't, +// we can optimize out calls to its isInitialized() method. +// +// already_seen is used to avoid checking the same type multiple times +// (and also to protect against recursion). +bool HasRequiredFields( + const Descriptor* type, + hash_set* already_seen) { + if (already_seen->count(type) > 0) { + // The type is already in cache. This means that either: + // a. The type has no required fields. + // b. We are in the midst of checking if the type has required fields, + // somewhere up the stack. In this case, we know that if the type + // has any required fields, they'll be found when we return to it, + // and the whole call to HasRequiredFields() will return true. + // Therefore, we don't have to check if this type has required fields + // here. + return false; + } + already_seen->insert(type); + + // If the type has extensions, an extension with message type could contain + // required fields, so we have to be conservative and assume such an + // extension exists. + if (type->extension_range_count() > 0) return true; + + for (int i = 0; i < type->field_count(); i++) { + const FieldDescriptor* field = type->field(i); + if (field->is_required()) { + return true; + } + if (GetJavaType(field) == JAVATYPE_MESSAGE) { + if (HasRequiredFields(field->message_type(), already_seen)) { + return true; + } + } + } + + return false; +} + +bool HasRequiredFields(const Descriptor* type) { + hash_set already_seen; + return HasRequiredFields(type, &already_seen); +} + +bool HasRepeatedFields(const Descriptor* descriptor) { + for (int i = 0; i < descriptor->field_count(); ++i) { + const FieldDescriptor* field = descriptor->field(i); + if (field->is_repeated()) { + return true; + } + } + return false; +} + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_helpers.h b/src/google/protobuf/compiler/java/java_helpers.h index 3937f069..6d1eae0a 100644 --- a/src/google/protobuf/compiler/java/java_helpers.h +++ b/src/google/protobuf/compiler/java/java_helpers.h @@ -49,6 +49,9 @@ namespace java { extern const char kThickSeparator[]; extern const char kThinSeparator[]; +// Converts a name to camel-case. If cap_first_letter is true, capitalize the +// first letter. +string UnderscoresToCamelCase(const string& name, bool cap_first_letter); // Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes // "fooBarBaz" or "FooBarBaz", respectively. string UnderscoresToCamelCase(const FieldDescriptor* field); @@ -58,15 +61,22 @@ string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field); // of lower-casing the first letter of the name.) string UnderscoresToCamelCase(const MethodDescriptor* method); +// Get an identifier that uniquely identifies this type within the file. +// This is used to declare static variables related to this type at the +// outermost file scope. +string UniqueFileScopeIdentifier(const Descriptor* descriptor); + // Strips ".proto" or ".protodevel" from the end of a filename. string StripProto(const string& filename); -// Gets the unqualified class name for the file. Each .proto file becomes a -// single Java class, with all its contents nested in that class. -string FileClassName(const FileDescriptor* file); +// Gets the unqualified class name for the file. For each .proto file, there +// will be one Java class containing all the immutable messages and another +// Java class containing all the mutable messages. +// TODO(xiaofeng): remove the default value after updating client code. +string FileClassName(const FileDescriptor* file, bool immutable = true); // Returns the file's Java package name. -string FileJavaPackage(const FileDescriptor* file); +string FileJavaPackage(const FileDescriptor* file, bool immutable = true); // Returns output directory for the given package name. string JavaPackageToDir(string package_name); @@ -74,17 +84,46 @@ string JavaPackageToDir(string package_name); // Converts the given fully-qualified name in the proto namespace to its // fully-qualified name in the Java namespace, given that it is in the given // file. -string ToJavaName(const string& full_name, const FileDescriptor* file); - -// These return the fully-qualified class name corresponding to the given -// descriptor. +// TODO(xiaofeng): this method is deprecated and should be removed in the +// future. +string ToJavaName(const string& full_name, + const FileDescriptor* file); + +// TODO(xiaofeng): the following methods are kept for they are exposed +// publicly in //google/protobuf/compiler/java/names.h. They return +// immutable names only and should be removed after mutable API is +// integrated into google3. string ClassName(const Descriptor* descriptor); string ClassName(const EnumDescriptor* descriptor); string ClassName(const ServiceDescriptor* descriptor); string ClassName(const FileDescriptor* descriptor); -inline string ExtensionIdentifierName(const FieldDescriptor* descriptor) { - return ToJavaName(descriptor->full_name(), descriptor->file()); +// Comma-separate list of option-specified interfaces implemented by the +// Message, to follow the "implements" declaration of the Message definition. +string ExtraMessageInterfaces(const Descriptor* descriptor); +// Comma-separate list of option-specified interfaces implemented by the +// MutableMessage, to follow the "implements" declaration of the MutableMessage +// definition. +string ExtraMutableMessageInterfaces(const Descriptor* descriptor); +// Comma-separate list of option-specified interfaces implemented by the +// Builder, to follow the "implements" declaration of the Builder definition. +string ExtraBuilderInterfaces(const Descriptor* descriptor); +// Comma-separate list of option-specified interfaces extended by the +// MessageOrBuilder, to follow the "extends" declaration of the +// MessageOrBuilder definition. +string ExtraMessageOrBuilderInterfaces(const Descriptor* descriptor); + +// Get the unqualified Java class name for mutable messages. i.e. without +// package or outer classnames. +inline string ShortMutableJavaClassName(const Descriptor* descriptor) { + return descriptor->name(); +} + + +// Whether we should generate multiple java files for messages. +inline bool MultipleJavaFiles( + const FileDescriptor* descriptor, bool immutable) { + return descriptor->options().java_multiple_files(); } // Get the unqualified name that should be used for a field's field @@ -115,11 +154,23 @@ JavaType GetJavaType(const FieldDescriptor* field); // types. const char* BoxedPrimitiveTypeName(JavaType type); -string DefaultValue(const FieldDescriptor* field); +// Get the name of the java enum constant representing this type. E.g., +// "INT32" for FieldDescriptor::TYPE_INT32. The enum constant's full +// name is "com.google.protobuf.WireFormat.FieldType.INT32". +const char* FieldTypeName(const FieldDescriptor::Type field_type); + +class ClassNameResolver; +string DefaultValue(const FieldDescriptor* field, bool immutable, + ClassNameResolver* name_resolver); +inline string ImmutableDefaultValue(const FieldDescriptor* field, + ClassNameResolver* name_resolver) { + return DefaultValue(field, true, name_resolver); +} bool IsDefaultValueJavaDefault(const FieldDescriptor* field); -// Does this message class keep track of unknown fields? -inline bool HasUnknownFields(const Descriptor* descriptor) { +// Does this message class use UnknownFieldSet? +// Otherwise, unknown fields will be stored in a ByteString object +inline bool UseUnknownFieldSet(const Descriptor* descriptor) { return descriptor->file()->options().optimize_for() != FileOptions::LITE_RUNTIME; } @@ -163,6 +214,15 @@ inline bool HasGenericServices(const FileDescriptor *file) { file->options().java_generic_services(); } +inline bool IsLazy(const FieldDescriptor* descriptor) { + // Currently, the proto-lite version suports lazy field. + // TODO(niwasaki): Support lazy fields also for other proto runtimes. + if (descriptor->file()->options().optimize_for() != + FileOptions::LITE_RUNTIME) { + return false; + } + return descriptor->options().lazy(); +} // Methods for shared bitfields. @@ -212,6 +272,48 @@ string GenerateGetBitMutableLocal(int bitIndex); // Example: "mutable_bitField1_ = (mutable_bitField1_ | 0x04)" string GenerateSetBitMutableLocal(int bitIndex); +// Returns whether the JavaType is a reference type. +bool IsReferenceType(JavaType type); + +// Returns the capitalized name for calling relative functions in +// CodedInputStream +const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable); + +// For encodings with fixed sizes, returns that size in bytes. Otherwise +// returns -1. +int FixedSize(FieldDescriptor::Type type); + +// Comparators used to sort fields in MessageGenerator +struct FieldOrderingByNumber { + inline bool operator()(const FieldDescriptor* a, + const FieldDescriptor* b) const { + return a->number() < b->number(); + } +}; + +struct ExtensionRangeOrdering { + bool operator()(const Descriptor::ExtensionRange* a, + const Descriptor::ExtensionRange* b) const { + return a->start < b->start; + } +}; + +// Sort the fields of the given Descriptor by number into a new[]'d array +// and return it. The caller should delete the returned array. +const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor); + +// Check a message type and its sub-message types recursively to see if any of +// them has a required field. Return true if a required field is found. +bool HasRequiredFields(const Descriptor* descriptor); + +// Whether a .proto file supports field presence test for non-message types. +inline bool SupportFieldPresence(const FileDescriptor* descriptor) { + return true; +} + +// Check whether a mesasge has repeated fields. +bool HasRepeatedFields(const Descriptor* descriptor); + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.cc b/src/google/protobuf/compiler/java/java_lazy_message_field.cc new file mode 100644 index 00000000..32d97b6f --- /dev/null +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.cc @@ -0,0 +1,826 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: niwasaki@google.com (Naoki Iwasaki) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +ImmutableLazyMessageFieldGenerator:: +ImmutableLazyMessageFieldGenerator( + const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableMessageFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { +} + +ImmutableLazyMessageFieldGenerator::~ImmutableLazyMessageFieldGenerator() {} + +void ImmutableLazyMessageFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private com.google.protobuf.LazyFieldLite $name$_ =\n" + " new com.google.protobuf.LazyFieldLite();\n"); + + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" + "}\n"); + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " return $name$_;\n" + "}\n"); + } +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + + printer->Print(variables_, + "private com.google.protobuf.LazyFieldLite $name$_ =\n" + " new com.google.protobuf.LazyFieldLite();\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return ($type$) $name$_.getValue($type$.getDefaultInstance());\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "$name$_.setValue(value);\n" + "$on_changed$\n", + + NULL, // Lazy fields are supported only for lite-runtime. + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "$name$_.setValue(builderForValue.build());\n" + "$on_changed$\n", + + NULL, + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder merge$capitalized_name$($type$ value)", + + "if ($get_has_field_bit_builder$ &&\n" + " !$name$_.containsDefaultInstance()) {\n" + " $name$_.setValue(\n" + " $type$.newBuilder(\n" + " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" + "} else {\n" + " $name$_.setValue(value);\n" + "}\n" + "$on_changed$\n", + + NULL, + + "$set_has_field_bit_builder$;\n" + "return this;\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "$name$_.clear();\n" + "$on_changed$\n", + + NULL, + + "$clear_has_field_bit_builder$;\n" + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " $set_has_field_bit_builder$;\n" + " $on_changed$\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " return $name$_;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); + } +} + + +void ImmutableLazyMessageFieldGenerator:: +GenerateInitializationCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.clear();\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateBuilderClearCode(io::Printer* printer) const { + printer->Print(variables_, "$name$_.clear();\n"); + printer->Print(variables_, "$clear_has_field_bit_builder$;\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " $name$_.merge(other.$name$_);\n" + " $set_has_field_bit_builder$;\n" + "}\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + + printer->Print(variables_, + "result.$name$_.setByteString(\n" + " $name$_.toByteString(),\n" + " $name$_.getExtensionRegistry());\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$name$_.setByteString(input.readBytes(), extensionRegistry);\n"); + printer->Print(variables_, + "$set_has_field_bit_message$;\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + // Do not de-serialize lazy fields. + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " output.writeBytes($number$, $name$_.toByteString());\n" + "}\n"); +} + +void ImmutableLazyMessageFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($get_has_field_bit_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, $name$_);\n" + "}\n"); +} + +// =================================================================== + +ImmutableLazyMessageOneofFieldGenerator:: +ImmutableLazyMessageOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableLazyMessageFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); + variables_["lazy_type"] = "com.google.protobuf.LazyFieldLite"; +} + +ImmutableLazyMessageOneofFieldGenerator:: +~ImmutableLazyMessageOneofFieldGenerator() {} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" + " $type$.getDefaultInstance());\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) (($lazy_type$) $oneof_name$_).getValue(\n" + " $type$.getDefaultInstance());\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + "}\n" + "(($lazy_type$) $oneof_name$_).setValue(value);\n" + "$on_changed$\n", + + NULL, // Lazy fields are supported only for lite-runtime. + + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + "}\n" + "(($lazy_type$) $oneof_name$_).setValue(builderForValue.build());\n" + "$on_changed$\n", + + NULL, + + "return this;\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder merge$capitalized_name$($type$ value)", + + "if ($has_oneof_case_message$ &&\n" + " !(($lazy_type$) $oneof_name$_).containsDefaultInstance()) {\n" + " (($lazy_type$) $oneof_name$_).setValue(\n" + " $type$.newBuilder(\n" + " get$capitalized_name$()).mergeFrom(value).buildPartial());\n" + "} else {\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + " $set_oneof_case_message$;\n" + " }\n" + " (($lazy_type$) $oneof_name$_).setValue(value);\n" + "}\n" + "$on_changed$\n", + + NULL, + + "return this;\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + "}\n", + + NULL, + + "return this;\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + "}\n" + "(($lazy_type$) $oneof_name$_).merge(\n" + " ($lazy_type$) other.$oneof_name$_);\n" + "$set_oneof_case_message$;\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n"); + printer->Indent(); + + printer->Print(variables_, + "result.$oneof_name$_ = new $lazy_type$();\n" + "(($lazy_type$) result.$oneof_name$_).setByteString(\n" + " (($lazy_type$) $oneof_name$_).toByteString(),\n" + " (($lazy_type$) $oneof_name$_).getExtensionRegistry());\n"); + printer->Outdent(); + printer->Print("}\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = new $lazy_type$();\n" + "}\n" + "(($lazy_type$) $oneof_name$_).setByteString(\n" + " input.readBytes(), extensionRegistry);\n" + "$set_oneof_case_message$;\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + // Do not de-serialize lazy fields. + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeBytes(\n" + " $number$, (($lazy_type$) $oneof_name$_).toByteString());\n" + "}\n"); +} + +void ImmutableLazyMessageOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, ($lazy_type$) $oneof_name$_);\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutableLazyMessageFieldGenerator:: +RepeatedImmutableLazyMessageFieldGenerator( + const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : RepeatedImmutableMessageFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { +} + + +RepeatedImmutableLazyMessageFieldGenerator:: +~RepeatedImmutableLazyMessageFieldGenerator() {} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + printer->Print(variables_, + "private java.util.List $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$>\n" + " get$capitalized_name$List() {\n" + " java.util.List<$type$> list =\n" + " new java.util.ArrayList<$type$>($name$_.size());\n" + " for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" + " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" + " }\n" + " return list;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List\n" + " get$capitalized_name$OrBuilderList() {\n" + " return get$capitalized_name$List();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public int get$capitalized_name$Count() {\n" + " return $name$_.size();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$(int index) {\n" + " return ($type$)\n" + " $name$_.get(index).getValue($type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " return ($type$OrBuilder)\n" + " $name$_.get(index).getValue($type$.getDefaultInstance());\n" + "}\n"); +} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + + printer->Print(variables_, + "private java.util.List $name$_ =\n" + " java.util.Collections.emptyList();\n" + + "private void ensure$capitalized_name$IsMutable() {\n" + " if (!$get_mutable_bit_builder$) {\n" + " $name$_ =\n" + " new java.util.ArrayList(\n" + " $name$_);\n" + " $set_mutable_bit_builder$;\n" + " }\n" + "}\n" + "\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;\n" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // repeated field of type "Field" called "RepeatedField". + + // List getRepeatedFieldList() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public java.util.List<$type$> get$capitalized_name$List()", + + "java.util.List<$type$> list =\n" + " new java.util.ArrayList<$type$>($name$_.size());\n" + "for (com.google.protobuf.LazyFieldLite lf : $name$_) {\n" + " list.add(($type$) lf.getValue($type$.getDefaultInstance()));\n" + "}\n" + "return java.util.Collections.unmodifiableList(list);\n", + + "return $name$Builder_.getMessageList();\n", + + NULL); + + // int getRepeatedFieldCount() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public int get$capitalized_name$Count()", + + "return $name$_.size();\n", + "return $name$Builder_.getCount();\n", + + NULL); + + // Field getRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$(int index)", + + "return ($type$) $name$_.get(index).getValue(\n" + " $type$.getDefaultInstance());\n", + + "return $name$Builder_.getMessage(index);\n", + + NULL); + + // Builder setRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$ value)", + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" + "$on_changed$\n", + "$name$Builder_.setMessage(index, value);\n", + "return this;\n"); + + // Builder setRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.set(index, com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(value));\n" + + "$on_changed$\n", + + "$name$Builder_.addMessage(value);\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(value));\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, value);\n", + + "return this;\n"); + + // Builder addRepeatedField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(builderForValue.build());\n", + + "return this;\n"); + + // Builder addRepeatedField(int index, Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder add$capitalized_name$(\n" + " int index, $type$.Builder builderForValue)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.add(index, com.google.protobuf.LazyFieldLite.fromValue(\n" + " builderForValue.build()));\n" + "$on_changed$\n", + + "$name$Builder_.addMessage(index, builderForValue.build());\n", + + "return this;\n"); + + // Builder addAllRepeatedField(Iterable values) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder addAll$capitalized_name$(\n" + " java.lang.Iterable values)", + + "ensure$capitalized_name$IsMutable();\n" + "for (com.google.protobuf.MessageLite v : values) {\n" + " $name$_.add(com.google.protobuf.LazyFieldLite.fromValue(v));\n" + "}\n" + "$on_changed$\n", + + "$name$Builder_.addAllMessages(values);\n", + + "return this;\n"); + + // Builder clearAllRepeatedField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "$name$_ = java.util.Collections.emptyList();\n" + "$clear_mutable_bit_builder$;\n" + "$on_changed$\n", + + "$name$Builder_.clear();\n", + + "return this;\n"); + + // Builder removeRepeatedField(int index) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder remove$capitalized_name$(int index)", + + "ensure$capitalized_name$IsMutable();\n" + "$name$_.remove(index);\n" + "$on_changed$\n", + + "$name$Builder_.remove(index);\n", + + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().getBuilder(index);\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder(\n" + " int index) {\n" + " if ($name$Builder_ == null) {\n" + " return $name$_.get(index);" + " } else {\n" + " return $name$Builder_.getMessageOrBuilder(index);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List \n" + " get$capitalized_name$OrBuilderList() {\n" + " if ($name$Builder_ != null) {\n" + " return $name$Builder_.getMessageOrBuilderList();\n" + " } else {\n" + " return java.util.Collections.unmodifiableList($name$_);\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder add$capitalized_name$Builder(\n" + " int index) {\n" + " return get$capitalized_name$FieldBuilder().addBuilder(\n" + " index, $type$.getDefaultInstance());\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.util.List<$type$.Builder> \n" + " get$capitalized_name$BuilderList() {\n" + " return get$capitalized_name$FieldBuilder().getBuilderList();\n" + "}\n" + "private com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " $name$Builder_ = new com.google.protobuf.RepeatedFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " $name$_,\n" + " $get_mutable_bit_builder$,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $name$_ = null;\n" + " }\n" + " return $name$Builder_;\n" + "}\n"); + } +} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "if (!$get_mutable_bit_parser$) {\n" + " $name$_ =\n" + " new java.util.ArrayList();\n" + " $set_mutable_bit_parser$;\n" + "}\n" + "$name$_.add(new com.google.protobuf.LazyFieldLite(\n" + " extensionRegistry, input.readBytes()));\n"); +} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " output.writeBytes($number$, $name$_.get(i).toByteString());\n" + "}\n"); +} + +void RepeatedImmutableLazyMessageFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "for (int i = 0; i < $name$_.size(); i++) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeLazyFieldSize($number$, $name$_.get(i));\n" + "}\n"); +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_lazy_message_field.h b/src/google/protobuf/compiler/java/java_lazy_message_field.h new file mode 100644 index 00000000..2a1f8574 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_lazy_message_field.h @@ -0,0 +1,121 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: niwasaki@google.com (Naoki Iwasaki) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ + +#include +#include + +namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + } + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +class ImmutableLazyMessageFieldGenerator + : public ImmutableMessageFieldGenerator { + public: + explicit ImmutableLazyMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableLazyMessageFieldGenerator(); + + // overroads ImmutableMessageFieldGenerator --------------------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateInitializationCode(io::Printer* printer) const; + void GenerateBuilderClearCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageFieldGenerator); +}; + +class ImmutableLazyMessageOneofFieldGenerator + : public ImmutableLazyMessageFieldGenerator { + public: + ImmutableLazyMessageOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableLazyMessageOneofFieldGenerator(); + + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableLazyMessageOneofFieldGenerator); +}; + +class RepeatedImmutableLazyMessageFieldGenerator + : public RepeatedImmutableMessageFieldGenerator { + public: + explicit RepeatedImmutableLazyMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableLazyMessageFieldGenerator(); + + // overroads RepeatedImmutableMessageFieldGenerator ------------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableLazyMessageFieldGenerator); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_LAZY_MESSAGE_FIELD_H__ diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc index 9322e242..1cd08f7d 100644 --- a/src/google/protobuf/compiler/java/java_message.cc +++ b/src/google/protobuf/compiler/java/java_message.cc @@ -37,12 +37,16 @@ #include #include #include +#include #include +#include #include #include #include +#include #include +#include #include #include #include @@ -59,107 +63,31 @@ using internal::WireFormat; using internal::WireFormatLite; namespace { - -void PrintFieldComment(io::Printer* printer, const FieldDescriptor* field) { - // Print the field's proto-syntax definition as a comment. We don't want to - // print group bodies so we cut off after the first line. - string def = field->DebugString(); - printer->Print("// $def$\n", - "def", def.substr(0, def.find_first_of('\n'))); +bool GenerateHasBits(const Descriptor* descriptor) { + return SupportFieldPresence(descriptor->file()) || + HasRepeatedFields(descriptor); } - -struct FieldOrderingByNumber { - inline bool operator()(const FieldDescriptor* a, - const FieldDescriptor* b) const { - return a->number() < b->number(); - } -}; - -struct ExtensionRangeOrdering { - bool operator()(const Descriptor::ExtensionRange* a, - const Descriptor::ExtensionRange* b) const { - return a->start < b->start; - } -}; - -// Sort the fields of the given Descriptor by number into a new[]'d array -// and return it. -const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) { - const FieldDescriptor** fields = - new const FieldDescriptor*[descriptor->field_count()]; - for (int i = 0; i < descriptor->field_count(); i++) { - fields[i] = descriptor->field(i); - } - sort(fields, fields + descriptor->field_count(), - FieldOrderingByNumber()); - return fields; -} - -// Get an identifier that uniquely identifies this type within the file. -// This is used to declare static variables related to this type at the -// outermost file scope. -string UniqueFileScopeIdentifier(const Descriptor* descriptor) { - return "static_" + StringReplace(descriptor->full_name(), ".", "_", true); -} - -// Returns true if the message type has any required fields. If it doesn't, -// we can optimize out calls to its isInitialized() method. -// -// already_seen is used to avoid checking the same type multiple times -// (and also to protect against recursion). -static bool HasRequiredFields( - const Descriptor* type, - hash_set* already_seen) { - if (already_seen->count(type) > 0) { - // The type is already in cache. This means that either: - // a. The type has no required fields. - // b. We are in the midst of checking if the type has required fields, - // somewhere up the stack. In this case, we know that if the type - // has any required fields, they'll be found when we return to it, - // and the whole call to HasRequiredFields() will return true. - // Therefore, we don't have to check if this type has required fields - // here. - return false; - } - already_seen->insert(type); - - // If the type has extensions, an extension with message type could contain - // required fields, so we have to be conservative and assume such an - // extension exists. - if (type->extension_range_count() > 0) return true; - - for (int i = 0; i < type->field_count(); i++) { - const FieldDescriptor* field = type->field(i); - if (field->is_required()) { - return true; - } - if (GetJavaType(field) == JAVATYPE_MESSAGE) { - if (HasRequiredFields(field->message_type(), already_seen)) { - return true; - } - } - } - - return false; -} - -static bool HasRequiredFields(const Descriptor* type) { - hash_set already_seen; - return HasRequiredFields(type, &already_seen); -} - } // namespace // =================================================================== MessageGenerator::MessageGenerator(const Descriptor* descriptor) - : descriptor_(descriptor), - field_generators_(descriptor) { -} + : descriptor_(descriptor) {} MessageGenerator::~MessageGenerator() {} -void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { +// =================================================================== +// TODO(api): Move this class to a separate immutable_message.cc file. +ImmutableMessageGenerator::ImmutableMessageGenerator( + const Descriptor* descriptor, Context* context) + : MessageGenerator(descriptor), context_(context), + name_resolver_(context->GetNameResolver()), + field_generators_(descriptor, context_) { +} + +ImmutableMessageGenerator::~ImmutableMessageGenerator() {} + +void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { // Because descriptor.proto (com.google.protobuf.DescriptorProtos) is // used in the construction of descriptors, we have a tricky bootstrapping @@ -171,12 +99,12 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); + vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier( descriptor_->containing_type()); } - if (descriptor_->file()->options().java_multiple_files()) { + if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { // We can only make these package-private since the classes that use them // are in separate files. vars["private"] = ""; @@ -186,31 +114,28 @@ void MessageGenerator::GenerateStaticVariables(io::Printer* printer) { // The descriptor for this type. printer->Print(vars, - "$private$static com.google.protobuf.Descriptors.Descriptor\n" + "$private$static final com.google.protobuf.Descriptors.Descriptor\n" " internal_$identifier$_descriptor;\n"); // And the FieldAccessorTable. - printer->Print(vars, - "$private$static\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" - " internal_$identifier$_fieldAccessorTable;\n"); + GenerateFieldAccessorTable(printer); } // Generate static members for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(descriptor_->nested_type(i)) + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateStaticVariables(printer); } } -void MessageGenerator::GenerateStaticVariableInitializers( +void ImmutableMessageGenerator::GenerateStaticVariableInitializers( io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { map vars; vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); vars["index"] = SimpleItoa(descriptor_->index()); - vars["classname"] = ClassName(descriptor_); + vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_); if (descriptor_->containing_type() != NULL) { vars["parent"] = UniqueFileScopeIdentifier( descriptor_->containing_type()); @@ -228,56 +153,95 @@ void MessageGenerator::GenerateStaticVariableInitializers( } // And the FieldAccessorTable. - printer->Print(vars, - "internal_$identifier$_fieldAccessorTable = new\n" - " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" - " internal_$identifier$_descriptor,\n" - " new java.lang.String[] { "); - for (int i = 0; i < descriptor_->field_count(); i++) { - printer->Print( - "\"$field_name$\", ", - "field_name", - UnderscoresToCapitalizedCamelCase(descriptor_->field(i))); - } - printer->Print( - "});\n"); + GenerateFieldAccessorTableInitializer(printer); } // Generate static member initializers for all nested types. for (int i = 0; i < descriptor_->nested_type_count(); i++) { // TODO(kenton): Reuse MessageGenerator objects? - MessageGenerator(descriptor_->nested_type(i)) + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateStaticVariableInitializers(printer); } } +void ImmutableMessageGenerator:: +GenerateFieldAccessorTable(io::Printer* printer) { + map vars; + vars["identifier"] = UniqueFileScopeIdentifier(descriptor_); + if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) { + // We can only make these package-private since the classes that use them + // are in separate files. + vars["private"] = ""; + } else { + vars["private"] = "private "; + } + printer->Print(vars, + "$private$static\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable\n" + " internal_$identifier$_fieldAccessorTable;\n"); +} + +void ImmutableMessageGenerator:: +GenerateFieldAccessorTableInitializer(io::Printer* printer) { + printer->Print( + "internal_$identifier$_fieldAccessorTable = new\n" + " com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n" + " internal_$identifier$_descriptor,\n" + " new java.lang.String[] { ", + "identifier", + UniqueFileScopeIdentifier(descriptor_)); + for (int i = 0; i < descriptor_->field_count(); i++) { + const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + printer->Print( + "\"$field_name$\", ", + "field_name", info->capitalized_name); + } + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + const OneofDescriptor* oneof = descriptor_->oneof_decl(i); + const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof); + printer->Print( + "\"$oneof_name$\", ", + "oneof_name", info->capitalized_name); + } + printer->Print("});\n"); +} + // =================================================================== -void MessageGenerator::GenerateInterface(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessage.\n" " ExtendableMessageOrBuilder<$classname$> {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } else { printer->Print( "public interface $classname$OrBuilder extends \n" + " $extra_interfaces$\n" " com.google.protobuf.GeneratedMessageLite.\n" " ExtendableMessageOrBuilder<$classname$> {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public interface $classname$OrBuilder\n" - " extends com.google.protobuf.MessageOrBuilder {\n", + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageOrBuilder {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } else { printer->Print( - "public interface $classname$OrBuilder\n" - " extends com.google.protobuf.MessageLiteOrBuilder {\n", + "public interface $classname$OrBuilder extends\n" + " $extra_interfaces$\n" + " com.google.protobuf.MessageLiteOrBuilder {\n", + "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_), "classname", descriptor_->name()); } } @@ -285,7 +249,6 @@ void MessageGenerator::GenerateInterface(io::Printer* printer) { printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("\n"); - PrintFieldComment(printer, descriptor_->field(i)); field_generators_.get(descriptor_->field(i)) .GenerateInterfaceMembers(printer); } @@ -296,10 +259,10 @@ void MessageGenerator::GenerateInterface(io::Printer* printer) { // =================================================================== -void MessageGenerator::Generate(io::Printer* printer) { +void ImmutableMessageGenerator::Generate(io::Printer* printer) { bool is_own_file = descriptor_->containing_type() == NULL && - descriptor_->file()->options().java_multiple_files(); + MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); WriteMessageDocComment(printer, descriptor_); @@ -308,41 +271,51 @@ void MessageGenerator::Generate(io::Printer* printer) { if (descriptor_->extension_range_count() > 0) { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public $static$ final class $classname$ extends\n" + "public$static$final class $classname$ extends\n" " com.google.protobuf.GeneratedMessage.ExtendableMessage<\n" - " $classname$> implements $classname$OrBuilder {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); builder_type = strings::Substitute( "com.google.protobuf.GeneratedMessage.ExtendableBuilder<$0, ?>", - ClassName(descriptor_)); + name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( - "public $static$ final class $classname$ extends\n" + "public$static$final class $classname$ extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n" - " $classname$> implements $classname$OrBuilder {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + " $classname$> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); builder_type = strings::Substitute( "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>", - ClassName(descriptor_)); + name_resolver_->GetImmutableClassName(descriptor_)); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessage\n" - " implements $classname$OrBuilder {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + "public$static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessage implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); builder_type = "com.google.protobuf.GeneratedMessage.Builder"; } else { printer->Print( - "public $static$ final class $classname$ extends\n" - " com.google.protobuf.GeneratedMessageLite\n" - " implements $classname$OrBuilder {\n", - "static", is_own_file ? "" : "static", - "classname", descriptor_->name()); + "public$static$final class $classname$ extends\n" + " com.google.protobuf.GeneratedMessageLite implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "static", is_own_file ? " " : " static ", + "classname", descriptor_->name(), + "extra_interfaces", ExtraMessageInterfaces(descriptor_)); builder_type = "com.google.protobuf.GeneratedMessageLite.Builder"; } } @@ -359,8 +332,8 @@ void MessageGenerator::Generate(io::Printer* printer) { "}\n", "classname", descriptor_->name(), "buildertype", builder_type, - "set_unknown_fields", HasUnknownFields(descriptor_) - ? " this.unknownFields = builder.getUnknownFields();" : ""); + "set_unknown_fields", + " this.unknownFields = builder.getUnknownFields();"); printer->Print( // Used when constructing the default instance, which cannot be initialized // immediately because it may cyclically refer to other default instances. @@ -376,11 +349,12 @@ void MessageGenerator::Generate(io::Printer* printer) { "}\n" "\n", "classname", descriptor_->name(), - "set_default_unknown_fields", HasUnknownFields(descriptor_) + "set_default_unknown_fields", UseUnknownFieldSet(descriptor_) ? " this.unknownFields =" - " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " : ""); + " com.google.protobuf.UnknownFieldSet.getDefaultInstance(); " + : " this.unknownFields = com.google.protobuf.ByteString.EMPTY;"); - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( "private final com.google.protobuf.UnknownFieldSet unknownFields;\n" "" @@ -389,6 +363,9 @@ void MessageGenerator::Generate(io::Printer* printer) { " getUnknownFields() {\n" " return this.unknownFields;\n" "}\n"); + } else { + printer->Print( + "private final com.google.protobuf.ByteString unknownFields;\n"); } if (HasGeneratedMethods(descriptor_)) { @@ -400,30 +377,102 @@ void MessageGenerator::Generate(io::Printer* printer) { // Nested types for (int i = 0; i < descriptor_->enum_type_count(); i++) { - EnumGenerator(descriptor_->enum_type(i)).Generate(printer); + EnumGenerator(descriptor_->enum_type(i), true, context_) + .Generate(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator messageGenerator(descriptor_->nested_type(i)); + ImmutableMessageGenerator messageGenerator( + descriptor_->nested_type(i), context_); messageGenerator.GenerateInterface(printer); messageGenerator.Generate(printer); } - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForMessage(); + if (GenerateHasBits(descriptor_)) { + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForMessage(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); + + // oneof + map vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // OneofCase enum + printer->Print(vars, + "public enum $oneof_capitalized_name$Case\n" + " implements com.google.protobuf.Internal.EnumLite {\n"); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "$field_name$($field_number$),\n", + "field_name", + ToUpper(field->name()), + "field_number", + SimpleItoa(field->number())); + } + printer->Print( + "$cap_oneof_name$_NOT_SET(0);\n", + "cap_oneof_name", + ToUpper(vars["oneof_name"])); + printer->Print(vars, + "private int value = 0;\n" + "private $oneof_capitalized_name$Case(int value) {\n" + " this.value = value;\n" + "}\n"); + printer->Print(vars, + "public static $oneof_capitalized_name$Case valueOf(int value) {\n" + " switch (value) {\n"); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + " case $field_number$: return $field_name$;\n", + "field_number", + SimpleItoa(field->number()), + "field_name", + ToUpper(field->name())); + } + printer->Print( + " case 0: return $cap_oneof_name$_NOT_SET;\n" + " default: throw new java.lang.IllegalArgumentException(\n" + " \"Value is undefined for this oneof enum.\");\n" + " }\n" + "}\n" + "public int getNumber() {\n" + " return this.value;\n" + "}\n", + "cap_oneof_name", ToUpper(vars["oneof_name"])); + printer->Outdent(); + printer->Print("};\n\n"); + // oneofCase() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + "get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.valueOf(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n"); } // Fields for (int i = 0; i < descriptor_->field_count(); i++) { - PrintFieldComment(printer, descriptor_->field(i)); printer->Print("public static final int $constant_name$ = $number$;\n", "constant_name", FieldConstantName(descriptor_->field(i)), "number", SimpleItoa(descriptor_->field(i)->number())); @@ -436,9 +485,12 @@ void MessageGenerator::Generate(io::Printer* printer) { printer->Print("private void initFields() {\n"); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateInitializationCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateInitializationCode(printer); + } } + printer->Outdent(); printer->Print("}\n"); @@ -451,6 +503,7 @@ void MessageGenerator::Generate(io::Printer* printer) { GenerateEqualsAndHashCode(printer); } + GenerateParseFromMethods(printer); GenerateBuilder(printer); @@ -471,7 +524,8 @@ void MessageGenerator::Generate(io::Printer* printer) { // because the defaultInstance is used by the extension to lazily retrieve // the outer class's FileDescriptor. for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator(descriptor_->extension(i)).Generate(printer); + ImmutableExtensionGenerator(descriptor_->extension(i), context_) + .Generate(printer); } printer->Outdent(); @@ -481,10 +535,10 @@ void MessageGenerator::Generate(io::Printer* printer) { // =================================================================== -void MessageGenerator:: +void ImmutableMessageGenerator:: GenerateMessageSerializationMethods(io::Printer* printer) { scoped_array sorted_fields( - SortFieldsByNumber(descriptor_)); + SortFieldsByNumber(descriptor_)); vector sorted_extensions; for (int i = 0; i < descriptor_->extension_range_count(); ++i) { @@ -513,14 +567,14 @@ GenerateMessageSerializationMethods(io::Printer* printer) { " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" " newMessageSetExtensionWriter();\n", "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } else { printer->Print( "com.google.protobuf.GeneratedMessage$lite$\n" " .ExtendableMessage<$classname$>.ExtensionWriter extensionWriter =\n" " newExtensionWriter();\n", "lite", HasDescriptorMethods(descriptor_) ? "" : "Lite", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } } @@ -539,7 +593,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { if (descriptor_->options().message_set_wire_format()) { printer->Print( "getUnknownFields().writeAsMessageSetTo(output);\n"); @@ -547,6 +601,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "getUnknownFields().writeTo(output);\n"); } + } else { + printer->Print( + "output.writeRawBytes(unknownFields);\n"); } printer->Outdent(); @@ -575,7 +632,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { } } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { if (descriptor_->options().message_set_wire_format()) { printer->Print( "size += getUnknownFields().getSerializedSizeAsMessageSet();\n"); @@ -583,6 +640,9 @@ GenerateMessageSerializationMethods(io::Printer* printer) { printer->Print( "size += getUnknownFields().getSerializedSize();\n"); } + } else { + printer->Print( + "size += unknownFields.size();\n"); } printer->Outdent(); @@ -602,7 +662,7 @@ GenerateMessageSerializationMethods(io::Printer* printer) { "\n"); } -void MessageGenerator:: +void ImmutableMessageGenerator:: GenerateParseFromMethods(io::Printer* printer) { // Note: These are separate from GenerateMessageSerializationMethods() // because they need to be generated even for messages that are optimized @@ -661,15 +721,15 @@ GenerateParseFromMethods(io::Printer* printer) { " return PARSER.parseFrom(input, extensionRegistry);\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } -void MessageGenerator::GenerateSerializeOneField( +void ImmutableMessageGenerator::GenerateSerializeOneField( io::Printer* printer, const FieldDescriptor* field) { field_generators_.get(field).GenerateSerializationCode(printer); } -void MessageGenerator::GenerateSerializeOneExtensionRange( +void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange( io::Printer* printer, const Descriptor::ExtensionRange* range) { printer->Print( "extensionWriter.writeUntil($end$, output);\n", @@ -678,7 +738,7 @@ void MessageGenerator::GenerateSerializeOneExtensionRange( // =================================================================== -void MessageGenerator::GenerateBuilder(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "public static Builder newBuilder() { return Builder.create(); }\n" "public Builder newBuilderForType() { return newBuilder(); }\n" @@ -687,7 +747,7 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { "}\n" "public Builder toBuilder() { return newBuilder(this); }\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasNestedBuilders(descriptor_)) { printer->Print( @@ -706,29 +766,40 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessage.ExtendableBuilder<\n" - " $classname$, Builder> implements $classname$OrBuilder {\n", - "classname", ClassName(descriptor_)); + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<\n" - " $classname$, Builder> implements $classname$OrBuilder {\n", - "classname", ClassName(descriptor_)); + " $classname$, Builder> implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } } else { if (HasDescriptorMethods(descriptor_)) { printer->Print( "public static final class Builder extends\n" - " com.google.protobuf.GeneratedMessage.Builder\n" - " implements $classname$OrBuilder {\n", - "classname", ClassName(descriptor_)); + " com.google.protobuf.GeneratedMessage.Builder implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } else { printer->Print( "public static final class Builder extends\n" " com.google.protobuf.GeneratedMessageLite.Builder<\n" " $classname$, Builder>\n" - " implements $classname$OrBuilder {\n", - "classname", ClassName(descriptor_)); + " implements\n" + " $extra_interfaces$\n" + " $classname$OrBuilder {\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "extra_interfaces", ExtraBuilderInterfaces(descriptor_)); } } printer->Indent(); @@ -741,21 +812,54 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { GenerateBuilderParsingMethods(printer); } - // Integers for bit fields. - int totalBits = 0; - for (int i = 0; i < descriptor_->field_count(); i++) { - totalBits += field_generators_.get(descriptor_->field(i)) - .GetNumBitsForBuilder(); + // oneof + map vars; + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + vars["oneof_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name; + vars["oneof_capitalized_name"] = context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name; + vars["oneof_index"] = SimpleItoa(descriptor_->oneof_decl(i)->index()); + // oneofCase_ and oneof_ + printer->Print(vars, + "private int $oneof_name$Case_ = 0;\n" + "private java.lang.Object $oneof_name$_;\n"); + // oneofCase() and clearOneof() + printer->Print(vars, + "public $oneof_capitalized_name$Case\n" + " get$oneof_capitalized_name$Case() {\n" + " return $oneof_capitalized_name$Case.valueOf(\n" + " $oneof_name$Case_);\n" + "}\n" + "\n" + "public Builder clear$oneof_capitalized_name$() {\n" + " $oneof_name$Case_ = 0;\n" + " $oneof_name$_ = null;\n"); + if (HasDescriptorMethods(descriptor_)) { + printer->Print(" onChanged();\n"); + } + printer->Print( + " return this;\n" + "}\n" + "\n"); } - int totalInts = (totalBits + 31) / 32; - for (int i = 0; i < totalInts; i++) { - printer->Print("private int $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); + + if (GenerateHasBits(descriptor_)) { + // Integers for bit fields. + int totalBits = 0; + for (int i = 0; i < descriptor_->field_count(); i++) { + totalBits += field_generators_.get(descriptor_->field(i)) + .GetNumBitsForBuilder(); + } + int totalInts = (totalBits + 31) / 32; + for (int i = 0; i < totalInts; i++) { + printer->Print("private int $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } } for (int i = 0; i < descriptor_->field_count(); i++) { printer->Print("\n"); - PrintFieldComment(printer, descriptor_->field(i)); field_generators_.get(descriptor_->field(i)) .GenerateBuilderMembers(printer); } @@ -769,7 +873,8 @@ void MessageGenerator::GenerateBuilder(io::Printer* printer) { printer->Print("}\n"); } -void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateDescriptorMethods(io::Printer* printer) { if (HasDescriptorMethods(descriptor_)) { if (!descriptor_->options().no_standard_descriptor_accessor()) { printer->Print( @@ -778,7 +883,7 @@ void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) { " return $fileclass$.internal_$identifier$_descriptor;\n" "}\n" "\n", - "fileclass", ClassName(descriptor_->file()), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), "identifier", UniqueFileScopeIdentifier(descriptor_)); } printer->Print( @@ -789,22 +894,23 @@ void MessageGenerator::GenerateDescriptorMethods(io::Printer* printer) { " $classname$.class, $classname$.Builder.class);\n" "}\n" "\n", - "classname", ClassName(descriptor_), - "fileclass", ClassName(descriptor_->file()), + "classname", name_resolver_->GetImmutableClassName(descriptor_), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), "identifier", UniqueFileScopeIdentifier(descriptor_)); } } // =================================================================== -void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateCommonBuilderMethods(io::Printer* printer) { printer->Print( "// Construct using $classname$.newBuilder()\n" "private Builder() {\n" " maybeForceBuilderInitialization();\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( @@ -813,7 +919,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " super(parent);\n" " maybeForceBuilderInitialization();\n" "}\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } @@ -825,8 +931,10 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { printer->Indent(); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateFieldBuilderInitializationCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateFieldBuilderInitializationCode(printer); + } } printer->Outdent(); printer->Outdent(); @@ -847,13 +955,23 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "\n" "public Builder clear() {\n" " super.clear();\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)) - .GenerateBuilderClearCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get(descriptor_->field(i)) + .GenerateBuilderClearCode(printer); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print( + "$oneof_name$Case_ = 0;\n" + "$oneof_name$_ = null;\n", + "oneof_name", context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); } printer->Outdent(); @@ -866,7 +984,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " return create().mergeFrom(buildPartial());\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); if (HasDescriptorMethods(descriptor_)) { printer->Print( "public com.google.protobuf.Descriptors.Descriptor\n" @@ -874,7 +992,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " return $fileclass$.internal_$identifier$_descriptor;\n" "}\n" "\n", - "fileclass", ClassName(descriptor_->file()), + "fileclass", name_resolver_->GetImmutableClassName(descriptor_->file()), "identifier", UniqueFileScopeIdentifier(descriptor_)); } printer->Print( @@ -882,7 +1000,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " return $classname$.getDefaultInstance();\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); // ----------------------------------------------------------------- @@ -897,30 +1015,34 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { "\n" "public $classname$ buildPartial() {\n" " $classname$ result = new $classname$(this);\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); - // Local vars for from and to bit fields to avoid accessing the builder and - // message over and over for these fields. Seems to provide a slight - // perforamance improvement in micro benchmark and this is also what proto1 - // code does. int totalBuilderBits = 0; int totalMessageBits = 0; for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldGenerator& field = field_generators_.get(descriptor_->field(i)); + const ImmutableFieldGenerator& field = + field_generators_.get(descriptor_->field(i)); totalBuilderBits += field.GetNumBitsForBuilder(); totalMessageBits += field.GetNumBitsForMessage(); } int totalBuilderInts = (totalBuilderBits + 31) / 32; int totalMessageInts = (totalMessageBits + 31) / 32; - for (int i = 0; i < totalBuilderInts; i++) { - printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); - } - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("int to_$bit_field_name$ = 0;\n", - "bit_field_name", GetBitFieldName(i)); + + if (GenerateHasBits(descriptor_)) { + // Local vars for from and to bit fields to avoid accessing the builder and + // message over and over for these fields. Seems to provide a slight + // perforamance improvement in micro benchmark and this is also what proto1 + // code does. + for (int i = 0; i < totalBuilderInts; i++) { + printer->Print("int from_$bit_field_name$ = $bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("int to_$bit_field_name$ = 0;\n", + "bit_field_name", GetBitFieldName(i)); + } } // Output generation code for each field. @@ -928,10 +1050,18 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { field_generators_.get(descriptor_->field(i)).GenerateBuildingCode(printer); } - // Copy the bit field results to the generated message - for (int i = 0; i < totalMessageInts; i++) { - printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", - "bit_field_name", GetBitFieldName(i)); + if (GenerateHasBits(descriptor_)) { + // Copy the bit field results to the generated message + for (int i = 0; i < totalMessageInts; i++) { + printer->Print("result.$bit_field_name$ = to_$bit_field_name$;\n", + "bit_field_name", GetBitFieldName(i)); + } + } + + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + printer->Print("result.$oneof_name$Case_ = $oneof_name$Case_;\n", + "oneof_name", context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name); } printer->Outdent(); @@ -945,7 +1075,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " return result;\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); // ----------------------------------------------------------------- @@ -963,7 +1093,7 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " }\n" "}\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } printer->Print( @@ -971,11 +1101,48 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { // Optimization: If other is the default instance, we know none of its // fields are set so we can skip the merge. " if (other == $classname$.getDefaultInstance()) return this;\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); for (int i = 0; i < descriptor_->field_count(); i++) { - field_generators_.get(descriptor_->field(i)).GenerateMergingCode(printer); + if (!descriptor_->field(i)->containing_oneof()) { + field_generators_.get( + descriptor_->field(i)).GenerateMergingCode(printer); + } + } + + // Merge oneof fields. + for (int i = 0; i < descriptor_->oneof_decl_count(); ++i) { + printer->Print( + "switch (other.get$oneof_capitalized_name$Case()) {\n", + "oneof_capitalized_name", + context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->capitalized_name); + printer->Indent(); + for (int j = 0; j < descriptor_->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = descriptor_->oneof_decl(i)->field(j); + printer->Print( + "case $field_name$: {\n", + "field_name", + ToUpper(field->name())); + printer->Indent(); + field_generators_.get(field).GenerateMergingCode(printer); + printer->Print( + "break;\n"); + printer->Outdent(); + printer->Print( + "}\n"); + } + printer->Print( + "case $cap_oneof_name$_NOT_SET: {\n" + " break;\n" + "}\n", + "cap_oneof_name", + ToUpper(context_->GetOneofGeneratorInfo( + descriptor_->oneof_decl(i))->name)); + printer->Outdent(); + printer->Print( + "}\n"); } printer->Outdent(); @@ -986,9 +1153,13 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { " this.mergeExtensionFields(other);\n"); } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( " this.mergeUnknownFields(other.getUnknownFields());\n"); + } else { + printer->Print( + " setUnknownFields(\n" + " getUnknownFields().concat(other.unknownFields));\n"); } printer->Print( @@ -1000,7 +1171,8 @@ void MessageGenerator::GenerateCommonBuilderMethods(io::Printer* printer) { // =================================================================== -void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateBuilderParsingMethods(io::Printer* printer) { printer->Print( "public Builder mergeFrom(\n" " com.google.protobuf.CodedInputStream input,\n" @@ -1019,12 +1191,12 @@ void MessageGenerator::GenerateBuilderParsingMethods(io::Printer* printer) { " }\n" " return this;\n" "}\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); } // =================================================================== -void MessageGenerator::GenerateIsInitialized( +void ImmutableMessageGenerator::GenerateIsInitialized( io::Printer* printer, UseMemoization useMemoization) { bool memoization = useMemoization == MEMOIZE; if (memoization) { @@ -1039,9 +1211,11 @@ void MessageGenerator::GenerateIsInitialized( printer->Indent(); if (memoization) { + // Don't directly compare to -1 to avoid an Android x86 JIT bug. printer->Print( "byte isInitialized = memoizedIsInitialized;\n" - "if (isInitialized != -1) return isInitialized == 1;\n" + "if (isInitialized == 1) return true;\n" + "if (isInitialized == 0) return false;\n" "\n"); } @@ -1050,6 +1224,7 @@ void MessageGenerator::GenerateIsInitialized( // "has" fields into a single bitfield. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); if (field->is_required()) { printer->Print( @@ -1057,7 +1232,7 @@ void MessageGenerator::GenerateIsInitialized( " $memoize$\n" " return false;\n" "}\n", - "name", UnderscoresToCapitalizedCamelCase(field), + "name", info->capitalized_name, "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); } } @@ -1065,6 +1240,7 @@ void MessageGenerator::GenerateIsInitialized( // Now check that all embedded messages are initialized. for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); if (GetJavaType(field) == JAVATYPE_MESSAGE && HasRequiredFields(field->message_type())) { switch (field->label()) { @@ -1074,8 +1250,9 @@ void MessageGenerator::GenerateIsInitialized( " $memoize$\n" " return false;\n" "}\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field), + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; case FieldDescriptor::LABEL_OPTIONAL: @@ -1086,8 +1263,9 @@ void MessageGenerator::GenerateIsInitialized( " return false;\n" " }\n" "}\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field), + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; case FieldDescriptor::LABEL_REPEATED: @@ -1098,8 +1276,9 @@ void MessageGenerator::GenerateIsInitialized( " return false;\n" " }\n" "}\n", - "type", ClassName(field->message_type()), - "name", UnderscoresToCapitalizedCamelCase(field), + "type", name_resolver_->GetImmutableClassName( + field->message_type()), + "name", info->capitalized_name, "memoize", memoization ? "memoizedIsInitialized = 0;" : ""); break; } @@ -1130,7 +1309,21 @@ void MessageGenerator::GenerateIsInitialized( // =================================================================== -void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { +namespace { +bool CheckHasBitsForEqualsAndHashCode(const FieldDescriptor* field) { + if (field->is_repeated()) { + return false; + } + if (SupportFieldPresence(field->file())) { + return true; + } + return GetJavaType(field) == JAVATYPE_MESSAGE && + field->containing_oneof() == NULL; +} +} // namespace + +void ImmutableMessageGenerator:: +GenerateEqualsAndHashCode(io::Printer* printer) { printer->Print( "@java.lang.Override\n" "public boolean equals(final java.lang.Object obj) {\n"); @@ -1144,20 +1337,22 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { "}\n" "$classname$ other = ($classname$) obj;\n" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Print("boolean result = true;\n"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated()) { + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); + if (check_has_bits) { printer->Print( "result = result && (has$name$() == other.has$name$());\n" "if (has$name$()) {\n", - "name", UnderscoresToCapitalizedCamelCase(field)); + "name", info->capitalized_name); printer->Indent(); } field_generators_.get(field).GenerateEqualsCode(printer); - if (!field->is_repeated()) { + if (check_has_bits) { printer->Outdent(); printer->Print( "}\n"); @@ -1180,8 +1375,6 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { "}\n" "\n"); - printer->Print( - "private int memoizedHashCode = 0;\n"); printer->Print( "@java.lang.Override\n" "public int hashCode() {\n"); @@ -1194,18 +1387,29 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { printer->Outdent(); printer->Print( "}\n" - "int hash = 41;\n" - "hash = (19 * hash) + getDescriptorForType().hashCode();\n"); + "int hash = 41;\n"); + + if (HasDescriptorMethods(descriptor_)) { + printer->Print("hash = (19 * hash) + getDescriptorForType().hashCode();\n"); + } else { + // Include the hash of the class so that two objects with different types + // but the same field values will probably have different hashes. + printer->Print("hash = (19 * hash) + $classname$.class.hashCode();\n", + "classname", name_resolver_->GetImmutableClassName(descriptor_)); + } + for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (!field->is_repeated()) { + const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field); + bool check_has_bits = CheckHasBitsForEqualsAndHashCode(field); + if (check_has_bits) { printer->Print( "if (has$name$()) {\n", - "name", UnderscoresToCapitalizedCamelCase(field)); + "name", info->capitalized_name); printer->Indent(); } field_generators_.get(field).GenerateHashCode(printer); - if (!field->is_repeated()) { + if (check_has_bits) { printer->Outdent(); printer->Print("}\n"); } @@ -1216,8 +1420,15 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { "hash = hashFields(hash, getExtensionFields());\n"); } } + + if (UseUnknownFieldSet(descriptor_)) { + printer->Print( + "hash = (29 * hash) + getUnknownFields().hashCode();\n"); + } else { + printer->Print( + "hash = (29 * hash) + unknownFields.hashCode();\n"); + } printer->Print( - "hash = (29 * hash) + getUnknownFields().hashCode();\n" "memoizedHashCode = hash;\n" "return hash;\n"); printer->Outdent(); @@ -1228,20 +1439,22 @@ void MessageGenerator::GenerateEqualsAndHashCode(io::Printer* printer) { // =================================================================== -void MessageGenerator::GenerateExtensionRegistrationCode(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateExtensionRegistrationCode(io::Printer* printer) { for (int i = 0; i < descriptor_->extension_count(); i++) { - ExtensionGenerator(descriptor_->extension(i)) + ImmutableExtensionGenerator(descriptor_->extension(i), context_) .GenerateRegistrationCode(printer); } for (int i = 0; i < descriptor_->nested_type_count(); i++) { - MessageGenerator(descriptor_->nested_type(i)) + ImmutableMessageGenerator(descriptor_->nested_type(i), context_) .GenerateExtensionRegistrationCode(printer); } } // =================================================================== -void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { +void ImmutableMessageGenerator:: +GenerateParsingConstructor(io::Printer* printer) { scoped_array sorted_fields( SortFieldsByNumber(descriptor_)); @@ -1260,7 +1473,8 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { // Use builder bits to track mutable repeated fields. int totalBuilderBits = 0; for (int i = 0; i < descriptor_->field_count(); i++) { - const FieldGenerator& field = field_generators_.get(descriptor_->field(i)); + const ImmutableFieldGenerator& field = + field_generators_.get(descriptor_->field(i)); totalBuilderBits += field.GetNumBitsForBuilder(); } int totalBuilderInts = (totalBuilderBits + 31) / 32; @@ -1269,10 +1483,17 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { "bit_field_name", GetBitFieldName(i)); } - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( "com.google.protobuf.UnknownFieldSet.Builder unknownFields =\n" " com.google.protobuf.UnknownFieldSet.newBuilder();\n"); + } else { + printer->Print( + "com.google.protobuf.ByteString.Output unknownFieldsOutput =\n" + " com.google.protobuf.ByteString.newOutput();\n" + "com.google.protobuf.CodedOutputStream unknownFieldsCodedOutput =\n" + " com.google.protobuf.CodedOutputStream.newInstance(\n" + " unknownFieldsOutput);\n"); } printer->Print( @@ -1300,8 +1521,8 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { " }\n" " break;\n" "}\n", - "unknown_fields", HasUnknownFields(descriptor_) - ? " unknownFields," : ""); + "unknown_fields", UseUnknownFieldSet(descriptor_) + ? " unknownFields," : " unknownFieldsCodedOutput,"); for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = sorted_fields[i]; @@ -1362,9 +1583,18 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { } // Make unknown fields immutable. - if (HasUnknownFields(descriptor_)) { + if (UseUnknownFieldSet(descriptor_)) { printer->Print( "this.unknownFields = unknownFields.build();\n"); + } else { + printer->Print( + "try {\n" + " unknownFieldsCodedOutput.flush();\n" + "} catch (java.io.IOException e) {\n" + "// Should not happen\n" + "} finally {\n" + " unknownFields = unknownFieldsOutput.toByteString();\n" + "}\n"); } // Make extensions immutable. @@ -1379,7 +1609,7 @@ void MessageGenerator::GenerateParsingConstructor(io::Printer* printer) { } // =================================================================== -void MessageGenerator::GenerateParser(io::Printer* printer) { +void ImmutableMessageGenerator::GenerateParser(io::Printer* printer) { printer->Print( "public static com.google.protobuf.Parser<$classname$> PARSER =\n" " new com.google.protobuf.AbstractParser<$classname$>() {\n", @@ -1429,6 +1659,7 @@ void MessageGenerator::GenerateParser(io::Printer* printer) { "classname", descriptor_->name()); } + } // namespace java } // namespace compiler } // namespace protobuf diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h index a30f0202..406910dc 100644 --- a/src/google/protobuf/compiler/java/java_message.h +++ b/src/google/protobuf/compiler/java/java_message.h @@ -36,11 +36,17 @@ #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__ #include -#include +#include #include namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { class Printer; // printer.h } @@ -53,26 +59,45 @@ namespace java { class MessageGenerator { public: explicit MessageGenerator(const Descriptor* descriptor); - ~MessageGenerator(); + virtual ~MessageGenerator(); // All static variables have to be declared at the top-level of the file // so that we can control initialization order, which is important for // DescriptorProto bootstrapping to work. - void GenerateStaticVariables(io::Printer* printer); + virtual void GenerateStaticVariables(io::Printer* printer) = 0; // Output code which initializes the static variables generated by // GenerateStaticVariables(). - void GenerateStaticVariableInitializers(io::Printer* printer); + virtual void GenerateStaticVariableInitializers(io::Printer* printer) = 0; // Generate the class itself. - void Generate(io::Printer* printer); + virtual void Generate(io::Printer* printer) = 0; // Generates the base interface that both the class and its builder implement - void GenerateInterface(io::Printer* printer); + virtual void GenerateInterface(io::Printer* printer) = 0; // Generate code to register all contained extensions with an // ExtensionRegistry. - void GenerateExtensionRegistrationCode(io::Printer* printer); + virtual void GenerateExtensionRegistrationCode(io::Printer* printer) = 0; + + protected: + const Descriptor* descriptor_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); +}; + +class ImmutableMessageGenerator : public MessageGenerator { + public: + explicit ImmutableMessageGenerator(const Descriptor* descriptor, + Context* context); + virtual ~ImmutableMessageGenerator(); + + virtual void Generate(io::Printer* printer); + virtual void GenerateInterface(io::Printer* printer); + virtual void GenerateExtensionRegistrationCode(io::Printer* printer); + virtual void GenerateStaticVariables(io::Printer* printer); + virtual void GenerateStaticVariableInitializers(io::Printer* printer); private: enum UseMemoization { @@ -80,6 +105,9 @@ class MessageGenerator { DONT_MEMOIZE }; + void GenerateFieldAccessorTable(io::Printer* printer); + void GenerateFieldAccessorTableInitializer(io::Printer* printer); + void GenerateMessageSerializationMethods(io::Printer* printer); void GenerateParseFromMethods(io::Printer* printer); void GenerateSerializeOneField(io::Printer* printer, @@ -94,14 +122,14 @@ class MessageGenerator { void GenerateIsInitialized(io::Printer* printer, UseMemoization useMemoization); void GenerateEqualsAndHashCode(io::Printer* printer); - void GenerateParser(io::Printer* printer); void GenerateParsingConstructor(io::Printer* printer); - const Descriptor* descriptor_; - FieldGeneratorMap field_generators_; + Context* context_; + ClassNameResolver* name_resolver_; + FieldGeneratorMap field_generators_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_message_field.cc b/src/google/protobuf/compiler/java/java_message_field.cc index b0b284f7..80b9a382 100644 --- a/src/google/protobuf/compiler/java/java_message_field.cc +++ b/src/google/protobuf/compiler/java/java_message_field.cc @@ -35,9 +35,11 @@ #include #include +#include #include #include #include +#include #include #include #include @@ -49,19 +51,18 @@ namespace java { namespace { -// TODO(kenton): Factor out a "SetCommonFieldVariables()" to get rid of -// repeat code between this and the other field types. void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, map* variables) { - (*variables)["name"] = - UnderscoresToCamelCase(descriptor); - (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); - (*variables)["constant_name"] = FieldConstantName(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); - (*variables)["type"] = ClassName(descriptor->message_type()); + SetCommonFieldVariables(descriptor, info, variables); + + (*variables)["type"] = + name_resolver->GetImmutableClassName(descriptor->message_type()); + (*variables)["mutable_type"] = + name_resolver->GetMutableClassName(descriptor->message_type()); (*variables)["group_or_message"] = (GetType(descriptor) == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message"; @@ -72,14 +73,28 @@ void SetMessageVariables(const FieldDescriptor* descriptor, (*variables)["on_changed"] = HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; - // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["set_has_field_bit_builder"] = + GenerateSetBit(builderBitIndex) + ";"; + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex) + ";"; - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex); + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_builder"] = ""; + (*variables)["clear_has_field_bit_builder"] = ""; + + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != null"; + } // For repated builders, one bit is used for whether the array is immutable. (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -103,35 +118,41 @@ void SetMessageVariables(const FieldDescriptor* descriptor, // =================================================================== -MessageFieldGenerator:: -MessageFieldGenerator(const FieldDescriptor* descriptor, +ImmutableMessageFieldGenerator:: +ImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, int messageBitIndex, - int builderBitIndex) + int builderBitIndex, + Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex) { - SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - &variables_); + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { + SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -MessageFieldGenerator::~MessageFieldGenerator() {} +ImmutableMessageFieldGenerator::~ImmutableMessageFieldGenerator() {} -int MessageFieldGenerator::GetNumBitsForMessage() const { +int ImmutableMessageFieldGenerator::GetNumBitsForMessage() const { return 1; } -int MessageFieldGenerator::GetNumBitsForBuilder() const { +int ImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { // TODO(jonp): In the future, consider having a method specific to the // interface so that builders can choose dynamically to either return a // message or a nested builder, so that asking for the interface doesn't // cause a message to ever be built. - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + if (SupportFieldPresence(descriptor_->file()) || + descriptor_->containing_oneof() == NULL) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); @@ -143,31 +164,56 @@ GenerateInterfaceMembers(io::Printer* printer) const { } } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private $type$ $name$_;\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public $type$ get$capitalized_name$() {\n" - " return $name$_;\n" - "}\n"); + PrintExtraFieldInfo(variables_, printer); - if (HasNestedBuilders(descriptor_->containing_type())) { + if (SupportFieldPresence(descriptor_->file())) { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" " return $name$_;\n" "}\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder " + "get$capitalized_name$OrBuilder() {\n" + " return $name$_;\n" + "}\n"); + } + } else { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $name$_ != null;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n" + "}\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder " + "get$capitalized_name$OrBuilder() {\n" + " return get$capitalized_name$();\n" + "}\n"); + } } } -void MessageFieldGenerator::PrintNestedBuilderCondition( +void ImmutableMessageFieldGenerator::PrintNestedBuilderCondition( io::Printer* printer, const char* regular_case, const char* nested_builder_case) const { @@ -186,7 +232,7 @@ void MessageFieldGenerator::PrintNestedBuilderCondition( } } -void MessageFieldGenerator::PrintNestedBuilderFunction( +void ImmutableMessageFieldGenerator::PrintNestedBuilderFunction( io::Printer* printer, const char* method_prototype, const char* regular_case, @@ -203,15 +249,22 @@ void MessageFieldGenerator::PrintNestedBuilderFunction( printer->Print("}\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { // When using nested-builders, the code initially works just like the // non-nested builder case. It only creates a nested builder lazily on // demand and then forever delegates to it after creation. - printer->Print(variables_, - // Used when the builder is null. - "private $type$ $name$_ = $type$.getDefaultInstance();\n"); + bool support_field_presence = SupportFieldPresence(descriptor_->file()); + + if (support_field_presence) { + printer->Print(variables_, + // Used when the builder is null. + "private $type$ $name$_ = $type$.getDefaultInstance();\n"); + } else { + printer->Print(variables_, + "private $type$ $name$_ = null;\n"); + } if (HasNestedBuilders(descriptor_->containing_type())) { printer->Print(variables_, @@ -227,17 +280,26 @@ GenerateBuilderMembers(io::Printer* printer) const { // boolean hasField() WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); + if (support_field_presence) { + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + } else { + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $name$Builder_ != null || $name$_ != null;\n" + "}\n"); + } // Field getField() WriteFieldDocComment(printer, descriptor_); PrintNestedBuilderFunction(printer, "$deprecation$public $type$ get$capitalized_name$()", - "return $name$_;\n", + support_field_presence + ? "return $name$_;\n" + : "return $name$_ == null ? $type$.getDefaultInstance() : $name$_;\n", "return $name$Builder_.getMessage();\n", @@ -256,7 +318,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$name$Builder_.setMessage(value);\n", - "$set_has_field_bit_builder$;\n" + "$set_has_field_bit_builder$\n" "return this;\n"); // Field.Builder setField(Field.Builder builderForValue) @@ -270,7 +332,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$name$Builder_.setMessage(builderForValue.build());\n", - "$set_has_field_bit_builder$;\n" + "$set_has_field_bit_builder$\n" "return this;\n"); // Field.Builder mergeField(Field value) @@ -278,18 +340,26 @@ GenerateBuilderMembers(io::Printer* printer) const { PrintNestedBuilderFunction(printer, "$deprecation$public Builder merge$capitalized_name$($type$ value)", - "if ($get_has_field_bit_builder$ &&\n" - " $name$_ != $type$.getDefaultInstance()) {\n" - " $name$_ =\n" - " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" - "} else {\n" - " $name$_ = value;\n" - "}\n" - "$on_changed$\n", + support_field_presence + ? "if ($get_has_field_bit_builder$ &&\n" + " $name$_ != $type$.getDefaultInstance()) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + "} else {\n" + " $name$_ = value;\n" + "}\n" + "$on_changed$\n" + : "if ($name$_ != null) {\n" + " $name$_ =\n" + " $type$.newBuilder($name$_).mergeFrom(value).buildPartial();\n" + "} else {\n" + " $name$_ = value;\n" + "}\n" + "$on_changed$\n", "$name$Builder_.mergeFrom(value);\n", - "$set_has_field_bit_builder$;\n" + "$set_has_field_bit_builder$\n" "return this;\n"); // Field.Builder clearField() @@ -297,19 +367,25 @@ GenerateBuilderMembers(io::Printer* printer) const { PrintNestedBuilderFunction(printer, "$deprecation$public Builder clear$capitalized_name$()", - "$name$_ = $type$.getDefaultInstance();\n" - "$on_changed$\n", + support_field_presence + ? "$name$_ = $type$.getDefaultInstance();\n" + "$on_changed$\n" + : "$name$_ = null;\n" + "$on_changed$\n", - "$name$Builder_.clear();\n", + support_field_presence + ? "$name$Builder_.clear();\n" + : "$name$_ = null;\n" + "$name$Builder_ = null;\n", - "$clear_has_field_bit_builder$;\n" + "$clear_has_field_bit_builder$\n" "return this;\n"); if (HasNestedBuilders(descriptor_->containing_type())) { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" - " $set_has_field_bit_builder$;\n" + " $set_has_field_bit_builder$\n" " $on_changed$\n" " return get$capitalized_name$FieldBuilder().getBuilder();\n" "}\n"); @@ -318,8 +394,16 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" " if ($name$Builder_ != null) {\n" " return $name$Builder_.getMessageOrBuilder();\n" - " } else {\n" - " return $name$_;\n" + " } else {\n"); + if (support_field_presence) { + printer->Print(variables_, + " return $name$_;\n"); + } else { + printer->Print(variables_, + " return $name$_ == null ?\n" + " $type$.getDefaultInstance() : $name$_;\n"); + } + printer->Print(variables_, " }\n" "}\n"); WriteFieldDocComment(printer, descriptor_); @@ -330,7 +414,7 @@ GenerateBuilderMembers(io::Printer* printer) const { " if ($name$Builder_ == null) {\n" " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" " $type$, $type$.Builder, $type$OrBuilder>(\n" - " $name$_,\n" + " get$capitalized_name$(),\n" " getParentForChildren(),\n" " isClean());\n" " $name$_ = null;\n" @@ -340,28 +424,40 @@ GenerateBuilderMembers(io::Printer* printer) const { } } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { - printer->Print(variables_, - "get$capitalized_name$FieldBuilder();\n"); + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "get$capitalized_name$FieldBuilder();\n"); + } } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { - printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n"); + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, "$name$_ = $type$.getDefaultInstance();\n"); + } } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { - PrintNestedBuilderCondition(printer, - "$name$_ = $type$.getDefaultInstance();\n", + if (SupportFieldPresence(descriptor_->file())) { + PrintNestedBuilderCondition(printer, + "$name$_ = $type$.getDefaultInstance();\n", - "$name$Builder_.clear();\n"); - printer->Print(variables_, "$clear_has_field_bit_builder$;\n"); + "$name$Builder_.clear();\n"); + printer->Print(variables_, "$clear_has_field_bit_builder$\n"); + } else { + PrintNestedBuilderCondition(printer, + "$name$_ = null;\n", + + "$name$_ = null;\n" + "$name$Builder_ = null;\n"); + } } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { printer->Print(variables_, "if (other.has$capitalized_name$()) {\n" @@ -369,13 +465,14 @@ GenerateMergingCode(io::Printer* printer) const { "}\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { - - printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n"); + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } PrintNestedBuilderCondition(printer, "result.$name$_ = $name$_;\n", @@ -383,11 +480,11 @@ GenerateBuildingCode(io::Printer* printer) const { "result.$name$_ = $name$Builder_.build();\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "$type$.Builder subBuilder = null;\n" - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " subBuilder = $name$_.toBuilder();\n" "}\n"); @@ -404,74 +501,344 @@ GenerateParsingCode(io::Printer* printer) const { "if (subBuilder != null) {\n" " subBuilder.mergeFrom($name$_);\n" " $name$_ = subBuilder.buildPartial();\n" - "}\n"); - printer->Print(variables_, - "$set_has_field_bit_message$;\n"); + "}\n" + "$set_has_field_bit_message$\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { // noop for messages. } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " output.write$group_or_message$($number$, $name$_);\n" "}\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" " .compute$group_or_message$Size($number$, $name$_);\n" "}\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "result = result && get$capitalized_name$()\n" " .equals(other.get$capitalized_name$());\n"); } -void MessageFieldGenerator:: +void ImmutableMessageFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n" "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); } -string MessageFieldGenerator::GetBoxedType() const { - return ClassName(descriptor_->message_type()); +string ImmutableMessageFieldGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->message_type()); +} + +// =================================================================== + +ImmutableMessageOneofFieldGenerator:: +ImmutableMessageOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableMessageFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutableMessageOneofFieldGenerator:: +~ImmutableMessageOneofFieldGenerator() {} + +void ImmutableMessageOneofFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + "}\n"); + } +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + // When using nested-builders, the code initially works just like the + // non-nested builder case. It only creates a nested builder lazily on + // demand and then forever delegates to it after creation. + if (HasNestedBuilders(descriptor_->containing_type())) { + printer->Print(variables_, + // If this builder is non-null, it is used and the other fields are + // ignored. + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> $name$Builder_;" + "\n"); + } + + // The comments above the methods below are based on a hypothetical + // field of type "Field" called "Field". + + if (SupportFieldPresence(descriptor_->file())) { + // boolean hasField() + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + // Field getField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public $type$ get$capitalized_name$()", + + "if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + "}\n" + "return $type$.getDefaultInstance();\n", + + "if ($has_oneof_case_message$) {\n" + " return $name$Builder_.getMessage();\n" + "}\n" + "return $type$.getDefaultInstance();\n", + + NULL); + + // Field.Builder setField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$($type$ value)", + + "if (value == null) {\n" + " throw new NullPointerException();\n" + "}\n" + "$oneof_name$_ = value;\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(value);\n", + + "$set_oneof_case_message$;\n" + "return this;\n"); + + // Field.Builder setField(Field.Builder builderForValue) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder set$capitalized_name$(\n" + " $type$.Builder builderForValue)", + + "$oneof_name$_ = builderForValue.build();\n" + "$on_changed$\n", + + "$name$Builder_.setMessage(builderForValue.build());\n", + + "$set_oneof_case_message$;\n" + "return this;\n"); + + // Field.Builder mergeField(Field value) + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder merge$capitalized_name$($type$ value)", + + "if ($has_oneof_case_message$ &&\n" + " $oneof_name$_ != $type$.getDefaultInstance()) {\n" + " $oneof_name$_ = $type$.newBuilder(($type$) $oneof_name$_)\n" + " .mergeFrom(value).buildPartial();\n" + "} else {\n" + " $oneof_name$_ = value;\n" + "}\n" + "$on_changed$\n", + + "if ($has_oneof_case_message$) {\n" + " $name$Builder_.mergeFrom(value);\n" + "}\n" + "$name$Builder_.setMessage(value);\n", + + "$set_oneof_case_message$;\n" + "return this;\n"); + + // Field.Builder clearField() + WriteFieldDocComment(printer, descriptor_); + PrintNestedBuilderFunction(printer, + "$deprecation$public Builder clear$capitalized_name$()", + + "if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + "}\n", + + "if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + "}\n" + "$name$Builder_.clear();\n", + + "return this;\n"); + + if (HasNestedBuilders(descriptor_->containing_type())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$.Builder get$capitalized_name$Builder() {\n" + " return get$capitalized_name$FieldBuilder().getBuilder();\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$OrBuilder get$capitalized_name$OrBuilder() {\n" + " if (($has_oneof_case_message$) && ($name$Builder_ != null)) {\n" + " return $name$Builder_.getMessageOrBuilder();\n" + " } else {\n" + " if ($has_oneof_case_message$) {\n" + " return ($type$) $oneof_name$_;\n" + " }\n" + " return $type$.getDefaultInstance();\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "private com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder> \n" + " get$capitalized_name$FieldBuilder() {\n" + " if ($name$Builder_ == null) {\n" + " if (!($has_oneof_case_message$)) {\n" + " $oneof_name$_ = $type$.getDefaultInstance();\n" + " }\n" + " $name$Builder_ = new com.google.protobuf.SingleFieldBuilder<\n" + " $type$, $type$.Builder, $type$OrBuilder>(\n" + " ($type$) $oneof_name$_,\n" + " getParentForChildren(),\n" + " isClean());\n" + " $oneof_name$_ = null;\n" + " }\n" + " $set_oneof_case_message$;\n" + " return $name$Builder_;\n" + "}\n"); + } +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n"); + printer->Indent(); + + PrintNestedBuilderCondition(printer, + "result.$oneof_name$_ = $oneof_name$_;\n", + + "result.$oneof_name$_ = $name$Builder_.build();\n"); + + printer->Outdent(); + printer->Print("}\n"); +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "merge$capitalized_name$(other.get$capitalized_name$());\n"); +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$type$.Builder subBuilder = null;\n" + "if ($has_oneof_case_message$) {\n" + " subBuilder = (($type$) $oneof_name$_).toBuilder();\n" + "}\n"); + + if (GetType(descriptor_) == FieldDescriptor::TYPE_GROUP) { + printer->Print(variables_, + "$oneof_name$_ = input.readGroup($number$, $type$.PARSER,\n" + " extensionRegistry);\n"); + } else { + printer->Print(variables_, + "$oneof_name$_ = input.readMessage($type$.PARSER, extensionRegistry);\n"); + } + + printer->Print(variables_, + "if (subBuilder != null) {\n" + " subBuilder.mergeFrom(($type$) $oneof_name$_);\n" + " $oneof_name$_ = subBuilder.buildPartial();\n" + "}\n"); + printer->Print(variables_, + "$set_oneof_case_message$;\n"); +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.write$group_or_message$($number$, ($type$) $oneof_name$_);\n" + "}\n"); +} + +void ImmutableMessageOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$group_or_message$Size($number$, ($type$) $oneof_name$_);\n" + "}\n"); } // =================================================================== -RepeatedMessageFieldGenerator:: -RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex) +RepeatedImmutableMessageFieldGenerator:: +RepeatedImmutableMessageFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex) { + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { SetMessageVariables(descriptor, messageBitIndex, builderBitIndex, - &variables_); + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {} +RepeatedImmutableMessageFieldGenerator:: +~RepeatedImmutableMessageFieldGenerator() {} -int RepeatedMessageFieldGenerator::GetNumBitsForMessage() const { +int RepeatedImmutableMessageFieldGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedMessageFieldGenerator::GetNumBitsForBuilder() const { +int RepeatedImmutableMessageFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { // TODO(jonp): In the future, consider having methods specific to the // interface so that builders can choose dynamically to either return a @@ -499,10 +866,11 @@ GenerateInterfaceMembers(io::Printer* printer) const { } } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private java.util.List<$type$> $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public java.util.List<$type$> get$capitalized_name$List() {\n" @@ -533,7 +901,7 @@ GenerateMembers(io::Printer* printer) const { } -void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition( +void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderCondition( io::Printer* printer, const char* regular_case, const char* nested_builder_case) const { @@ -552,7 +920,7 @@ void RepeatedMessageFieldGenerator::PrintNestedBuilderCondition( } } -void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction( +void RepeatedImmutableMessageFieldGenerator::PrintNestedBuilderFunction( io::Printer* printer, const char* method_prototype, const char* regular_case, @@ -569,7 +937,7 @@ void RepeatedMessageFieldGenerator::PrintNestedBuilderFunction( printer->Print("}\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { // When using nested-builders, the code initially works just like the // non-nested builder case. It only creates a nested builder lazily on @@ -737,7 +1105,8 @@ GenerateBuilderMembers(io::Printer* printer) const { " java.lang.Iterable values)", "ensure$capitalized_name$IsMutable();\n" - "super.addAll(values, $name$_);\n" + "com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" "$on_changed$\n", "$name$Builder_.addAllMessages(values);\n", @@ -836,18 +1205,18 @@ GenerateBuilderMembers(io::Printer* printer) const { } } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { printer->Print(variables_, "get$capitalized_name$FieldBuilder();\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = java.util.Collections.emptyList();\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { PrintNestedBuilderCondition(printer, "$name$_ = java.util.Collections.emptyList();\n" @@ -856,7 +1225,7 @@ GenerateBuilderClearCode(io::Printer* printer) const { "$name$Builder_.clear();\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { // The code below does two optimizations (non-nested builder case): // 1. If the other list is empty, there's nothing to do. This ensures we @@ -890,7 +1259,7 @@ GenerateMergingCode(io::Printer* printer) const { "}\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { // The code below (non-nested builder case) ensures that the result has an // immutable list. If our list is immutable, we can just reuse it. If not, @@ -905,7 +1274,7 @@ GenerateBuildingCode(io::Printer* printer) const { "result.$name$_ = $name$Builder_.build();\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "if (!$get_mutable_bit_parser$) {\n" @@ -923,7 +1292,7 @@ GenerateParsingCode(io::Printer* printer) const { } } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { printer->Print(variables_, "if ($get_mutable_bit_parser$) {\n" @@ -931,7 +1300,7 @@ GenerateParsingDoneCode(io::Printer* printer) const { "}\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" @@ -939,7 +1308,7 @@ GenerateSerializationCode(io::Printer* printer) const { "}\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "for (int i = 0; i < $name$_.size(); i++) {\n" @@ -948,14 +1317,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { "}\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "result = result && get$capitalized_name$List()\n" " .equals(other.get$capitalized_name$List());\n"); } -void RepeatedMessageFieldGenerator:: +void RepeatedImmutableMessageFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, "if (get$capitalized_name$Count() > 0) {\n" @@ -964,8 +1333,8 @@ GenerateHashCode(io::Printer* printer) const { "}\n"); } -string RepeatedMessageFieldGenerator::GetBoxedType() const { - return ClassName(descriptor_->message_type()); +string RepeatedImmutableMessageFieldGenerator::GetBoxedType() const { + return name_resolver_->GetImmutableClassName(descriptor_->message_type()); } } // namespace java diff --git a/src/google/protobuf/compiler/java/java_message_field.h b/src/google/protobuf/compiler/java/java_message_field.h index 5c8078a1..f7b491e5 100644 --- a/src/google/protobuf/compiler/java/java_message_field.h +++ b/src/google/protobuf/compiler/java/java_message_field.h @@ -40,17 +40,27 @@ #include namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + namespace protobuf { namespace compiler { namespace java { -class MessageFieldGenerator : public FieldGenerator { +class ImmutableMessageFieldGenerator : public ImmutableFieldGenerator { public: - explicit MessageFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex); - ~MessageFieldGenerator(); + explicit ImmutableMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableMessageFieldGenerator(); - // implements FieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -70,13 +80,13 @@ class MessageFieldGenerator : public FieldGenerator { string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; const int messageBitIndex_; const int builderBitIndex_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator); + Context* context_; + ClassNameResolver* name_resolver_; void PrintNestedBuilderCondition(io::Printer* printer, const char* regular_case, const char* nested_builder_case) const; @@ -84,15 +94,39 @@ class MessageFieldGenerator : public FieldGenerator { const char* method_prototype, const char* regular_case, const char* nested_builder_case, const char* trailing_code) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldGenerator); }; -class RepeatedMessageFieldGenerator : public FieldGenerator { +class ImmutableMessageOneofFieldGenerator + : public ImmutableMessageFieldGenerator { public: - explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex); - ~RepeatedMessageFieldGenerator(); + ImmutableMessageOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableMessageOneofFieldGenerator(); - // implements FieldGenerator --------------------------------------- + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldGenerator); +}; + +class RepeatedImmutableMessageFieldGenerator : public ImmutableFieldGenerator { + public: + explicit RepeatedImmutableMessageFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableMessageFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -112,13 +146,13 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; const int messageBitIndex_; const int builderBitIndex_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator); + Context* context_; + ClassNameResolver* name_resolver_; void PrintNestedBuilderCondition(io::Printer* printer, const char* regular_case, const char* nested_builder_case) const; @@ -126,6 +160,9 @@ class RepeatedMessageFieldGenerator : public FieldGenerator { const char* method_prototype, const char* regular_case, const char* nested_builder_case, const char* trailing_code) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_name_resolver.cc b/src/google/protobuf/compiler/java/java_name_resolver.cc new file mode 100644 index 00000000..7f52d234 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_name_resolver.cc @@ -0,0 +1,266 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +namespace { +// A suffix that will be appended to the file's outer class name if the name +// conflicts with some other types defined in the file. +const char* kOuterClassNameSuffix = "OuterClass"; + +// Strip package name from a descriptor's full name. +// For example: +// Full name : foo.Bar.Baz +// Package name: foo +// After strip : Bar.Baz +string StripPackageName(const string& full_name, + const FileDescriptor* file) { + if (file->package().empty()) { + return full_name; + } else { + // Strip package name + return full_name.substr(file->package().size() + 1); + } +} + +// Get the name of a message's Java class without package name prefix. +string ClassNameWithoutPackage(const Descriptor* descriptor, + bool immutable) { + return StripPackageName(descriptor->full_name(), + descriptor->file()); +} + +// Get the name of an enum's Java class without package name prefix. +string ClassNameWithoutPackage(const EnumDescriptor* descriptor, + bool immutable) { + // Doesn't append "Mutable" for enum type's name. + const Descriptor* message_descriptor = descriptor->containing_type(); + if (message_descriptor == NULL) { + return descriptor->name(); + } else { + return ClassNameWithoutPackage(message_descriptor, immutable) + + "." + descriptor->name(); + } +} + +// Get the name of a service's Java class without package name prefix. +string ClassNameWithoutPackage(const ServiceDescriptor* descriptor, + bool immutable) { + string full_name = StripPackageName(descriptor->full_name(), + descriptor->file()); + // We don't allow nested service definitions. + GOOGLE_CHECK(full_name.find('.') == string::npos); + return full_name; +} + +// Check whether a given message or its nested types has the given class name. +bool MessageHasConflictingClassName(const Descriptor* message, + const string& classname) { + if (message->name() == classname) return true; + for (int i = 0; i < message->nested_type_count(); ++i) { + if (MessageHasConflictingClassName(message->nested_type(i), classname)) { + return true; + } + } + for (int i = 0; i < message->enum_type_count(); ++i) { + if (message->enum_type(i)->name() == classname) { + return true; + } + } + return false; +} + +} // namespace + +ClassNameResolver::ClassNameResolver() { +} + +ClassNameResolver::~ClassNameResolver() { +} + +string ClassNameResolver::GetFileDefaultImmutableClassName( + const FileDescriptor* file) { + string basename; + string::size_type last_slash = file->name().find_last_of('/'); + if (last_slash == string::npos) { + basename = file->name(); + } else { + basename = file->name().substr(last_slash + 1); + } + return UnderscoresToCamelCase(StripProto(basename), true); +} + +string ClassNameResolver::GetFileImmutableClassName( + const FileDescriptor* file) { + string& class_name = file_immutable_outer_class_names_[file]; + if (class_name.empty()) { + if (file->options().has_java_outer_classname()) { + class_name = file->options().java_outer_classname(); + } else { + class_name = GetFileDefaultImmutableClassName(file); + if (HasConflictingClassName(file, class_name)) { + class_name += kOuterClassNameSuffix; + } + } + } + return class_name; +} + +string ClassNameResolver::GetFileClassName(const FileDescriptor* file, + bool immutable) { + if (immutable) { + return GetFileImmutableClassName(file); + } else { + return "Mutable" + GetFileImmutableClassName(file); + } +} + +// Check whether there is any type defined in the proto file that has +// the given class name. +bool ClassNameResolver::HasConflictingClassName( + const FileDescriptor* file, const string& classname) { + for (int i = 0; i < file->enum_type_count(); i++) { + if (file->enum_type(i)->name() == classname) { + return true; + } + } + for (int i = 0; i < file->service_count(); i++) { + if (file->service(i)->name() == classname) { + return true; + } + } + for (int i = 0; i < file->message_type_count(); i++) { + if (MessageHasConflictingClassName(file->message_type(i), classname)) { + return true; + } + } + return false; +} + +string ClassNameResolver::GetDescriptorClassName( + const FileDescriptor* descriptor) { + return GetFileImmutableClassName(descriptor) + "InternalDescriptors"; +} + +string ClassNameResolver::GetClassName(const FileDescriptor* descriptor, + bool immutable) { + string result = FileJavaPackage(descriptor, immutable); + if (!result.empty()) result += '.'; + result += GetFileClassName(descriptor, immutable); + return result; +} + +// Get the full name of a Java class by prepending the Java package name +// or outer class name. +string ClassNameResolver::GetClassFullName(const string& name_without_package, + const FileDescriptor* file, + bool immutable, + bool multiple_files) { + string result; + if (multiple_files) { + result = FileJavaPackage(file, immutable); + } else { + result = GetClassName(file, immutable); + } + if (!result.empty()) { + result += '.'; + } + result += name_without_package; + return result; +} + +string ClassNameResolver::GetClassName(const Descriptor* descriptor, + bool immutable) { + return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), + descriptor->file(), immutable, + MultipleJavaFiles(descriptor->file(), immutable)); +} + +string ClassNameResolver::GetClassName(const EnumDescriptor* descriptor, + bool immutable) { + return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), + descriptor->file(), immutable, + MultipleJavaFiles(descriptor->file(), immutable)); +} + +string ClassNameResolver::GetClassName(const ServiceDescriptor* descriptor, + bool immutable) { + return GetClassFullName(ClassNameWithoutPackage(descriptor, immutable), + descriptor->file(), immutable, + MultipleJavaFiles(descriptor->file(), immutable)); +} + +// Get the Java Class style full name of a message. +string ClassNameResolver::GetJavaClassFullName( + const string& name_without_package, + const FileDescriptor* file, + bool immutable) { + string result; + if (MultipleJavaFiles(file, immutable)) { + result = FileJavaPackage(file, immutable); + if (!result.empty()) result += '.'; + } else { + result = GetClassName(file, immutable); + if (!result.empty()) result += '$'; + } + result += StringReplace(name_without_package, ".", "$", true); + return result; +} + +string ClassNameResolver::GetExtensionIdentifierName( + const FieldDescriptor* descriptor, bool immutable) { + return GetClassName(descriptor->containing_type(), immutable) + "." + + descriptor->name(); +} + + +string ClassNameResolver::GetJavaImmutableClassName( + const Descriptor* descriptor) { + return GetJavaClassFullName( + ClassNameWithoutPackage(descriptor, true), + descriptor->file(), true); +} + + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_name_resolver.h b/src/google/protobuf/compiler/java/java_name_resolver.h new file mode 100644 index 00000000..1d3e185c --- /dev/null +++ b/src/google/protobuf/compiler/java/java_name_resolver.h @@ -0,0 +1,124 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ + +#include +#include + +#include + +namespace google { +namespace protobuf { +class Descriptor; +class EnumDescriptor; +class FieldDescriptor; +class FileDescriptor; +class ServiceDescriptor; + +namespace compiler { +namespace java { + +// Used to get the Java class related names for a given descriptor. It caches +// the results to avoid redundant calculation across multiple name queries. +// Thread-safety note: This class is *not* thread-safe. +class ClassNameResolver { + public: + ClassNameResolver(); + ~ClassNameResolver(); + + // Gets the unqualified outer class name for the file. + string GetFileClassName(const FileDescriptor* file, bool immutable); + // Gets the unqualified immutable outer class name of a file. + string GetFileImmutableClassName(const FileDescriptor* file); + // Gets the unqualified default immutable outer class name of a file + // (converted from the proto file's name). + string GetFileDefaultImmutableClassName(const FileDescriptor* file); + + // Check whether there is any type defined in the proto file that has + // the given class name. + bool HasConflictingClassName(const FileDescriptor* file, + const string& classname); + + // Gets the name of the outer class that holds descriptor information. + // Descriptors are shared between immutable messages and mutable messages. + // Since both of them are generated optionally, the descriptors need to be + // put in another common place. + string GetDescriptorClassName(const FileDescriptor* file); + + // Gets the fully-qualified class name corresponding to the given descriptor. + string GetClassName(const Descriptor* descriptor, bool immutable); + string GetClassName(const EnumDescriptor* descriptor, bool immutable); + string GetClassName(const ServiceDescriptor* descriptor, bool immutable); + string GetClassName(const FileDescriptor* descriptor, bool immutable); + + template + string GetImmutableClassName(const DescriptorType* descriptor) { + return GetClassName(descriptor, true); + } + template + string GetMutableClassName(const DescriptorType* descriptor) { + return GetClassName(descriptor, false); + } + + // Gets the fully qualified name of an extension identifier. + string GetExtensionIdentifierName(const FieldDescriptor* descriptor, + bool immutable); + + // Gets the fully qualified name for generated classes in Java convention. + // Nested classes will be separated using '$' instead of '.' + // For example: + // com.package.OuterClass$OuterMessage$InnerMessage + string GetJavaImmutableClassName(const Descriptor* descriptor); + private: + // Get the full name of a Java class by prepending the Java package name + // or outer class name. + string GetClassFullName(const string& name_without_package, + const FileDescriptor* file, + bool immutable, + bool multiple_files); + // Get the Java Class style full name of a message. + string GetJavaClassFullName( + const string& name_without_package, + const FileDescriptor* file, + bool immutable); + // Caches the result to provide better performance. + map file_immutable_outer_class_names_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver); +}; + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__ diff --git a/src/google/protobuf/compiler/java/java_plugin_unittest.cc b/src/google/protobuf/compiler/java/java_plugin_unittest.cc index ccc94c9d..52577626 100644 --- a/src/google/protobuf/compiler/java/java_plugin_unittest.cc +++ b/src/google/protobuf/compiler/java/java_plugin_unittest.cc @@ -34,6 +34,8 @@ // It seemed like parameterizing it would add more complexity than it is // worth. +#include + #include #include #include @@ -71,7 +73,7 @@ class TestGenerator : public CodeGenerator { void TryInsert(const string& filename, const string& insertion_point, GeneratorContext* context) const { scoped_ptr output( - context->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -81,16 +83,16 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(JavaPluginTest, PluginTest) { - File::WriteStringToFileOrDie( - "syntax = \"proto2\";\n" - "package foo;\n" - "option java_package = \"\";\n" - "option java_outer_classname = \"Test\";\n" - "message Bar {\n" - " message Baz {}\n" - "}\n" - "enum Qux { BLAH = 1; }\n", - TestTempDir() + "/test.proto"); + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "option java_package = \"\";\n" + "option java_outer_classname = \"Test\";\n" + "message Bar {\n" + " message Baz {}\n" + "}\n" + "enum Qux { BLAH = 1; }\n", + true)); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/java/java_primitive_field.cc b/src/google/protobuf/compiler/java/java_primitive_field.cc index 0140e23f..031a1293 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.cc +++ b/src/google/protobuf/compiler/java/java_primitive_field.cc @@ -35,10 +35,12 @@ #include #include -#include -#include #include +#include +#include #include +#include +#include #include #include #include @@ -73,107 +75,25 @@ const char* PrimitiveTypeName(JavaType type) { return NULL; } -bool IsReferenceType(JavaType type) { - switch (type) { - case JAVATYPE_INT : return false; - case JAVATYPE_LONG : return false; - case JAVATYPE_FLOAT : return false; - case JAVATYPE_DOUBLE : return false; - case JAVATYPE_BOOLEAN: return false; - case JAVATYPE_STRING : return true; - case JAVATYPE_BYTES : return true; - case JAVATYPE_ENUM : return true; - case JAVATYPE_MESSAGE: return true; - - // No default because we want the compiler to complain if any new - // JavaTypes are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return false; -} - -const char* GetCapitalizedType(const FieldDescriptor* field) { - switch (GetType(field)) { - case FieldDescriptor::TYPE_INT32 : return "Int32" ; - case FieldDescriptor::TYPE_UINT32 : return "UInt32" ; - case FieldDescriptor::TYPE_SINT32 : return "SInt32" ; - case FieldDescriptor::TYPE_FIXED32 : return "Fixed32" ; - case FieldDescriptor::TYPE_SFIXED32: return "SFixed32"; - case FieldDescriptor::TYPE_INT64 : return "Int64" ; - case FieldDescriptor::TYPE_UINT64 : return "UInt64" ; - case FieldDescriptor::TYPE_SINT64 : return "SInt64" ; - case FieldDescriptor::TYPE_FIXED64 : return "Fixed64" ; - case FieldDescriptor::TYPE_SFIXED64: return "SFixed64"; - case FieldDescriptor::TYPE_FLOAT : return "Float" ; - case FieldDescriptor::TYPE_DOUBLE : return "Double" ; - case FieldDescriptor::TYPE_BOOL : return "Bool" ; - case FieldDescriptor::TYPE_STRING : return "String" ; - case FieldDescriptor::TYPE_BYTES : return "Bytes" ; - case FieldDescriptor::TYPE_ENUM : return "Enum" ; - case FieldDescriptor::TYPE_GROUP : return "Group" ; - case FieldDescriptor::TYPE_MESSAGE : return "Message" ; - - // No default because we want the compiler to complain if any new - // types are added. - } - - GOOGLE_LOG(FATAL) << "Can't get here."; - return NULL; -} - -// For encodings with fixed sizes, returns that size in bytes. Otherwise -// returns -1. -int FixedSize(FieldDescriptor::Type type) { - switch (type) { - case FieldDescriptor::TYPE_INT32 : return -1; - case FieldDescriptor::TYPE_INT64 : return -1; - case FieldDescriptor::TYPE_UINT32 : return -1; - case FieldDescriptor::TYPE_UINT64 : return -1; - case FieldDescriptor::TYPE_SINT32 : return -1; - case FieldDescriptor::TYPE_SINT64 : return -1; - case FieldDescriptor::TYPE_FIXED32 : return WireFormatLite::kFixed32Size; - case FieldDescriptor::TYPE_FIXED64 : return WireFormatLite::kFixed64Size; - case FieldDescriptor::TYPE_SFIXED32: return WireFormatLite::kSFixed32Size; - case FieldDescriptor::TYPE_SFIXED64: return WireFormatLite::kSFixed64Size; - case FieldDescriptor::TYPE_FLOAT : return WireFormatLite::kFloatSize; - case FieldDescriptor::TYPE_DOUBLE : return WireFormatLite::kDoubleSize; - - case FieldDescriptor::TYPE_BOOL : return WireFormatLite::kBoolSize; - case FieldDescriptor::TYPE_ENUM : return -1; - - case FieldDescriptor::TYPE_STRING : return -1; - case FieldDescriptor::TYPE_BYTES : return -1; - case FieldDescriptor::TYPE_GROUP : return -1; - case FieldDescriptor::TYPE_MESSAGE : return -1; - - // No default because we want the compiler to complain if any new - // types are added. - } - GOOGLE_LOG(FATAL) << "Can't get here."; - return -1; -} - void SetPrimitiveVariables(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, map* variables) { - (*variables)["name"] = - UnderscoresToCamelCase(descriptor); - (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); - (*variables)["constant_name"] = FieldConstantName(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); + SetCommonFieldVariables(descriptor, info, variables); + (*variables)["type"] = PrimitiveTypeName(GetJavaType(descriptor)); (*variables)["boxed_type"] = BoxedPrimitiveTypeName(GetJavaType(descriptor)); (*variables)["field_type"] = (*variables)["type"]; (*variables)["field_list_type"] = "java.util.List<" + (*variables)["boxed_type"] + ">"; (*variables)["empty_list"] = "java.util.Collections.emptyList()"; - (*variables)["default"] = DefaultValue(descriptor); + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); (*variables)["default_init"] = IsDefaultValueJavaDefault(descriptor) ? - "" : ("= " + DefaultValue(descriptor)); - (*variables)["capitalized_type"] = GetCapitalizedType(descriptor); + "" : ("= " + ImmutableDefaultValue(descriptor, name_resolver)); + (*variables)["capitalized_type"] = + GetCapitalizedType(descriptor, /* immutable = */ true); (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( WireFormat::TagSize(descriptor->number(), GetType(descriptor))); @@ -196,14 +116,33 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["on_changed"] = HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; - // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex); + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["set_has_field_bit_builder"] = + GenerateSetBit(builderBitIndex) + ";"; + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex) + ";"; + + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_builder"] = ""; + (*variables)["clear_has_field_bit_builder"] = ""; + + if (descriptor->type() == FieldDescriptor::TYPE_BYTES) { + (*variables)["is_field_present_message"] = + "!" + (*variables)["name"] + "_.isEmpty()"; + } else { + (*variables)["is_field_present_message"] = + (*variables)["name"] + "_ != " + (*variables)["default"]; + } + } // For repated builders, one bit is used for whether the array is immutable. (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); @@ -227,46 +166,53 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, // =================================================================== -PrimitiveFieldGenerator:: -PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex) +ImmutablePrimitiveFieldGenerator:: +ImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex) { + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - &variables_); + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {} +ImmutablePrimitiveFieldGenerator::~ImmutablePrimitiveFieldGenerator() {} -int PrimitiveFieldGenerator::GetNumBitsForMessage() const { +int ImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { return 1; } -int PrimitiveFieldGenerator::GetNumBitsForBuilder() const { +int ImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private $field_type$ $name$_;\n"); - - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -275,16 +221,18 @@ GenerateMembers(io::Printer* printer) const { "}\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, "private $field_type$ $name$_ $default_init$;\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -296,7 +244,7 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" "$null_check$" - " $set_has_field_bit_builder$;\n" + " $set_has_field_bit_builder$\n" " $name$_ = value;\n" " $on_changed$\n" " return this;\n" @@ -305,7 +253,7 @@ GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public Builder clear$capitalized_name$() {\n" - " $clear_has_field_bit_builder$;\n"); + " $clear_has_field_bit_builder$\n"); JavaType type = GetJavaType(descriptor_); if (type == JAVATYPE_STRING || type == JAVATYPE_BYTES) { // The default value is not a simple literal so we want to avoid executing @@ -322,70 +270,80 @@ GenerateBuilderMembers(io::Printer* printer) const { "}\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for primitives } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$;\n"); + "$clear_has_field_bit_builder$\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " set$capitalized_name$(other.get$capitalized_name$());\n" - "}\n"); + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } else { + printer->Print(variables_, + "if (other.get$capitalized_name$() != $default$) {\n" + " set$capitalized_name$(other.get$capitalized_name$());\n" + "}\n"); + } } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n" "result.$name$_ = $name$_;\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, - "$set_has_field_bit_message$;\n" + "$set_has_field_bit_message$\n" "$name$_ = input.read$capitalized_type$();\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { // noop for primitives. } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " output.write$capitalized_type$($number$, $name$_);\n" "}\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" " .compute$capitalized_type$Size($number$, $name$_);\n" "}\n"); } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { switch (GetJavaType(descriptor_)) { case JAVATYPE_INT: @@ -398,14 +356,18 @@ GenerateEqualsCode(io::Printer* printer) const { case JAVATYPE_FLOAT: printer->Print(variables_, - "result = result && (Float.floatToIntBits(get$capitalized_name$())" - " == Float.floatToIntBits(other.get$capitalized_name$()));\n"); + "result = result && (\n" + " java.lang.Float.floatToIntBits(get$capitalized_name$())\n" + " == java.lang.Float.floatToIntBits(\n" + " other.get$capitalized_name$()));\n"); break; case JAVATYPE_DOUBLE: printer->Print(variables_, - "result = result && (Double.doubleToLongBits(get$capitalized_name$())" - " == Double.doubleToLongBits(other.get$capitalized_name$()));\n"); + "result = result && (\n" + " java.lang.Double.doubleToLongBits(get$capitalized_name$())\n" + " == java.lang.Double.doubleToLongBits(\n" + " other.get$capitalized_name$()));\n"); break; case JAVATYPE_STRING: @@ -423,7 +385,7 @@ GenerateEqualsCode(io::Printer* printer) const { } } -void PrimitiveFieldGenerator:: +void ImmutablePrimitiveFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n"); @@ -435,24 +397,26 @@ GenerateHashCode(io::Printer* printer) const { case JAVATYPE_LONG: printer->Print(variables_, - "hash = (53 * hash) + hashLong(get$capitalized_name$());\n"); + "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" + " get$capitalized_name$());\n"); break; case JAVATYPE_BOOLEAN: printer->Print(variables_, - "hash = (53 * hash) + hashBoolean(get$capitalized_name$());\n"); + "hash = (53 * hash) + com.google.protobuf.Internal.hashBoolean(\n" + " get$capitalized_name$());\n"); break; case JAVATYPE_FLOAT: printer->Print(variables_, - "hash = (53 * hash) + Float.floatToIntBits(\n" + "hash = (53 * hash) + java.lang.Float.floatToIntBits(\n" " get$capitalized_name$());\n"); break; case JAVATYPE_DOUBLE: printer->Print(variables_, - "hash = (53 * hash) + hashLong(\n" - " Double.doubleToLongBits(get$capitalized_name$()));\n"); + "hash = (53 * hash) + com.google.protobuf.Internal.hashLong(\n" + " java.lang.Double.doubleToLongBits(get$capitalized_name$()));\n"); break; case JAVATYPE_STRING: @@ -469,33 +433,157 @@ GenerateHashCode(io::Printer* printer) const { } } -string PrimitiveFieldGenerator::GetBoxedType() const { +string ImmutablePrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } // =================================================================== -RepeatedPrimitiveFieldGenerator:: -RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex) +ImmutablePrimitiveOneofFieldGenerator:: +ImmutablePrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutablePrimitiveFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutablePrimitiveOneofFieldGenerator:: +~ImmutablePrimitiveOneofFieldGenerator() {} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); +} + + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public $type$ get$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " return ($boxed_type$) $oneof_name$_;\n" + " }\n" + " return $default$;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$($type$ value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + printer->Print(variables_, + "set$capitalized_name$(other.get$capitalized_name$());\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + printer->Print(variables_, + "$set_oneof_case_message$;\n" + "$oneof_name$_ = input.read$capitalized_type$();\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.write$capitalized_type$(\n" + " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" + "}\n"); +} + +void ImmutablePrimitiveOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .compute$capitalized_type$Size(\n" + " $number$, ($type$)(($boxed_type$) $oneof_name$_));\n" + "}\n"); +} + +// =================================================================== + +RepeatedImmutablePrimitiveFieldGenerator:: +RepeatedImmutablePrimitiveFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex) { + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - &variables_); + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {} +RepeatedImmutablePrimitiveFieldGenerator:: +~RepeatedImmutablePrimitiveFieldGenerator() {} -int RepeatedPrimitiveFieldGenerator::GetNumBitsForMessage() const { +int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedPrimitiveFieldGenerator::GetNumBitsForBuilder() const { +int RepeatedImmutablePrimitiveFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -509,10 +597,11 @@ GenerateInterfaceMembers(io::Printer* printer) const { } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private $field_list_type$ $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public java.util.List<$boxed_type$>\n" @@ -537,7 +626,7 @@ GenerateMembers(io::Printer* printer) const { } } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { // One field is the list and the bit field keeps track of whether the // list is immutable. If it's immutable, the invariant is that it must @@ -603,7 +692,8 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$public Builder addAll$capitalized_name$(\n" " java.lang.Iterable values) {\n" " ensure$capitalized_name$IsMutable();\n" - " super.addAll(values, $name$_);\n" + " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -617,24 +707,24 @@ GenerateBuilderMembers(io::Printer* printer) const { "}\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for primitives } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $empty_list$;\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $empty_list$;\n" "$clear_mutable_bit_builder$;\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { // The code below does two optimizations: // 1. If the other list is empty, there's nothing to do. This ensures we @@ -654,7 +744,7 @@ GenerateMergingCode(io::Printer* printer) const { "}\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { // The code below ensures that the result has an immutable list. If our // list is immutable, we can just reuse it. If not, we make it immutable. @@ -666,7 +756,7 @@ GenerateBuildingCode(io::Printer* printer) const { "result.$name$_ = $name$_;\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { printer->Print(variables_, "if (!$get_mutable_bit_parser$) {\n" @@ -676,7 +766,7 @@ GenerateParsingCode(io::Printer* printer) const { "$name$_.add(input.read$capitalized_type$());\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { printer->Print(variables_, "int length = input.readRawVarint32();\n" @@ -691,7 +781,7 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { "input.popLimit(limit);\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { printer->Print(variables_, "if ($get_mutable_bit_parser$) {\n" @@ -699,7 +789,7 @@ GenerateParsingDoneCode(io::Printer* printer) const { "}\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, @@ -718,7 +808,7 @@ GenerateSerializationCode(io::Printer* printer) const { } } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "{\n" @@ -761,14 +851,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "result = result && get$capitalized_name$List()\n" " .equals(other.get$capitalized_name$List());\n"); } -void RepeatedPrimitiveFieldGenerator:: +void RepeatedImmutablePrimitiveFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, "if (get$capitalized_name$Count() > 0) {\n" @@ -777,7 +867,7 @@ GenerateHashCode(io::Printer* printer) const { "}\n"); } -string RepeatedPrimitiveFieldGenerator::GetBoxedType() const { +string RepeatedImmutablePrimitiveFieldGenerator::GetBoxedType() const { return BoxedPrimitiveTypeName(GetJavaType(descriptor_)); } diff --git a/src/google/protobuf/compiler/java/java_primitive_field.h b/src/google/protobuf/compiler/java/java_primitive_field.h index 1b5b6d95..489e1b20 100644 --- a/src/google/protobuf/compiler/java/java_primitive_field.h +++ b/src/google/protobuf/compiler/java/java_primitive_field.h @@ -40,17 +40,27 @@ #include namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + namespace protobuf { namespace compiler { namespace java { -class PrimitiveFieldGenerator : public FieldGenerator { +class ImmutablePrimitiveFieldGenerator : public ImmutableFieldGenerator { public: - explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex); - ~PrimitiveFieldGenerator(); + explicit ImmutablePrimitiveFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutablePrimitiveFieldGenerator(); - // implements FieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -70,22 +80,47 @@ class PrimitiveFieldGenerator : public FieldGenerator { string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; const int messageBitIndex_; const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator); + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldGenerator); +}; + +class ImmutablePrimitiveOneofFieldGenerator + : public ImmutablePrimitiveFieldGenerator { + public: + ImmutablePrimitiveOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutablePrimitiveOneofFieldGenerator(); + + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldGenerator); }; -class RepeatedPrimitiveFieldGenerator : public FieldGenerator { +class RepeatedImmutablePrimitiveFieldGenerator + : public ImmutableFieldGenerator { public: - explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex); - ~RepeatedPrimitiveFieldGenerator(); + explicit RepeatedImmutablePrimitiveFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + virtual ~RepeatedImmutablePrimitiveFieldGenerator(); - // implements FieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -111,8 +146,10 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator { map variables_; const int messageBitIndex_; const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_service.cc b/src/google/protobuf/compiler/java/java_service.cc index bcd80359..aa5c5231 100644 --- a/src/google/protobuf/compiler/java/java_service.cc +++ b/src/google/protobuf/compiler/java/java_service.cc @@ -33,8 +33,11 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include + +#include #include #include +#include #include #include #include @@ -49,8 +52,17 @@ ServiceGenerator::ServiceGenerator(const ServiceDescriptor* descriptor) ServiceGenerator::~ServiceGenerator() {} -void ServiceGenerator::Generate(io::Printer* printer) { - bool is_own_file = descriptor_->file()->options().java_multiple_files(); +// =================================================================== +ImmutableServiceGenerator::ImmutableServiceGenerator( + const ServiceDescriptor* descriptor, Context* context) + : ServiceGenerator(descriptor), context_(context), + name_resolver_(context->GetNameResolver()) {} + +ImmutableServiceGenerator::~ImmutableServiceGenerator() {} + +void ImmutableServiceGenerator::Generate(io::Printer* printer) { + bool is_own_file = + MultipleJavaFiles(descriptor_->file(), /* immutable = */ true); WriteServiceDocComment(printer, descriptor_); printer->Print( "public $static$ abstract class $classname$\n" @@ -77,7 +89,7 @@ void ServiceGenerator::Generate(io::Printer* printer) { " getDescriptor() {\n" " return $file$.getDescriptor().getServices().get($index$);\n" "}\n", - "file", ClassName(descriptor_->file()), + "file", name_resolver_->GetImmutableClassName(descriptor_->file()), "index", SimpleItoa(descriptor_->index())); GenerateGetDescriptorForType(printer); @@ -98,7 +110,8 @@ void ServiceGenerator::Generate(io::Printer* printer) { printer->Print("}\n\n"); } -void ServiceGenerator::GenerateGetDescriptorForType(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateGetDescriptorForType( + io::Printer* printer) { printer->Print( "public final com.google.protobuf.Descriptors.ServiceDescriptor\n" " getDescriptorForType() {\n" @@ -106,7 +119,7 @@ void ServiceGenerator::GenerateGetDescriptorForType(io::Printer* printer) { "}\n"); } -void ServiceGenerator::GenerateInterface(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateInterface(io::Printer* printer) { printer->Print("public interface Interface {\n"); printer->Indent(); GenerateAbstractMethods(printer); @@ -114,7 +127,7 @@ void ServiceGenerator::GenerateInterface(io::Printer* printer) { printer->Print("}\n\n"); } -void ServiceGenerator::GenerateNewReflectiveServiceMethod( +void ImmutableServiceGenerator::GenerateNewReflectiveServiceMethod( io::Printer* printer) { printer->Print( "public static com.google.protobuf.Service newReflectiveService(\n" @@ -141,7 +154,7 @@ void ServiceGenerator::GenerateNewReflectiveServiceMethod( printer->Print("}\n\n"); } -void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( +void ImmutableServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( io::Printer* printer) { printer->Print( "public static com.google.protobuf.BlockingService\n" @@ -162,7 +175,7 @@ void ServiceGenerator::GenerateNewReflectiveBlockingServiceMethod( printer->Print("}\n\n"); } -void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { for (int i = 0; i < descriptor_->method_count(); i++) { const MethodDescriptor* method = descriptor_->method(i); WriteMethodDocComment(printer, method); @@ -171,7 +184,7 @@ void ServiceGenerator::GenerateAbstractMethods(io::Printer* printer) { } } -void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateCallMethod(io::Printer* printer) { printer->Print( "\n" "public final void callMethod(\n" @@ -194,8 +207,10 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { map vars; vars["index"] = SimpleItoa(i); vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = ClassName(method->input_type()); - vars["output"] = ClassName(method->output_type()); + vars["input"] = name_resolver_->GetImmutableClassName( + method->input_type()); + vars["output"] = name_resolver_->GetImmutableClassName( + method->output_type()); printer->Print(vars, "case $index$:\n" " this.$method$(controller, ($input$)request,\n" @@ -217,7 +232,8 @@ void ServiceGenerator::GenerateCallMethod(io::Printer* printer) { "\n"); } -void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateCallBlockingMethod( + io::Printer* printer) { printer->Print( "\n" "public final com.google.protobuf.Message callBlockingMethod(\n" @@ -239,8 +255,10 @@ void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) { map vars; vars["index"] = SimpleItoa(i); vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = ClassName(method->input_type()); - vars["output"] = ClassName(method->output_type()); + vars["input"] = name_resolver_->GetImmutableClassName( + method->input_type()); + vars["output"] = name_resolver_->GetImmutableClassName( + method->output_type()); printer->Print(vars, "case $index$:\n" " return impl.$method$(controller, ($input$)request);\n"); @@ -259,7 +277,7 @@ void ServiceGenerator::GenerateCallBlockingMethod(io::Printer* printer) { "\n"); } -void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, +void ImmutableServiceGenerator::GenerateGetPrototype(RequestOrResponse which, io::Printer* printer) { /* * TODO(cpovirk): The exception message says "Service.foo" when it may be @@ -283,7 +301,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, const MethodDescriptor* method = descriptor_->method(i); map vars; vars["index"] = SimpleItoa(i); - vars["type"] = ClassName( + vars["type"] = name_resolver_->GetImmutableClassName( (which == REQUEST) ? method->input_type() : method->output_type()); printer->Print(vars, "case $index$:\n" @@ -303,7 +321,7 @@ void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which, "\n"); } -void ServiceGenerator::GenerateStub(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateStub(io::Printer* printer) { printer->Print( "public static Stub newStub(\n" " com.google.protobuf.RpcChannel channel) {\n" @@ -312,7 +330,7 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) { "\n" "public static final class Stub extends $classname$ implements Interface {" "\n", - "classname", ClassName(descriptor_)); + "classname", name_resolver_->GetImmutableClassName(descriptor_)); printer->Indent(); printer->Print( @@ -335,7 +353,8 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) { map vars; vars["index"] = SimpleItoa(i); - vars["output"] = ClassName(method->output_type()); + vars["output"] = name_resolver_->GetImmutableClassName( + method->output_type()); printer->Print(vars, "channel.callMethod(\n" " getDescriptor().getMethods().get($index$),\n" @@ -357,7 +376,7 @@ void ServiceGenerator::GenerateStub(io::Printer* printer) { "\n"); } -void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) { +void ImmutableServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print( "public static BlockingInterface newBlockingStub(\n" " com.google.protobuf.BlockingRpcChannel channel) {\n" @@ -399,7 +418,8 @@ void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) { map vars; vars["index"] = SimpleItoa(i); - vars["output"] = ClassName(method->output_type()); + vars["output"] = name_resolver_->GetImmutableClassName( + method->output_type()); printer->Print(vars, "return ($output$) channel.callBlockingMethod(\n" " getDescriptor().getMethods().get($index$),\n" @@ -417,13 +437,13 @@ void ServiceGenerator::GenerateBlockingStub(io::Printer* printer) { printer->Print("}\n"); } -void ServiceGenerator::GenerateMethodSignature(io::Printer* printer, +void ImmutableServiceGenerator::GenerateMethodSignature(io::Printer* printer, const MethodDescriptor* method, IsAbstract is_abstract) { map vars; vars["name"] = UnderscoresToCamelCase(method); - vars["input"] = ClassName(method->input_type()); - vars["output"] = ClassName(method->output_type()); + vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); + vars["output"] = name_resolver_->GetImmutableClassName(method->output_type()); vars["abstract"] = (is_abstract == IS_ABSTRACT) ? "abstract" : ""; printer->Print(vars, "public $abstract$ void $name$(\n" @@ -432,13 +452,13 @@ void ServiceGenerator::GenerateMethodSignature(io::Printer* printer, " com.google.protobuf.RpcCallback<$output$> done)"); } -void ServiceGenerator::GenerateBlockingMethodSignature( +void ImmutableServiceGenerator::GenerateBlockingMethodSignature( io::Printer* printer, const MethodDescriptor* method) { map vars; vars["method"] = UnderscoresToCamelCase(method); - vars["input"] = ClassName(method->input_type()); - vars["output"] = ClassName(method->output_type()); + vars["input"] = name_resolver_->GetImmutableClassName(method->input_type()); + vars["output"] = name_resolver_->GetImmutableClassName(method->output_type()); printer->Print(vars, "\n" "public $output$ $method$(\n" diff --git a/src/google/protobuf/compiler/java/java_service.h b/src/google/protobuf/compiler/java/java_service.h index e07eebf7..0d52325e 100644 --- a/src/google/protobuf/compiler/java/java_service.h +++ b/src/google/protobuf/compiler/java/java_service.h @@ -40,8 +40,14 @@ namespace google { namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } namespace io { - class Printer; // printer.h + class Printer; // printer.h } } @@ -52,9 +58,27 @@ namespace java { class ServiceGenerator { public: explicit ServiceGenerator(const ServiceDescriptor* descriptor); - ~ServiceGenerator(); + virtual ~ServiceGenerator(); + + virtual void Generate(io::Printer* printer) = 0; + + enum RequestOrResponse { REQUEST, RESPONSE }; + enum IsAbstract { IS_ABSTRACT, IS_CONCRETE }; + + protected: + const ServiceDescriptor* descriptor_; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); +}; - void Generate(io::Printer* printer); +class ImmutableServiceGenerator : public ServiceGenerator { + public: + explicit ImmutableServiceGenerator(const ServiceDescriptor* descriptor, + Context* context); + virtual ~ImmutableServiceGenerator(); + + virtual void Generate(io::Printer* printer); private: @@ -80,7 +104,6 @@ class ServiceGenerator { void GenerateCallBlockingMethod(io::Printer* printer); // Generate the implementations of Service.get{Request,Response}Prototype(). - enum RequestOrResponse { REQUEST, RESPONSE }; void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer); // Generate a stub implementation of the service. @@ -88,7 +111,6 @@ class ServiceGenerator { // Generate a method signature, possibly abstract, without body or trailing // semicolon. - enum IsAbstract { IS_ABSTRACT, IS_CONCRETE }; void GenerateMethodSignature(io::Printer* printer, const MethodDescriptor* method, IsAbstract is_abstract); @@ -100,9 +122,9 @@ class ServiceGenerator { void GenerateBlockingMethodSignature(io::Printer* printer, const MethodDescriptor* method); - const ServiceDescriptor* descriptor_; - - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator); + Context* context_; + ClassNameResolver* name_resolver_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.cc b/src/google/protobuf/compiler/java/java_shared_code_generator.cc new file mode 100644 index 00000000..c9f80abf --- /dev/null +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.cc @@ -0,0 +1,223 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: xiaofeng@google.com (Feng Xiao) + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace compiler { +namespace java { + +SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file) + : name_resolver_(new ClassNameResolver), file_(file) { +} + +SharedCodeGenerator::~SharedCodeGenerator() { +} + +void SharedCodeGenerator::Generate(GeneratorContext* context, + vector* file_list) { + string java_package = FileJavaPackage(file_); + string package_dir = JavaPackageToDir(java_package); + + if (HasDescriptorMethods(file_)) { + // Generate descriptors. + string classname = name_resolver_->GetDescriptorClassName(file_); + string filename = package_dir + classname + ".java"; + file_list->push_back(filename); + scoped_ptr output(context->Open(filename)); + scoped_ptr printer(new io::Printer(output.get(), '$')); + + printer->Print( + "// Generated by the protocol buffer compiler. DO NOT EDIT!\n" + "// source: $filename$\n" + "\n", + "filename", file_->name()); + if (!java_package.empty()) { + printer->Print( + "package $package$;\n" + "\n", + "package", java_package); + } + printer->Print( + "public final class $classname$ {\n", + "classname", classname); + printer->Indent(); + GenerateDescriptors(printer.get()); + printer->Outdent(); + printer->Print( + "}\n"); + + printer.reset(); + output.reset(); + } +} + + +void SharedCodeGenerator::GenerateDescriptors(io::Printer* printer) { + // Embed the descriptor. We simply serialize the entire FileDescriptorProto + // and embed it as a string literal, which is parsed and built into real + // descriptors at initialization time. We unfortunately have to put it in + // a string literal, not a byte array, because apparently using a literal + // byte array causes the Java compiler to generate *instructions* to + // initialize each and every byte of the array, e.g. as if you typed: + // b[0] = 123; b[1] = 456; b[2] = 789; + // This makes huge bytecode files and can easily hit the compiler's internal + // code size limits (error "code to large"). String literals are apparently + // embedded raw, which is what we want. + FileDescriptorProto file_proto; + file_->CopyTo(&file_proto); + + + string file_data; + file_proto.SerializeToString(&file_data); + + printer->Print( + "public static com.google.protobuf.Descriptors.FileDescriptor\n" + " descriptor;\n" + "static {\n" + " java.lang.String[] descriptorData = {\n"); + printer->Indent(); + printer->Indent(); + + // Only write 40 bytes per line. + static const int kBytesPerLine = 40; + for (int i = 0; i < file_data.size(); i += kBytesPerLine) { + if (i > 0) { + // Every 400 lines, start a new string literal, in order to avoid the + // 64k length limit. + if (i % 400 == 0) { + printer->Print(",\n"); + } else { + printer->Print(" +\n"); + } + } + printer->Print("\"$data$\"", + "data", CEscape(file_data.substr(i, kBytesPerLine))); + } + + printer->Outdent(); + printer->Print("\n};\n"); + + // ----------------------------------------------------------------- + // Create the InternalDescriptorAssigner. + + printer->Print( + "com.google.protobuf.Descriptors.FileDescriptor." + "InternalDescriptorAssigner assigner =\n" + " new com.google.protobuf.Descriptors.FileDescriptor." + " InternalDescriptorAssigner() {\n" + " public com.google.protobuf.ExtensionRegistry assignDescriptors(\n" + " com.google.protobuf.Descriptors.FileDescriptor root) {\n" + " descriptor = root;\n" + // Custom options will be handled when immutable messages' outer class is + // loaded. Here we just return null and let custom options be unknown + // fields. + " return null;\n" + " }\n" + " };\n"); + + // ----------------------------------------------------------------- + // Find out all dependencies. + vector > dependencies; + for (int i = 0; i < file_->dependency_count(); i++) { + if (ShouldIncludeDependency(file_->dependency(i))) { + string filename = file_->dependency(i)->name(); + string classname = FileJavaPackage(file_->dependency(i)) + "." + + name_resolver_->GetDescriptorClassName( + file_->dependency(i)); + dependencies.push_back(make_pair(filename, classname)); + } + } + + // ----------------------------------------------------------------- + // Invoke internalBuildGeneratedFileFrom() to build the file. + printer->Print( + "com.google.protobuf.Descriptors.FileDescriptor\n" + " .internalBuildGeneratedFileFrom(descriptorData,\n"); + + printer->Print( + " $classname$.class,\n" + " new java.lang.String[] {\n", + "classname", name_resolver_->GetDescriptorClassName(file_)); + for (int i = 0; i < dependencies.size(); i++) { + const string& dependency = dependencies[i].second; + printer->Print( + // Here we load the dependency FileDescriptors lazily via Java + // reflection. This is to avoid breaking proto1 targets who have + // genproto dependencies for which we can't generate the descriptor + // class. They will compile fine but when users try to call reflection + // functions upon them it will fail. Users will have to get rid of + // genproto dependencies before they can use proto2 reflection on + // proto1 messages. + " \"$dependency$\",\n", + "dependency", dependency); + } + + printer->Print( + " }, new java.lang.String[] {\n"); + + for (int i = 0; i < dependencies.size(); i++) { + const string& filename = dependencies[i].first; + printer->Print( + " \"$filename$\",\n", + "filename", filename); + } + + printer->Print( + " }, assigner);\n"); + + printer->Outdent(); + printer->Print( + "}\n"); +} + +bool SharedCodeGenerator::ShouldIncludeDependency( + const FileDescriptor* descriptor) { + return true; +} + +} // namespace java +} // namespace compiler +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/compiler/java/java_shared_code_generator.h b/src/google/protobuf/compiler/java/java_shared_code_generator.h new file mode 100644 index 00000000..c5457bf1 --- /dev/null +++ b/src/google/protobuf/compiler/java/java_shared_code_generator.h @@ -0,0 +1,91 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Author: xiaofeng@google.com (Feng Xiao) +// +// Generators that generate shared code between immutable API and mutable API. + +#ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ +#define GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { + class FileDescriptor; // descriptor.h + namespace compiler { + class GeneratorContext; // code_generator.h + namespace java { + class ClassNameResolver; // name_resolver.h + } + } + namespace io { + class Printer; // printer.h + } +} + +namespace protobuf { +namespace compiler { +namespace java { + +// A generator that generates code that are shared between immutable API +// and mutable API. Currently only descriptors are shared. +class SharedCodeGenerator { + public: + explicit SharedCodeGenerator(const FileDescriptor* file); + ~SharedCodeGenerator(); + + void Generate(GeneratorContext* generator_context, + vector* file_list); + + private: + void GenerateDescriptors(io::Printer* printer); + + // Returns whether the dependency should be included in the output file. + // Always returns true for opensource, but used internally at Google to help + // improve compatibility with version 1 of protocol buffers. + bool ShouldIncludeDependency(const FileDescriptor* descriptor); + + scoped_ptr name_resolver_; + const FileDescriptor* file_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator); +}; + + +} // namespace java +} // namespace compiler +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_COMPILER_JAVA_SHARED_CODE_GENERATOR_H__ diff --git a/src/google/protobuf/compiler/java/java_string_field.cc b/src/google/protobuf/compiler/java/java_string_field.cc index 4815663b..374e1d4e 100644 --- a/src/google/protobuf/compiler/java/java_string_field.cc +++ b/src/google/protobuf/compiler/java/java_string_field.cc @@ -36,10 +36,12 @@ #include #include -#include -#include #include +#include +#include #include +#include +#include #include #include #include @@ -57,17 +59,16 @@ namespace { void SetPrimitiveVariables(const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex, + const FieldGeneratorInfo* info, + ClassNameResolver* name_resolver, map* variables) { - (*variables)["name"] = - UnderscoresToCamelCase(descriptor); - (*variables)["capitalized_name"] = - UnderscoresToCapitalizedCamelCase(descriptor); - (*variables)["constant_name"] = FieldConstantName(descriptor); - (*variables)["number"] = SimpleItoa(descriptor->number()); + SetCommonFieldVariables(descriptor, info, variables); + (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY"; - (*variables)["default"] = DefaultValue(descriptor); - (*variables)["default_init"] = ("= " + DefaultValue(descriptor)); + (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver); + (*variables)["default_init"] = + "= " + ImmutableDefaultValue(descriptor, name_resolver); (*variables)["capitalized_type"] = "String"; (*variables)["tag"] = SimpleItoa(WireFormat::MakeTag(descriptor)); (*variables)["tag_size"] = SimpleItoa( @@ -84,16 +85,30 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, (*variables)["on_changed"] = HasDescriptorMethods(descriptor->containing_type()) ? "onChanged();" : ""; - // For singular messages and builders, one bit is used for the hasField bit. - (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); - (*variables)["set_has_field_bit_message"] = GenerateSetBit(messageBitIndex); + if (SupportFieldPresence(descriptor->file())) { + // For singular messages and builders, one bit is used for the hasField bit. + (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex); + (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); + + // Note that these have a trailing ";". + (*variables)["set_has_field_bit_message"] = + GenerateSetBit(messageBitIndex) + ";"; + (*variables)["set_has_field_bit_builder"] = + GenerateSetBit(builderBitIndex) + ";"; + (*variables)["clear_has_field_bit_builder"] = + GenerateClearBit(builderBitIndex) + ";"; - (*variables)["get_has_field_bit_builder"] = GenerateGetBit(builderBitIndex); - (*variables)["set_has_field_bit_builder"] = GenerateSetBit(builderBitIndex); - (*variables)["clear_has_field_bit_builder"] = - GenerateClearBit(builderBitIndex); + (*variables)["is_field_present_message"] = GenerateGetBit(messageBitIndex); + } else { + (*variables)["set_has_field_bit_message"] = ""; + (*variables)["set_has_field_bit_builder"] = ""; + (*variables)["clear_has_field_bit_builder"] = ""; - // For repated builders, one bit is used for whether the array is immutable. + (*variables)["is_field_present_message"] = + "!get" + (*variables)["capitalized_name"] + "Bytes().isEmpty()"; + } + + // For repeated builders, one bit is used for whether the array is immutable. (*variables)["get_mutable_bit_builder"] = GenerateGetBit(builderBitIndex); (*variables)["set_mutable_bit_builder"] = GenerateSetBit(builderBitIndex); (*variables)["clear_mutable_bit_builder"] = GenerateClearBit(builderBitIndex); @@ -111,27 +126,34 @@ void SetPrimitiveVariables(const FieldDescriptor* descriptor, GenerateSetBitToLocal(messageBitIndex); } +bool CheckUtf8(const FieldDescriptor* descriptor) { + return descriptor->file()->options().java_string_check_utf8(); +} + } // namespace // =================================================================== -StringFieldGenerator:: -StringFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex) +ImmutableStringFieldGenerator:: +ImmutableStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex) { + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - &variables_); + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -StringFieldGenerator::~StringFieldGenerator() {} +ImmutableStringFieldGenerator::~ImmutableStringFieldGenerator() {} -int StringFieldGenerator::GetNumBitsForMessage() const { +int ImmutableStringFieldGenerator::GetNumBitsForMessage() const { return 1; } -int StringFieldGenerator::GetNumBitsForBuilder() const { +int ImmutableStringFieldGenerator::GetNumBitsForBuilder() const { return 1; } @@ -167,11 +189,13 @@ int StringFieldGenerator::GetNumBitsForBuilder() const { // For single fields, the logic for this is done inside the generated code. For // repeated fields, the logic is done in LazyStringArrayList and // UnmodifiableLazyStringList. -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$boolean has$capitalized_name$();\n"); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$boolean has$capitalized_name$();\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$java.lang.String get$capitalized_name$();\n"); @@ -181,15 +205,19 @@ GenerateInterfaceMembers(io::Printer* printer) const { " get$capitalized_name$Bytes();\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private java.lang.Object $name$_;\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_message$;\n" - "}\n"); + PrintExtraFieldInfo(variables_, printer); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_message$;\n" + "}\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -200,10 +228,17 @@ GenerateMembers(io::Printer* printer) const { " } else {\n" " com.google.protobuf.ByteString bs = \n" " (com.google.protobuf.ByteString) ref;\n" - " java.lang.String s = bs.toStringUtf8();\n" - " if (bs.isValidUtf8()) {\n" - " $name$_ = s;\n" - " }\n" + " java.lang.String s = bs.toStringUtf8();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " $name$_ = s;\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8()) {\n" + " $name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, " return s;\n" " }\n" "}\n"); @@ -224,24 +259,36 @@ GenerateMembers(io::Printer* printer) const { "}\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, "private java.lang.Object $name$_ $default_init$;\n"); - WriteFieldDocComment(printer, descriptor_); - printer->Print(variables_, - "$deprecation$public boolean has$capitalized_name$() {\n" - " return $get_has_field_bit_builder$;\n" - "}\n"); + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $get_has_field_bit_builder$;\n" + "}\n"); + } WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public java.lang.String get$capitalized_name$() {\n" " java.lang.Object ref = $name$_;\n" " if (!(ref instanceof java.lang.String)) {\n" - " java.lang.String s = ((com.google.protobuf.ByteString) ref)\n" - " .toStringUtf8();\n" - " $name$_ = s;\n" + " com.google.protobuf.ByteString bs =\n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " $name$_ = s;\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8()) {\n" + " $name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, " return s;\n" " } else {\n" " return (java.lang.String) ref;\n" @@ -269,7 +316,7 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$public Builder set$capitalized_name$(\n" " java.lang.String value) {\n" "$null_check$" - " $set_has_field_bit_builder$;\n" + " $set_has_field_bit_builder$\n" " $name$_ = value;\n" " $on_changed$\n" " return this;\n" @@ -277,7 +324,7 @@ GenerateBuilderMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$public Builder clear$capitalized_name$() {\n" - " $clear_has_field_bit_builder$;\n"); + " $clear_has_field_bit_builder$\n"); // The default value is not a simple literal so we want to avoid executing // it multiple times. Instead, get the default out of the default instance. printer->Print(variables_, @@ -291,89 +338,113 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, "$deprecation$public Builder set$capitalized_name$Bytes(\n" " com.google.protobuf.ByteString value) {\n" - "$null_check$" - " $set_has_field_bit_builder$;\n" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, + " $set_has_field_bit_builder$\n" " $name$_ = value;\n" " $on_changed$\n" " return this;\n" "}\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for primitives } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $default$;\n" - "$clear_has_field_bit_builder$;\n"); + "$clear_has_field_bit_builder$\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { - // Allow a slight breach of abstraction here in order to avoid forcing - // all string fields to Strings when copying fields from a Message. - printer->Print(variables_, - "if (other.has$capitalized_name$()) {\n" - " $set_has_field_bit_builder$;\n" - " $name$_ = other.$name$_;\n" - " $on_changed$\n" - "}\n"); + if (SupportFieldPresence(descriptor_->file())) { + // Allow a slight breach of abstraction here in order to avoid forcing + // all string fields to Strings when copying fields from a Message. + printer->Print(variables_, + "if (other.has$capitalized_name$()) {\n" + " $set_has_field_bit_builder$\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); + } else { + printer->Print(variables_, + "if (!other.get$capitalized_name$().isEmpty()) {\n" + " $name$_ = other.$name$_;\n" + " $on_changed$\n" + "}\n"); + } } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + printer->Print(variables_, + "if ($get_has_field_bit_from_local$) {\n" + " $set_has_field_bit_to_local$;\n" + "}\n"); + } printer->Print(variables_, - "if ($get_has_field_bit_from_local$) {\n" - " $set_has_field_bit_to_local$;\n" - "}\n" "result.$name$_ = $name$_;\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { - printer->Print(variables_, - "$set_has_field_bit_message$;\n" - "$name$_ = input.readBytes();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n" + "$set_has_field_bit_message$\n" + "$name$_ = s;\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "$set_has_field_bit_message$\n" + "$name$_ = bs;\n"); + } } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { // noop for strings. } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " output.writeBytes($number$, get$capitalized_name$Bytes());\n" "}\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, - "if ($get_has_field_bit_message$) {\n" + "if ($is_field_present_message$) {\n" " size += com.google.protobuf.CodedOutputStream\n" " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" "}\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "result = result && get$capitalized_name$()\n" " .equals(other.get$capitalized_name$());\n"); } -void StringFieldGenerator:: +void ImmutableStringFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, "hash = (37 * hash) + $constant_name$;\n"); @@ -381,39 +452,270 @@ GenerateHashCode(io::Printer* printer) const { "hash = (53 * hash) + get$capitalized_name$().hashCode();\n"); } -string StringFieldGenerator::GetBoxedType() const { +string ImmutableStringFieldGenerator::GetBoxedType() const { return "java.lang.String"; } +// =================================================================== + +ImmutableStringOneofFieldGenerator:: +ImmutableStringOneofFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) + : ImmutableStringFieldGenerator( + descriptor, messageBitIndex, builderBitIndex, context) { + const OneofGeneratorInfo* info = + context->GetOneofGeneratorInfo(descriptor->containing_oneof()); + SetCommonOneofVariables(descriptor, info, &variables_); +} + +ImmutableStringOneofFieldGenerator:: +~ImmutableStringOneofFieldGenerator() {} + +void ImmutableStringOneofFieldGenerator:: +GenerateMembers(io::Printer* printer) const { + PrintExtraFieldInfo(variables_, printer); + + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof java.lang.String) {\n" + " return (java.lang.String) ref;\n" + " } else {\n" + " com.google.protobuf.ByteString bs = \n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = s;\n" + " }\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8() && ($has_oneof_case_message$)) {\n" + " $oneof_name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, + " return s;\n" + " }\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof java.lang.String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = b;\n" + " }\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateBuilderMembers(io::Printer* printer) const { + if (SupportFieldPresence(descriptor_->file())) { + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public boolean has$capitalized_name$() {\n" + " return $has_oneof_case_message$;\n" + "}\n"); + } + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public java.lang.String get$capitalized_name$() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (!(ref instanceof java.lang.String)) {\n" + " com.google.protobuf.ByteString bs =\n" + " (com.google.protobuf.ByteString) ref;\n" + " java.lang.String s = bs.toStringUtf8();\n" + " if ($has_oneof_case_message$) {\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " $oneof_name$_ = s;\n"); + } else { + printer->Print(variables_, + " if (bs.isValidUtf8()) {\n" + " $oneof_name$_ = s;\n" + " }\n"); + } + printer->Print(variables_, + " }\n" + " return s;\n" + " } else {\n" + " return (java.lang.String) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public com.google.protobuf.ByteString\n" + " get$capitalized_name$Bytes() {\n" + " java.lang.Object ref $default_init$;\n" + " if ($has_oneof_case_message$) {\n" + " ref = $oneof_name$_;\n" + " }\n" + " if (ref instanceof String) {\n" + " com.google.protobuf.ByteString b = \n" + " com.google.protobuf.ByteString.copyFromUtf8(\n" + " (java.lang.String) ref);\n" + " if ($has_oneof_case_message$) {\n" + " $oneof_name$_ = b;\n" + " }\n" + " return b;\n" + " } else {\n" + " return (com.google.protobuf.ByteString) ref;\n" + " }\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$(\n" + " java.lang.String value) {\n" + "$null_check$" + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder clear$capitalized_name$() {\n" + " if ($has_oneof_case_message$) {\n" + " $clear_oneof_case_message$;\n" + " $oneof_name$_ = null;\n" + " $on_changed$\n" + " }\n" + " return this;\n" + "}\n"); + + WriteFieldDocComment(printer, descriptor_); + printer->Print(variables_, + "$deprecation$public Builder set$capitalized_name$Bytes(\n" + " com.google.protobuf.ByteString value) {\n" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, + " $set_oneof_case_message$;\n" + " $oneof_name$_ = value;\n" + " $on_changed$\n" + " return this;\n" + "}\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateMergingCode(io::Printer* printer) const { + // Allow a slight breach of abstraction here in order to avoid forcing + // all string fields to Strings when copying fields from a Message. + printer->Print(variables_, + "$set_oneof_case_message$;\n" + "$oneof_name$_ = other.$oneof_name$_;\n" + "$on_changed$\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateBuildingCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " result.$oneof_name$_ = $oneof_name$_;\n" + "}\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateParsingCode(io::Printer* printer) const { + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = s;\n}\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n" + "$set_oneof_case_message$;\n" + "$oneof_name$_ = bs;\n"); + } +} + +void ImmutableStringOneofFieldGenerator:: +GenerateSerializationCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " output.writeBytes($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} + +void ImmutableStringOneofFieldGenerator:: +GenerateSerializedSizeCode(io::Printer* printer) const { + printer->Print(variables_, + "if ($has_oneof_case_message$) {\n" + " size += com.google.protobuf.CodedOutputStream\n" + " .computeBytesSize($number$, get$capitalized_name$Bytes());\n" + "}\n"); +} // =================================================================== -RepeatedStringFieldGenerator:: -RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, - int builderBitIndex) +RepeatedImmutableStringFieldGenerator:: +RepeatedImmutableStringFieldGenerator(const FieldDescriptor* descriptor, + int messageBitIndex, + int builderBitIndex, + Context* context) : descriptor_(descriptor), messageBitIndex_(messageBitIndex), - builderBitIndex_(builderBitIndex) { + builderBitIndex_(builderBitIndex), context_(context), + name_resolver_(context->GetNameResolver()) { SetPrimitiveVariables(descriptor, messageBitIndex, builderBitIndex, - &variables_); + context->GetFieldGeneratorInfo(descriptor), + name_resolver_, &variables_); } -RepeatedStringFieldGenerator::~RepeatedStringFieldGenerator() {} +RepeatedImmutableStringFieldGenerator:: +~RepeatedImmutableStringFieldGenerator() {} -int RepeatedStringFieldGenerator::GetNumBitsForMessage() const { +int RepeatedImmutableStringFieldGenerator::GetNumBitsForMessage() const { return 0; } -int RepeatedStringFieldGenerator::GetNumBitsForBuilder() const { +int RepeatedImmutableStringFieldGenerator::GetNumBitsForBuilder() const { return 1; } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateInterfaceMembers(io::Printer* printer) const { WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$java.util.List\n" - "get$capitalized_name$List();\n"); + "$deprecation$com.google.protobuf.ProtocolStringList\n" + " get$capitalized_name$List();\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, "$deprecation$int get$capitalized_name$Count();\n"); @@ -427,13 +729,14 @@ GenerateInterfaceMembers(io::Printer* printer) const { } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateMembers(io::Printer* printer) const { printer->Print(variables_, "private com.google.protobuf.LazyStringList $name$_;\n"); + PrintExtraFieldInfo(variables_, printer); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public java.util.List\n" + "$deprecation$public com.google.protobuf.ProtocolStringList\n" " get$capitalized_name$List() {\n" " return $name$_;\n" // note: unmodifiable list "}\n"); @@ -461,7 +764,7 @@ GenerateMembers(io::Printer* printer) const { } } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateBuilderMembers(io::Printer* printer) const { // One field is the list and the bit field keeps track of whether the // list is immutable. If it's immutable, the invariant is that it must @@ -489,9 +792,9 @@ GenerateBuilderMembers(io::Printer* printer) const { // immutable. WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, - "$deprecation$public java.util.List\n" + "$deprecation$public com.google.protobuf.ProtocolStringList\n" " get$capitalized_name$List() {\n" - " return java.util.Collections.unmodifiableList($name$_);\n" + " return $name$_.getUnmodifiableView();\n" "}\n"); WriteFieldDocComment(printer, descriptor_); printer->Print(variables_, @@ -534,7 +837,8 @@ GenerateBuilderMembers(io::Printer* printer) const { "$deprecation$public Builder addAll$capitalized_name$(\n" " java.lang.Iterable values) {\n" " ensure$capitalized_name$IsMutable();\n" - " super.addAll(values, $name$_);\n" + " com.google.protobuf.AbstractMessageLite.Builder.addAll(\n" + " values, $name$_);\n" " $on_changed$\n" " return this;\n" "}\n"); @@ -551,7 +855,12 @@ GenerateBuilderMembers(io::Printer* printer) const { printer->Print(variables_, "$deprecation$public Builder add$capitalized_name$Bytes(\n" " com.google.protobuf.ByteString value) {\n" - "$null_check$" + "$null_check$"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " checkByteStringIsUtf8(value);\n"); + } + printer->Print(variables_, " ensure$capitalized_name$IsMutable();\n" " $name$_.add(value);\n" " $on_changed$\n" @@ -559,24 +868,24 @@ GenerateBuilderMembers(io::Printer* printer) const { "}\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateFieldBuilderInitializationCode(io::Printer* printer) const { // noop for primitives } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateInitializationCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $empty_list$;\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateBuilderClearCode(io::Printer* printer) const { printer->Print(variables_, "$name$_ = $empty_list$;\n" "$clear_mutable_bit_builder$;\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateMergingCode(io::Printer* printer) const { // The code below does two optimizations: // 1. If the other list is empty, there's nothing to do. This ensures we @@ -596,31 +905,43 @@ GenerateMergingCode(io::Printer* printer) const { "}\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateBuildingCode(io::Printer* printer) const { // The code below ensures that the result has an immutable list. If our // list is immutable, we can just reuse it. If not, we make it immutable. printer->Print(variables_, "if ($get_mutable_bit_builder$) {\n" - " $name$_ = new com.google.protobuf.UnmodifiableLazyStringList(\n" - " $name$_);\n" + " $name$_ = $name$_.getUnmodifiableView();\n" " $clear_mutable_bit_builder$;\n" "}\n" "result.$name$_ = $name$_;\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateParsingCode(io::Printer* printer) const { + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "String s = input.readStringRequireUtf8();\n"); + } else { + printer->Print(variables_, + "com.google.protobuf.ByteString bs = input.readBytes();\n"); + } printer->Print(variables_, "if (!$get_mutable_bit_parser$) {\n" " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" " $set_mutable_bit_parser$;\n" - "}\n" - "$name$_.add(input.readBytes());\n"); + "}\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + "$name$_.add(s);\n"); + } else { + printer->Print(variables_, + "$name$_.add(bs);\n"); + } } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateParsingCodeFromPacked(io::Printer* printer) const { printer->Print(variables_, "int length = input.readRawVarint32();\n" @@ -629,21 +950,30 @@ GenerateParsingCodeFromPacked(io::Printer* printer) const { " $name$_ = new com.google.protobuf.LazyStringArrayList();\n" " $set_mutable_bit_parser$;\n" "}\n" - "while (input.getBytesUntilLimit() > 0) {\n" - " $name$.add(input.read$capitalized_type$());\n" + "while (input.getBytesUntilLimit() > 0) {\n"); + if (CheckUtf8(descriptor_)) { + printer->Print(variables_, + " String s = input.readStringRequireUtf8();\n"); + } else { + printer->Print(variables_, + " String s = input.readString();\n"); + } + printer->Print(variables_, + " $name$.add(s);\n"); + printer->Print(variables_, "}\n" "input.popLimit(limit);\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateParsingDoneCode(io::Printer* printer) const { printer->Print(variables_, "if ($get_mutable_bit_parser$) {\n" - " $name$_ = new com.google.protobuf.UnmodifiableLazyStringList($name$_);\n" + " $name$_ = $name$_.getUnmodifiableView();\n" "}\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateSerializationCode(io::Printer* printer) const { if (descriptor_->options().packed()) { printer->Print(variables_, @@ -662,7 +992,7 @@ GenerateSerializationCode(io::Printer* printer) const { } } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print(variables_, "{\n" @@ -700,14 +1030,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const { printer->Print("}\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateEqualsCode(io::Printer* printer) const { printer->Print(variables_, "result = result && get$capitalized_name$List()\n" " .equals(other.get$capitalized_name$List());\n"); } -void RepeatedStringFieldGenerator:: +void RepeatedImmutableStringFieldGenerator:: GenerateHashCode(io::Printer* printer) const { printer->Print(variables_, "if (get$capitalized_name$Count() > 0) {\n" @@ -716,7 +1046,7 @@ GenerateHashCode(io::Printer* printer) const { "}\n"); } -string RepeatedStringFieldGenerator::GetBoxedType() const { +string RepeatedImmutableStringFieldGenerator::GetBoxedType() const { return "String"; } diff --git a/src/google/protobuf/compiler/java/java_string_field.h b/src/google/protobuf/compiler/java/java_string_field.h index 4f7532f4..348cbcbd 100644 --- a/src/google/protobuf/compiler/java/java_string_field.h +++ b/src/google/protobuf/compiler/java/java_string_field.h @@ -41,17 +41,27 @@ #include namespace google { +namespace protobuf { + namespace compiler { + namespace java { + class Context; // context.h + class ClassNameResolver; // name_resolver.h + } + } +} + namespace protobuf { namespace compiler { namespace java { -class StringFieldGenerator : public FieldGenerator { +class ImmutableStringFieldGenerator : public ImmutableFieldGenerator { public: - explicit StringFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex); - ~StringFieldGenerator(); + explicit ImmutableStringFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableStringFieldGenerator(); - // implements FieldGenerator --------------------------------------- + // implements ImmutableFieldGenerator --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -68,24 +78,49 @@ class StringFieldGenerator : public FieldGenerator { void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; + string GetBoxedType() const; - private: + protected: const FieldDescriptor* descriptor_; map variables_; const int messageBitIndex_; const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator); + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldGenerator); }; -class RepeatedStringFieldGenerator : public FieldGenerator { +class ImmutableStringOneofFieldGenerator + : public ImmutableStringFieldGenerator { public: - explicit RepeatedStringFieldGenerator(const FieldDescriptor* descriptor, - int messageBitIndex, int builderBitIndex); - ~RepeatedStringFieldGenerator(); + ImmutableStringOneofFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~ImmutableStringOneofFieldGenerator(); - // implements FieldGenerator --------------------------------------- + private: + void GenerateMembers(io::Printer* printer) const; + void GenerateBuilderMembers(io::Printer* printer) const; + void GenerateMergingCode(io::Printer* printer) const; + void GenerateBuildingCode(io::Printer* printer) const; + void GenerateParsingCode(io::Printer* printer) const; + void GenerateSerializationCode(io::Printer* printer) const; + void GenerateSerializedSizeCode(io::Printer* printer) const; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldGenerator); +}; + +class RepeatedImmutableStringFieldGenerator : public ImmutableFieldGenerator { + public: + explicit RepeatedImmutableStringFieldGenerator( + const FieldDescriptor* descriptor, int messageBitIndex, + int builderBitIndex, Context* context); + ~RepeatedImmutableStringFieldGenerator(); + + // implements ImmutableFieldGenerator --------------------------------------- int GetNumBitsForMessage() const; int GetNumBitsForBuilder() const; void GenerateInterfaceMembers(io::Printer* printer) const; @@ -103,6 +138,7 @@ class RepeatedStringFieldGenerator : public FieldGenerator { void GenerateFieldBuilderInitializationCode(io::Printer* printer) const; void GenerateEqualsCode(io::Printer* printer) const; void GenerateHashCode(io::Printer* printer) const; + string GetBoxedType() const; private: @@ -110,8 +146,10 @@ class RepeatedStringFieldGenerator : public FieldGenerator { map variables_; const int messageBitIndex_; const int builderBitIndex_; + Context* context_; + ClassNameResolver* name_resolver_; - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldGenerator); }; } // namespace java diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc index 0e35ed19..1f91817f 100644 --- a/src/google/protobuf/compiler/mock_code_generator.cc +++ b/src/google/protobuf/compiler/mock_code_generator.cc @@ -32,6 +32,8 @@ #include +#include + #include #include #include @@ -53,7 +55,7 @@ string CommaSeparatedList(const vector all_files) { for (int i = 0; i < all_files.size(); i++) { names.push_back(all_files[i]->name()); } - return JoinStrings(names, ","); + return Join(names, ","); } static const char* kFirstInsertionPointName = "first_mock_insertion_point"; @@ -77,11 +79,11 @@ void MockCodeGenerator::ExpectGenerated( const string& first_parsed_file_name, const string& output_directory) { string content; - ASSERT_TRUE(File::ReadFileToString( - output_directory + "/" + GetOutputFileName(name, file), &content)); + GOOGLE_CHECK_OK( + File::GetContents(output_directory + "/" + GetOutputFileName(name, file), + &content, true)); - vector lines; - SplitStringUsing(content, "\n", &lines); + vector lines = Split(content, "\n", true); while (!lines.empty() && lines.back().empty()) { lines.pop_back(); @@ -95,7 +97,7 @@ void MockCodeGenerator::ExpectGenerated( SplitStringUsing(insertions, ",", &insertion_list); } - ASSERT_EQ(lines.size(), 3 + insertion_list.size() * 2); + EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2); EXPECT_EQ(GetOutputFileContent(name, parameter, file, first_parsed_file_name, first_message_name), lines[0]); @@ -155,10 +157,8 @@ bool MockCodeGenerator::Generate( for (int i = 0; i < insert_into.size(); i++) { { - scoped_ptr output( - context->OpenForInsert( - GetOutputFileName(insert_into[i], file), - kFirstInsertionPointName)); + scoped_ptr output(context->OpenForInsert( + GetOutputFileName(insert_into[i], file), kFirstInsertionPointName)); io::Printer printer(output.get(), '$'); printer.PrintRaw(GetOutputFileContent(name_, "first_insert", file, context)); @@ -170,9 +170,8 @@ bool MockCodeGenerator::Generate( { scoped_ptr output( - context->OpenForInsert( - GetOutputFileName(insert_into[i], file), - kSecondInsertionPointName)); + context->OpenForInsert(GetOutputFileName(insert_into[i], file), + kSecondInsertionPointName)); io::Printer printer(output.get(), '$'); printer.PrintRaw(GetOutputFileContent(name_, "second_insert", file, context)); diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc index 23aa01ce..7e0df7e1 100644 --- a/src/google/protobuf/compiler/parser.cc +++ b/src/google/protobuf/compiler/parser.cc @@ -46,7 +46,7 @@ #include #include #include -#include +#include namespace google { namespace protobuf { @@ -343,6 +343,11 @@ void Parser::LocationRecorder::StartAt(const io::Tokenizer::Token& token) { location_->set_span(1, token.column); } +void Parser::LocationRecorder::StartAt(const LocationRecorder& other) { + location_->set_span(0, other.location_->span(0)); + location_->set_span(1, other.location_->span(1)); +} + void Parser::LocationRecorder::EndAt(const io::Tokenizer::Token& token) { if (token.line != location_->span(0)) { location_->add_span(token.line); @@ -489,15 +494,15 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, } else if (LookingAt("message")) { LocationRecorder location(root_location, FileDescriptorProto::kMessageTypeFieldNumber, file->message_type_size()); - return ParseMessageDefinition(file->add_message_type(), location); + return ParseMessageDefinition(file->add_message_type(), location, file); } else if (LookingAt("enum")) { LocationRecorder location(root_location, FileDescriptorProto::kEnumTypeFieldNumber, file->enum_type_size()); - return ParseEnumDefinition(file->add_enum_type(), location); + return ParseEnumDefinition(file->add_enum_type(), location, file); } else if (LookingAt("service")) { LocationRecorder location(root_location, FileDescriptorProto::kServiceFieldNumber, file->service_size()); - return ParseServiceDefinition(file->add_service(), location); + return ParseServiceDefinition(file->add_service(), location, file); } else if (LookingAt("extend")) { LocationRecorder location(root_location, FileDescriptorProto::kExtensionFieldNumber); @@ -505,18 +510,19 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, file->mutable_message_type(), root_location, FileDescriptorProto::kMessageTypeFieldNumber, - location); + location, file); } else if (LookingAt("import")) { return ParseImport(file->mutable_dependency(), file->mutable_public_dependency(), file->mutable_weak_dependency(), - root_location); + root_location, file); } else if (LookingAt("package")) { - return ParsePackage(file, root_location); + return ParsePackage(file, root_location, file); } else if (LookingAt("option")) { LocationRecorder location(root_location, FileDescriptorProto::kOptionsFieldNumber); - return ParseOption(file->mutable_options(), location, OPTION_STATEMENT); + return ParseOption(file->mutable_options(), location, file, + OPTION_STATEMENT); } else { AddError("Expected top-level statement (e.g. \"message\")."); return false; @@ -526,8 +532,10 @@ bool Parser::ParseTopLevelStatement(FileDescriptorProto* file, // ------------------------------------------------------------------- // Messages -bool Parser::ParseMessageDefinition(DescriptorProto* message, - const LocationRecorder& message_location) { +bool Parser::ParseMessageDefinition( + DescriptorProto* message, + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file) { DO(Consume("message")); { LocationRecorder location(message_location, @@ -536,7 +544,7 @@ bool Parser::ParseMessageDefinition(DescriptorProto* message, message, DescriptorPool::ErrorCollector::NAME); DO(ConsumeIdentifier(message->mutable_name(), "Expected message name.")); } - DO(ParseMessageBlock(message, message_location)); + DO(ParseMessageBlock(message, message_location, containing_file)); return true; } @@ -575,7 +583,8 @@ void AdjustExtensionRangesWithMaxEndNumber(DescriptorProto* message) { } // namespace bool Parser::ParseMessageBlock(DescriptorProto* message, - const LocationRecorder& message_location) { + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file) { DO(ConsumeEndOfDeclaration("{", &message_location)); while (!TryConsumeEndOfDeclaration("}", NULL)) { @@ -584,7 +593,7 @@ bool Parser::ParseMessageBlock(DescriptorProto* message, return false; } - if (!ParseMessageStatement(message, message_location)) { + if (!ParseMessageStatement(message, message_location, containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -598,7 +607,8 @@ bool Parser::ParseMessageBlock(DescriptorProto* message, } bool Parser::ParseMessageStatement(DescriptorProto* message, - const LocationRecorder& message_location) { + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file) { if (TryConsumeEndOfDeclaration(";", NULL)) { // empty statement; ignore return true; @@ -606,16 +616,18 @@ bool Parser::ParseMessageStatement(DescriptorProto* message, LocationRecorder location(message_location, DescriptorProto::kNestedTypeFieldNumber, message->nested_type_size()); - return ParseMessageDefinition(message->add_nested_type(), location); + return ParseMessageDefinition(message->add_nested_type(), location, + containing_file); } else if (LookingAt("enum")) { LocationRecorder location(message_location, DescriptorProto::kEnumTypeFieldNumber, message->enum_type_size()); - return ParseEnumDefinition(message->add_enum_type(), location); + return ParseEnumDefinition(message->add_enum_type(), location, + containing_file); } else if (LookingAt("extensions")) { LocationRecorder location(message_location, DescriptorProto::kExtensionRangeFieldNumber); - return ParseExtensions(message, location); + return ParseExtensions(message, location, containing_file); } else if (LookingAt("extend")) { LocationRecorder location(message_location, DescriptorProto::kExtensionFieldNumber); @@ -623,11 +635,21 @@ bool Parser::ParseMessageStatement(DescriptorProto* message, message->mutable_nested_type(), message_location, DescriptorProto::kNestedTypeFieldNumber, - location); + location, containing_file); } else if (LookingAt("option")) { LocationRecorder location(message_location, DescriptorProto::kOptionsFieldNumber); - return ParseOption(message->mutable_options(), location, OPTION_STATEMENT); + return ParseOption(message->mutable_options(), location, + containing_file, OPTION_STATEMENT); + } else if (LookingAt("oneof")) { + int oneof_index = message->oneof_decl_size(); + LocationRecorder oneof_location(message_location, + DescriptorProto::kOneofDeclFieldNumber, + oneof_index); + + return ParseOneof(message->add_oneof_decl(), message, + oneof_index, oneof_location, message_location, + containing_file); } else { LocationRecorder location(message_location, DescriptorProto::kFieldFieldNumber, @@ -636,7 +658,8 @@ bool Parser::ParseMessageStatement(DescriptorProto* message, message->mutable_nested_type(), message_location, DescriptorProto::kNestedTypeFieldNumber, - location); + location, + containing_file); } } @@ -644,17 +667,30 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, RepeatedPtrField* messages, const LocationRecorder& parent_location, int location_field_number_for_nested_type, - const LocationRecorder& field_location) { - // Parse label and type. - io::Tokenizer::Token label_token = input_->current(); + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { { LocationRecorder location(field_location, FieldDescriptorProto::kLabelFieldNumber); FieldDescriptorProto::Label label; - DO(ParseLabel(&label)); + DO(ParseLabel(&label, containing_file)); field->set_label(label); } + return ParseMessageFieldNoLabel(field, messages, parent_location, + location_field_number_for_nested_type, + field_location, + containing_file); +} + +bool Parser::ParseMessageFieldNoLabel( + FieldDescriptorProto* field, + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { + // Parse type. { LocationRecorder location(field_location); // add path later location.RecordLegacyLocation(field, DescriptorPool::ErrorCollector::TYPE); @@ -693,14 +729,14 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, } // Parse options. - DO(ParseFieldOptions(field, field_location)); + DO(ParseFieldOptions(field, field_location, containing_file)); // Deal with groups. if (field->has_type() && field->type() == FieldDescriptorProto::TYPE_GROUP) { // Awkward: Since a group declares both a message type and a field, we // have to create overlapping locations. LocationRecorder group_location(parent_location); - group_location.StartAt(label_token); + group_location.StartAt(field_location); group_location.AddPath(location_field_number_for_nested_type); group_location.AddPath(messages->size()); @@ -736,7 +772,7 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, field->set_type_name(group->name()); if (LookingAt("{")) { - DO(ParseMessageBlock(group, group_location)); + DO(ParseMessageBlock(group, group_location, containing_file)); } else { AddError("Missing group body."); return false; @@ -749,7 +785,8 @@ bool Parser::ParseMessageField(FieldDescriptorProto* field, } bool Parser::ParseFieldOptions(FieldDescriptorProto* field, - const LocationRecorder& field_location) { + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { if (!LookingAt("[")) return true; LocationRecorder location(field_location, @@ -762,9 +799,10 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field, if (LookingAt("default")) { // We intentionally pass field_location rather than location here, since // the default value is not actually an option. - DO(ParseDefaultAssignment(field, field_location)); + DO(ParseDefaultAssignment(field, field_location, containing_file)); } else { - DO(ParseOption(field->mutable_options(), location, OPTION_ASSIGNMENT)); + DO(ParseOption(field->mutable_options(), location, + containing_file, OPTION_ASSIGNMENT)); } } while (TryConsume(",")); @@ -772,8 +810,10 @@ bool Parser::ParseFieldOptions(FieldDescriptorProto* field, return true; } -bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, - const LocationRecorder& field_location) { +bool Parser::ParseDefaultAssignment( + FieldDescriptorProto* field, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file) { if (field->has_default_value()) { AddError("Already set option \"default\"."); field->clear_default_value(); @@ -790,8 +830,16 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, if (!field->has_type()) { // The field has a type name, but we don't know if it is a message or an - // enum yet. Assume an enum for now. - DO(ConsumeIdentifier(default_value, "Expected identifier.")); + // enum yet. (If it were a primitive type, |field| would have a type set + // already.) In this case, simply take the current string as the default + // value; we will catch the error later if it is not a valid enum value. + // (N.B. that we do not check whether the current token is an identifier: + // doing so throws strange errors when the user mistypes a primitive + // typename and we assume it's an enum. E.g.: "optional int foo = 1 [default + // = 42]". In such a case the fundamental error is really that "int" is not + // a type, not that "42" is not an identifier. See b/12533582.) + *default_value = input_->current().text; + input_->Next(); return true; } @@ -817,7 +865,8 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, } // Parse the integer to verify that it is not out-of-range. uint64 value; - DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + DO(ConsumeInteger64(max_value, &value, + "Expected integer for field default value.")); // And stringify it again. default_value->append(SimpleItoa(value)); break; @@ -839,7 +888,8 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, } // Parse the integer to verify that it is not out-of-range. uint64 value; - DO(ConsumeInteger64(max_value, &value, "Expected integer.")); + DO(ConsumeInteger64(max_value, &value, + "Expected integer for field default value.")); // And stringify it again. default_value->append(SimpleItoa(value)); break; @@ -871,7 +921,11 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, break; case FieldDescriptorProto::TYPE_STRING: - DO(ConsumeString(default_value, "Expected string.")); + // Note: When file opton java_string_check_utf8 is true, if a + // non-string representation (eg byte[]) is later supported, it must + // be checked for UTF-8-ness. + DO(ConsumeString(default_value, "Expected string for field default " + "value.")); break; case FieldDescriptorProto::TYPE_BYTES: @@ -880,7 +934,8 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, break; case FieldDescriptorProto::TYPE_ENUM: - DO(ConsumeIdentifier(default_value, "Expected identifier.")); + DO(ConsumeIdentifier(default_value, "Expected enum identifier for field " + "default value.")); break; case FieldDescriptorProto::TYPE_MESSAGE: @@ -893,7 +948,8 @@ bool Parser::ParseDefaultAssignment(FieldDescriptorProto* field, } bool Parser::ParseOptionNamePart(UninterpretedOption* uninterpreted_option, - const LocationRecorder& part_location) { + const LocationRecorder& part_location, + const FileDescriptorProto* containing_file) { UninterpretedOption::NamePart* name = uninterpreted_option->add_name(); string identifier; // We parse identifiers into this string. if (LookingAt("(")) { // This is an extension. @@ -957,6 +1013,7 @@ bool Parser::ParseUninterpretedBlock(string* value) { // UninterpretedOption, to be interpreted later. bool Parser::ParseOption(Message* options, const LocationRecorder& options_location, + const FileDescriptorProto* containing_file, OptionStyle style) { // Create an entry in the uninterpreted_option field. const FieldDescriptor* uninterpreted_option_field = options->GetDescriptor()-> @@ -988,14 +1045,16 @@ bool Parser::ParseOption(Message* options, { LocationRecorder part_location(name_location, uninterpreted_option->name_size()); - DO(ParseOptionNamePart(uninterpreted_option, part_location)); + DO(ParseOptionNamePart(uninterpreted_option, part_location, + containing_file)); } while (LookingAt(".")) { DO(Consume(".")); LocationRecorder part_location(name_location, uninterpreted_option->name_size()); - DO(ParseOptionNamePart(uninterpreted_option, part_location)); + DO(ParseOptionNamePart(uninterpreted_option, part_location, + containing_file)); } } @@ -1088,11 +1147,13 @@ bool Parser::ParseOption(Message* options, DO(ConsumeEndOfDeclaration(";", &location)); } + return true; } bool Parser::ParseExtensions(DescriptorProto* message, - const LocationRecorder& extensions_location) { + const LocationRecorder& extensions_location, + const FileDescriptorProto* containing_file) { // Parse the declaration. DO(Consume("extensions")); @@ -1150,7 +1211,8 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, RepeatedPtrField* messages, const LocationRecorder& parent_location, int location_field_number_for_nested_type, - const LocationRecorder& extend_location) { + const LocationRecorder& extend_location, + const FileDescriptorProto* containing_file) { DO(Consume("extend")); // Parse the extendee type. @@ -1192,7 +1254,65 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, if (!ParseMessageField(field, messages, parent_location, location_field_number_for_nested_type, - location)) { + location, + containing_file)) { + // This statement failed to parse. Skip it, but keep looping to parse + // other statements. + SkipStatement(); + } + } while (!TryConsumeEndOfDeclaration("}", NULL)); + + return true; +} + +bool Parser::ParseOneof(OneofDescriptorProto* oneof_decl, + DescriptorProto* containing_type, + int oneof_index, + const LocationRecorder& oneof_location, + const LocationRecorder& containing_type_location, + const FileDescriptorProto* containing_file) { + DO(Consume("oneof")); + + { + LocationRecorder name_location(oneof_location, + OneofDescriptorProto::kNameFieldNumber); + DO(ConsumeIdentifier(oneof_decl->mutable_name(), "Expected oneof name.")); + } + + DO(ConsumeEndOfDeclaration("{", &oneof_location)); + + do { + if (AtEnd()) { + AddError("Reached end of input in oneof definition (missing '}')."); + return false; + } + + // Print a nice error if the user accidentally tries to place a label + // on an individual member of a oneof. + if (LookingAt("required") || + LookingAt("optional") || + LookingAt("repeated")) { + AddError("Fields in oneofs must not have labels (required / optional " + "/ repeated)."); + // We can continue parsing here because we understand what the user + // meant. The error report will still make parsing fail overall. + input_->Next(); + } + + LocationRecorder field_location(containing_type_location, + DescriptorProto::kFieldFieldNumber, + containing_type->field_size()); + + FieldDescriptorProto* field = containing_type->add_field(); + field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); + field->set_oneof_index(oneof_index); + + if (!ParseMessageFieldNoLabel(field, + containing_type->mutable_nested_type(), + containing_type_location, + DescriptorProto::kNestedTypeFieldNumber, + field_location, + containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -1206,7 +1326,8 @@ bool Parser::ParseExtend(RepeatedPtrField* extensions, // Enums bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location) { + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file) { DO(Consume("enum")); { @@ -1217,12 +1338,13 @@ bool Parser::ParseEnumDefinition(EnumDescriptorProto* enum_type, DO(ConsumeIdentifier(enum_type->mutable_name(), "Expected enum name.")); } - DO(ParseEnumBlock(enum_type, enum_location)); + DO(ParseEnumBlock(enum_type, enum_location, containing_file)); return true; } bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location) { + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file) { DO(ConsumeEndOfDeclaration("{", &enum_location)); while (!TryConsumeEndOfDeclaration("}", NULL)) { @@ -1231,7 +1353,7 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, return false; } - if (!ParseEnumStatement(enum_type, enum_location)) { + if (!ParseEnumStatement(enum_type, enum_location, containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -1242,7 +1364,8 @@ bool Parser::ParseEnumBlock(EnumDescriptorProto* enum_type, } bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location) { + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file) { if (TryConsumeEndOfDeclaration(";", NULL)) { // empty statement; ignore return true; @@ -1250,16 +1373,17 @@ bool Parser::ParseEnumStatement(EnumDescriptorProto* enum_type, LocationRecorder location(enum_location, EnumDescriptorProto::kOptionsFieldNumber); return ParseOption(enum_type->mutable_options(), location, - OPTION_STATEMENT); + containing_file, OPTION_STATEMENT); } else { LocationRecorder location(enum_location, EnumDescriptorProto::kValueFieldNumber, enum_type->value_size()); - return ParseEnumConstant(enum_type->add_value(), location); + return ParseEnumConstant(enum_type->add_value(), location, containing_file); } } bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, - const LocationRecorder& enum_value_location) { + const LocationRecorder& enum_value_location, + const FileDescriptorProto* containing_file) { // Parse name. { LocationRecorder location(enum_value_location, @@ -1284,7 +1408,8 @@ bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, enum_value->set_number(number); } - DO(ParseEnumConstantOptions(enum_value, enum_value_location)); + DO(ParseEnumConstantOptions(enum_value, enum_value_location, + containing_file)); DO(ConsumeEndOfDeclaration(";", &enum_value_location)); @@ -1293,7 +1418,8 @@ bool Parser::ParseEnumConstant(EnumValueDescriptorProto* enum_value, bool Parser::ParseEnumConstantOptions( EnumValueDescriptorProto* value, - const LocationRecorder& enum_value_location) { + const LocationRecorder& enum_value_location, + const FileDescriptorProto* containing_file) { if (!LookingAt("[")) return true; LocationRecorder location( @@ -1302,7 +1428,8 @@ bool Parser::ParseEnumConstantOptions( DO(Consume("[")); do { - DO(ParseOption(value->mutable_options(), location, OPTION_ASSIGNMENT)); + DO(ParseOption(value->mutable_options(), location, + containing_file, OPTION_ASSIGNMENT)); } while (TryConsume(",")); DO(Consume("]")); @@ -1312,8 +1439,10 @@ bool Parser::ParseEnumConstantOptions( // ------------------------------------------------------------------- // Services -bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service, - const LocationRecorder& service_location) { +bool Parser::ParseServiceDefinition( + ServiceDescriptorProto* service, + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file) { DO(Consume("service")); { @@ -1324,12 +1453,13 @@ bool Parser::ParseServiceDefinition(ServiceDescriptorProto* service, DO(ConsumeIdentifier(service->mutable_name(), "Expected service name.")); } - DO(ParseServiceBlock(service, service_location)); + DO(ParseServiceBlock(service, service_location, containing_file)); return true; } bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, - const LocationRecorder& service_location) { + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file) { DO(ConsumeEndOfDeclaration("{", &service_location)); while (!TryConsumeEndOfDeclaration("}", NULL)) { @@ -1338,7 +1468,7 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, return false; } - if (!ParseServiceStatement(service, service_location)) { + if (!ParseServiceStatement(service, service_location, containing_file)) { // This statement failed to parse. Skip it, but keep looping to parse // other statements. SkipStatement(); @@ -1349,23 +1479,26 @@ bool Parser::ParseServiceBlock(ServiceDescriptorProto* service, } bool Parser::ParseServiceStatement(ServiceDescriptorProto* service, - const LocationRecorder& service_location) { + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file) { if (TryConsumeEndOfDeclaration(";", NULL)) { // empty statement; ignore return true; } else if (LookingAt("option")) { LocationRecorder location( service_location, ServiceDescriptorProto::kOptionsFieldNumber); - return ParseOption(service->mutable_options(), location, OPTION_STATEMENT); + return ParseOption(service->mutable_options(), location, + containing_file, OPTION_STATEMENT); } else { LocationRecorder location(service_location, ServiceDescriptorProto::kMethodFieldNumber, service->method_size()); - return ParseServiceMethod(service->add_method(), location); + return ParseServiceMethod(service->add_method(), location, containing_file); } } bool Parser::ParseServiceMethod(MethodDescriptorProto* method, - const LocationRecorder& method_location) { + const LocationRecorder& method_location, + const FileDescriptorProto* containing_file) { DO(Consume("rpc")); { @@ -1402,6 +1535,7 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, if (LookingAt("{")) { // Options! DO(ParseOptions(method_location, + containing_file, MethodDescriptorProto::kOptionsFieldNumber, method->mutable_options())); } else { @@ -1413,6 +1547,7 @@ bool Parser::ParseServiceMethod(MethodDescriptorProto* method, bool Parser::ParseOptions(const LocationRecorder& parent_location, + const FileDescriptorProto* containing_file, const int optionsFieldNumber, Message* mutable_options) { // Options! @@ -1428,7 +1563,8 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location, } else { LocationRecorder location(parent_location, optionsFieldNumber); - if (!ParseOption(mutable_options, location, OPTION_STATEMENT)) { + if (!ParseOption(mutable_options, location, containing_file, + OPTION_STATEMENT)) { // This statement failed to parse. Skip it, but keep looping to // parse other statements. SkipStatement(); @@ -1441,7 +1577,8 @@ bool Parser::ParseOptions(const LocationRecorder& parent_location, // ------------------------------------------------------------------- -bool Parser::ParseLabel(FieldDescriptorProto::Label* label) { +bool Parser::ParseLabel(FieldDescriptorProto::Label* label, + const FileDescriptorProto* containing_file) { if (TryConsume("optional")) { *label = FieldDescriptorProto::LABEL_OPTIONAL; return true; @@ -1510,7 +1647,8 @@ bool Parser::ParseUserDefinedType(string* type_name) { // =================================================================== bool Parser::ParsePackage(FileDescriptorProto* file, - const LocationRecorder& root_location) { + const LocationRecorder& root_location, + const FileDescriptorProto* containing_file) { if (file->has_package()) { AddError("Multiple package definitions."); // Don't append the new package to the old one. Just replace it. Not @@ -1544,7 +1682,8 @@ bool Parser::ParsePackage(FileDescriptorProto* file, bool Parser::ParseImport(RepeatedPtrField* dependency, RepeatedField* public_dependency, RepeatedField* weak_dependency, - const LocationRecorder& root_location) { + const LocationRecorder& root_location, + const FileDescriptorProto* containing_file) { DO(Consume("import")); if (LookingAt("public")) { LocationRecorder location( diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h index cfd3649b..6bca7fa7 100644 --- a/src/google/protobuf/compiler/parser.h +++ b/src/google/protobuf/compiler/parser.h @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include @@ -233,6 +232,9 @@ class LIBPROTOBUF_EXPORT Parser { // location to the given token instead. void StartAt(const io::Tokenizer::Token& token); + // Start at the same location as some other LocationRecorder. + void StartAt(const LocationRecorder& other); + // By default the location is considered to end at the previous token at // the time the LocationRecorder is destroyed. EndAt() sets the end // location to the given token instead. @@ -284,38 +286,50 @@ class LIBPROTOBUF_EXPORT Parser { // Parse various language high-level language construrcts. bool ParseMessageDefinition(DescriptorProto* message, - const LocationRecorder& message_location); + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file); bool ParseEnumDefinition(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location); + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file); bool ParseServiceDefinition(ServiceDescriptorProto* service, - const LocationRecorder& service_location); + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file); bool ParsePackage(FileDescriptorProto* file, - const LocationRecorder& root_location); + const LocationRecorder& root_location, + const FileDescriptorProto* containing_file); bool ParseImport(RepeatedPtrField* dependency, RepeatedField* public_dependency, RepeatedField* weak_dependency, - const LocationRecorder& root_location); + const LocationRecorder& root_location, + const FileDescriptorProto* containing_file); bool ParseOption(Message* options, - const LocationRecorder& options_location); + const LocationRecorder& options_location, + const FileDescriptorProto* containing_file); // These methods parse the contents of a message, enum, or service type and // add them to the given object. They consume the entire block including // the beginning and ending brace. bool ParseMessageBlock(DescriptorProto* message, - const LocationRecorder& message_location); + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file); bool ParseEnumBlock(EnumDescriptorProto* enum_type, - const LocationRecorder& enum_location); + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file); bool ParseServiceBlock(ServiceDescriptorProto* service, - const LocationRecorder& service_location); + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file); // Parse one statement within a message, enum, or service block, inclunding // final semicolon. bool ParseMessageStatement(DescriptorProto* message, - const LocationRecorder& message_location); + const LocationRecorder& message_location, + const FileDescriptorProto* containing_file); bool ParseEnumStatement(EnumDescriptorProto* message, - const LocationRecorder& enum_location); + const LocationRecorder& enum_location, + const FileDescriptorProto* containing_file); bool ParseServiceStatement(ServiceDescriptorProto* message, - const LocationRecorder& service_location); + const LocationRecorder& service_location, + const FileDescriptorProto* containing_file); // Parse a field of a message. If the field is a group, its type will be // added to "messages". @@ -329,11 +343,22 @@ class LIBPROTOBUF_EXPORT Parser { RepeatedPtrField* messages, const LocationRecorder& parent_location, int location_field_number_for_nested_type, - const LocationRecorder& field_location); + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file); + + // Like ParseMessageField() but expects the label has already been filled in + // by the caller. + bool ParseMessageFieldNoLabel(FieldDescriptorProto* field, + RepeatedPtrField* messages, + const LocationRecorder& parent_location, + int location_field_number_for_nested_type, + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file); // Parse an "extensions" declaration. bool ParseExtensions(DescriptorProto* message, - const LocationRecorder& extensions_location); + const LocationRecorder& extensions_location, + const FileDescriptorProto* containing_file); // Parse an "extend" declaration. (See also comments for // ParseMessageField().) @@ -341,30 +366,46 @@ class LIBPROTOBUF_EXPORT Parser { RepeatedPtrField* messages, const LocationRecorder& parent_location, int location_field_number_for_nested_type, - const LocationRecorder& extend_location); + const LocationRecorder& extend_location, + const FileDescriptorProto* containing_file); + + // Parse a "oneof" declaration. The caller is responsible for setting + // oneof_decl->label() since it will have had to parse the label before it + // knew it was parsing a oneof. + bool ParseOneof(OneofDescriptorProto* oneof_decl, + DescriptorProto* containing_type, + int oneof_index, + const LocationRecorder& oneof_location, + const LocationRecorder& containing_type_location, + const FileDescriptorProto* containing_file); // Parse a single enum value within an enum block. bool ParseEnumConstant(EnumValueDescriptorProto* enum_value, - const LocationRecorder& enum_value_location); + const LocationRecorder& enum_value_location, + const FileDescriptorProto* containing_file); // Parse enum constant options, i.e. the list in square brackets at the end // of the enum constant value definition. bool ParseEnumConstantOptions(EnumValueDescriptorProto* value, - const LocationRecorder& enum_value_location); + const LocationRecorder& enum_value_location, + const FileDescriptorProto* containing_file); // Parse a single method within a service definition. bool ParseServiceMethod(MethodDescriptorProto* method, - const LocationRecorder& method_location); + const LocationRecorder& method_location, + const FileDescriptorProto* containing_file); // Parse options of a single method or stream. bool ParseOptions(const LocationRecorder& parent_location, + const FileDescriptorProto* containing_file, const int optionsFieldNumber, Message* mutable_options); // Parse "required", "optional", or "repeated" and fill in "label" // with the value. - bool ParseLabel(FieldDescriptorProto::Label* label); + bool ParseLabel(FieldDescriptorProto::Label* label, + const FileDescriptorProto* containing_file); // Parse a type name and fill in "type" (if it is a primitive) or // "type_name" (if it is not) with the type parsed. @@ -377,12 +418,14 @@ class LIBPROTOBUF_EXPORT Parser { // Parses field options, i.e. the stuff in square brackets at the end // of a field definition. Also parses default value. bool ParseFieldOptions(FieldDescriptorProto* field, - const LocationRecorder& field_location); + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file); // Parse the "default" option. This needs special handling because its // type is the field's type. bool ParseDefaultAssignment(FieldDescriptorProto* field, - const LocationRecorder& field_location); + const LocationRecorder& field_location, + const FileDescriptorProto* containing_file); enum OptionStyle { OPTION_ASSIGNMENT, // just "name = value" @@ -394,6 +437,7 @@ class LIBPROTOBUF_EXPORT Parser { // is set to the parsed value. bool ParseOption(Message* options, const LocationRecorder& options_location, + const FileDescriptorProto* containing_file, OptionStyle style); // Parses a single part of a multipart option name. A multipart name consists @@ -401,7 +445,8 @@ class LIBPROTOBUF_EXPORT Parser { // of identifiers separated by dots and enclosed in parentheses. E.g., // "foo.(bar.baz).qux". bool ParseOptionNamePart(UninterpretedOption* uninterpreted_option, - const LocationRecorder& part_location); + const LocationRecorder& part_location, + const FileDescriptorProto* containing_file); // Parses a string surrounded by balanced braces. Strips off the outer // braces and stores the enclosed string in *value. diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc index c61ac60e..847370a8 100644 --- a/src/google/protobuf/compiler/parser_unittest.cc +++ b/src/google/protobuf/compiler/parser_unittest.cc @@ -32,6 +32,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include #include #include #include @@ -47,7 +48,7 @@ #include #include #include -#include +#include #include #include @@ -436,6 +437,69 @@ TEST_F(ParseMessageTest, FieldOptions) { "}"); } +TEST_F(ParseMessageTest, Oneof) { + ExpectParsesTo( + "message TestMessage {\n" + " oneof foo {\n" + " int32 a = 1;\n" + " string b = 2;\n" + " TestMessage c = 3;\n" + " group D = 4 { optional int32 i = 5; }\n" + " }\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " + " oneof_index:0 }" + " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " + " oneof_index:0 }" + " field { name:\"c\" label:LABEL_OPTIONAL type_name:\"TestMessage\" " + " number:3 oneof_index:0 }" + " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_GROUP " + " type_name:\"D\" number:4 oneof_index:0 }" + " oneof_decl {" + " name: \"foo\"" + " }" + " nested_type {" + " name: \"D\"" + " field { name:\"i\" label:LABEL_OPTIONAL type:TYPE_INT32 number:5 }" + " }" + "}"); +} + +TEST_F(ParseMessageTest, MultipleOneofs) { + ExpectParsesTo( + "message TestMessage {\n" + " oneof foo {\n" + " int32 a = 1;\n" + " string b = 2;\n" + " }\n" + " oneof bar {\n" + " int32 c = 3;\n" + " string d = 4;\n" + " }\n" + "}\n", + + "message_type {" + " name: \"TestMessage\"" + " field { name:\"a\" label:LABEL_OPTIONAL type:TYPE_INT32 number:1 " + " oneof_index:0 }" + " field { name:\"b\" label:LABEL_OPTIONAL type:TYPE_STRING number:2 " + " oneof_index:0 }" + " field { name:\"c\" label:LABEL_OPTIONAL type:TYPE_INT32 number:3 " + " oneof_index:1 }" + " field { name:\"d\" label:LABEL_OPTIONAL type:TYPE_STRING number:4 " + " oneof_index:1 }" + " oneof_decl {" + " name: \"foo\"" + " }" + " oneof_decl {" + " name: \"bar\"" + " }" + "}"); +} + TEST_F(ParseMessageTest, Group) { ExpectParsesTo( "message TestMessage {\n" @@ -575,6 +639,7 @@ TEST_F(ParseMessageTest, MultipleExtensionsOneExtendee) { " type_name:\"TestMessage\" extendee: \"Extendee1\" }"); } + // =================================================================== typedef ParserTest ParseEnumTest; @@ -681,6 +746,8 @@ TEST_F(ParseServiceTest, MethodsAndStreams) { "}"); } + + // =================================================================== // imports and packages @@ -870,7 +937,7 @@ TEST_F(ParseErrorTest, DefaultValueTypeMismatch) { "message TestMessage {\n" " optional uint32 foo = 1 [default=true];\n" "}\n", - "1:35: Expected integer.\n"); + "1:35: Expected integer for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueNotBoolean) { @@ -886,7 +953,7 @@ TEST_F(ParseErrorTest, DefaultValueNotString) { "message TestMessage {\n" " optional string foo = 1 [default=1];\n" "}\n", - "1:35: Expected string.\n"); + "1:35: Expected string for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueUnsignedNegative) { @@ -934,7 +1001,7 @@ TEST_F(ParseErrorTest, DefaultValueMissing) { "message TestMessage {\n" " optional uint32 foo = 1 [default=];\n" "}\n", - "1:35: Expected integer.\n"); + "1:35: Expected integer for field default value.\n"); } TEST_F(ParseErrorTest, DefaultValueForGroup) { @@ -953,6 +1020,27 @@ TEST_F(ParseErrorTest, DuplicateDefaultValue) { "1:37: Already set option \"default\".\n"); } +TEST_F(ParseErrorTest, MissingOneofName) { + ExpectHasErrors( + "message TestMessage {\n" + " oneof {\n" + " int32 bar = 1;\n" + " }\n" + "}\n", + "1:8: Expected oneof name.\n"); +} + +TEST_F(ParseErrorTest, LabelInOneof) { + ExpectHasErrors( + "message TestMessage {\n" + " oneof foo {\n" + " optional int32 bar = 1;\n" + " }\n" + "}\n", + "2:4: Fields in oneofs must not have labels (required / optional " + "/ repeated).\n"); +} + TEST_F(ParseErrorTest, GroupNotCapitalized) { ExpectHasErrors( "message TestMessage {\n" @@ -1244,17 +1332,93 @@ TEST_F(ParserValidationErrorTest, MethodOutputTypeError) { } +TEST_F(ParserValidationErrorTest, ResovledUndefinedError) { + // Create another file which defines symbol ".base.bar". + FileDescriptorProto other_file; + other_file.set_name("base.proto"); + other_file.set_package("base"); + other_file.add_message_type()->set_name("bar"); + EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); + + // Define "foo.base" and try "base.bar". + // "base.bar" is resolved to "foo.base.bar" which is not defined. + ExpectHasValidationErrors( + "package foo.base;\n" + "import \"base.proto\";\n" + "message qux {\n" + " optional base.bar baz = 1;\n" + " optional .base.bar quz = 2;\n" + "}\n", + "3:11: \"base.bar\" is resolved to \"foo.base.bar\"," + " which is not defined. The innermost scope is searched first " + "in name resolution. Consider using a leading '.'(i.e., \".base.bar\")" + " to start from the outermost scope.\n"); +} + +TEST_F(ParserValidationErrorTest, ResovledUndefinedOptionError) { + // Build descriptor message in test pool + FileDescriptorProto descriptor_proto; + DescriptorProto::descriptor()->file()->CopyTo(&descriptor_proto); + ASSERT_TRUE(pool_.BuildFile(descriptor_proto) != NULL); + + // base2.proto: + // package baz + // import google/protobuf/descriptor.proto + // message Bar { optional int32 foo = 1; } + // extend FileOptions { optional Bar bar = 7672757; } + FileDescriptorProto other_file; + other_file.set_name("base2.proto"); + other_file.set_package("baz"); + other_file.add_dependency(); + other_file.set_dependency(0, descriptor_proto.name()); + + DescriptorProto* message(other_file.add_message_type()); + message->set_name("Bar"); + FieldDescriptorProto* field(message->add_field()); + field->set_name("foo"); + field->set_number(1); + field->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); + field->set_type(FieldDescriptorProto_Type_TYPE_INT32); + + FieldDescriptorProto* extension(other_file.add_extension()); + extension->set_name("bar"); + extension->set_number(7672757); + extension->set_label(FieldDescriptorProto_Label_LABEL_OPTIONAL); + extension->set_type(FieldDescriptorProto_Type_TYPE_MESSAGE); + extension->set_type_name("Bar"); + extension->set_extendee("google.protobuf.FileOptions"); + + EXPECT_TRUE(pool_.BuildFile(other_file) != NULL); + + // qux.proto: + // package qux.baz + // option (baz.bar).foo = 1; + // + // Although "baz.bar" is already defined, the lookup code will try + // "qux.baz.bar", since it's the match from the innermost scope, + // which will cause a symbol not defined error. + ExpectHasValidationErrors( + "package qux.baz;\n" + "import \"base2.proto\";\n" + "option (baz.bar).foo = 1;\n", + "2:7: Option \"(baz.bar)\" is resolved to \"(qux.baz.bar)\"," + " which is not defined. The innermost scope is searched first " + "in name resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\")" + " to start from the outermost scope.\n"); +} + // =================================================================== // Test that the output from FileDescriptor::DebugString() (and all other // descriptor types) is parseable, and results in the same Descriptor -// definitions again afoter parsing (not, however, that the order of messages +// definitions again afoter parsing (note, however, that the order of messages // cannot be guaranteed to be the same) typedef ParserTest ParseDecriptorDebugTest; class CompareDescriptorNames { public: - bool operator()(const DescriptorProto* left, const DescriptorProto* right) { + bool operator()(const DescriptorProto* left, + const DescriptorProto* right) const { return left->name() < right->name(); } }; @@ -1298,7 +1462,8 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { FileDescriptorProto parsed; parser_->Parse(input_.get(), &parsed); EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type); - ASSERT_EQ("", error_collector_.text_); + ASSERT_EQ("", error_collector_.text_) + << "Failed to parse:\n" << debug_string; // We now have a FileDescriptorProto, but to compare with the expected we // need to link to a FileDecriptor, then output back to a proto. We'll @@ -1317,6 +1482,8 @@ TEST_F(ParseDecriptorDebugTest, TestAllDescriptorTypes) { ASSERT_TRUE(pool_.BuildFile(import_proto) != NULL); const FileDescriptor* actual = pool_.BuildFile(parsed); parsed.Clear(); + ASSERT_TRUE(actual != NULL) + << "Failed to validate:\n" << debug_string; actual->CopyTo(&parsed); ASSERT_TRUE(actual != NULL); @@ -1871,6 +2038,31 @@ TEST_F(SourceInfoTest, ExtensionRanges) { EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); } +TEST_F(SourceInfoTest, Oneofs) { + EXPECT_TRUE(Parse( + "message Foo {\n" + " $a$oneof $c$foo$d$ {\n" + " $e$int32$f$ $g$a$h$ = $i$1$j$;$k$\n" + " }$r$\n" + "}\n")); + + const OneofDescriptorProto& oneof_decl = file_.message_type(0).oneof_decl(0); + const FieldDescriptorProto& field = file_.message_type(0).field(0); + + EXPECT_TRUE(HasSpan('a', 'r', oneof_decl)); + EXPECT_TRUE(HasSpan('c', 'd', oneof_decl, "name")); + + EXPECT_TRUE(HasSpan('e', 'k', field)); + EXPECT_TRUE(HasSpan('e', 'f', field, "type")); + EXPECT_TRUE(HasSpan('g', 'h', field, "name")); + EXPECT_TRUE(HasSpan('i', 'j', field, "number")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(file_.message_type(0))); + EXPECT_TRUE(HasSpan(file_.message_type(0), "name")); +} + TEST_F(SourceInfoTest, NestedMessages) { EXPECT_TRUE(Parse( "message Foo {\n" @@ -2029,6 +2221,7 @@ TEST_F(SourceInfoTest, MethodsAndStreams) { EXPECT_TRUE(HasSpan(file_.service(0), "name")); } + TEST_F(SourceInfoTest, Options) { EXPECT_TRUE(Parse( "$a$option $b$foo$c$.$d$($e$bar.baz$f$)$g$ = " @@ -2365,6 +2558,51 @@ TEST_F(SourceInfoTest, DocComments3) { bar.options().uninterpreted_option(0), "aggregate_value")); } +TEST_F(SourceInfoTest, DocCommentsOneof) { + EXPECT_TRUE(Parse( + "// ignored\n" + "syntax = \"proto2\";\n" + "// Foo leading\n" + "$a$message Foo {\n" + " /* Foo trailing\n" + " */\n" + " // ignored\n" + " /* bar leading\n" + " * line 2 */\n" + " $b$oneof bar {\n" + " /* bar trailing\n" + " * line 2 */\n" + " // ignored\n" + " /* bar_int leading\n" + " */\n" + " $c$int32 bar_int = 1;$d$ // bar_int trailing\n" + " // ignored\n" + " }$e$\n" + "}$f$\n")); + + const DescriptorProto& foo = file_.message_type(0); + const OneofDescriptorProto& bar = foo.oneof_decl(0); + const FieldDescriptorProto& bar_int = foo.field(0); + + EXPECT_TRUE(HasSpanWithComment('a', 'f', foo, + " Foo leading\n", + " Foo trailing\n")); + EXPECT_TRUE(HasSpanWithComment('b', 'e', bar, + " bar leading\n line 2 ", + " bar trailing\n line 2 ")); + EXPECT_TRUE(HasSpanWithComment('c', 'd', bar_int, + " bar_int leading\n", + " bar_int trailing\n")); + + // Ignore these. + EXPECT_TRUE(HasSpan(file_)); + EXPECT_TRUE(HasSpan(foo, "name")); + EXPECT_TRUE(HasSpan(bar, "name")); + EXPECT_TRUE(HasSpan(bar_int, "type")); + EXPECT_TRUE(HasSpan(bar_int, "name")); + EXPECT_TRUE(HasSpan(bar_int, "number")); +} + // =================================================================== } // anonymous namespace diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc index 6525d15c..b5cd01b5 100644 --- a/src/google/protobuf/compiler/plugin.pb.cc +++ b/src/google/protobuf/compiler/plugin.pb.cc @@ -171,6 +171,7 @@ const int CodeGeneratorRequest::kProtoFileFieldNumber; CodeGeneratorRequest::CodeGeneratorRequest() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorRequest) } void CodeGeneratorRequest::InitAsDefaultInstance() { @@ -180,20 +181,23 @@ CodeGeneratorRequest::CodeGeneratorRequest(const CodeGeneratorRequest& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest) } void CodeGeneratorRequest::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorRequest::~CodeGeneratorRequest() { + // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorRequest) SharedDtor(); } void CodeGeneratorRequest::SharedDtor() { - if (parameter_ != &::google::protobuf::internal::GetEmptyString()) { + if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete parameter_; } if (this != default_instance_) { @@ -222,11 +226,9 @@ CodeGeneratorRequest* CodeGeneratorRequest::New() const { } void CodeGeneratorRequest::Clear() { - if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { - if (has_parameter()) { - if (parameter_ != &::google::protobuf::internal::GetEmptyString()) { - parameter_->clear(); - } + if (has_parameter()) { + if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + parameter_->clear(); } } file_to_generate_.Clear(); @@ -237,23 +239,27 @@ void CodeGeneratorRequest::Clear() { bool CodeGeneratorRequest::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorRequest) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated string file_to_generate = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { parse_file_to_generate: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->add_file_to_generate())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->file_to_generate(this->file_to_generate_size() - 1).data(), this->file_to_generate(this->file_to_generate_size() - 1).length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "file_to_generate"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(10)) goto parse_file_to_generate; if (input->ExpectTag(18)) goto parse_parameter; @@ -262,16 +268,16 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( // optional string parameter = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_parameter: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_parameter())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "parameter"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_proto_file; break; @@ -279,24 +285,24 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( // repeated .google.protobuf.FileDescriptorProto proto_file = 15; case 15: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 122) { parse_proto_file: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_proto_file())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_proto_file; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -304,27 +310,35 @@ bool CodeGeneratorRequest::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorRequest) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorRequest) + return false; #undef DO_ } void CodeGeneratorRequest::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorRequest) // repeated string file_to_generate = 1; for (int i = 0; i < this->file_to_generate_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->file_to_generate(i).data(), this->file_to_generate(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "file_to_generate"); ::google::protobuf::internal::WireFormatLite::WriteString( 1, this->file_to_generate(i), output); } // optional string parameter = 2; if (has_parameter()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "parameter"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->parameter(), output); } @@ -338,24 +352,28 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorRequest) } ::google::protobuf::uint8* CodeGeneratorRequest::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest) // repeated string file_to_generate = 1; for (int i = 0; i < this->file_to_generate_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->file_to_generate(i).data(), this->file_to_generate(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "file_to_generate"); target = ::google::protobuf::internal::WireFormatLite:: WriteStringToArray(1, this->file_to_generate(i), target); } // optional string parameter = 2; if (has_parameter()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->parameter().data(), this->parameter().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "parameter"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->parameter(), target); @@ -372,6 +390,7 @@ void CodeGeneratorRequest::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorRequest) return target; } @@ -451,9 +470,7 @@ void CodeGeneratorRequest::CopyFrom(const CodeGeneratorRequest& from) { bool CodeGeneratorRequest::IsInitialized() const { - for (int i = 0; i < proto_file_size(); i++) { - if (!this->proto_file(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->proto_file())) return false; return true; } @@ -488,6 +505,7 @@ const int CodeGeneratorResponse_File::kContentFieldNumber; CodeGeneratorResponse_File::CodeGeneratorResponse_File() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } void CodeGeneratorResponse_File::InitAsDefaultInstance() { @@ -497,28 +515,31 @@ CodeGeneratorResponse_File::CodeGeneratorResponse_File(const CodeGeneratorRespon : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File) } void CodeGeneratorResponse_File::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorResponse_File::~CodeGeneratorResponse_File() { + // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse.File) SharedDtor(); } void CodeGeneratorResponse_File::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } - if (insertion_point_ != &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete insertion_point_; } - if (content_ != &::google::protobuf::internal::GetEmptyString()) { + if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete content_; } if (this != default_instance_) { @@ -547,19 +568,19 @@ CodeGeneratorResponse_File* CodeGeneratorResponse_File::New() const { } void CodeGeneratorResponse_File::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 7) { if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } if (has_insertion_point()) { - if (insertion_point_ != &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_->clear(); } } if (has_content()) { - if (content_ != &::google::protobuf::internal::GetEmptyString()) { + if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_->clear(); } } @@ -570,21 +591,25 @@ void CodeGeneratorResponse_File::Clear() { bool CodeGeneratorResponse_File::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse.File) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_insertion_point; break; @@ -592,16 +617,16 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( // optional string insertion_point = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_insertion_point: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_insertion_point())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "insertion_point"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_content; break; @@ -609,26 +634,27 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( // optional string content = 15; case 15: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 122) { parse_content: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_content())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "content"); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -636,36 +662,45 @@ bool CodeGeneratorResponse_File::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse.File) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse.File) + return false; #undef DO_ } void CodeGeneratorResponse_File::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse.File) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } // optional string insertion_point = 2; if (has_insertion_point()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "insertion_point"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->insertion_point(), output); } // optional string content = 15; if (has_content()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "content"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 15, this->content(), output); } @@ -673,15 +708,18 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse.File) } ::google::protobuf::uint8* CodeGeneratorResponse_File::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); @@ -689,9 +727,10 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( // optional string insertion_point = 2; if (has_insertion_point()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->insertion_point().data(), this->insertion_point().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "insertion_point"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->insertion_point(), target); @@ -699,9 +738,10 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( // optional string content = 15; if (has_content()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->content().data(), this->content().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "content"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 15, this->content(), target); @@ -711,6 +751,7 @@ void CodeGeneratorResponse_File::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse.File) return target; } @@ -826,6 +867,7 @@ const int CodeGeneratorResponse::kFileFieldNumber; CodeGeneratorResponse::CodeGeneratorResponse() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.compiler.CodeGeneratorResponse) } void CodeGeneratorResponse::InitAsDefaultInstance() { @@ -835,20 +877,23 @@ CodeGeneratorResponse::CodeGeneratorResponse(const CodeGeneratorResponse& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse) } void CodeGeneratorResponse::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } CodeGeneratorResponse::~CodeGeneratorResponse() { + // @@protoc_insertion_point(destructor:google.protobuf.compiler.CodeGeneratorResponse) SharedDtor(); } void CodeGeneratorResponse::SharedDtor() { - if (error_ != &::google::protobuf::internal::GetEmptyString()) { + if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete error_; } if (this != default_instance_) { @@ -877,11 +922,9 @@ CodeGeneratorResponse* CodeGeneratorResponse::New() const { } void CodeGeneratorResponse::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - if (has_error()) { - if (error_ != &::google::protobuf::internal::GetEmptyString()) { - error_->clear(); - } + if (has_error()) { + if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + error_->clear(); } } file_.Clear(); @@ -891,21 +934,25 @@ void CodeGeneratorResponse::Clear() { bool CodeGeneratorResponse::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.compiler.CodeGeneratorResponse) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string error = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_error())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "error"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_file; break; @@ -913,24 +960,24 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; case 15: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 122) { parse_file: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_file())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(122)) goto parse_file; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -938,18 +985,25 @@ bool CodeGeneratorResponse::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.compiler.CodeGeneratorResponse) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.compiler.CodeGeneratorResponse) + return false; #undef DO_ } void CodeGeneratorResponse::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.compiler.CodeGeneratorResponse) // optional string error = 1; if (has_error()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "error"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->error(), output); } @@ -963,15 +1017,18 @@ void CodeGeneratorResponse::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.compiler.CodeGeneratorResponse) } ::google::protobuf::uint8* CodeGeneratorResponse::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse) // optional string error = 1; if (has_error()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->error().data(), this->error().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "error"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->error(), target); @@ -988,6 +1045,7 @@ void CodeGeneratorResponse::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.compiler.CodeGeneratorResponse) return target; } diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h index d26a135e..b590d8df 100644 --- a/src/google/protobuf/compiler/plugin.pb.h +++ b/src/google/protobuf/compiler/plugin.pb.h @@ -89,7 +89,6 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -143,13 +142,11 @@ class LIBPROTOC_EXPORT CodeGeneratorRequest : public ::google::protobuf::Message ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::std::string> file_to_generate_; ::std::string* parameter_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > proto_file_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); @@ -206,7 +203,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -260,13 +256,11 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse_File : public ::google::protobuf::M ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_; ::std::string* insertion_point_; ::std::string* content_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); @@ -323,7 +317,6 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -363,12 +356,10 @@ class LIBPROTOC_EXPORT CodeGeneratorResponse : public ::google::protobuf::Messag ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* error_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File > file_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - friend void LIBPROTOC_EXPORT protobuf_AddDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fcompiler_2fplugin_2eproto(); @@ -391,39 +382,49 @@ inline void CodeGeneratorRequest::clear_file_to_generate() { file_to_generate_.Clear(); } inline const ::std::string& CodeGeneratorRequest::file_to_generate(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_.Get(index); } inline ::std::string* CodeGeneratorRequest::mutable_file_to_generate(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_.Mutable(index); } inline void CodeGeneratorRequest::set_file_to_generate(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) file_to_generate_.Mutable(index)->assign(value); } inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value) { file_to_generate_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) { file_to_generate_.Mutable(index)->assign( reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline ::std::string* CodeGeneratorRequest::add_file_to_generate() { return file_to_generate_.Add(); } inline void CodeGeneratorRequest::add_file_to_generate(const ::std::string& value) { file_to_generate_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::add_file_to_generate(const char* value) { file_to_generate_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) { file_to_generate_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) } inline const ::google::protobuf::RepeatedPtrField< ::std::string>& CodeGeneratorRequest::file_to_generate() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return file_to_generate_; } inline ::google::protobuf::RepeatedPtrField< ::std::string>* CodeGeneratorRequest::mutable_file_to_generate() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate) return &file_to_generate_; } @@ -438,54 +439,59 @@ inline void CodeGeneratorRequest::clear_has_parameter() { _has_bits_[0] &= ~0x00000002u; } inline void CodeGeneratorRequest::clear_parameter() { - if (parameter_ != &::google::protobuf::internal::GetEmptyString()) { + if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_->clear(); } clear_has_parameter(); } inline const ::std::string& CodeGeneratorRequest::parameter() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.parameter) return *parameter_; } inline void CodeGeneratorRequest::set_parameter(const ::std::string& value) { set_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyString()) { + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_ = new ::std::string; } parameter_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value) { set_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyString()) { + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_ = new ::std::string; } parameter_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline void CodeGeneratorRequest::set_parameter(const char* value, size_t size) { set_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyString()) { + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_ = new ::std::string; } parameter_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.parameter) } inline ::std::string* CodeGeneratorRequest::mutable_parameter() { set_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyString()) { + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { parameter_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.parameter) return parameter_; } inline ::std::string* CodeGeneratorRequest::release_parameter() { clear_has_parameter(); - if (parameter_ == &::google::protobuf::internal::GetEmptyString()) { + if (parameter_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = parameter_; - parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* parameter) { - if (parameter_ != &::google::protobuf::internal::GetEmptyString()) { + if (parameter_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete parameter_; } if (parameter) { @@ -493,8 +499,9 @@ inline void CodeGeneratorRequest::set_allocated_parameter(::std::string* paramet parameter_ = parameter; } else { clear_has_parameter(); - parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + parameter_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorRequest.parameter) } // repeated .google.protobuf.FileDescriptorProto proto_file = 15; @@ -505,20 +512,25 @@ inline void CodeGeneratorRequest::clear_proto_file() { proto_file_.Clear(); } inline const ::google::protobuf::FileDescriptorProto& CodeGeneratorRequest::proto_file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Get(index); } inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::mutable_proto_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Mutable(index); } inline ::google::protobuf::FileDescriptorProto* CodeGeneratorRequest::add_proto_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& CodeGeneratorRequest::proto_file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return proto_file_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* CodeGeneratorRequest::mutable_proto_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorRequest.proto_file) return &proto_file_; } @@ -537,54 +549,59 @@ inline void CodeGeneratorResponse_File::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } inline void CodeGeneratorResponse_File::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } clear_has_name(); } inline const ::std::string& CodeGeneratorResponse_File::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.name) return *name_; } inline void CodeGeneratorResponse_File::set_name(const ::std::string& value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline void CodeGeneratorResponse_File::set_name(const char* value, size_t size) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.name) } inline ::std::string* CodeGeneratorResponse_File::mutable_name() { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.name) return name_; } inline ::std::string* CodeGeneratorResponse_File::release_name() { clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (name) { @@ -592,8 +609,9 @@ inline void CodeGeneratorResponse_File::set_allocated_name(::std::string* name) name_ = name; } else { clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.name) } // optional string insertion_point = 2; @@ -607,54 +625,59 @@ inline void CodeGeneratorResponse_File::clear_has_insertion_point() { _has_bits_[0] &= ~0x00000002u; } inline void CodeGeneratorResponse_File::clear_insertion_point() { - if (insertion_point_ != &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_->clear(); } clear_has_insertion_point(); } inline const ::std::string& CodeGeneratorResponse_File::insertion_point() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return *insertion_point_; } inline void CodeGeneratorResponse_File::set_insertion_point(const ::std::string& value) { set_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_ = new ::std::string; } insertion_point_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value) { set_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_ = new ::std::string; } insertion_point_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline void CodeGeneratorResponse_File::set_insertion_point(const char* value, size_t size) { set_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_ = new ::std::string; } insertion_point_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } inline ::std::string* CodeGeneratorResponse_File::mutable_insertion_point() { set_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { insertion_point_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) return insertion_point_; } inline ::std::string* CodeGeneratorResponse_File::release_insertion_point() { clear_has_insertion_point(); - if (insertion_point_ == &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = insertion_point_; - insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::string* insertion_point) { - if (insertion_point_ != &::google::protobuf::internal::GetEmptyString()) { + if (insertion_point_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete insertion_point_; } if (insertion_point) { @@ -662,8 +685,9 @@ inline void CodeGeneratorResponse_File::set_allocated_insertion_point(::std::str insertion_point_ = insertion_point; } else { clear_has_insertion_point(); - insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + insertion_point_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point) } // optional string content = 15; @@ -677,54 +701,59 @@ inline void CodeGeneratorResponse_File::clear_has_content() { _has_bits_[0] &= ~0x00000004u; } inline void CodeGeneratorResponse_File::clear_content() { - if (content_ != &::google::protobuf::internal::GetEmptyString()) { + if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_->clear(); } clear_has_content(); } inline const ::std::string& CodeGeneratorResponse_File::content() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.File.content) return *content_; } inline void CodeGeneratorResponse_File::set_content(const ::std::string& value) { set_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyString()) { + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_ = new ::std::string; } content_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value) { set_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyString()) { + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_ = new ::std::string; } content_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline void CodeGeneratorResponse_File::set_content(const char* value, size_t size) { set_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyString()) { + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_ = new ::std::string; } content_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.File.content) } inline ::std::string* CodeGeneratorResponse_File::mutable_content() { set_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyString()) { + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { content_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.File.content) return content_; } inline ::std::string* CodeGeneratorResponse_File::release_content() { clear_has_content(); - if (content_ == &::google::protobuf::internal::GetEmptyString()) { + if (content_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = content_; - content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* content) { - if (content_ != &::google::protobuf::internal::GetEmptyString()) { + if (content_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete content_; } if (content) { @@ -732,8 +761,9 @@ inline void CodeGeneratorResponse_File::set_allocated_content(::std::string* con content_ = content; } else { clear_has_content(); - content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + content_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.File.content) } // ------------------------------------------------------------------- @@ -751,54 +781,59 @@ inline void CodeGeneratorResponse::clear_has_error() { _has_bits_[0] &= ~0x00000001u; } inline void CodeGeneratorResponse::clear_error() { - if (error_ != &::google::protobuf::internal::GetEmptyString()) { + if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_->clear(); } clear_has_error(); } inline const ::std::string& CodeGeneratorResponse::error() const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.error) return *error_; } inline void CodeGeneratorResponse::set_error(const ::std::string& value) { set_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyString()) { + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_ = new ::std::string; } error_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value) { set_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyString()) { + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_ = new ::std::string; } error_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorResponse.error) } inline void CodeGeneratorResponse::set_error(const char* value, size_t size) { set_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyString()) { + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_ = new ::std::string; } error_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorResponse.error) } inline ::std::string* CodeGeneratorResponse::mutable_error() { set_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyString()) { + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { error_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.error) return error_; } inline ::std::string* CodeGeneratorResponse::release_error() { clear_has_error(); - if (error_ == &::google::protobuf::internal::GetEmptyString()) { + if (error_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = error_; - error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) { - if (error_ != &::google::protobuf::internal::GetEmptyString()) { + if (error_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete error_; } if (error) { @@ -806,8 +841,9 @@ inline void CodeGeneratorResponse::set_allocated_error(::std::string* error) { error_ = error; } else { clear_has_error(); - error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + error_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.compiler.CodeGeneratorResponse.error) } // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15; @@ -818,20 +854,25 @@ inline void CodeGeneratorResponse::clear_file() { file_.Clear(); } inline const ::google::protobuf::compiler::CodeGeneratorResponse_File& CodeGeneratorResponse::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Get(index); } inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Mutable(index); } inline ::google::protobuf::compiler::CodeGeneratorResponse_File* CodeGeneratorResponse::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorResponse.file) return file_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >& CodeGeneratorResponse::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.compiler.CodeGeneratorResponse.file) return file_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::compiler::CodeGeneratorResponse_File >* CodeGeneratorResponse::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.compiler.CodeGeneratorResponse.file) return &file_; } diff --git a/src/google/protobuf/compiler/python/python_generator.cc b/src/google/protobuf/compiler/python/python_generator.cc index 211ac70c..067d856b 100644 --- a/src/google/protobuf/compiler/python/python_generator.cc +++ b/src/google/protobuf/compiler/python/python_generator.cc @@ -28,6 +28,8 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +//#PY25 compatible generated code for GAE. +// Copyright 2007 Google Inc. All Rights Reserved. // Author: robinson@google.com (Will Robinson) // // This module outputs pure-Python protocol message classes that will @@ -45,6 +47,7 @@ #include #include #include +#include #include #include @@ -128,6 +131,7 @@ void PrintTopBoilerplate( printer->Print( "# Generated by the protocol buffer compiler. DO NOT EDIT!\n" "# source: $filename$\n" + "\nimport sys\n_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))" //##PY25 "\n", "filename", file->name()); if (HasTopLevelEnums(file)) { @@ -138,7 +142,8 @@ void PrintTopBoilerplate( "from google.protobuf import descriptor as _descriptor\n" "from google.protobuf import message as _message\n" "from google.protobuf import reflection as _reflection\n" - ); + "from google.protobuf import symbol_database as " + "_symbol_database\n"); if (HasGenericServices(file)) { printer->Print( "from google.protobuf import service as _service\n" @@ -151,7 +156,8 @@ void PrintTopBoilerplate( "from google.protobuf import descriptor_pb2\n"); } printer->Print( - "# @@protoc_insertion_point(imports)\n"); + "# @@protoc_insertion_point(imports)\n\n" + "_sym_db = _symbol_database.Default()\n"); printer->Print("\n\n"); } @@ -217,14 +223,14 @@ string StringifyDefaultValue(const FieldDescriptor& field) { case FieldDescriptor::CPPTYPE_ENUM: return SimpleItoa(field.default_value_enum()->number()); case FieldDescriptor::CPPTYPE_STRING: - if (field.type() == FieldDescriptor::TYPE_STRING) { - return "unicode(\"" + CEscape(field.default_value_string()) + - "\", \"utf-8\")"; - } else { - return "\"" + CEscape(field.default_value_string()) + "\""; - } - case FieldDescriptor::CPPTYPE_MESSAGE: - return "None"; +//##!PY25 return "b\"" + CEscape(field.default_value_string()) + +//##!PY25 (field.type() != FieldDescriptor::TYPE_STRING ? "\"" : +//##!PY25 "\".decode('utf-8')"); + return "_b(\"" + CEscape(field.default_value_string()) + //##PY25 + (field.type() != FieldDescriptor::TYPE_STRING ? "\")" : //##PY25 + "\").decode('utf-8')"); //##PY25 + case FieldDescriptor::CPPTYPE_MESSAGE: + return "None"; } // (We could add a default case above but then we wouldn't get the nice // compiler warning when a new type is added.) @@ -330,14 +336,25 @@ void Generator::PrintFileDescriptor() const { printer_->Print(m, file_descriptor_template); printer_->Indent(); printer_->Print( - "serialized_pb='$value$'", +//##!PY25 "serialized_pb=b'$value$'\n", + "serialized_pb=_b('$value$')\n", //##PY25 "value", strings::CHexEscape(file_descriptor_serialized_)); + if (file_->dependency_count() != 0) { + printer_->Print(",\ndependencies=["); + for (int i = 0; i < file_->dependency_count(); ++i) { + string module_name = ModuleName(file_->dependency(i)->name()); + printer_->Print("$module_name$.DESCRIPTOR,", "module_name", module_name); + } + printer_->Print("]"); + } // TODO(falk): Also print options and fix the message_type, enum_type, // service and extension later in the generation. printer_->Outdent(); printer_->Print(")\n"); + printer_->Print("_sym_db.RegisterFileDescriptor($name$)\n", "name", + kDescriptorKey); printer_->Print("\n"); } @@ -382,7 +399,9 @@ void Generator::PrintAllNestedEnumsInFile() const { // enum_descriptor. void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { map m; - m["descriptor_name"] = ModuleLevelDescriptorName(enum_descriptor); + string module_level_descriptor_name = + ModuleLevelDescriptorName(enum_descriptor); + m["descriptor_name"] = module_level_descriptor_name; m["name"] = enum_descriptor.name(); m["full_name"] = enum_descriptor.full_name(); m["file"] = kDescriptorKey; @@ -412,6 +431,8 @@ void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const { PrintSerializedPbInterval(enum_descriptor, edp); printer_->Outdent(); printer_->Print(")\n"); + printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name", + module_level_descriptor_name); printer_->Print("\n"); } @@ -522,27 +543,36 @@ void Generator::PrintServiceDescriptor( void Generator::PrintServiceClass(const ServiceDescriptor& descriptor) const { // Print the service. - printer_->Print("class $class_name$(_service.Service):\n", + printer_->Print("$class_name$ = service_reflection.GeneratedServiceType(" + "'$class_name$', (_service.Service,), dict(\n", "class_name", descriptor.name()); printer_->Indent(); printer_->Print( - "__metaclass__ = service_reflection.GeneratedServiceType\n" - "$descriptor_key$ = $descriptor_name$\n", + "$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); + printer_->Print( + "__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("))\n\n"); printer_->Outdent(); } void Generator::PrintServiceStub(const ServiceDescriptor& descriptor) const { // Print the service stub. - printer_->Print("class $class_name$_Stub($class_name$):\n", + printer_->Print("$class_name$_Stub = " + "service_reflection.GeneratedServiceStubType(" + "'$class_name$_Stub', ($class_name$,), dict(\n", "class_name", descriptor.name()); printer_->Indent(); printer_->Print( - "__metaclass__ = service_reflection.GeneratedServiceStubType\n" - "$descriptor_key$ = $descriptor_name$\n", + "$descriptor_key$ = $descriptor_name$,\n", "descriptor_key", kDescriptorKey, "descriptor_name", ModuleLevelServiceDescriptorName(descriptor)); + printer_->Print( + "__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("))\n\n"); printer_->Outdent(); } @@ -635,7 +665,12 @@ void Generator::PrintNestedDescriptors( // Prints all messages in |file|. void Generator::PrintMessages() const { for (int i = 0; i < file_->message_type_count(); ++i) { - PrintMessage(*file_->message_type(i)); + vector to_register; + PrintMessage(*file_->message_type(i), "", &to_register); + for (int j = 0; j < to_register.size(); ++j) { + printer_->Print("_sym_db.RegisterMessage($name$)\n", "name", + to_register[j]); + } printer_->Print("\n"); } } @@ -647,33 +682,40 @@ void Generator::PrintMessages() const { // reflection.py will use to construct the meat of the class itself. // // Mutually recursive with PrintNestedMessages(). -void Generator::PrintMessage( - const Descriptor& message_descriptor) const { - printer_->Print("class $name$(_message.Message):\n", "name", - message_descriptor.name()); +// Collect nested message names to_register for the symbol_database. +void Generator::PrintMessage(const Descriptor& message_descriptor, + const string& prefix, + vector* to_register) const { + string qualified_name(prefix + message_descriptor.name()); + to_register->push_back(qualified_name); + printer_->Print( + "$name$ = _reflection.GeneratedProtocolMessageType('$name$', " + "(_message.Message,), dict(\n", + "name", message_descriptor.name()); printer_->Indent(); - printer_->Print("__metaclass__ = _reflection.GeneratedProtocolMessageType\n"); - PrintNestedMessages(message_descriptor); + + PrintNestedMessages(message_descriptor, qualified_name + ".", to_register); map m; m["descriptor_key"] = kDescriptorKey; m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor); - printer_->Print(m, "$descriptor_key$ = $descriptor_name$\n"); - - printer_->Print( - "\n" - "# @@protoc_insertion_point(class_scope:$full_name$)\n", - "full_name", message_descriptor.full_name()); - + printer_->Print(m, "$descriptor_key$ = $descriptor_name$,\n"); + printer_->Print("__module__ = '$module_name$'\n", + "module_name", ModuleName(file_->name())); + printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n", + "full_name", message_descriptor.full_name()); + printer_->Print("))\n"); printer_->Outdent(); } // Prints all nested messages within |containing_descriptor|. // Mutually recursive with PrintMessage(). -void Generator::PrintNestedMessages( - const Descriptor& containing_descriptor) const { +void Generator::PrintNestedMessages(const Descriptor& containing_descriptor, + const string& prefix, + vector* to_register) const { for (int i = 0; i < containing_descriptor.nested_type_count(); ++i) { printer_->Print("\n"); - PrintMessage(*containing_descriptor.nested_type(i)); + PrintMessage(*containing_descriptor.nested_type(i), prefix, to_register); + printer_->Print(",\n"); } } @@ -714,6 +756,29 @@ void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const { printer_->Print(m, file_descriptor_template); } +void Generator::AddEnumToFileDescriptor( + const EnumDescriptor& descriptor) const { + map m; + m["descriptor_name"] = kDescriptorKey; + m["enum_name"] = descriptor.name(); + m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor); + const char file_descriptor_template[] = + "$descriptor_name$.enum_types_by_name['$enum_name$'] = " + "$enum_descriptor_name$\n"; + printer_->Print(m, file_descriptor_template); +} + +void Generator::AddExtensionToFileDescriptor( + const FieldDescriptor& descriptor) const { + map m; + m["descriptor_name"] = kDescriptorKey; + m["field_name"] = descriptor.name(); + const char file_descriptor_template[] = + "$descriptor_name$.extensions_by_name['$field_name$'] = " + "$field_name$\n"; + printer_->Print(m, file_descriptor_template); +} + // Sets any necessary message_type and enum_type attributes // for the Python version of |field|. // @@ -778,7 +843,7 @@ void Generator::FixContainingTypeInDescriptor( const string parent_name = ModuleLevelDescriptorName( *containing_descriptor); printer_->Print( - "$nested_name$.containing_type = $parent_name$;\n", + "$nested_name$.containing_type = $parent_name$\n", "nested_name", nested_name, "parent_name", parent_name); } @@ -795,6 +860,12 @@ void Generator::FixForeignFieldsInDescriptors() const { for (int i = 0; i < file_->message_type_count(); ++i) { AddMessageToFileDescriptor(*file_->message_type(i)); } + for (int i = 0; i < file_->enum_type_count(); ++i) { + AddEnumToFileDescriptor(*file_->enum_type(i)); + } + for (int i = 0; i < file_->extension_count(); ++i) { + AddExtensionToFileDescriptor(*file_->extension(i)); + } printer_->Print("\n"); } @@ -875,8 +946,10 @@ string Generator::OptionsValue( return "None"; } else { string full_class_name = "descriptor_pb2." + class_name; - return "_descriptor._ParseOptions(" + full_class_name + "(), '" - + CEscape(serialized_options)+ "')"; +//##!PY25 return "_descriptor._ParseOptions(" + full_class_name + "(), b'" +//##!PY25 + CEscape(serialized_options)+ "')"; + return "_descriptor._ParseOptions(" + full_class_name + "(), _b('" //##PY25 + + CEscape(serialized_options)+ "'))"; //##PY25 } } diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h index a3f22cee..40dfddf3 100644 --- a/src/google/protobuf/compiler/python/python_generator.h +++ b/src/google/protobuf/compiler/python/python_generator.h @@ -94,8 +94,11 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { void PrintNestedDescriptors(const Descriptor& containing_descriptor) const; void PrintMessages() const; - void PrintMessage(const Descriptor& message_descriptor) const; - void PrintNestedMessages(const Descriptor& containing_descriptor) const; + void PrintMessage(const Descriptor& message_descriptor, const string& prefix, + vector* to_register) const; + void PrintNestedMessages(const Descriptor& containing_descriptor, + const string& prefix, + vector* to_register) const; void FixForeignFieldsInDescriptors() const; void FixForeignFieldsInDescriptor( @@ -105,6 +108,8 @@ class LIBPROTOC_EXPORT Generator : public CodeGenerator { const FieldDescriptor& field, const string& python_dict_name) const; void AddMessageToFileDescriptor(const Descriptor& descriptor) const; + void AddEnumToFileDescriptor(const EnumDescriptor& descriptor) const; + void AddExtensionToFileDescriptor(const FieldDescriptor& descriptor) const; string FieldReferencingExpression(const Descriptor* containing_type, const FieldDescriptor& field, const string& python_dict_name) const; diff --git a/src/google/protobuf/compiler/python/python_plugin_unittest.cc b/src/google/protobuf/compiler/python/python_plugin_unittest.cc index da619ad3..77da8a87 100644 --- a/src/google/protobuf/compiler/python/python_plugin_unittest.cc +++ b/src/google/protobuf/compiler/python/python_plugin_unittest.cc @@ -34,6 +34,8 @@ // It seemed like parameterizing it would add more complexity than it is // worth. +#include + #include #include #include @@ -68,7 +70,7 @@ class TestGenerator : public CodeGenerator { void TryInsert(const string& filename, const string& insertion_point, GeneratorContext* context) const { scoped_ptr output( - context->OpenForInsert(filename, insertion_point)); + context->OpenForInsert(filename, insertion_point)); io::Printer printer(output.get(), '$'); printer.Print("// inserted $name$\n", "name", insertion_point); } @@ -78,13 +80,13 @@ class TestGenerator : public CodeGenerator { // not verify that they are correctly-placed; that would require actually // compiling the output which is a bit more than I care to do for this test. TEST(PythonPluginTest, PluginTest) { - File::WriteStringToFileOrDie( - "syntax = \"proto2\";\n" - "package foo;\n" - "message Bar {\n" - " message Baz {}\n" - "}\n", - TestTempDir() + "/test.proto"); + GOOGLE_CHECK_OK(File::SetContents(TestTempDir() + "/test.proto", + "syntax = \"proto2\";\n" + "package foo;\n" + "message Bar {\n" + " message Baz {}\n" + "}\n", + true)); google::protobuf::compiler::CommandLineInterface cli; cli.SetInputsAreProtoPathRelative(true); diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc index 67da120d..ca4b874d 100644 --- a/src/google/protobuf/compiler/subprocess.cc +++ b/src/google/protobuf/compiler/subprocess.cc @@ -449,7 +449,7 @@ bool Subprocess::Communicate(const Message& input, Message* output, } if (!output->ParseFromString(output_data)) { - *error = "Plugin output is unparseable."; + *error = "Plugin output is unparseable: " + CEscape(output_data); return false; } diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc index 3f0d15f7..abd13a0b 100644 --- a/src/google/protobuf/descriptor.cc +++ b/src/google/protobuf/descriptor.cc @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -43,9 +44,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -53,7 +56,7 @@ #include #include #include -#include +#include #include #undef PACKAGE // autoheader #defines this. :( @@ -131,6 +134,8 @@ const char * const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = { "repeated", // LABEL_REPEATED }; +static const char * const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty"; + #ifndef _MSC_VER // MSVC doesn't need these and won't even accept them. const int FieldDescriptor::kMaxNumber; const int FieldDescriptor::kFirstReservedNumber; @@ -234,13 +239,14 @@ struct PointerStringPairHash { struct Symbol { enum Type { - NULL_SYMBOL, MESSAGE, FIELD, ENUM, ENUM_VALUE, SERVICE, METHOD, + NULL_SYMBOL, MESSAGE, FIELD, ONEOF, ENUM, ENUM_VALUE, SERVICE, METHOD, PACKAGE }; Type type; union { const Descriptor* descriptor; const FieldDescriptor* field_descriptor; + const OneofDescriptor* oneof_descriptor; const EnumDescriptor* enum_descriptor; const EnumValueDescriptor* enum_value_descriptor; const ServiceDescriptor* service_descriptor; @@ -266,6 +272,7 @@ struct Symbol { CONSTRUCTOR(Descriptor , MESSAGE , descriptor ) CONSTRUCTOR(FieldDescriptor , FIELD , field_descriptor ) + CONSTRUCTOR(OneofDescriptor , ONEOF , oneof_descriptor ) CONSTRUCTOR(EnumDescriptor , ENUM , enum_descriptor ) CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor ) CONSTRUCTOR(ServiceDescriptor , SERVICE , service_descriptor ) @@ -278,6 +285,7 @@ struct Symbol { case NULL_SYMBOL: return NULL; case MESSAGE : return descriptor ->file(); case FIELD : return field_descriptor ->file(); + case ONEOF : return oneof_descriptor ->containing_type()->file(); case ENUM : return enum_descriptor ->file(); case ENUM_VALUE : return enum_value_descriptor->type()->file(); case SERVICE : return service_descriptor ->file(); @@ -314,7 +322,7 @@ typedef hash_map ExtensionsGroupedByDescriptorMap; - +typedef hash_map LocationsByPathMap; } // anonymous namespace // =================================================================== @@ -368,10 +376,18 @@ class DescriptorPool::Tables { vector pending_files_; // A set of files which we have tried to load from the fallback database - // and encountered errors. We will not attempt to load them again. + // and encountered errors. We will not attempt to load them again during + // execution of the current public API call, but for compatibility with + // legacy clients, this is cleared at the beginning of each public API call. // Not used when fallback_database_ == NULL. hash_set known_bad_files_; + // A set of symbols which we have tried to load from the fallback database + // and encountered errors. We will not attempt to load them again during + // execution of the current public API call, but for compatibility with + // legacy clients, this is cleared at the beginning of each public API call. + hash_set known_bad_symbols_; + // The set of descriptors for which we've already loaded the full // set of extensions numbers from fallback_database_. hash_set extensions_loaded_from_db_; @@ -388,7 +404,7 @@ class DescriptorPool::Tables { // declaring Symbol in descriptor.h, which would drag all kinds of other // stuff into the header. Yay C++. Symbol FindByNameHelper( - const DescriptorPool* pool, const string& name) const; + const DescriptorPool* pool, const string& name); // These return NULL if not found. inline const FileDescriptor* FindFile(const string& key) const; @@ -529,17 +545,34 @@ class FileDescriptorTables { // fails because we allow duplicates; the first field by the name wins. void AddFieldByStylizedNames(const FieldDescriptor* field); + // Populates p->first->locations_by_path_ from p->second. + // Unusual signature dictated by GoogleOnceDynamic. + static void BuildLocationsByPath( + pair* p); + + // Returns the location denoted by the specified path through info, + // or NULL if not found. + // The value of info must be that of the corresponding FileDescriptor. + // (Conceptually a pure function, but stateful as an optimisation.) + const SourceCodeInfo_Location* GetSourceLocation( + const vector& path, const SourceCodeInfo* info) const; + private: SymbolsByParentMap symbols_by_parent_; FieldsByNameMap fields_by_lowercase_name_; FieldsByNameMap fields_by_camelcase_name_; FieldsByNumberMap fields_by_number_; // Not including extensions. EnumValuesByNumberMap enum_values_by_number_; + + // Populated on first request to save space, hence constness games. + mutable GoogleOnceDynamic locations_by_path_once_; + mutable LocationsByPathMap locations_by_path_; }; DescriptorPool::Tables::Tables() // Start some hash_map and hash_set objects with a small # of buckets : known_bad_files_(3), + known_bad_symbols_(3), extensions_loaded_from_db_(3), symbols_by_name_(3), files_by_name_(3) {} @@ -663,8 +696,10 @@ inline Symbol FileDescriptorTables::FindNestedSymbolOfType( } Symbol DescriptorPool::Tables::FindByNameHelper( - const DescriptorPool* pool, const string& name) const { + const DescriptorPool* pool, const string& name) { MutexLockMaybe lock(pool->mutex_); + known_bad_symbols_.clear(); + known_bad_files_.clear(); Symbol result = FindSymbol(name); if (result.IsNull() && pool->underlay_ != NULL) { @@ -835,6 +870,22 @@ void* DescriptorPool::Tables::AllocateBytes(int size) { return result; } +void FileDescriptorTables::BuildLocationsByPath( + pair* p) { + for (int i = 0, len = p->second->location_size(); i < len; ++i) { + const SourceCodeInfo_Location* loc = &p->second->location().Get(i); + p->first->locations_by_path_[Join(loc->path(), ",")] = loc; + } +} + +const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation( + const vector& path, const SourceCodeInfo* info) const { + pair p( + make_pair(this, info)); + locations_by_path_once_.Init(&FileDescriptorTables::BuildLocationsByPath, &p); + return FindPtrOrNull(locations_by_path_, Join(path, ",")); +} + // =================================================================== // DescriptorPool @@ -847,7 +898,8 @@ DescriptorPool::DescriptorPool() underlay_(NULL), tables_(new Tables), enforce_dependencies_(true), - allow_unknown_(false) {} + allow_unknown_(false), + enforce_weak_(false) {} DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, ErrorCollector* error_collector) @@ -857,7 +909,8 @@ DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database, underlay_(NULL), tables_(new Tables), enforce_dependencies_(true), - allow_unknown_(false) { + allow_unknown_(false), + enforce_weak_(false) { } DescriptorPool::DescriptorPool(const DescriptorPool* underlay) @@ -867,7 +920,8 @@ DescriptorPool::DescriptorPool(const DescriptorPool* underlay) underlay_(underlay), tables_(new Tables), enforce_dependencies_(true), - allow_unknown_(false) {} + allow_unknown_(false), + enforce_weak_(false) {} DescriptorPool::~DescriptorPool() { if (mutex_ != NULL) delete mutex_; @@ -880,6 +934,14 @@ void DescriptorPool::InternalDontEnforceDependencies() { enforce_dependencies_ = false; } +void DescriptorPool::AddUnusedImportTrackFile(const string& file_name) { + unused_import_track_files_.insert(file_name); +} + +void DescriptorPool::ClearUnusedImportTrackFiles() { + unused_import_track_files_.clear(); +} + bool DescriptorPool::InternalIsFileLoaded(const string& filename) const { MutexLockMaybe lock(mutex_); return tables_->FindFile(filename) != NULL; @@ -961,6 +1023,8 @@ void DescriptorPool::InternalAddGeneratedFile( const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const { MutexLockMaybe lock(mutex_); + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); const FileDescriptor* result = tables_->FindFile(name); if (result != NULL) return result; if (underlay_ != NULL) { @@ -977,6 +1041,8 @@ const FileDescriptor* DescriptorPool::FindFileByName(const string& name) const { const FileDescriptor* DescriptorPool::FindFileContainingSymbol( const string& symbol_name) const { MutexLockMaybe lock(mutex_); + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); Symbol result = tables_->FindSymbol(symbol_name); if (!result.IsNull()) return result.GetFile(); if (underlay_ != NULL) { @@ -1019,6 +1085,12 @@ const FieldDescriptor* DescriptorPool::FindExtensionByName( } } +const OneofDescriptor* DescriptorPool::FindOneofByName( + const string& name) const { + Symbol result = tables_->FindByNameHelper(this, name); + return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : NULL; +} + const EnumDescriptor* DescriptorPool::FindEnumTypeByName( const string& name) const { Symbol result = tables_->FindByNameHelper(this, name); @@ -1047,6 +1119,8 @@ const MethodDescriptor* DescriptorPool::FindMethodByName( const FieldDescriptor* DescriptorPool::FindExtensionByNumber( const Descriptor* extendee, int number) const { MutexLockMaybe lock(mutex_); + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); const FieldDescriptor* result = tables_->FindExtension(extendee, number); if (result != NULL) { return result; @@ -1067,6 +1141,8 @@ const FieldDescriptor* DescriptorPool::FindExtensionByNumber( void DescriptorPool::FindAllExtensions( const Descriptor* extendee, vector* out) const { MutexLockMaybe lock(mutex_); + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); // Initialize tables_->extensions_ from the fallback database first // (but do this only once per descriptor). @@ -1091,6 +1167,7 @@ void DescriptorPool::FindAllExtensions( } } + // ------------------------------------------------------------------- const FieldDescriptor* @@ -1137,6 +1214,17 @@ Descriptor::FindFieldByName(const string& key) const { } } +const OneofDescriptor* +Descriptor::FindOneofByName(const string& key) const { + Symbol result = + file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF); + if (!result.IsNull()) { + return result.oneof_descriptor; + } else { + return NULL; + } +} + const FieldDescriptor* Descriptor::FindExtensionByName(const string& key) const { Symbol result = @@ -1301,16 +1389,17 @@ FileDescriptor::FindExtensionByCamelcaseName(const string& key) const { } } -bool Descriptor::IsExtensionNumber(int number) const { +const Descriptor::ExtensionRange* +Descriptor::FindExtensionRangeContainingNumber(int number) const { // Linear search should be fine because we don't expect a message to have // more than a couple extension ranges. for (int i = 0; i < extension_range_count(); i++) { if (number >= extension_range(i)->start && number < extension_range(i)->end) { - return true; + return extension_range(i); } } - return false; + return NULL; } // ------------------------------------------------------------------- @@ -1326,7 +1415,6 @@ bool DescriptorPool::TryFindFileInFallbackDatabase(const string& name) const { tables_->known_bad_files_.insert(name); return false; } - return true; } @@ -1355,36 +1443,38 @@ bool DescriptorPool::IsSubSymbolOfBuiltType(const string& name) const { bool DescriptorPool::TryFindSymbolInFallbackDatabase(const string& name) const { if (fallback_database_ == NULL) return false; - // We skip looking in the fallback database if the name is a sub-symbol of - // any descriptor that already exists in the descriptor pool (except for - // package descriptors). This is valid because all symbols except for - // packages are defined in a single file, so if the symbol exists then we - // should already have its definition. - // - // The other reason to do this is to support "overriding" type definitions - // by merging two databases that define the same type. (Yes, people do - // this.) The main difficulty with making this work is that - // FindFileContainingSymbol() is allowed to return both false positives - // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false - // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). When two - // such databases are merged, looking up a non-existent sub-symbol of a type - // that already exists in the descriptor pool can result in an attempt to - // load multiple definitions of the same type. The check below avoids this. - if (IsSubSymbolOfBuiltType(name)) return false; + if (tables_->known_bad_symbols_.count(name) > 0) return false; FileDescriptorProto file_proto; - if (!fallback_database_->FindFileContainingSymbol(name, &file_proto)) { - return false; - } - - if (tables_->FindFile(file_proto.name()) != NULL) { - // We've already loaded this file, and it apparently doesn't contain the - // symbol we're looking for. Some DescriptorDatabases return false - // positives. - return false; - } - - if (BuildFileFromDatabase(file_proto) == NULL) { + if (// We skip looking in the fallback database if the name is a sub-symbol + // of any descriptor that already exists in the descriptor pool (except + // for package descriptors). This is valid because all symbols except + // for packages are defined in a single file, so if the symbol exists + // then we should already have its definition. + // + // The other reason to do this is to support "overriding" type + // definitions by merging two databases that define the same type. (Yes, + // people do this.) The main difficulty with making this work is that + // FindFileContainingSymbol() is allowed to return both false positives + // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and false + // negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase). + // When two such databases are merged, looking up a non-existent + // sub-symbol of a type that already exists in the descriptor pool can + // result in an attempt to load multiple definitions of the same type. + // The check below avoids this. + IsSubSymbolOfBuiltType(name) + + // Look up file containing this symbol in fallback database. + || !fallback_database_->FindFileContainingSymbol(name, &file_proto) + + // Check if we've already built this file. If so, it apparently doesn't + // contain the symbol we're looking for. Some DescriptorDatabases + // return false positives. + || tables_->FindFile(file_proto.name()) != NULL + + // Build the file. + || BuildFileFromDatabase(file_proto) == NULL) { + tables_->known_bad_symbols_.insert(name); return false; } @@ -1511,6 +1601,9 @@ void Descriptor::CopyTo(DescriptorProto* proto) const { for (int i = 0; i < field_count(); i++) { field(i)->CopyTo(proto->add_field()); } + for (int i = 0; i < oneof_decl_count(); i++) { + oneof_decl(i)->CopyTo(proto->add_oneof_decl()); + } for (int i = 0; i < nested_type_count(); i++) { nested_type(i)->CopyTo(proto->add_nested_type()); } @@ -1571,11 +1664,19 @@ void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const { proto->set_default_value(DefaultValueAsString(false)); } + if (containing_oneof() != NULL && !is_extension()) { + proto->set_oneof_index(containing_oneof()->index()); + } + if (&options() != &FieldOptions::default_instance()) { proto->mutable_options()->CopyFrom(options()); } } +void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const { + proto->set_name(name()); +} + void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const { proto->set_name(name()); @@ -1679,7 +1780,7 @@ bool RetrieveOptions(int depth, bool FormatBracketedOptions(int depth, const Message &options, string *output) { vector all_options; if (RetrieveOptions(depth, options, &all_options)) { - output->append(JoinStrings(all_options, ", ")); + output->append(Join(all_options, ", ")); } return !all_options.empty(); } @@ -1766,7 +1867,7 @@ string FileDescriptor::DebugString() const { strings::SubstituteAndAppend(&contents, "extend .$0 {\n", containing_type->full_name()); } - extension(i)->DebugString(1, &contents); + extension(i)->DebugString(1, FieldDescriptor::PRINT_LABEL, &contents); } if (extension_count() > 0) contents.append("}\n\n"); @@ -1813,7 +1914,12 @@ void Descriptor::DebugString(int depth, string *contents) const { enum_type(i)->DebugString(depth, contents); } for (int i = 0; i < field_count(); i++) { - field(i)->DebugString(depth, contents); + if (field(i)->containing_oneof() == NULL) { + field(i)->DebugString(depth, FieldDescriptor::PRINT_LABEL, contents); + } else if (field(i)->containing_oneof()->field(0) == field(i)) { + // This is the first field in this oneof, so print the whole oneof. + field(i)->containing_oneof()->DebugString(depth, contents); + } } for (int i = 0; i < extension_range_count(); i++) { @@ -1832,7 +1938,8 @@ void Descriptor::DebugString(int depth, string *contents) const { strings::SubstituteAndAppend(contents, "$0 extend .$1 {\n", prefix, containing_type->full_name()); } - extension(i)->DebugString(depth + 1, contents); + extension(i)->DebugString( + depth + 1, FieldDescriptor::PRINT_LABEL, contents); } if (extension_count() > 0) strings::SubstituteAndAppend(contents, "$0 }\n", prefix); @@ -1848,14 +1955,16 @@ string FieldDescriptor::DebugString() const { containing_type()->full_name()); depth = 1; } - DebugString(depth, &contents); + DebugString(depth, PRINT_LABEL, &contents); if (is_extension()) { - contents.append("}\n"); + contents.append("}\n"); } return contents; } -void FieldDescriptor::DebugString(int depth, string *contents) const { +void FieldDescriptor::DebugString(int depth, + PrintLabelFlag print_label_flag, + string *contents) const { string prefix(depth * 2, ' '); string field_type; switch (type()) { @@ -1869,9 +1978,15 @@ void FieldDescriptor::DebugString(int depth, string *contents) const { field_type = kTypeToName[type()]; } - strings::SubstituteAndAppend(contents, "$0$1 $2 $3 = $4", + string label; + if (print_label_flag == PRINT_LABEL) { + label = kLabelToName[this->label()]; + label.push_back(' '); + } + + strings::SubstituteAndAppend(contents, "$0$1$2 $3 = $4", prefix, - kLabelToName[label()], + label, field_type, type() == TYPE_GROUP ? message_type()->name() : name(), @@ -1902,6 +2017,23 @@ void FieldDescriptor::DebugString(int depth, string *contents) const { } } +string OneofDescriptor::DebugString() const { + string contents; + DebugString(0, &contents); + return contents; +} + +void OneofDescriptor::DebugString(int depth, string* contents) const { + string prefix(depth * 2, ' '); + ++depth; + strings::SubstituteAndAppend( + contents, "$0 oneof $1 {\n", prefix, name()); + for (int i = 0; i < field_count(); i++) { + field(i)->DebugString(depth, FieldDescriptor::OMIT_LABEL, contents); + } + strings::SubstituteAndAppend(contents, "$0}\n", prefix); +} + string EnumDescriptor::DebugString() const { string contents; DebugString(0, &contents); @@ -1984,29 +2116,21 @@ void MethodDescriptor::DebugString(int depth, string *contents) const { // Location methods =============================================== -static bool PathsEqual(const vector& x, const RepeatedField& y) { - if (x.size() != y.size()) return false; - for (int i = 0; i < x.size(); ++i) { - if (x[i] != y.Get(i)) return false; - } - return true; -} - bool FileDescriptor::GetSourceLocation(const vector& path, SourceLocation* out_location) const { GOOGLE_CHECK_NOTNULL(out_location); - const SourceCodeInfo* info = source_code_info_; - for (int i = 0; info && i < info->location_size(); ++i) { - if (PathsEqual(path, info->location(i).path())) { - const RepeatedField& span = info->location(i).span(); + if (source_code_info_) { + if (const SourceCodeInfo_Location* loc = + tables_->GetSourceLocation(path, source_code_info_)) { + const RepeatedField& span = loc->span(); if (span.size() == 3 || span.size() == 4) { out_location->start_line = span.Get(0); out_location->start_column = span.Get(1); out_location->end_line = span.Get(span.size() == 3 ? 0 : 2); out_location->end_column = span.Get(span.size() - 1); - out_location->leading_comments = info->location(i).leading_comments(); - out_location->trailing_comments = info->location(i).trailing_comments(); + out_location->leading_comments = loc->leading_comments(); + out_location->trailing_comments = loc->trailing_comments(); return true; } } @@ -2030,6 +2154,12 @@ bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const { return file()->GetSourceLocation(path, out_location); } +bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const { + vector path; + GetLocationPath(&path); + return containing_type()->file()->GetSourceLocation(path, out_location); +} + bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const { vector path; GetLocationPath(&path); @@ -2067,8 +2197,25 @@ void Descriptor::GetLocationPath(vector* output) const { } void FieldDescriptor::GetLocationPath(vector* output) const { + if (is_extension()) { + if (extension_scope() == NULL) { + output->push_back(FileDescriptorProto::kExtensionFieldNumber); + output->push_back(index()); + } else { + extension_scope()->GetLocationPath(output); + output->push_back(DescriptorProto::kExtensionFieldNumber); + output->push_back(index()); + } + } else { + containing_type()->GetLocationPath(output); + output->push_back(DescriptorProto::kFieldFieldNumber); + output->push_back(index()); + } +} + +void OneofDescriptor::GetLocationPath(vector* output) const { containing_type()->GetLocationPath(output); - output->push_back(DescriptorProto::kFieldFieldNumber); + output->push_back(DescriptorProto::kOneofDeclFieldNumber); output->push_back(index()); } @@ -2154,6 +2301,10 @@ class DescriptorBuilder { FileDescriptorTables* file_tables_; set dependencies_; + // unused_dependency_ is used to record the unused imported files. + // Note: public import is not considered. + set unused_dependency_; + // If LookupSymbol() finds a symbol that is in a file which is not a declared // dependency of this file, it will fail, but will set // possible_undeclared_dependency_ to point at that file. This is only used @@ -2164,10 +2315,22 @@ class DescriptorBuilder { const FileDescriptor* possible_undeclared_dependency_; string possible_undeclared_dependency_name_; + // If LookupSymbol() could resolve a symbol which is not defined, + // record the resolved name. This is only used by AddNotDefinedError() + // to report a more useful error message. + string undefine_resolved_name_; + void AddError(const string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const string& error); + void AddError(const string& element_name, + const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const char* error); + void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here); + void AddTwiceListedError(const FileDescriptorProto& proto, int index); + void AddImportError(const FileDescriptorProto& proto, int index); // Adds an error indicating that undefined_symbol was not defined. Must // only be called after LookupSymbol() fails. @@ -2177,6 +2340,10 @@ class DescriptorBuilder { DescriptorPool::ErrorCollector::ErrorLocation location, const string& undefined_symbol); + void AddWarning(const string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const string& error); + // Silly helper which determines if the given file is in the given package. // I.e., either file->package() == package_name or file->package() is a // nested package within package_name. @@ -2311,6 +2478,9 @@ class DescriptorBuilder { void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto, const Descriptor* parent, Descriptor::ExtensionRange* result); + void BuildOneof(const OneofDescriptorProto& proto, + Descriptor* parent, + OneofDescriptor* result); void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent, EnumDescriptor* result); @@ -2324,6 +2494,8 @@ class DescriptorBuilder { const ServiceDescriptor* parent, MethodDescriptor* result); + void LogUnusedDependency(const FileDescriptor* result); + // Must be run only after building. // // NOTE: Options will not be available during cross-linking, as they @@ -2459,6 +2631,9 @@ class DescriptorBuilder { static inline bool get_allow_unknown(const DescriptorPool* pool) { return pool->allow_unknown_; } + static inline bool get_enforce_weak(const DescriptorPool* pool) { + return pool->enforce_weak_; + } static inline bool get_is_placeholder(const Descriptor* descriptor) { return descriptor->is_placeholder_; } @@ -2501,6 +2676,8 @@ const FileDescriptor* DescriptorPool::BuildFile( "DescriptorDatabase. You must instead find a way to get your file " "into the underlying database."; GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK. + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); return DescriptorBuilder(this, tables_.get(), NULL).BuildFile(proto); } @@ -2512,6 +2689,8 @@ const FileDescriptor* DescriptorPool::BuildFileCollectingErrors( "DescriptorDatabase. You must instead find a way to get your file " "into the underlying database."; GOOGLE_CHECK(mutex_ == NULL); // Implied by the above GOOGLE_CHECK. + tables_->known_bad_symbols_.clear(); + tables_->known_bad_files_.clear(); return DescriptorBuilder(this, tables_.get(), error_collector).BuildFile(proto); } @@ -2519,8 +2698,16 @@ const FileDescriptor* DescriptorPool::BuildFileCollectingErrors( const FileDescriptor* DescriptorPool::BuildFileFromDatabase( const FileDescriptorProto& proto) const { mutex_->AssertHeld(); - return DescriptorBuilder(this, tables_.get(), - default_error_collector_).BuildFile(proto); + if (tables_->known_bad_files_.count(proto.name()) > 0) { + return NULL; + } + const FileDescriptor* result = + DescriptorBuilder(this, tables_.get(), + default_error_collector_).BuildFile(proto); + if (result == NULL) { + tables_->known_bad_files_.insert(proto.name()); + } + return result; } DescriptorBuilder::DescriptorBuilder( @@ -2531,7 +2718,8 @@ DescriptorBuilder::DescriptorBuilder( tables_(tables), error_collector_(error_collector), had_errors_(false), - possible_undeclared_dependency_(NULL) {} + possible_undeclared_dependency_(NULL), + undefine_resolved_name_("") {} DescriptorBuilder::~DescriptorBuilder() {} @@ -2553,21 +2741,53 @@ void DescriptorBuilder::AddError( had_errors_ = true; } +void DescriptorBuilder::AddError( + const string& element_name, + const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const char* error) { + AddError(element_name, descriptor, location, string(error)); +} + void DescriptorBuilder::AddNotDefinedError( const string& element_name, const Message& descriptor, DescriptorPool::ErrorCollector::ErrorLocation location, const string& undefined_symbol) { - if (possible_undeclared_dependency_ == NULL) { + if (possible_undeclared_dependency_ == NULL && + undefine_resolved_name_.empty()) { AddError(element_name, descriptor, location, "\"" + undefined_symbol + "\" is not defined."); } else { - AddError(element_name, descriptor, location, - "\"" + possible_undeclared_dependency_name_ + - "\" seems to be defined in \"" + - possible_undeclared_dependency_->name() + "\", which is not " - "imported by \"" + filename_ + "\". To use it here, please " - "add the necessary import."); + if (possible_undeclared_dependency_ != NULL) { + AddError(element_name, descriptor, location, + "\"" + possible_undeclared_dependency_name_ + + "\" seems to be defined in \"" + + possible_undeclared_dependency_->name() + "\", which is not " + "imported by \"" + filename_ + "\". To use it here, please " + "add the necessary import."); + } + if (!undefine_resolved_name_.empty()) { + AddError(element_name, descriptor, location, + "\"" + undefined_symbol + "\" is resolved to \"" + + undefine_resolved_name_ + "\", which is not defined. " + "The innermost scope is searched first in name resolution. " + "Consider using a leading '.'(i.e., \"." + + undefined_symbol + + "\") to start from the outermost scope."); + } + } +} + +void DescriptorBuilder::AddWarning( + const string& element_name, const Message& descriptor, + DescriptorPool::ErrorCollector::ErrorLocation location, + const string& error) { + if (error_collector_ == NULL) { + GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error; + } else { + error_collector_->AddWarning(filename_, element_name, &descriptor, location, + error); } } @@ -2628,7 +2848,10 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) { // Only find symbols which were defined in this file or one of its // dependencies. const FileDescriptor* file = result.GetFile(); - if (file == file_ || dependencies_.count(file) > 0) return result; + if (file == file_ || dependencies_.count(file) > 0) { + unused_dependency_.erase(file); + return result; + } if (result.type == Symbol::PACKAGE) { // Arg, this is overcomplicated. The symbol is a package name. It could @@ -2654,6 +2877,7 @@ Symbol DescriptorBuilder::FindSymbol(const string& name) { Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( const string& name, const string& relative_to, ResolveMode resolve_mode) { possible_undeclared_dependency_ = NULL; + undefine_resolved_name_.clear(); if (name.size() > 0 && name[0] == '.') { // Fully-qualified name. @@ -2702,7 +2926,11 @@ Symbol DescriptorBuilder::LookupSymbolNoPlaceholder( if (result.IsAggregate()) { scope_to_try.append(name, first_part_of_name.size(), name.size() - first_part_of_name.size()); - return FindSymbol(scope_to_try); + result = FindSymbol(scope_to_try); + if (result.IsNull()) { + undefine_resolved_name_ = scope_to_try; + } + return result; } else { // We found a symbol but it's not an aggregate. Continue the loop. } @@ -2755,7 +2983,7 @@ Symbol DescriptorBuilder::NewPlaceholder(const string& name, placeholder_name = tables_->AllocateString( placeholder_full_name->substr(dotpos + 1)); } else { - placeholder_package = &::google::protobuf::internal::GetEmptyString(); + placeholder_package = &internal::GetEmptyString(); placeholder_name = placeholder_full_name; } @@ -2771,6 +2999,7 @@ Symbol DescriptorBuilder::NewPlaceholder(const string& name, placeholder_file->pool_ = pool_; placeholder_file->options_ = &FileOptions::default_instance(); placeholder_file->tables_ = &FileDescriptorTables::kEmpty; + placeholder_file->is_placeholder_ = true; // All other fields are zero or NULL. if (placeholder_type == PLACEHOLDER_ENUM) { @@ -2841,10 +3070,11 @@ const FileDescriptor* DescriptorBuilder::NewPlaceholderFile( memset(placeholder, 0, sizeof(*placeholder)); placeholder->name_ = tables_->AllocateString(name); - placeholder->package_ = &::google::protobuf::internal::GetEmptyString(); + placeholder->package_ = &internal::GetEmptyString(); placeholder->pool_ = pool_; placeholder->options_ = &FileOptions::default_instance(); placeholder->tables_ = &FileDescriptorTables::kEmpty; + placeholder->is_placeholder_ = true; // All other fields are zero or NULL. return placeholder; @@ -3015,6 +3245,45 @@ template void DescriptorBuilder::AllocateOptionsImpl( METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \ } +void DescriptorBuilder::AddRecursiveImportError( + const FileDescriptorProto& proto, int from_here) { + string error_message("File recursively imports itself: "); + for (int i = from_here; i < tables_->pending_files_.size(); i++) { + error_message.append(tables_->pending_files_[i]); + error_message.append(" -> "); + } + error_message.append(proto.name()); + + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + error_message); +} + +void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto, + int index) { + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, + "Import \"" + proto.dependency(index) + "\" was listed twice."); +} + +void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto, + int index) { + string message; + if (pool_->fallback_database_ == NULL) { + message = "Import \"" + proto.dependency(index) + + "\" has not been loaded."; + } else { + message = "Import \"" + proto.dependency(index) + + "\" was not found or had errors."; + } + AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, message); +} + +static bool ExistingFileMatchesProto(const FileDescriptor* existing_file, + const FileDescriptorProto& proto) { + FileDescriptorProto existing_proto; + existing_file->CopyTo(&existing_proto); + return existing_proto.SerializeAsString() == proto.SerializeAsString(); +} + const FileDescriptor* DescriptorBuilder::BuildFile( const FileDescriptorProto& proto) { filename_ = proto.name(); @@ -3027,9 +3296,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile( const FileDescriptor* existing_file = tables_->FindFile(filename_); if (existing_file != NULL) { // File already in pool. Compare the existing one to the input. - FileDescriptorProto existing_proto; - existing_file->CopyTo(&existing_proto); - if (existing_proto.SerializeAsString() == proto.SerializeAsString()) { + if (ExistingFileMatchesProto(existing_file, proto)) { // They're identical. Return the existing descriptor. return existing_file; } @@ -3048,15 +3315,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile( // at all. for (int i = 0; i < tables_->pending_files_.size(); i++) { if (tables_->pending_files_[i] == proto.name()) { - string error_message("File recursively imports itself: "); - for (; i < tables_->pending_files_.size(); i++) { - error_message.append(tables_->pending_files_[i]); - error_message.append(" -> "); - } - error_message.append(proto.name()); - - AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, - error_message); + AddRecursiveImportError(proto, i); return NULL; } } @@ -3083,6 +3342,7 @@ const FileDescriptor* DescriptorBuilder::BuildFile( FileDescriptor* result = tables_->Allocate(); file_ = result; + result->is_placeholder_ = false; if (proto.has_source_code_info()) { SourceCodeInfo *info = tables_->AllocateMessage(); info->CopyFrom(proto.source_code_info()); @@ -3129,11 +3389,14 @@ const FileDescriptor* DescriptorBuilder::BuildFile( result->dependency_count_ = proto.dependency_size(); result->dependencies_ = tables_->AllocateArray(proto.dependency_size()); + unused_dependency_.clear(); + set weak_deps; + for (int i = 0; i < proto.weak_dependency_size(); ++i) { + weak_deps.insert(proto.weak_dependency(i)); + } for (int i = 0; i < proto.dependency_size(); i++) { if (!seen_dependencies.insert(proto.dependency(i)).second) { - AddError(proto.name(), proto, - DescriptorPool::ErrorCollector::OTHER, - "Import \"" + proto.dependency(i) + "\" was listed twice."); + AddTwiceListedError(proto, i); } const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i)); @@ -3142,20 +3405,20 @@ const FileDescriptor* DescriptorBuilder::BuildFile( } if (dependency == NULL) { - if (pool_->allow_unknown_) { + if (pool_->allow_unknown_ || + (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) { dependency = NewPlaceholderFile(proto.dependency(i)); } else { - string message; - if (pool_->fallback_database_ == NULL) { - message = "Import \"" + proto.dependency(i) + - "\" has not been loaded."; - } else { - message = "Import \"" + proto.dependency(i) + - "\" was not found or had errors."; - } - AddError(proto.name(), proto, - DescriptorPool::ErrorCollector::OTHER, - message); + AddImportError(proto, i); + } + } else { + // Add to unused_dependency_ to track unused imported files. + // Note: do not track unused imported files for public import. + if (pool_->enforce_dependencies_ && + (pool_->unused_import_track_files_.find(proto.name()) != + pool_->unused_import_track_files_.end()) && + (dependency->public_dependency_count() == 0)) { + unused_dependency_.insert(dependency); } } @@ -3171,6 +3434,8 @@ const FileDescriptor* DescriptorBuilder::BuildFile( int index = proto.public_dependency(i); if (index >= 0 && index < proto.dependency_size()) { result->public_dependencies_[public_dependency_count++] = index; + // Do not track unused imported files for public import. + unused_dependency_.erase(result->dependency(index)); } else { AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER, @@ -3237,6 +3502,11 @@ const FileDescriptor* DescriptorBuilder::BuildFile( ValidateFileOptions(result, proto); } + + if (!unused_dependency_.empty()) { + LogUnusedDependency(result); + } + if (had_errors_) { tables_->RollbackToLastCheckpoint(); return NULL; @@ -3264,6 +3534,8 @@ void DescriptorBuilder::BuildMessage(const DescriptorProto& proto, result->is_placeholder_ = false; result->is_unqualified_placeholder_ = false; + // Build oneofs first so that fields and extension ranges can refer to them. + BUILD_ARRAY(proto, result, oneof_decl , BuildOneof , result); BUILD_ARRAY(proto, result, field , BuildField , result); BUILD_ARRAY(proto, result, nested_type , BuildMessage , result); BUILD_ARRAY(proto, result, enum_type , BuildEnum , result); @@ -3354,6 +3626,19 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->label_ = static_cast( implicit_cast(proto.label())); + // An extension cannot have a required field (b/13365836). + if (result->is_extension_ && + result->label_ == FieldDescriptor::LABEL_REQUIRED) { + AddError(result->full_name(), proto, + // Error location `TYPE`: we would really like to indicate + // `LABEL`, but the `ErrorLocation` enum has no entry for this, and + // we don't necessarily know about all implementations of the + // `ErrorCollector` interface to extend them to handle the new + // error location type properly. + DescriptorPool::ErrorCollector::TYPE, + "Message extensions cannot have required fields."); + } + // Some of these may be filled in when cross-linking. result->containing_type_ = NULL; result->extension_scope_ = NULL; @@ -3397,7 +3682,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->default_value_float_ = numeric_limits::quiet_NaN(); } else { result->default_value_float_ = - NoLocaleStrtod(proto.default_value().c_str(), &end_pos); + io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos); } break; case FieldDescriptor::CPPTYPE_DOUBLE: @@ -3409,7 +3694,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->default_value_double_ = numeric_limits::quiet_NaN(); } else { result->default_value_double_ = - NoLocaleStrtod(proto.default_value().c_str(), &end_pos); + io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos); } break; case FieldDescriptor::CPPTYPE_BOOL: @@ -3451,7 +3736,8 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, if (proto.default_value().empty() || *end_pos != '\0') { AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::DEFAULT_VALUE, - "Couldn't parse default value."); + "Couldn't parse default value \"" + proto.default_value() + + "\"."); } } } else { @@ -3483,7 +3769,7 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, result->default_value_enum_ = NULL; break; case FieldDescriptor::CPPTYPE_STRING: - result->default_value_string_ = &::google::protobuf::internal::GetEmptyString(); + result->default_value_string_ = &internal::GetEmptyString(); break; case FieldDescriptor::CPPTYPE_MESSAGE: break; @@ -3524,6 +3810,16 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, } result->extension_scope_ = parent; + + if (proto.has_oneof_index()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::OTHER, + "FieldDescriptorProto.oneof_index should not be set for " + "extensions."); + } + + // Fill in later (maybe). + result->containing_oneof_ = NULL; } else { if (proto.has_extendee()) { AddError(result->full_name(), proto, @@ -3532,6 +3828,23 @@ void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto, } result->containing_type_ = parent; + + if (proto.has_oneof_index()) { + if (proto.oneof_index() < 0 || + proto.oneof_index() >= parent->oneof_decl_count()) { + AddError(result->full_name(), proto, + DescriptorPool::ErrorCollector::OTHER, + strings::Substitute("FieldDescriptorProto.oneof_index $0 is " + "out of range for type \"$1\".", + proto.oneof_index(), + parent->name())); + result->containing_oneof_ = NULL; + } else { + result->containing_oneof_ = parent->oneof_decl(proto.oneof_index()); + } + } else { + result->containing_oneof_ = NULL; + } } // Copy options. @@ -3569,6 +3882,28 @@ void DescriptorBuilder::BuildExtensionRange( } } +void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto, + Descriptor* parent, + OneofDescriptor* result) { + string* full_name = tables_->AllocateString(parent->full_name()); + full_name->append(1, '.'); + full_name->append(proto.name()); + + ValidateSymbolName(proto.name(), *full_name, proto); + + result->name_ = tables_->AllocateString(proto.name()); + result->full_name_ = full_name; + + result->containing_type_ = parent; + + // We need to fill these in later. + result->field_count_ = 0; + result->fields_ = NULL; + + AddSymbol(result->full_name(), parent, result->name(), + proto, Symbol(result)); +} + void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent, EnumDescriptor* result) { @@ -3778,6 +4113,46 @@ void DescriptorBuilder::CrossLinkMessage( for (int i = 0; i < message->extension_count(); i++) { CrossLinkField(&message->extensions_[i], proto.extension(i)); } + + // Set up field array for each oneof. + + // First count the number of fields per oneof. + for (int i = 0; i < message->field_count(); i++) { + const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof(); + if (oneof_decl != NULL) { + // Must go through oneof_decls_ array to get a non-const version of the + // OneofDescriptor. + ++message->oneof_decls_[oneof_decl->index()].field_count_; + } + } + + // Then allocate the arrays. + for (int i = 0; i < message->oneof_decl_count(); i++) { + OneofDescriptor* oneof_decl = &message->oneof_decls_[i]; + + if (oneof_decl->field_count() == 0) { + AddError(message->full_name() + "." + oneof_decl->name(), + proto.oneof_decl(i), + DescriptorPool::ErrorCollector::NAME, + "Oneof must have at least one field."); + } + + oneof_decl->fields_ = + tables_->AllocateArray(oneof_decl->field_count_); + oneof_decl->field_count_ = 0; + } + + // Then fill them in. + for (int i = 0; i < message->field_count(); i++) { + const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof(); + if (oneof_decl != NULL) { + OneofDescriptor* mutable_oneof_decl = + &message->oneof_decls_[oneof_decl->index()]; + message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_; + mutable_oneof_decl->fields_[mutable_oneof_decl->field_count_++] = + message->field(i); + } + } } void DescriptorBuilder::CrossLinkField( @@ -3802,7 +4177,10 @@ void DescriptorBuilder::CrossLinkField( } field->containing_type_ = extendee.descriptor; - if (!field->containing_type()->IsExtensionNumber(field->number())) { + const Descriptor::ExtensionRange* extension_range = field->containing_type() + ->FindExtensionRangeContainingNumber(field->number()); + + if (extension_range == NULL) { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER, strings::Substitute("\"$0\" does not declare $1 as an " @@ -3812,6 +4190,17 @@ void DescriptorBuilder::CrossLinkField( } } + if (field->containing_oneof() != NULL) { + if (field->label() != FieldDescriptor::LABEL_OPTIONAL) { + // Note that this error will never happen when parsing .proto files. + // It can only happen if you manually construct a FileDescriptorProto + // that is incorrect. + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::NAME, + "Fields of oneofs must themselves have label LABEL_OPTIONAL."); + } + } + if (proto.has_type_name()) { // Assume we are expecting a message type unless the proto contains some // evidence that it expects an enum type. This only makes a difference if @@ -3824,6 +4213,11 @@ void DescriptorBuilder::CrossLinkField( expecting_enum ? PLACEHOLDER_ENUM : PLACEHOLDER_MESSAGE, LOOKUP_TYPES); + // If the type is a weak type, we change the type to a google.protobuf.Empty field. + if (type.IsNull() && !pool_->enforce_weak_ && proto.options().weak()) { + type = FindSymbol(kNonLinkedWeakMessageReplacementName); + } + if (type.IsNull()) { AddNotDefinedError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE, @@ -3875,21 +4269,34 @@ void DescriptorBuilder::CrossLinkField( } if (field->has_default_value()) { - // We can't just use field->enum_type()->FindValueByName() here - // because that locks the pool's mutex, which we have already locked - // at this point. - Symbol default_value = - LookupSymbolNoPlaceholder(proto.default_value(), - field->enum_type()->full_name()); - - if (default_value.type == Symbol::ENUM_VALUE && - default_value.enum_value_descriptor->type() == field->enum_type()) { - field->default_value_enum_ = default_value.enum_value_descriptor; - } else { + // Ensure that the default value is an identifier. Parser cannot always + // verify this because it does not have complete type information. + // N.B. that this check yields better error messages but is not + // necessary for correctness (an enum symbol must be a valid identifier + // anyway), only for better errors. + if (!io::Tokenizer::IsIdentifier(proto.default_value())) { AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::DEFAULT_VALUE, - "Enum type \"" + field->enum_type()->full_name() + - "\" has no value named \"" + proto.default_value() + "\"."); + "Default value for an enum field must be an identifier."); + } else { + // We can't just use field->enum_type()->FindValueByName() here + // because that locks the pool's mutex, which we have already locked + // at this point. + Symbol default_value = + LookupSymbolNoPlaceholder(proto.default_value(), + field->enum_type()->full_name()); + + if (default_value.type == Symbol::ENUM_VALUE && + default_value.enum_value_descriptor->type() == + field->enum_type()) { + field->default_value_enum_ = default_value.enum_value_descriptor; + } else { + AddError(field->full_name(), proto, + DescriptorPool::ErrorCollector::DEFAULT_VALUE, + "Enum type \"" + field->enum_type()->full_name() + + "\" has no value named \"" + proto.default_value() + + "\"."); + } } } else if (field->enum_type()->value_count() > 0) { // All enums must have at least one value, or we would have reported @@ -3933,12 +4340,26 @@ void DescriptorBuilder::CrossLinkField( field->containing_type()->full_name(), conflicting_field->name())); } - } - - if (field->is_extension()) { - // No need for error checking: if the extension number collided, - // we've already been informed of it by the if() above. - tables_->AddExtension(field); + } else { + if (field->is_extension()) { + if (!tables_->AddExtension(field)) { + const FieldDescriptor* conflicting_field = + tables_->FindExtension(field->containing_type(), field->number()); + string error_msg = strings::Substitute( + "Extension number $0 has already been used in \"$1\" by extension " + "\"$2\" defined in $3.", + field->number(), + field->containing_type()->full_name(), + conflicting_field->full_name(), + conflicting_field->file()->name()); + // Conflicting extension numbers should be an error. However, before + // turning this into an error we need to fix all existing broken + // protos first. + // TODO(xiaofeng): Change this to an error. + AddWarning(field->full_name(), proto, + DescriptorPool::ErrorCollector::NUMBER, error_msg); + } + } } // Add the field to the lowercase-name and camelcase-name tables. @@ -4022,7 +4443,6 @@ static bool IsLite(const FileDescriptor* file) { // TODO(kenton): I don't even remember how many of these conditions are // actually possible. I'm just being super-safe. return file != NULL && - &file->options() != NULL && &file->options() != &FileOptions::default_instance() && file->options().optimize_for() == FileOptions::LITE_RUNTIME; } @@ -4050,6 +4470,7 @@ void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file, } } + void DescriptorBuilder::ValidateMessageOptions(Descriptor* message, const DescriptorProto& proto) { VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field); @@ -4388,6 +4809,15 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // so we will just leave it as uninterpreted. AddWithoutInterpreting(*uninterpreted_option_, options); return true; + } else if (!(builder_->undefine_resolved_name_).empty()) { + // Option is resolved to a name which is not defined. + return AddNameError( + "Option \"" + debug_msg_name + "\" is resolved to \"(" + + builder_->undefine_resolved_name_ + + ")\", which is not defined. The innermost scope is searched first " + "in name resolution. Consider using a leading '.'(i.e., \"(." + + debug_msg_name.substr(1) + + "\") to start from the outermost scope."); } else { return AddNameError("Option \"" + debug_msg_name + "\" unknown."); } @@ -4408,14 +4838,15 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( "\" is not a field or extension of message \"" + descriptor->name() + "\"."); } - } else if (field->is_repeated()) { - return AddNameError("Option field \"" + debug_msg_name + - "\" is repeated. Repeated options are not " - "supported."); } else if (i < uninterpreted_option_->name_size() - 1) { if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) { return AddNameError("Option \"" + debug_msg_name + "\" is an atomic type, not a message."); + } else if (field->is_repeated()) { + return AddNameError("Option field \"" + debug_msg_name + + "\" is a repeated message. Repeated message " + "options must be initialized using an " + "aggregate value."); } else { // Drill down into the submessage. intermediate_fields.push_back(field); @@ -4432,7 +4863,7 @@ bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption( // known will populate them correctly. // First see if the option is already set. - if (!ExamineIfOptionIsSet( + if (!field->is_repeated() && !ExamineIfOptionIsSet( intermediate_fields.begin(), intermediate_fields.end(), field, debug_msg_name, @@ -4947,5 +5378,39 @@ void DescriptorBuilder::OptionInterpreter::SetUInt64(int number, uint64 value, } } +void DescriptorBuilder::LogUnusedDependency(const FileDescriptor* result) { + + if (!unused_dependency_.empty()) { + std::set annotation_extensions; + annotation_extensions.insert("google.protobuf.MessageOptions"); + annotation_extensions.insert("google.protobuf.FileOptions"); + annotation_extensions.insert("google.protobuf.FieldOptions"); + annotation_extensions.insert("google.protobuf.EnumOptions"); + annotation_extensions.insert("google.protobuf.EnumValueOptions"); + annotation_extensions.insert("google.protobuf.ServiceOptions"); + annotation_extensions.insert("google.protobuf.MethodOptions"); + annotation_extensions.insert("google.protobuf.StreamOptions"); + for (set::const_iterator + it = unused_dependency_.begin(); + it != unused_dependency_.end(); ++it) { + // Do not log warnings for proto files which extend annotations. + int i; + for (i = 0 ; i < (*it)->extension_count(); ++i) { + if (annotation_extensions.find( + (*it)->extension(i)->containing_type()->full_name()) + != annotation_extensions.end()) { + break; + } + } + // Log warnings for unused imported files. + if (i == (*it)->extension_count()) { + GOOGLE_LOG(WARNING) << "Warning: Unused import: \"" << result->name() + << "\" imports \"" << (*it)->name() + << "\" which is not used."; + } + } + } +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h index 33e3af72..93fd4339 100644 --- a/src/google/protobuf/descriptor.h +++ b/src/google/protobuf/descriptor.h @@ -54,14 +54,11 @@ #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__ #define GOOGLE_PROTOBUF_DESCRIPTOR_H__ +#include #include #include #include -// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h. -#ifdef TYPE_BOOL -#undef TYPE_BOOL -#endif // TYPE_BOOL namespace google { namespace protobuf { @@ -69,6 +66,7 @@ namespace protobuf { // Defined in this file. class Descriptor; class FieldDescriptor; +class OneofDescriptor; class EnumDescriptor; class EnumValueDescriptor; class ServiceDescriptor; @@ -80,6 +78,7 @@ class DescriptorPool; // Defined in descriptor.proto class DescriptorProto; class FieldDescriptorProto; +class OneofDescriptorProto; class EnumDescriptorProto; class EnumValueDescriptorProto; class ServiceDescriptorProto; @@ -163,6 +162,11 @@ class LIBPROTOBUF_EXPORT Descriptor { // will be suitable for re-parsing. string DebugString() const; + // Returns true if this is a placeholder for an unknown type. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + // Field stuff ----------------------------------------------------- // The number of fields in this message type. @@ -190,6 +194,15 @@ class LIBPROTOBUF_EXPORT Descriptor { const FieldDescriptor* FindFieldByCamelcaseName( const string& camelcase_name) const; + // The number of oneofs in this message type. + int oneof_decl_count() const; + // Get a oneof by index, where 0 <= index < oneof_decl_count(). + // These are returned in the order they were defined in the .proto file. + const OneofDescriptor* oneof_decl(int index) const; + + // Looks up a oneof by name. Returns NULL if no such oneof exists. + const OneofDescriptor* FindOneofByName(const string& name) const; + // Nested type stuff ----------------------------------------------- // The number of nested types in this message type. @@ -236,6 +249,9 @@ class LIBPROTOBUF_EXPORT Descriptor { // Returns true if the number is in one of the extension ranges. bool IsExtensionNumber(int number) const; + // Returns NULL if no extension range contains the given number. + const ExtensionRange* FindExtensionRangeContainingNumber(int number) const; + // The number of extensions -- extending *other* messages -- that were // defined nested within this message type's scope. int extension_count() const; @@ -286,6 +302,8 @@ class LIBPROTOBUF_EXPORT Descriptor { int field_count_; FieldDescriptor* fields_; + int oneof_decl_count_; + OneofDescriptor* oneof_decls_; int nested_type_count_; Descriptor* nested_types_; int enum_type_count_; @@ -303,6 +321,7 @@ class LIBPROTOBUF_EXPORT Descriptor { friend class DescriptorBuilder; friend class EnumDescriptor; friend class FieldDescriptor; + friend class OneofDescriptor; friend class MethodDescriptor; friend class FileDescriptor; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Descriptor); @@ -473,6 +492,13 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // this is the extended type. Never NULL. const Descriptor* containing_type() const; + // If the field is a member of a oneof, this is the one, otherwise this is + // NULL. + const OneofDescriptor* containing_oneof() const; + + // If the field is a member of a oneof, returns the index in that oneof. + int index_in_oneof() const; + // An extension may be declared within the scope of another message. If this // field is an extension (is_extension() is true), then extension_scope() // returns that message, or NULL if the extension was declared at global @@ -481,10 +507,10 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { const Descriptor* extension_scope() const; // If type is TYPE_MESSAGE or TYPE_GROUP, returns a descriptor for the - // message or the group type. Otherwise, undefined. + // message or the group type. Otherwise, returns null. const Descriptor* message_type() const; // If type is TYPE_ENUM, returns a descriptor for the enum. Otherwise, - // undefined. + // returns null. const EnumDescriptor* enum_type() const; // EXPERIMENTAL; DO NOT USE. @@ -510,6 +536,12 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { // Helper method to get the CppType for a particular Type. static CppType TypeToCppType(Type type); + // Helper method to get the name of a Type. + static const char* TypeName(Type type); + + // Helper method to get the name of a CppType. + static const char* CppTypeName(CppType cpp_type); + // Return true iff [packed = true] is valid for fields of this type. static inline bool IsTypePackable(Type field_type); @@ -524,7 +556,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { typedef FieldOptions OptionsType; // See Descriptor::DebugString(). - void DebugString(int depth, string *contents) const; + enum PrintLabelFlag { PRINT_LABEL, OMIT_LABEL }; + void DebugString(int depth, PrintLabelFlag print_label_flag, + string* contents) const; // formats the default value appropriately and returns it as a string. // Must have a default value to call this. If quote_string_type is true, then @@ -544,7 +578,9 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { Type type_; Label label_; bool is_extension_; + int index_in_oneof_; const Descriptor* containing_type_; + const OneofDescriptor* containing_oneof_; const Descriptor* extension_scope_; const Descriptor* message_type_; const EnumDescriptor* enum_type_; @@ -581,9 +617,66 @@ class LIBPROTOBUF_EXPORT FieldDescriptor { friend class DescriptorBuilder; friend class FileDescriptor; friend class Descriptor; + friend class OneofDescriptor; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldDescriptor); }; +// Describes a oneof defined in a message type. +class LIBPROTOBUF_EXPORT OneofDescriptor { + public: + const string& name() const; // Name of this oneof. + const string& full_name() const; // Fully-qualified name of the oneof. + + // Index of this oneof within the message's oneof array. + int index() const; + + // The Descriptor for the message containing this oneof. + const Descriptor* containing_type() const; + + // The number of (non-extension) fields which are members of this oneof. + int field_count() const; + // Get a member of this oneof, in the order in which they were declared in the + // .proto file. Does not include extensions. + const FieldDescriptor* field(int index) const; + + // See Descriptor::CopyTo(). + void CopyTo(OneofDescriptorProto* proto) const; + + // See Descriptor::DebugString(). + string DebugString() const; + + // Source Location --------------------------------------------------- + + // Updates |*out_location| to the source location of the complete + // extent of this oneof declaration. Returns false and leaves + // |*out_location| unchanged iff location information was not available. + bool GetSourceLocation(SourceLocation* out_location) const; + + private: + // See Descriptor::DebugString(). + void DebugString(int depth, string* contents) const; + + // Walks up the descriptor tree to generate the source location path + // to this descriptor from the file root. + void GetLocationPath(vector* output) const; + + const string* name_; + const string* full_name_; + const Descriptor* containing_type_; + bool is_extendable_; + int field_count_; + const FieldDescriptor** fields_; + // IMPORTANT: If you add a new field, make sure to search for all instances + // of Allocate() and AllocateArray() + // in descriptor.cc and update them to initialize the field. + + // Must be constructed using DescriptorPool. + OneofDescriptor() {} + friend class DescriptorBuilder; + friend class Descriptor; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofDescriptor); +}; + // Describes an enum type defined in a .proto file. To get the EnumDescriptor // for a generated enum type, call TypeName_descriptor(). Use DescriptorPool // to construct your own descriptors. @@ -630,6 +723,11 @@ class LIBPROTOBUF_EXPORT EnumDescriptor { // See Descriptor::DebugString(). string DebugString() const; + // Returns true if this is a placeholder for an unknown enum. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + // Source Location --------------------------------------------------- // Updates |*out_location| to the source location of the complete @@ -984,6 +1082,11 @@ class LIBPROTOBUF_EXPORT FileDescriptor { // See Descriptor::DebugString(). string DebugString() const; + // Returns true if this is a placeholder for an unknown file. This will + // only be the case if this descriptor comes from a DescriptorPool + // with AllowUnknownDependencies() set. + bool is_placeholder() const; + private: // Source Location --------------------------------------------------- @@ -1013,6 +1116,7 @@ class LIBPROTOBUF_EXPORT FileDescriptor { int service_count_; ServiceDescriptor* services_; int extension_count_; + bool is_placeholder_; FieldDescriptor* extensions_; const FileOptions* options_; @@ -1026,6 +1130,7 @@ class LIBPROTOBUF_EXPORT FileDescriptor { friend class DescriptorBuilder; friend class Descriptor; friend class FieldDescriptor; + friend class OneofDescriptor; friend class EnumDescriptor; friend class EnumValueDescriptor; friend class MethodDescriptor; @@ -1083,6 +1188,10 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // to GOOGLE_LOG(ERROR). Remember that files are built on-demand, so this // ErrorCollector may be called from any thread that calls one of the // Find*By*() methods. + // - The DescriptorDatabase must not be mutated during the lifetime of + // the DescriptorPool. Even if the client takes care to avoid data races, + // changes to the content of the DescriptorDatabase may not be reflected + // in subsequent lookups in the DescriptorPool. class ErrorCollector; explicit DescriptorPool(DescriptorDatabase* fallback_database, ErrorCollector* error_collector = NULL); @@ -1113,6 +1222,7 @@ class LIBPROTOBUF_EXPORT DescriptorPool { const Descriptor* FindMessageTypeByName(const string& name) const; const FieldDescriptor* FindFieldByName(const string& name) const; const FieldDescriptor* FindExtensionByName(const string& name) const; + const OneofDescriptor* FindOneofByName(const string& name) const; const EnumDescriptor* FindEnumTypeByName(const string& name) const; const EnumValueDescriptor* FindEnumValueByName(const string& name) const; const ServiceDescriptor* FindServiceByName(const string& name) const; @@ -1157,7 +1267,8 @@ class LIBPROTOBUF_EXPORT DescriptorPool { OTHER // some other problem }; - // Reports an error in the FileDescriptorProto. + // Reports an error in the FileDescriptorProto. Use this function if the + // problem occured should interrupt building the FileDescriptorProto. virtual void AddError( const string& filename, // File name in which the error occurred. const string& element_name, // Full name of the erroneous element. @@ -1166,6 +1277,16 @@ class LIBPROTOBUF_EXPORT DescriptorPool { const string& message // Human-readable error message. ) = 0; + // Reports a warning in the FileDescriptorProto. Use this function if the + // problem occured should NOT interrupt building the FileDescriptorProto. + virtual void AddWarning( + const string& filename, // File name in which the error occurred. + const string& element_name, // Full name of the erroneous element. + const Message* descriptor, // Descriptor of the erroneous element. + ErrorLocation location, // One of the location constants, above. + const string& message // Human-readable error message. + ) {} + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector); }; @@ -1186,7 +1307,8 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // to types or other files that are not found in the DescriptorPool (or its // backing DescriptorDatabase, if any). If you call // AllowUnknownDependencies(), however, then unknown types and files - // will be replaced by placeholder descriptors. This can allow you to + // will be replaced by placeholder descriptors (which can be identified by + // the is_placeholder() method). This can allow you to // perform some useful operations with a .proto file even if you do not // have access to other .proto files on which it depends. However, some // heuristics must be used to fill in the gaps in information, and these @@ -1195,10 +1317,15 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // or an enum, as well as what package it resides in. Furthermore, // placeholder types will not be discoverable via FindMessageTypeByName() // and similar methods, which could confuse some descriptor-based algorithms. - // Generally, the results of this option should only be relied upon for - // debugging purposes. + // Generally, the results of this option should be handled with extreme care. void AllowUnknownDependencies() { allow_unknown_ = true; } + // By default, weak imports are allowed to be missing, in which case we will + // use a placeholder for the dependency and convert the field to be an Empty + // message field. If you call EnforceWeakDependencies(true), however, the + // DescriptorPool will report a import not found error. + void EnforceWeakDependencies(bool enforce) { enforce_weak_ = enforce; } + // Internal stuff -------------------------------------------------- // These methods MUST NOT be called from outside the proto2 library. // These methods may contain hidden pitfalls and may be removed in a @@ -1254,6 +1381,12 @@ class LIBPROTOBUF_EXPORT DescriptorPool { // lazy descriptor initialization behavior. bool InternalIsFileLoaded(const string& filename) const; + + // Add a file to unused_import_track_files_. DescriptorBuilder will log + // warnings for those files if there is any unused import. + void AddUnusedImportTrackFile(const string& file_name); + void ClearUnusedImportTrackFiles(); + private: friend class Descriptor; friend class FieldDescriptor; @@ -1298,6 +1431,8 @@ class LIBPROTOBUF_EXPORT DescriptorPool { bool enforce_dependencies_; bool allow_unknown_; + bool enforce_weak_; + std::set unused_import_track_files_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool); }; @@ -1325,10 +1460,12 @@ PROTOBUF_DEFINE_ACCESSOR(Descriptor, file, const FileDescriptor*) PROTOBUF_DEFINE_ACCESSOR(Descriptor, containing_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(Descriptor, field_count, int) +PROTOBUF_DEFINE_ACCESSOR(Descriptor, oneof_decl_count, int) PROTOBUF_DEFINE_ACCESSOR(Descriptor, nested_type_count, int) PROTOBUF_DEFINE_ACCESSOR(Descriptor, enum_type_count, int) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, field, const FieldDescriptor*) +PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, oneof_decl, const OneofDescriptor*) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, nested_type, const Descriptor*) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, enum_type, const EnumDescriptor*) @@ -1338,7 +1475,8 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension_range, const Descriptor::ExtensionRange*) PROTOBUF_DEFINE_ARRAY_ACCESSOR(Descriptor, extension, const FieldDescriptor*) -PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(Descriptor, MessageOptions); +PROTOBUF_DEFINE_ACCESSOR(Descriptor, is_placeholder, bool) PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, full_name) @@ -1350,6 +1488,9 @@ PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, is_extension, bool) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, type, FieldDescriptor::Type) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, label, FieldDescriptor::Label) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, containing_oneof, + const OneofDescriptor*) +PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, index_in_oneof, int) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, extension_scope, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, message_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, enum_type, const EnumDescriptor*) @@ -1368,6 +1509,11 @@ PROTOBUF_DEFINE_ACCESSOR(FieldDescriptor, default_value_enum, const EnumValueDescriptor*) PROTOBUF_DEFINE_STRING_ACCESSOR(FieldDescriptor, default_value_string) +PROTOBUF_DEFINE_STRING_ACCESSOR(OneofDescriptor, name) +PROTOBUF_DEFINE_STRING_ACCESSOR(OneofDescriptor, full_name) +PROTOBUF_DEFINE_ACCESSOR(OneofDescriptor, containing_type, const Descriptor*) +PROTOBUF_DEFINE_ACCESSOR(OneofDescriptor, field_count, int) + PROTOBUF_DEFINE_STRING_ACCESSOR(EnumDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(EnumDescriptor, full_name) PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, file, const FileDescriptor*) @@ -1375,7 +1521,8 @@ PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, containing_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, value_count, int) PROTOBUF_DEFINE_ARRAY_ACCESSOR(EnumDescriptor, value, const EnumValueDescriptor*) -PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(EnumDescriptor, EnumOptions); +PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, is_placeholder, bool) PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(EnumValueDescriptor, full_name) @@ -1389,14 +1536,14 @@ PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, file, const FileDescriptor*) PROTOBUF_DEFINE_ACCESSOR(ServiceDescriptor, method_count, int) PROTOBUF_DEFINE_ARRAY_ACCESSOR(ServiceDescriptor, method, const MethodDescriptor*) -PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(ServiceDescriptor, ServiceOptions); PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(MethodDescriptor, full_name) PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, service, const ServiceDescriptor*) PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, input_type, const Descriptor*) PROTOBUF_DEFINE_ACCESSOR(MethodDescriptor, output_type, const Descriptor*) -PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(MethodDescriptor, MethodOptions); PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, name) PROTOBUF_DEFINE_STRING_ACCESSOR(FileDescriptor, package) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, pool, const DescriptorPool*) @@ -1407,7 +1554,8 @@ PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, message_type_count, int) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, enum_type_count, int) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, service_count, int) PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, extension_count, int) -PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FileDescriptor, FileOptions) +PROTOBUF_DEFINE_OPTIONS_ACCESSOR(FileDescriptor, FileOptions); +PROTOBUF_DEFINE_ACCESSOR(FileDescriptor, is_placeholder, bool) PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, message_type, const Descriptor*) PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, enum_type, const EnumDescriptor*) @@ -1422,6 +1570,10 @@ PROTOBUF_DEFINE_ARRAY_ACCESSOR(FileDescriptor, extension, // A few accessors differ from the macros... +inline bool Descriptor::IsExtensionNumber(int number) const { + return FindExtensionRangeContainingNumber(number) != NULL; +} + inline bool FieldDescriptor::is_required() const { return label() == LABEL_REQUIRED; } @@ -1458,6 +1610,10 @@ inline int Descriptor::index() const { } } +inline int OneofDescriptor::index() const { + return this - containing_type_->oneof_decls_; +} + inline int EnumDescriptor::index() const { if (containing_type_ == NULL) { return this - file_->enum_types_; @@ -1494,6 +1650,14 @@ inline FieldDescriptor::CppType FieldDescriptor::TypeToCppType(Type type) { return kTypeToCppTypeMap[type]; } +inline const char* FieldDescriptor::TypeName(Type type) { + return kTypeToName[type]; +} + +inline const char* FieldDescriptor::CppTypeName(CppType cpp_type) { + return kCppTypeToName[cpp_type]; +} + inline bool FieldDescriptor::IsTypePackable(Type field_type) { return (field_type != FieldDescriptor::TYPE_STRING && field_type != FieldDescriptor::TYPE_GROUP && @@ -1515,6 +1679,12 @@ inline const FileDescriptor* FileDescriptor::weak_dependency( return dependencies_[weak_dependencies_[index]]; } +// Can't use PROTOBUF_DEFINE_ARRAY_ACCESSOR because fields_ is actually an array +// of pointers rather than the usual array of objects. +inline const FieldDescriptor* OneofDescriptor::field(int index) const { + return fields_[index]; +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc index cfd4817d..c3aa2fb6 100644 --- a/src/google/protobuf/descriptor.pb.cc +++ b/src/google/protobuf/descriptor.pb.cc @@ -38,6 +38,9 @@ const ::google::protobuf::internal::GeneratedMessageReflection* FieldDescriptorProto_reflection_ = NULL; const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Type_descriptor_ = NULL; const ::google::protobuf::EnumDescriptor* FieldDescriptorProto_Label_descriptor_ = NULL; +const ::google::protobuf::Descriptor* OneofDescriptorProto_descriptor_ = NULL; +const ::google::protobuf::internal::GeneratedMessageReflection* + OneofDescriptorProto_reflection_ = NULL; const ::google::protobuf::Descriptor* EnumDescriptorProto_descriptor_ = NULL; const ::google::protobuf::internal::GeneratedMessageReflection* EnumDescriptorProto_reflection_ = NULL; @@ -136,13 +139,14 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(FileDescriptorProto)); DescriptorProto_descriptor_ = file->message_type(2); - static const int DescriptorProto_offsets_[7] = { + static const int DescriptorProto_offsets_[8] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, field_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, nested_type_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, enum_type_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, extension_range_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, oneof_decl_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(DescriptorProto, options_), }; DescriptorProto_reflection_ = @@ -173,7 +177,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(DescriptorProto_ExtensionRange)); FieldDescriptorProto_descriptor_ = file->message_type(3); - static const int FieldDescriptorProto_offsets_[8] = { + static const int FieldDescriptorProto_offsets_[9] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, number_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, label_), @@ -181,6 +185,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, type_name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, extendee_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, default_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, oneof_index_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldDescriptorProto, options_), }; FieldDescriptorProto_reflection_ = @@ -196,7 +201,22 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { sizeof(FieldDescriptorProto)); FieldDescriptorProto_Type_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(0); FieldDescriptorProto_Label_descriptor_ = FieldDescriptorProto_descriptor_->enum_type(1); - EnumDescriptorProto_descriptor_ = file->message_type(4); + OneofDescriptorProto_descriptor_ = file->message_type(4); + static const int OneofDescriptorProto_offsets_[1] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, name_), + }; + OneofDescriptorProto_reflection_ = + new ::google::protobuf::internal::GeneratedMessageReflection( + OneofDescriptorProto_descriptor_, + OneofDescriptorProto::default_instance_, + OneofDescriptorProto_offsets_, + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _has_bits_[0]), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(OneofDescriptorProto, _unknown_fields_), + -1, + ::google::protobuf::DescriptorPool::generated_pool(), + ::google::protobuf::MessageFactory::generated_factory(), + sizeof(OneofDescriptorProto)); + EnumDescriptorProto_descriptor_ = file->message_type(5); static const int EnumDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumDescriptorProto, value_), @@ -213,7 +233,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(EnumDescriptorProto)); - EnumValueDescriptorProto_descriptor_ = file->message_type(5); + EnumValueDescriptorProto_descriptor_ = file->message_type(6); static const int EnumValueDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueDescriptorProto, number_), @@ -230,7 +250,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(EnumValueDescriptorProto)); - ServiceDescriptorProto_descriptor_ = file->message_type(6); + ServiceDescriptorProto_descriptor_ = file->message_type(7); static const int ServiceDescriptorProto_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceDescriptorProto, method_), @@ -247,7 +267,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(ServiceDescriptorProto)); - MethodDescriptorProto_descriptor_ = file->message_type(7); + MethodDescriptorProto_descriptor_ = file->message_type(8); static const int MethodDescriptorProto_offsets_[4] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodDescriptorProto, input_type_), @@ -265,17 +285,19 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(MethodDescriptorProto)); - FileOptions_descriptor_ = file->message_type(8); - static const int FileOptions_offsets_[10] = { + FileOptions_descriptor_ = file->message_type(9); + static const int FileOptions_offsets_[12] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_outer_classname_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_multiple_files_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generate_equals_and_hash_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_string_check_utf8_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, optimize_for_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, go_package_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, cc_generic_services_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, java_generic_services_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, py_generic_services_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FileOptions, uninterpreted_option_), }; FileOptions_reflection_ = @@ -290,10 +312,11 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(FileOptions)); FileOptions_OptimizeMode_descriptor_ = FileOptions_descriptor_->enum_type(0); - MessageOptions_descriptor_ = file->message_type(9); - static const int MessageOptions_offsets_[3] = { + MessageOptions_descriptor_ = file->message_type(10); + static const int MessageOptions_offsets_[4] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, message_set_wire_format_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, no_standard_descriptor_accessor_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MessageOptions, uninterpreted_option_), }; MessageOptions_reflection_ = @@ -307,7 +330,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(MessageOptions)); - FieldOptions_descriptor_ = file->message_type(10); + FieldOptions_descriptor_ = file->message_type(11); static const int FieldOptions_offsets_[7] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, ctype_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(FieldOptions, packed_), @@ -329,9 +352,10 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::MessageFactory::generated_factory(), sizeof(FieldOptions)); FieldOptions_CType_descriptor_ = FieldOptions_descriptor_->enum_type(0); - EnumOptions_descriptor_ = file->message_type(11); - static const int EnumOptions_offsets_[2] = { + EnumOptions_descriptor_ = file->message_type(12); + static const int EnumOptions_offsets_[3] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, allow_alias_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumOptions, uninterpreted_option_), }; EnumOptions_reflection_ = @@ -345,8 +369,9 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(EnumOptions)); - EnumValueOptions_descriptor_ = file->message_type(12); - static const int EnumValueOptions_offsets_[1] = { + EnumValueOptions_descriptor_ = file->message_type(13); + static const int EnumValueOptions_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(EnumValueOptions, uninterpreted_option_), }; EnumValueOptions_reflection_ = @@ -360,8 +385,9 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(EnumValueOptions)); - ServiceOptions_descriptor_ = file->message_type(13); - static const int ServiceOptions_offsets_[1] = { + ServiceOptions_descriptor_ = file->message_type(14); + static const int ServiceOptions_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(ServiceOptions, uninterpreted_option_), }; ServiceOptions_reflection_ = @@ -375,8 +401,9 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(ServiceOptions)); - MethodOptions_descriptor_ = file->message_type(14); - static const int MethodOptions_offsets_[1] = { + MethodOptions_descriptor_ = file->message_type(15); + static const int MethodOptions_offsets_[2] = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, deprecated_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(MethodOptions, uninterpreted_option_), }; MethodOptions_reflection_ = @@ -390,7 +417,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(MethodOptions)); - UninterpretedOption_descriptor_ = file->message_type(15); + UninterpretedOption_descriptor_ = file->message_type(16); static const int UninterpretedOption_offsets_[7] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, name_), GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(UninterpretedOption, identifier_value_), @@ -427,7 +454,7 @@ void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto() { ::google::protobuf::DescriptorPool::generated_pool(), ::google::protobuf::MessageFactory::generated_factory(), sizeof(UninterpretedOption_NamePart)); - SourceCodeInfo_descriptor_ = file->message_type(16); + SourceCodeInfo_descriptor_ = file->message_type(17); static const int SourceCodeInfo_offsets_[1] = { GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(SourceCodeInfo, location_), }; @@ -482,6 +509,8 @@ void protobuf_RegisterTypes(const ::std::string&) { DescriptorProto_ExtensionRange_descriptor_, &DescriptorProto_ExtensionRange::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( FieldDescriptorProto_descriptor_, &FieldDescriptorProto::default_instance()); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( + OneofDescriptorProto_descriptor_, &OneofDescriptorProto::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( EnumDescriptorProto_descriptor_, &EnumDescriptorProto::default_instance()); ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage( @@ -527,6 +556,8 @@ void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto() { delete DescriptorProto_ExtensionRange_reflection_; delete FieldDescriptorProto::default_instance_; delete FieldDescriptorProto_reflection_; + delete OneofDescriptorProto::default_instance_; + delete OneofDescriptorProto_reflection_; delete EnumDescriptorProto::default_instance_; delete EnumDescriptorProto_reflection_; delete EnumValueDescriptorProto::default_instance_; @@ -580,7 +611,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "\0132%.google.protobuf.FieldDescriptorProto" "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File" "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog" - "le.protobuf.SourceCodeInfo\"\251\003\n\017Descripto" + "le.protobuf.SourceCodeInfo\"\344\003\n\017Descripto" "rProto\022\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.go" "ogle.protobuf.FieldDescriptorProto\0228\n\tex" "tension\030\006 \003(\0132%.google.protobuf.FieldDes" @@ -588,16 +619,18 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "le.protobuf.DescriptorProto\0227\n\tenum_type" "\030\004 \003(\0132$.google.protobuf.EnumDescriptorP" "roto\022H\n\017extension_range\030\005 \003(\0132/.google.p" - "rotobuf.DescriptorProto.ExtensionRange\0220" - "\n\007options\030\007 \001(\0132\037.google.protobuf.Messag" - "eOptions\032,\n\016ExtensionRange\022\r\n\005start\030\001 \001(" - "\005\022\013\n\003end\030\002 \001(\005\"\224\005\n\024FieldDescriptorProto\022" - "\014\n\004name\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004" - " \001(\0162+.google.protobuf.FieldDescriptorPr" - "oto.Label\0228\n\004type\030\005 \001(\0162*.google.protobu" - "f.FieldDescriptorProto.Type\022\021\n\ttype_name" - "\030\006 \001(\t\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_valu" - "e\030\007 \001(\t\022.\n\007options\030\010 \001(\0132\035.google.protob" + "rotobuf.DescriptorProto.ExtensionRange\0229" + "\n\noneof_decl\030\010 \003(\0132%.google.protobuf.One" + "ofDescriptorProto\0220\n\007options\030\007 \001(\0132\037.goo" + "gle.protobuf.MessageOptions\032,\n\016Extension" + "Range\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"\251\005\n\024Fi" + "eldDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006numb" + "er\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobu" + "f.FieldDescriptorProto.Label\0228\n\004type\030\005 \001" + "(\0162*.google.protobuf.FieldDescriptorProt" + "o.Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 " + "\001(\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_inde" + "x\030\t \001(\005\022.\n\007options\030\010 \001(\0132\035.google.protob" "uf.FieldOptions\"\266\002\n\004Type\022\017\n\013TYPE_DOUBLE\020" "\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013TYP" "E_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIXED" @@ -607,69 +640,75 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { "\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n\rT" "YPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYPE_" "SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022\022\n" - "\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"\214\001" - "\n\023EnumDescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005v" - "alue\030\002 \003(\0132).google.protobuf.EnumValueDe" - "scriptorProto\022-\n\007options\030\003 \001(\0132\034.google." - "protobuf.EnumOptions\"l\n\030EnumValueDescrip" - "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222" - "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa" - "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n" - "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro" - "tobuf.MethodDescriptorProto\0220\n\007options\030\003" - " \001(\0132\037.google.protobuf.ServiceOptions\"\177\n" - "\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\n" - "input_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n" - "\007options\030\004 \001(\0132\036.google.protobuf.MethodO" - "ptions\"\351\003\n\013FileOptions\022\024\n\014java_package\030\001" - " \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023ja" - "va_multiple_files\030\n \001(\010:\005false\022,\n\035java_g" - "enerate_equals_and_hash\030\024 \001(\010:\005false\022F\n\014" - "optimize_for\030\t \001(\0162).google.protobuf.Fil" - "eOptions.OptimizeMode:\005SPEED\022\022\n\ngo_packa" - "ge\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005f" - "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal" - "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022C" - "\n\024uninterpreted_option\030\347\007 \003(\0132$.google.p" - "rotobuf.UninterpretedOption\":\n\014OptimizeM" - "ode\022\t\n\005SPEED\020\001\022\r\n\tCODE_SIZE\020\002\022\020\n\014LITE_RU" - "NTIME\020\003*\t\010\350\007\020\200\200\200\200\002\"\270\001\n\016MessageOptions\022&\n" - "\027message_set_wire_format\030\001 \001(\010:\005false\022.\n" - "\037no_standard_descriptor_accessor\030\002 \001(\010:\005" - "false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.g" - "oogle.protobuf.UninterpretedOption*\t\010\350\007\020" - "\200\200\200\200\002\"\276\002\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#." - "google.protobuf.FieldOptions.CType:\006STRI" - "NG\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 \001(\010:\005false\022" - "\031\n\ndeprecated\030\003 \001(\010:\005false\022\034\n\024experiment" - "al_map_key\030\t \001(\t\022\023\n\004weak\030\n \001(\010:\005false\022C\n" - "\024uninterpreted_option\030\347\007 \003(\0132$.google.pr" - "otobuf.UninterpretedOption\"/\n\005CType\022\n\n\006S" - "TRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_PIECE\020\002*\t\010\350\007" - "\020\200\200\200\200\002\"x\n\013EnumOptions\022\031\n\013allow_alias\030\002 \001" - "(\010:\004true\022C\n\024uninterpreted_option\030\347\007 \003(\0132" + "\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\"$\n" + "\024OneofDescriptorProto\022\014\n\004name\030\001 \001(\t\"\214\001\n\023" + "EnumDescriptorProto\022\014\n\004name\030\001 \001(\t\0228\n\005val" + "ue\030\002 \003(\0132).google.protobuf.EnumValueDesc" + "riptorProto\022-\n\007options\030\003 \001(\0132\034.google.pr" + "otobuf.EnumOptions\"l\n\030EnumValueDescripto" + "rProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222\n\007" + "options\030\003 \001(\0132!.google.protobuf.EnumValu" + "eOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n\004n" + "ame\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.proto" + "buf.MethodDescriptorProto\0220\n\007options\030\003 \001" + "(\0132\037.google.protobuf.ServiceOptions\"\177\n\025M" + "ethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n\nin" + "put_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/\n\007o" + "ptions\030\004 \001(\0132\036.google.protobuf.MethodOpt" + "ions\"\253\004\n\013FileOptions\022\024\n\014java_package\030\001 \001" + "(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\"\n\023java" + "_multiple_files\030\n \001(\010:\005false\022,\n\035java_gen" + "erate_equals_and_hash\030\024 \001(\010:\005false\022%\n\026ja" + "va_string_check_utf8\030\033 \001(\010:\005false\022F\n\014opt" + "imize_for\030\t \001(\0162).google.protobuf.FileOp" + "tions.OptimizeMode:\005SPEED\022\022\n\ngo_package\030" + "\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005fals" + "e\022$\n\025java_generic_services\030\021 \001(\010:\005false\022" + "\"\n\023py_generic_services\030\022 \001(\010:\005false\022\031\n\nd" + "eprecated\030\027 \001(\010:\005false\022C\n\024uninterpreted_" + "option\030\347\007 \003(\0132$.google.protobuf.Uninterp" + "retedOption\":\n\014OptimizeMode\022\t\n\005SPEED\020\001\022\r" + "\n\tCODE_SIZE\020\002\022\020\n\014LITE_RUNTIME\020\003*\t\010\350\007\020\200\200\200" + "\200\002\"\323\001\n\016MessageOptions\022&\n\027message_set_wir" + "e_format\030\001 \001(\010:\005false\022.\n\037no_standard_des" + "criptor_accessor\030\002 \001(\010:\005false\022\031\n\ndepreca" + "ted\030\003 \001(\010:\005false\022C\n\024uninterpreted_option" + "\030\347\007 \003(\0132$.google.protobuf.UninterpretedO" + "ption*\t\010\350\007\020\200\200\200\200\002\"\276\002\n\014FieldOptions\022:\n\005cty" + "pe\030\001 \001(\0162#.google.protobuf.FieldOptions." + "CType:\006STRING\022\016\n\006packed\030\002 \001(\010\022\023\n\004lazy\030\005 " + "\001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\034\n" + "\024experimental_map_key\030\t \001(\t\022\023\n\004weak\030\n \001(" + "\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132" + "$.google.protobuf.UninterpretedOption\"/\n" + "\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_P" + "IECE\020\002*\t\010\350\007\020\200\200\200\200\002\"\215\001\n\013EnumOptions\022\023\n\013all" + "ow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 \001(\010:\005fals" + "e\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.googl" + "e.protobuf.UninterpretedOption*\t\010\350\007\020\200\200\200\200" + "\002\"}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(" + "\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132" "$.google.protobuf.UninterpretedOption*\t\010" - "\350\007\020\200\200\200\200\002\"b\n\020EnumValueOptions\022C\n\024uninterp" - "reted_option\030\347\007 \003(\0132$.google.protobuf.Un" - "interpretedOption*\t\010\350\007\020\200\200\200\200\002\"`\n\016ServiceO" - "ptions\022C\n\024uninterpreted_option\030\347\007 \003(\0132$." - "google.protobuf.UninterpretedOption*\t\010\350\007" - "\020\200\200\200\200\002\"_\n\rMethodOptions\022C\n\024uninterpreted" - "_option\030\347\007 \003(\0132$.google.protobuf.Uninter" - "pretedOption*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023Uninterprete" - "dOption\022;\n\004name\030\002 \003(\0132-.google.protobuf." - "UninterpretedOption.NamePart\022\030\n\020identifi" - "er_value\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001" - "(\004\022\032\n\022negative_int_value\030\005 \001(\003\022\024\n\014double" - "_value\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017ag" - "gregate_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_" - "part\030\001 \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\261\001\n\016Sou" - "rceCodeInfo\022:\n\010location\030\001 \003(\0132(.google.p" - "rotobuf.SourceCodeInfo.Location\032c\n\010Locat" - "ion\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022" - "\030\n\020leading_comments\030\003 \001(\t\022\031\n\021trailing_co" - "mments\030\004 \001(\tB)\n\023com.google.protobufB\020Des" - "criptorProtosH\001", 4135); + "\350\007\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated" + "\030! \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007" + " \003(\0132$.google.protobuf.UninterpretedOpti" + "on*\t\010\350\007\020\200\200\200\200\002\"z\n\rMethodOptions\022\031\n\ndeprec" + "ated\030! \001(\010:\005false\022C\n\024uninterpreted_optio" + "n\030\347\007 \003(\0132$.google.protobuf.Uninterpreted" + "Option*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023UninterpretedOptio" + "n\022;\n\004name\030\002 \003(\0132-.google.protobuf.Uninte" + "rpretedOption.NamePart\022\030\n\020identifier_val" + "ue\030\003 \001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022" + "negative_int_value\030\005 \001(\003\022\024\n\014double_value" + "\030\006 \001(\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregat" + "e_value\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001" + " \002(\t\022\024\n\014is_extension\030\002 \002(\010\"\261\001\n\016SourceCod" + "eInfo\022:\n\010location\030\001 \003(\0132(.google.protobu" + "f.SourceCodeInfo.Location\032c\n\010Location\022\020\n" + "\004path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lea" + "ding_comments\030\003 \001(\t\022\031\n\021trailing_comments" + "\030\004 \001(\tB)\n\023com.google.protobufB\020Descripto" + "rProtosH\001", 4449); ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( "google/protobuf/descriptor.proto", &protobuf_RegisterTypes); FileDescriptorSet::default_instance_ = new FileDescriptorSet(); @@ -677,6 +716,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { DescriptorProto::default_instance_ = new DescriptorProto(); DescriptorProto_ExtensionRange::default_instance_ = new DescriptorProto_ExtensionRange(); FieldDescriptorProto::default_instance_ = new FieldDescriptorProto(); + OneofDescriptorProto::default_instance_ = new OneofDescriptorProto(); EnumDescriptorProto::default_instance_ = new EnumDescriptorProto(); EnumValueDescriptorProto::default_instance_ = new EnumValueDescriptorProto(); ServiceDescriptorProto::default_instance_ = new ServiceDescriptorProto(); @@ -697,6 +737,7 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() { DescriptorProto::default_instance_->InitAsDefaultInstance(); DescriptorProto_ExtensionRange::default_instance_->InitAsDefaultInstance(); FieldDescriptorProto::default_instance_->InitAsDefaultInstance(); + OneofDescriptorProto::default_instance_->InitAsDefaultInstance(); EnumDescriptorProto::default_instance_->InitAsDefaultInstance(); EnumValueDescriptorProto::default_instance_->InitAsDefaultInstance(); ServiceDescriptorProto::default_instance_->InitAsDefaultInstance(); @@ -731,6 +772,7 @@ const int FileDescriptorSet::kFileFieldNumber; FileDescriptorSet::FileDescriptorSet() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorSet) } void FileDescriptorSet::InitAsDefaultInstance() { @@ -740,6 +782,7 @@ FileDescriptorSet::FileDescriptorSet(const FileDescriptorSet& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorSet) } void FileDescriptorSet::SharedCtor() { @@ -748,6 +791,7 @@ void FileDescriptorSet::SharedCtor() { } FileDescriptorSet::~FileDescriptorSet() { + // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorSet) SharedDtor(); } @@ -785,30 +829,34 @@ void FileDescriptorSet::Clear() { bool FileDescriptorSet::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorSet) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.FileDescriptorProto file = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { parse_file: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_file())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(10)) goto parse_file; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -816,12 +864,18 @@ bool FileDescriptorSet::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FileDescriptorSet) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FileDescriptorSet) + return false; #undef DO_ } void FileDescriptorSet::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FileDescriptorSet) // repeated .google.protobuf.FileDescriptorProto file = 1; for (int i = 0; i < this->file_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -832,10 +886,12 @@ void FileDescriptorSet::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorSet) } ::google::protobuf::uint8* FileDescriptorSet::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet) // repeated .google.protobuf.FileDescriptorProto file = 1; for (int i = 0; i < this->file_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -847,6 +903,7 @@ void FileDescriptorSet::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorSet) return target; } @@ -904,9 +961,7 @@ void FileDescriptorSet::CopyFrom(const FileDescriptorSet& from) { bool FileDescriptorSet::IsInitialized() const { - for (int i = 0; i < file_size(); i++) { - if (!this->file(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->file())) return false; return true; } @@ -947,6 +1002,7 @@ const int FileDescriptorProto::kSourceCodeInfoFieldNumber; FileDescriptorProto::FileDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FileDescriptorProto) } void FileDescriptorProto::InitAsDefaultInstance() { @@ -958,26 +1014,29 @@ FileDescriptorProto::FileDescriptorProto(const FileDescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto) } void FileDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; source_code_info_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } FileDescriptorProto::~FileDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.FileDescriptorProto) SharedDtor(); } void FileDescriptorProto::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } - if (package_ != &::google::protobuf::internal::GetEmptyString()) { + if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete package_; } if (this != default_instance_) { @@ -1008,19 +1067,19 @@ FileDescriptorProto* FileDescriptorProto::New() const { } void FileDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 3) { if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } if (has_package()) { - if (package_ != &::google::protobuf::internal::GetEmptyString()) { + if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_->clear(); } } } - if (_has_bits_[9 / 32] & (0xffu << (9 % 32))) { + if (_has_bits_[8 / 32] & 1536) { if (has_options()) { if (options_ != NULL) options_->::google::protobuf::FileOptions::Clear(); } @@ -1041,21 +1100,25 @@ void FileDescriptorProto::Clear() { bool FileDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FileDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_package; break; @@ -1063,16 +1126,16 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // optional string package = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_package: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_package())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->package().data(), this->package().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "package"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_dependency; break; @@ -1080,17 +1143,17 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated string dependency = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_dependency: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->add_dependency())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->dependency(this->dependency_size() - 1).data(), this->dependency(this->dependency_size() - 1).length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "dependency"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_dependency; if (input->ExpectTag(34)) goto parse_message_type; @@ -1099,13 +1162,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.DescriptorProto message_type = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 34) { parse_message_type: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_message_type())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(34)) goto parse_message_type; if (input->ExpectTag(42)) goto parse_enum_type; @@ -1114,13 +1176,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.EnumDescriptorProto enum_type = 5; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 42) { parse_enum_type: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_enum_type())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(42)) goto parse_enum_type; if (input->ExpectTag(50)) goto parse_service; @@ -1129,13 +1190,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.ServiceDescriptorProto service = 6; case 6: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 50) { parse_service: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_service())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(50)) goto parse_service; if (input->ExpectTag(58)) goto parse_extension; @@ -1144,13 +1204,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.FieldDescriptorProto extension = 7; case 7: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 58) { parse_extension: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_extension())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(58)) goto parse_extension; if (input->ExpectTag(66)) goto parse_options; @@ -1159,13 +1218,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.FileOptions options = 8; case 8: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 66) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(74)) goto parse_source_code_info; break; @@ -1173,13 +1231,12 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.SourceCodeInfo source_code_info = 9; case 9: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 74) { parse_source_code_info: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_source_code_info())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(80)) goto parse_public_dependency; break; @@ -1187,20 +1244,17 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated int32 public_dependency = 10; case 10: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 80) { parse_public_dependency: DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( 1, 80, input, this->mutable_public_dependency()))); - } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) - == ::google::protobuf::internal::WireFormatLite:: - WIRETYPE_LENGTH_DELIMITED) { + } else if (tag == 82) { DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, this->mutable_public_dependency()))); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(80)) goto parse_public_dependency; if (input->ExpectTag(88)) goto parse_weak_dependency; @@ -1209,31 +1263,29 @@ bool FileDescriptorProto::MergePartialFromCodedStream( // repeated int32 weak_dependency = 11; case 11: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 88) { parse_weak_dependency: DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( 1, 88, input, this->mutable_weak_dependency()))); - } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) - == ::google::protobuf::internal::WireFormatLite:: - WIRETYPE_LENGTH_DELIMITED) { + } else if (tag == 90) { DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitiveNoInline< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, this->mutable_weak_dependency()))); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(88)) goto parse_weak_dependency; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -1241,35 +1293,44 @@ bool FileDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FileDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FileDescriptorProto) + return false; #undef DO_ } void FileDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FileDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } // optional string package = 2; if (has_package()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->package().data(), this->package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "package"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->package(), output); } // repeated string dependency = 3; for (int i = 0; i < this->dependency_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->dependency(i).data(), this->dependency(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "dependency"); ::google::protobuf::internal::WireFormatLite::WriteString( 3, this->dependency(i), output); } @@ -1326,15 +1387,18 @@ void FileDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FileDescriptorProto) } ::google::protobuf::uint8* FileDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); @@ -1342,9 +1406,10 @@ void FileDescriptorProto::SerializeWithCachedSizes( // optional string package = 2; if (has_package()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->package().data(), this->package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "package"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->package(), target); @@ -1352,9 +1417,10 @@ void FileDescriptorProto::SerializeWithCachedSizes( // repeated string dependency = 3; for (int i = 0; i < this->dependency_size(); i++) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->dependency(i).data(), this->dependency(i).length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "dependency"); target = ::google::protobuf::internal::WireFormatLite:: WriteStringToArray(3, this->dependency(i), target); } @@ -1417,6 +1483,7 @@ void FileDescriptorProto::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileDescriptorProto) return target; } @@ -1579,18 +1646,10 @@ void FileDescriptorProto::CopyFrom(const FileDescriptorProto& from) { bool FileDescriptorProto::IsInitialized() const { - for (int i = 0; i < message_type_size(); i++) { - if (!this->message_type(i).IsInitialized()) return false; - } - for (int i = 0; i < enum_type_size(); i++) { - if (!this->enum_type(i).IsInitialized()) return false; - } - for (int i = 0; i < service_size(); i++) { - if (!this->service(i).IsInitialized()) return false; - } - for (int i = 0; i < extension_size(); i++) { - if (!this->extension(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->message_type())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->service())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false; if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -1635,6 +1694,7 @@ const int DescriptorProto_ExtensionRange::kEndFieldNumber; DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto.ExtensionRange) } void DescriptorProto_ExtensionRange::InitAsDefaultInstance() { @@ -1644,6 +1704,7 @@ DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(const DescriptorP : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange) } void DescriptorProto_ExtensionRange::SharedCtor() { @@ -1654,6 +1715,7 @@ void DescriptorProto_ExtensionRange::SharedCtor() { } DescriptorProto_ExtensionRange::~DescriptorProto_ExtensionRange() { + // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto.ExtensionRange) SharedDtor(); } @@ -1684,30 +1746,44 @@ DescriptorProto_ExtensionRange* DescriptorProto_ExtensionRange::New() const { } void DescriptorProto_ExtensionRange::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - start_ = 0; - end_ = 0; - } +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + ZR_(start_, end_); + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); } bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto.ExtensionRange) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional int32 start = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 8) { DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &start_))); set_has_start(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_end; break; @@ -1715,25 +1791,25 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( // optional int32 end = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_end: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &end_))); set_has_end(); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -1741,12 +1817,18 @@ bool DescriptorProto_ExtensionRange::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto.ExtensionRange) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto.ExtensionRange) + return false; #undef DO_ } void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto.ExtensionRange) // optional int32 start = 1; if (has_start()) { ::google::protobuf::internal::WireFormatLite::WriteInt32(1, this->start(), output); @@ -1761,10 +1843,12 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto.ExtensionRange) } ::google::protobuf::uint8* DescriptorProto_ExtensionRange::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange) // optional int32 start = 1; if (has_start()) { target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(1, this->start(), target); @@ -1779,6 +1863,7 @@ void DescriptorProto_ExtensionRange::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto.ExtensionRange) return target; } @@ -1882,12 +1967,14 @@ const int DescriptorProto::kExtensionFieldNumber; const int DescriptorProto::kNestedTypeFieldNumber; const int DescriptorProto::kEnumTypeFieldNumber; const int DescriptorProto::kExtensionRangeFieldNumber; +const int DescriptorProto::kOneofDeclFieldNumber; const int DescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER DescriptorProto::DescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.DescriptorProto) } void DescriptorProto::InitAsDefaultInstance() { @@ -1898,21 +1985,24 @@ DescriptorProto::DescriptorProto(const DescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto) } void DescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } DescriptorProto::~DescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.DescriptorProto) SharedDtor(); } void DescriptorProto::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (this != default_instance_) { @@ -1942,9 +2032,9 @@ DescriptorProto* DescriptorProto::New() const { } void DescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 129) { if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } @@ -1957,27 +2047,32 @@ void DescriptorProto::Clear() { nested_type_.Clear(); enum_type_.Clear(); extension_range_.Clear(); + oneof_decl_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); } bool DescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.DescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_field; break; @@ -1985,13 +2080,12 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.FieldDescriptorProto field = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_field: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_field())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_field; if (input->ExpectTag(26)) goto parse_nested_type; @@ -2000,13 +2094,12 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.DescriptorProto nested_type = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_nested_type: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_nested_type())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_nested_type; if (input->ExpectTag(34)) goto parse_enum_type; @@ -2015,13 +2108,12 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.EnumDescriptorProto enum_type = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 34) { parse_enum_type: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_enum_type())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(34)) goto parse_enum_type; if (input->ExpectTag(42)) goto parse_extension_range; @@ -2030,13 +2122,12 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 42) { parse_extension_range: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_extension_range())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(42)) goto parse_extension_range; if (input->ExpectTag(50)) goto parse_extension; @@ -2045,13 +2136,12 @@ bool DescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.FieldDescriptorProto extension = 6; case 6: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 50) { parse_extension: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_extension())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(50)) goto parse_extension; if (input->ExpectTag(58)) goto parse_options; @@ -2060,23 +2150,37 @@ bool DescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.MessageOptions options = 7; case 7: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 58) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(66)) goto parse_oneof_decl; + break; + } + + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + case 8: { + if (tag == 66) { + parse_oneof_decl: + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, add_oneof_decl())); + } else { + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectTag(66)) goto parse_oneof_decl; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -2084,18 +2188,25 @@ bool DescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.DescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.DescriptorProto) + return false; #undef DO_ } void DescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.DescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } @@ -2135,19 +2246,28 @@ void DescriptorProto::SerializeWithCachedSizes( 7, this->options(), output); } + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + for (int i = 0; i < this->oneof_decl_size(); i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 8, this->oneof_decl(i), output); + } + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.DescriptorProto) } ::google::protobuf::uint8* DescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); @@ -2195,10 +2315,18 @@ void DescriptorProto::SerializeWithCachedSizes( 7, this->options(), target); } + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + for (int i = 0; i < this->oneof_decl_size(); i++) { + target = ::google::protobuf::internal::WireFormatLite:: + WriteMessageNoVirtualToArray( + 8, this->oneof_decl(i), target); + } + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.DescriptorProto) return target; } @@ -2261,6 +2389,14 @@ int DescriptorProto::ByteSize() const { this->extension_range(i)); } + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + total_size += 1 * this->oneof_decl_size(); + for (int i = 0; i < this->oneof_decl_size(); i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual( + this->oneof_decl(i)); + } + if (!unknown_fields().empty()) { total_size += ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( @@ -2291,6 +2427,7 @@ void DescriptorProto::MergeFrom(const DescriptorProto& from) { nested_type_.MergeFrom(from.nested_type_); enum_type_.MergeFrom(from.enum_type_); extension_range_.MergeFrom(from.extension_range_); + oneof_decl_.MergeFrom(from.oneof_decl_); if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { if (from.has_name()) { set_name(from.name()); @@ -2316,18 +2453,10 @@ void DescriptorProto::CopyFrom(const DescriptorProto& from) { bool DescriptorProto::IsInitialized() const { - for (int i = 0; i < field_size(); i++) { - if (!this->field(i).IsInitialized()) return false; - } - for (int i = 0; i < extension_size(); i++) { - if (!this->extension(i).IsInitialized()) return false; - } - for (int i = 0; i < nested_type_size(); i++) { - if (!this->nested_type(i).IsInitialized()) return false; - } - for (int i = 0; i < enum_type_size(); i++) { - if (!this->enum_type(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->field())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->extension())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->nested_type())) return false; + if (!::google::protobuf::internal::AllAreInitialized(this->enum_type())) return false; if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -2342,6 +2471,7 @@ void DescriptorProto::Swap(DescriptorProto* other) { nested_type_.Swap(&other->nested_type_); enum_type_.Swap(&other->enum_type_); extension_range_.Swap(&other->extension_range_); + oneof_decl_.Swap(&other->oneof_decl_); std::swap(options_, other->options_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -2444,12 +2574,14 @@ const int FieldDescriptorProto::kTypeFieldNumber; const int FieldDescriptorProto::kTypeNameFieldNumber; const int FieldDescriptorProto::kExtendeeFieldNumber; const int FieldDescriptorProto::kDefaultValueFieldNumber; +const int FieldDescriptorProto::kOneofIndexFieldNumber; const int FieldDescriptorProto::kOptionsFieldNumber; #endif // !_MSC_VER FieldDescriptorProto::FieldDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FieldDescriptorProto) } void FieldDescriptorProto::InitAsDefaultInstance() { @@ -2460,36 +2592,40 @@ FieldDescriptorProto::FieldDescriptorProto(const FieldDescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto) } void FieldDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); number_ = 0; label_ = 1; type_ = 1; - type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + oneof_index_ = 0; options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } FieldDescriptorProto::~FieldDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.FieldDescriptorProto) SharedDtor(); } void FieldDescriptorProto::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } - if (type_name_ != &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete type_name_; } - if (extendee_ != &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete extendee_; } - if (default_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete default_value_; } if (this != default_instance_) { @@ -2519,9 +2655,9 @@ FieldDescriptorProto* FieldDescriptorProto::New() const { } void FieldDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 255) { if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } @@ -2529,23 +2665,24 @@ void FieldDescriptorProto::Clear() { label_ = 1; type_ = 1; if (has_type_name()) { - if (type_name_ != &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_->clear(); } } if (has_extendee()) { - if (extendee_ != &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_->clear(); } } if (has_default_value()) { - if (default_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_->clear(); } } - if (has_options()) { - if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); - } + oneof_index_ = 0; + } + if (has_options()) { + if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); } ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -2553,21 +2690,25 @@ void FieldDescriptorProto::Clear() { bool FieldDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FieldDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_extendee; break; @@ -2575,16 +2716,16 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional string extendee = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_extendee: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_extendee())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->extendee().data(), this->extendee().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "extendee"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(24)) goto parse_number; break; @@ -2592,15 +2733,14 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional int32 number = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 24) { parse_number: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &number_))); set_has_number(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(32)) goto parse_label; break; @@ -2608,8 +2748,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.FieldDescriptorProto.Label label = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 32) { parse_label: int value; DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< @@ -2621,7 +2760,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( mutable_unknown_fields()->AddVarint(4, value); } } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(40)) goto parse_type; break; @@ -2629,8 +2768,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.FieldDescriptorProto.Type type = 5; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 40) { parse_type: int value; DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< @@ -2642,7 +2780,7 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( mutable_unknown_fields()->AddVarint(5, value); } } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(50)) goto parse_type_name; break; @@ -2650,16 +2788,16 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional string type_name = 6; case 6: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 50) { parse_type_name: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_type_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->type_name().data(), this->type_name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "type_name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(58)) goto parse_default_value; break; @@ -2667,16 +2805,16 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional string default_value = 7; case 7: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 58) { parse_default_value: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_default_value())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->default_value().data(), this->default_value().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "default_value"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(66)) goto parse_options; break; @@ -2684,23 +2822,38 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.FieldOptions options = 8; case 8: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 66) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(72)) goto parse_oneof_index; + break; + } + + // optional int32 oneof_index = 9; + case 9: { + if (tag == 72) { + parse_oneof_index: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &oneof_index_))); + set_has_oneof_index(); + } else { + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -2708,27 +2861,35 @@ bool FieldDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FieldDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FieldDescriptorProto) + return false; #undef DO_ } void FieldDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FieldDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } // optional string extendee = 2; if (has_extendee()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->extendee().data(), this->extendee().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "extendee"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->extendee(), output); } @@ -2751,19 +2912,21 @@ void FieldDescriptorProto::SerializeWithCachedSizes( // optional string type_name = 6; if (has_type_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->type_name().data(), this->type_name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "type_name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 6, this->type_name(), output); } // optional string default_value = 7; if (has_default_value()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->default_value().data(), this->default_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "default_value"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 7, this->default_value(), output); } @@ -2773,19 +2936,27 @@ void FieldDescriptorProto::SerializeWithCachedSizes( 8, this->options(), output); } + // optional int32 oneof_index = 9; + if (has_oneof_index()) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(9, this->oneof_index(), output); + } + if (!unknown_fields().empty()) { ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FieldDescriptorProto) } ::google::protobuf::uint8* FieldDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); @@ -2793,9 +2964,10 @@ void FieldDescriptorProto::SerializeWithCachedSizes( // optional string extendee = 2; if (has_extendee()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->extendee().data(), this->extendee().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "extendee"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->extendee(), target); @@ -2820,9 +2992,10 @@ void FieldDescriptorProto::SerializeWithCachedSizes( // optional string type_name = 6; if (has_type_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->type_name().data(), this->type_name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "type_name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 6, this->type_name(), target); @@ -2830,9 +3003,10 @@ void FieldDescriptorProto::SerializeWithCachedSizes( // optional string default_value = 7; if (has_default_value()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->default_value().data(), this->default_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "default_value"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 7, this->default_value(), target); @@ -2845,10 +3019,16 @@ void FieldDescriptorProto::SerializeWithCachedSizes( 8, this->options(), target); } + // optional int32 oneof_index = 9; + if (has_oneof_index()) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(9, this->oneof_index(), target); + } + if (!unknown_fields().empty()) { target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldDescriptorProto) return target; } @@ -2903,6 +3083,15 @@ int FieldDescriptorProto::ByteSize() const { this->default_value()); } + // optional int32 oneof_index = 9; + if (has_oneof_index()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->oneof_index()); + } + + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { // optional .google.protobuf.FieldOptions options = 8; if (has_options()) { total_size += 1 + @@ -2958,6 +3147,11 @@ void FieldDescriptorProto::MergeFrom(const FieldDescriptorProto& from) { if (from.has_default_value()) { set_default_value(from.default_value()); } + if (from.has_oneof_index()) { + set_oneof_index(from.oneof_index()); + } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { if (from.has_options()) { mutable_options()->::google::protobuf::FieldOptions::MergeFrom(from.options()); } @@ -2994,6 +3188,7 @@ void FieldDescriptorProto::Swap(FieldDescriptorProto* other) { std::swap(type_name_, other->type_name_); std::swap(extendee_, other->extendee_); std::swap(default_value_, other->default_value_); + std::swap(oneof_index_, other->oneof_index_); std::swap(options_, other->options_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -3010,6 +3205,249 @@ void FieldDescriptorProto::Swap(FieldDescriptorProto* other) { } +// =================================================================== + +#ifndef _MSC_VER +const int OneofDescriptorProto::kNameFieldNumber; +#endif // !_MSC_VER + +OneofDescriptorProto::OneofDescriptorProto() + : ::google::protobuf::Message() { + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.OneofDescriptorProto) +} + +void OneofDescriptorProto::InitAsDefaultInstance() { +} + +OneofDescriptorProto::OneofDescriptorProto(const OneofDescriptorProto& from) + : ::google::protobuf::Message() { + SharedCtor(); + MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto) +} + +void OneofDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); + _cached_size_ = 0; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ::memset(_has_bits_, 0, sizeof(_has_bits_)); +} + +OneofDescriptorProto::~OneofDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.OneofDescriptorProto) + SharedDtor(); +} + +void OneofDescriptorProto::SharedDtor() { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (this != default_instance_) { + } +} + +void OneofDescriptorProto::SetCachedSize(int size) const { + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); +} +const ::google::protobuf::Descriptor* OneofDescriptorProto::descriptor() { + protobuf_AssignDescriptorsOnce(); + return OneofDescriptorProto_descriptor_; +} + +const OneofDescriptorProto& OneofDescriptorProto::default_instance() { + if (default_instance_ == NULL) protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + return *default_instance_; +} + +OneofDescriptorProto* OneofDescriptorProto::default_instance_ = NULL; + +OneofDescriptorProto* OneofDescriptorProto::New() const { + return new OneofDescriptorProto; +} + +void OneofDescriptorProto::Clear() { + if (has_name()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_->clear(); + } + } + ::memset(_has_bits_, 0, sizeof(_has_bits_)); + mutable_unknown_fields()->Clear(); +} + +bool OneofDescriptorProto::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.OneofDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional string name = 1; + case 1: { + if (tag == 10) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_name())); + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::PARSE, + "name"); + } else { + goto handle_unusual; + } + if (input->ExpectAtEnd()) goto success; + break; + } + + default: { + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.OneofDescriptorProto) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.OneofDescriptorProto) + return false; +#undef DO_ +} + +void OneofDescriptorProto::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.OneofDescriptorProto) + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 1, this->name(), output); + } + + if (!unknown_fields().empty()) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + unknown_fields(), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.OneofDescriptorProto) +} + +::google::protobuf::uint8* OneofDescriptorProto::SerializeWithCachedSizesToArray( + ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto) + // optional string name = 1; + if (has_name()) { + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( + this->name().data(), this->name().length(), + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->name(), target); + } + + if (!unknown_fields().empty()) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + unknown_fields(), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.OneofDescriptorProto) + return target; +} + +int OneofDescriptorProto::ByteSize() const { + int total_size = 0; + + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional string name = 1; + if (has_name()) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->name()); + } + + } + if (!unknown_fields().empty()) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + unknown_fields()); + } + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); + _cached_size_ = total_size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); + return total_size; +} + +void OneofDescriptorProto::MergeFrom(const ::google::protobuf::Message& from) { + GOOGLE_CHECK_NE(&from, this); + const OneofDescriptorProto* source = + ::google::protobuf::internal::dynamic_cast_if_available( + &from); + if (source == NULL) { + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + MergeFrom(*source); + } +} + +void OneofDescriptorProto::MergeFrom(const OneofDescriptorProto& from) { + GOOGLE_CHECK_NE(&from, this); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_name()) { + set_name(from.name()); + } + } + mutable_unknown_fields()->MergeFrom(from.unknown_fields()); +} + +void OneofDescriptorProto::CopyFrom(const ::google::protobuf::Message& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void OneofDescriptorProto::CopyFrom(const OneofDescriptorProto& from) { + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool OneofDescriptorProto::IsInitialized() const { + + return true; +} + +void OneofDescriptorProto::Swap(OneofDescriptorProto* other) { + if (other != this) { + std::swap(name_, other->name_); + std::swap(_has_bits_[0], other->_has_bits_[0]); + _unknown_fields_.Swap(&other->_unknown_fields_); + std::swap(_cached_size_, other->_cached_size_); + } +} + +::google::protobuf::Metadata OneofDescriptorProto::GetMetadata() const { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::Metadata metadata; + metadata.descriptor = OneofDescriptorProto_descriptor_; + metadata.reflection = OneofDescriptorProto_reflection_; + return metadata; +} + + // =================================================================== #ifndef _MSC_VER @@ -3021,6 +3459,7 @@ const int EnumDescriptorProto::kOptionsFieldNumber; EnumDescriptorProto::EnumDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.EnumDescriptorProto) } void EnumDescriptorProto::InitAsDefaultInstance() { @@ -3031,21 +3470,24 @@ EnumDescriptorProto::EnumDescriptorProto(const EnumDescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto) } void EnumDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } EnumDescriptorProto::~EnumDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumDescriptorProto) SharedDtor(); } void EnumDescriptorProto::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (this != default_instance_) { @@ -3075,9 +3517,9 @@ EnumDescriptorProto* EnumDescriptorProto::New() const { } void EnumDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 5) { if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } @@ -3092,21 +3534,25 @@ void EnumDescriptorProto::Clear() { bool EnumDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.EnumDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_value; break; @@ -3114,13 +3560,12 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.EnumValueDescriptorProto value = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_value: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_value())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_value; if (input->ExpectTag(26)) goto parse_options; @@ -3129,23 +3574,23 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.EnumOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -3153,18 +3598,25 @@ bool EnumDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.EnumDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.EnumDescriptorProto) + return false; #undef DO_ } void EnumDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.EnumDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } @@ -3184,15 +3636,18 @@ void EnumDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.EnumDescriptorProto) } ::google::protobuf::uint8* EnumDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); @@ -3216,6 +3671,7 @@ void EnumDescriptorProto::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumDescriptorProto) return target; } @@ -3297,9 +3753,7 @@ void EnumDescriptorProto::CopyFrom(const EnumDescriptorProto& from) { bool EnumDescriptorProto::IsInitialized() const { - for (int i = 0; i < value_size(); i++) { - if (!this->value(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->value())) return false; if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -3337,6 +3791,7 @@ const int EnumValueDescriptorProto::kOptionsFieldNumber; EnumValueDescriptorProto::EnumValueDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.EnumValueDescriptorProto) } void EnumValueDescriptorProto::InitAsDefaultInstance() { @@ -3347,22 +3802,25 @@ EnumValueDescriptorProto::EnumValueDescriptorProto(const EnumValueDescriptorProt : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueDescriptorProto) } void EnumValueDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); number_ = 0; options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } EnumValueDescriptorProto::~EnumValueDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumValueDescriptorProto) SharedDtor(); } void EnumValueDescriptorProto::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (this != default_instance_) { @@ -3392,9 +3850,9 @@ EnumValueDescriptorProto* EnumValueDescriptorProto::New() const { } void EnumValueDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 7) { if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } @@ -3409,21 +3867,25 @@ void EnumValueDescriptorProto::Clear() { bool EnumValueDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_number; break; @@ -3431,15 +3893,14 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( // optional int32 number = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_number: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, &number_))); set_has_number(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_options; break; @@ -3447,23 +3908,23 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.EnumValueOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -3471,18 +3932,25 @@ bool EnumValueDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.EnumValueDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValueDescriptorProto) + return false; #undef DO_ } void EnumValueDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValueDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } @@ -3501,15 +3969,18 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueDescriptorProto) } ::google::protobuf::uint8* EnumValueDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); @@ -3531,6 +4002,7 @@ void EnumValueDescriptorProto::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueDescriptorProto) return target; } @@ -3650,6 +4122,7 @@ const int ServiceDescriptorProto::kOptionsFieldNumber; ServiceDescriptorProto::ServiceDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.ServiceDescriptorProto) } void ServiceDescriptorProto::InitAsDefaultInstance() { @@ -3660,21 +4133,24 @@ ServiceDescriptorProto::ServiceDescriptorProto(const ServiceDescriptorProto& fro : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto) } void ServiceDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } ServiceDescriptorProto::~ServiceDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.ServiceDescriptorProto) SharedDtor(); } void ServiceDescriptorProto::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (this != default_instance_) { @@ -3704,9 +4180,9 @@ ServiceDescriptorProto* ServiceDescriptorProto::New() const { } void ServiceDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 5) { if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } @@ -3721,21 +4197,25 @@ void ServiceDescriptorProto::Clear() { bool ServiceDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.ServiceDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_method; break; @@ -3743,13 +4223,12 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( // repeated .google.protobuf.MethodDescriptorProto method = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_method: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_method())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_method; if (input->ExpectTag(26)) goto parse_options; @@ -3758,23 +4237,23 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.ServiceOptions options = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -3782,18 +4261,25 @@ bool ServiceDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.ServiceDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.ServiceDescriptorProto) + return false; #undef DO_ } void ServiceDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.ServiceDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } @@ -3813,15 +4299,18 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceDescriptorProto) } ::google::protobuf::uint8* ServiceDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); @@ -3845,6 +4334,7 @@ void ServiceDescriptorProto::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceDescriptorProto) return target; } @@ -3926,9 +4416,7 @@ void ServiceDescriptorProto::CopyFrom(const ServiceDescriptorProto& from) { bool ServiceDescriptorProto::IsInitialized() const { - for (int i = 0; i < method_size(); i++) { - if (!this->method(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->method())) return false; if (has_options()) { if (!this->options().IsInitialized()) return false; } @@ -3967,6 +4455,7 @@ const int MethodDescriptorProto::kOptionsFieldNumber; MethodDescriptorProto::MethodDescriptorProto() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.MethodDescriptorProto) } void MethodDescriptorProto::InitAsDefaultInstance() { @@ -3977,29 +4466,32 @@ MethodDescriptorProto::MethodDescriptorProto(const MethodDescriptorProto& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto) } void MethodDescriptorProto::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); options_ = NULL; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } MethodDescriptorProto::~MethodDescriptorProto() { + // @@protoc_insertion_point(destructor:google.protobuf.MethodDescriptorProto) SharedDtor(); } void MethodDescriptorProto::SharedDtor() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } - if (input_type_ != &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete input_type_; } - if (output_type_ != &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete output_type_; } if (this != default_instance_) { @@ -4029,19 +4521,19 @@ MethodDescriptorProto* MethodDescriptorProto::New() const { } void MethodDescriptorProto::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 15) { if (has_name()) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } } if (has_input_type()) { - if (input_type_ != &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_->clear(); } } if (has_output_type()) { - if (output_type_ != &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_->clear(); } } @@ -4055,21 +4547,25 @@ void MethodDescriptorProto::Clear() { bool MethodDescriptorProto::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.MethodDescriptorProto) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string name = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_input_type; break; @@ -4077,16 +4573,16 @@ bool MethodDescriptorProto::MergePartialFromCodedStream( // optional string input_type = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_input_type: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_input_type())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->input_type().data(), this->input_type().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "input_type"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_output_type; break; @@ -4094,16 +4590,16 @@ bool MethodDescriptorProto::MergePartialFromCodedStream( // optional string output_type = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_output_type: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_output_type())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->output_type().data(), this->output_type().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "output_type"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(34)) goto parse_options; break; @@ -4111,23 +4607,23 @@ bool MethodDescriptorProto::MergePartialFromCodedStream( // optional .google.protobuf.MethodOptions options = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 34) { parse_options: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, mutable_options())); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -4135,36 +4631,45 @@ bool MethodDescriptorProto::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.MethodDescriptorProto) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.MethodDescriptorProto) + return false; #undef DO_ } void MethodDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.MethodDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name(), output); } // optional string input_type = 2; if (has_input_type()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->input_type().data(), this->input_type().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "input_type"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 2, this->input_type(), output); } // optional string output_type = 3; if (has_output_type()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->output_type().data(), this->output_type().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "output_type"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 3, this->output_type(), output); } @@ -4178,15 +4683,18 @@ void MethodDescriptorProto::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.MethodDescriptorProto) } ::google::protobuf::uint8* MethodDescriptorProto::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto) // optional string name = 1; if (has_name()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name().data(), this->name().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name(), target); @@ -4194,9 +4702,10 @@ void MethodDescriptorProto::SerializeWithCachedSizes( // optional string input_type = 2; if (has_input_type()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->input_type().data(), this->input_type().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "input_type"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 2, this->input_type(), target); @@ -4204,9 +4713,10 @@ void MethodDescriptorProto::SerializeWithCachedSizes( // optional string output_type = 3; if (has_output_type()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->output_type().data(), this->output_type().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "output_type"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 3, this->output_type(), target); @@ -4223,6 +4733,7 @@ void MethodDescriptorProto::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodDescriptorProto) return target; } @@ -4372,17 +4883,20 @@ const int FileOptions::kJavaPackageFieldNumber; const int FileOptions::kJavaOuterClassnameFieldNumber; const int FileOptions::kJavaMultipleFilesFieldNumber; const int FileOptions::kJavaGenerateEqualsAndHashFieldNumber; +const int FileOptions::kJavaStringCheckUtf8FieldNumber; const int FileOptions::kOptimizeForFieldNumber; const int FileOptions::kGoPackageFieldNumber; const int FileOptions::kCcGenericServicesFieldNumber; const int FileOptions::kJavaGenericServicesFieldNumber; const int FileOptions::kPyGenericServicesFieldNumber; +const int FileOptions::kDeprecatedFieldNumber; const int FileOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER FileOptions::FileOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FileOptions) } void FileOptions::InitAsDefaultInstance() { @@ -4392,34 +4906,39 @@ FileOptions::FileOptions(const FileOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions) } void FileOptions::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); java_multiple_files_ = false; java_generate_equals_and_hash_ = false; + java_string_check_utf8_ = false; optimize_for_ = 1; - go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); cc_generic_services_ = false; java_generic_services_ = false; py_generic_services_ = false; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } FileOptions::~FileOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.FileOptions) SharedDtor(); } void FileOptions::SharedDtor() { - if (java_package_ != &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete java_package_; } - if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete java_outer_classname_; } - if (go_package_ != &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete go_package_; } if (this != default_instance_) { @@ -4449,31 +4968,40 @@ FileOptions* FileOptions::New() const { void FileOptions::Clear() { _extensions_.Clear(); - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + if (_has_bits_[0 / 32] & 255) { + ZR_(java_multiple_files_, cc_generic_services_); if (has_java_package()) { - if (java_package_ != &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_->clear(); } } if (has_java_outer_classname()) { - if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_->clear(); } } - java_multiple_files_ = false; - java_generate_equals_and_hash_ = false; optimize_for_ = 1; if (has_go_package()) { - if (go_package_ != &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { go_package_->clear(); } } - cc_generic_services_ = false; - java_generic_services_ = false; - } - if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { - py_generic_services_ = false; } + ZR_(java_generic_services_, deprecated_); + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -4481,21 +5009,25 @@ void FileOptions::Clear() { bool FileOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FileOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional string java_package = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_java_package())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_package().data(), this->java_package().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "java_package"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(66)) goto parse_java_outer_classname; break; @@ -4503,16 +5035,16 @@ bool FileOptions::MergePartialFromCodedStream( // optional string java_outer_classname = 8; case 8: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 66) { parse_java_outer_classname: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_java_outer_classname())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_outer_classname().data(), this->java_outer_classname().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "java_outer_classname"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(72)) goto parse_optimize_for; break; @@ -4520,8 +5052,7 @@ bool FileOptions::MergePartialFromCodedStream( // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; case 9: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 72) { parse_optimize_for: int value; DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< @@ -4533,7 +5064,7 @@ bool FileOptions::MergePartialFromCodedStream( mutable_unknown_fields()->AddVarint(9, value); } } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(80)) goto parse_java_multiple_files; break; @@ -4541,15 +5072,14 @@ bool FileOptions::MergePartialFromCodedStream( // optional bool java_multiple_files = 10 [default = false]; case 10: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 80) { parse_java_multiple_files: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &java_multiple_files_))); set_has_java_multiple_files(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(90)) goto parse_go_package; break; @@ -4557,16 +5087,16 @@ bool FileOptions::MergePartialFromCodedStream( // optional string go_package = 11; case 11: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 90) { parse_go_package: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_go_package())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->go_package().data(), this->go_package().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "go_package"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(128)) goto parse_cc_generic_services; break; @@ -4574,15 +5104,14 @@ bool FileOptions::MergePartialFromCodedStream( // optional bool cc_generic_services = 16 [default = false]; case 16: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 128) { parse_cc_generic_services: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &cc_generic_services_))); set_has_cc_generic_services(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(136)) goto parse_java_generic_services; break; @@ -4590,15 +5119,14 @@ bool FileOptions::MergePartialFromCodedStream( // optional bool java_generic_services = 17 [default = false]; case 17: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 136) { parse_java_generic_services: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &java_generic_services_))); set_has_java_generic_services(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(144)) goto parse_py_generic_services; break; @@ -4606,15 +5134,14 @@ bool FileOptions::MergePartialFromCodedStream( // optional bool py_generic_services = 18 [default = false]; case 18: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 144) { parse_py_generic_services: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &py_generic_services_))); set_has_py_generic_services(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(160)) goto parse_java_generate_equals_and_hash; break; @@ -4622,15 +5149,44 @@ bool FileOptions::MergePartialFromCodedStream( // optional bool java_generate_equals_and_hash = 20 [default = false]; case 20: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 160) { parse_java_generate_equals_and_hash: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &java_generate_equals_and_hash_))); set_has_java_generate_equals_and_hash(); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(184)) goto parse_deprecated; + break; + } + + // optional bool deprecated = 23 [default = false]; + case 23: { + if (tag == 184) { + parse_deprecated: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(216)) goto parse_java_string_check_utf8; + break; + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + case 27: { + if (tag == 216) { + parse_java_string_check_utf8: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &java_string_check_utf8_))); + set_has_java_string_check_utf8(); + } else { + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; @@ -4638,24 +5194,24 @@ bool FileOptions::MergePartialFromCodedStream( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -4668,27 +5224,35 @@ bool FileOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FileOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FileOptions) + return false; #undef DO_ } void FileOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FileOptions) // optional string java_package = 1; if (has_java_package()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_package().data(), this->java_package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "java_package"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->java_package(), output); } // optional string java_outer_classname = 8; if (has_java_outer_classname()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_outer_classname().data(), this->java_outer_classname().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "java_outer_classname"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 8, this->java_outer_classname(), output); } @@ -4705,10 +5269,11 @@ void FileOptions::SerializeWithCachedSizes( // optional string go_package = 11; if (has_go_package()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->go_package().data(), this->go_package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "go_package"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 11, this->go_package(), output); } @@ -4732,6 +5297,16 @@ void FileOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteBool(20, this->java_generate_equals_and_hash(), output); } + // optional bool deprecated = 23 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(23, this->deprecated(), output); + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + if (has_java_string_check_utf8()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(27, this->java_string_check_utf8(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -4746,15 +5321,18 @@ void FileOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FileOptions) } ::google::protobuf::uint8* FileOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions) // optional string java_package = 1; if (has_java_package()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_package().data(), this->java_package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "java_package"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->java_package(), target); @@ -4762,9 +5340,10 @@ void FileOptions::SerializeWithCachedSizes( // optional string java_outer_classname = 8; if (has_java_outer_classname()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->java_outer_classname().data(), this->java_outer_classname().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "java_outer_classname"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 8, this->java_outer_classname(), target); @@ -4783,9 +5362,10 @@ void FileOptions::SerializeWithCachedSizes( // optional string go_package = 11; if (has_go_package()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->go_package().data(), this->go_package().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "go_package"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 11, this->go_package(), target); @@ -4811,6 +5391,16 @@ void FileOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(20, this->java_generate_equals_and_hash(), target); } + // optional bool deprecated = 23 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(23, this->deprecated(), target); + } + + // optional bool java_string_check_utf8 = 27 [default = false]; + if (has_java_string_check_utf8()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(27, this->java_string_check_utf8(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -4826,6 +5416,7 @@ void FileOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FileOptions) return target; } @@ -4857,6 +5448,11 @@ int FileOptions::ByteSize() const { total_size += 2 + 1; } + // optional bool java_string_check_utf8 = 27 [default = false]; + if (has_java_string_check_utf8()) { + total_size += 2 + 1; + } + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; if (has_optimize_for()) { total_size += 1 + @@ -4875,18 +5471,23 @@ int FileOptions::ByteSize() const { total_size += 2 + 1; } + } + if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { // optional bool java_generic_services = 17 [default = false]; if (has_java_generic_services()) { total_size += 2 + 1; } - } - if (_has_bits_[8 / 32] & (0xffu << (8 % 32))) { // optional bool py_generic_services = 18 [default = false]; if (has_py_generic_services()) { total_size += 2 + 1; } + // optional bool deprecated = 23 [default = false]; + if (has_deprecated()) { + total_size += 2 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -4937,6 +5538,9 @@ void FileOptions::MergeFrom(const FileOptions& from) { if (from.has_java_generate_equals_and_hash()) { set_java_generate_equals_and_hash(from.java_generate_equals_and_hash()); } + if (from.has_java_string_check_utf8()) { + set_java_string_check_utf8(from.java_string_check_utf8()); + } if (from.has_optimize_for()) { set_optimize_for(from.optimize_for()); } @@ -4946,14 +5550,17 @@ void FileOptions::MergeFrom(const FileOptions& from) { if (from.has_cc_generic_services()) { set_cc_generic_services(from.cc_generic_services()); } + } + if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { if (from.has_java_generic_services()) { set_java_generic_services(from.java_generic_services()); } - } - if (from._has_bits_[8 / 32] & (0xffu << (8 % 32))) { if (from.has_py_generic_services()) { set_py_generic_services(from.py_generic_services()); } + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -4973,9 +5580,7 @@ void FileOptions::CopyFrom(const FileOptions& from) { bool FileOptions::IsInitialized() const { - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; if (!_extensions_.IsInitialized()) return false; return true; } @@ -4986,11 +5591,13 @@ void FileOptions::Swap(FileOptions* other) { std::swap(java_outer_classname_, other->java_outer_classname_); std::swap(java_multiple_files_, other->java_multiple_files_); std::swap(java_generate_equals_and_hash_, other->java_generate_equals_and_hash_); + std::swap(java_string_check_utf8_, other->java_string_check_utf8_); std::swap(optimize_for_, other->optimize_for_); std::swap(go_package_, other->go_package_); std::swap(cc_generic_services_, other->cc_generic_services_); std::swap(java_generic_services_, other->java_generic_services_); std::swap(py_generic_services_, other->py_generic_services_); + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -5013,12 +5620,14 @@ void FileOptions::Swap(FileOptions* other) { #ifndef _MSC_VER const int MessageOptions::kMessageSetWireFormatFieldNumber; const int MessageOptions::kNoStandardDescriptorAccessorFieldNumber; +const int MessageOptions::kDeprecatedFieldNumber; const int MessageOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER MessageOptions::MessageOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.MessageOptions) } void MessageOptions::InitAsDefaultInstance() { @@ -5028,16 +5637,19 @@ MessageOptions::MessageOptions(const MessageOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions) } void MessageOptions::SharedCtor() { _cached_size_ = 0; message_set_wire_format_ = false; no_standard_descriptor_accessor_ = false; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } MessageOptions::~MessageOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.MessageOptions) SharedDtor(); } @@ -5069,10 +5681,21 @@ MessageOptions* MessageOptions::New() const { void MessageOptions::Clear() { _extensions_.Clear(); - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - message_set_wire_format_ = false; - no_standard_descriptor_accessor_ = false; - } +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + ZR_(message_set_wire_format_, deprecated_); + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -5080,20 +5703,23 @@ void MessageOptions::Clear() { bool MessageOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.MessageOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional bool message_set_wire_format = 1 [default = false]; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 8) { DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &message_set_wire_format_))); set_has_message_set_wire_format(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_no_standard_descriptor_accessor; break; @@ -5101,15 +5727,29 @@ bool MessageOptions::MergePartialFromCodedStream( // optional bool no_standard_descriptor_accessor = 2 [default = false]; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_no_standard_descriptor_accessor: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &no_standard_descriptor_accessor_))); set_has_no_standard_descriptor_accessor(); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(24)) goto parse_deprecated; + break; + } + + // optional bool deprecated = 3 [default = false]; + case 3: { + if (tag == 24) { + parse_deprecated: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; @@ -5117,24 +5757,24 @@ bool MessageOptions::MergePartialFromCodedStream( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -5147,12 +5787,18 @@ bool MessageOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.MessageOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.MessageOptions) + return false; #undef DO_ } void MessageOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.MessageOptions) // optional bool message_set_wire_format = 1 [default = false]; if (has_message_set_wire_format()) { ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->message_set_wire_format(), output); @@ -5163,6 +5809,11 @@ void MessageOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->no_standard_descriptor_accessor(), output); } + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -5177,10 +5828,12 @@ void MessageOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.MessageOptions) } ::google::protobuf::uint8* MessageOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions) // optional bool message_set_wire_format = 1 [default = false]; if (has_message_set_wire_format()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->message_set_wire_format(), target); @@ -5191,6 +5844,11 @@ void MessageOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->no_standard_descriptor_accessor(), target); } + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -5206,6 +5864,7 @@ void MessageOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MessageOptions) return target; } @@ -5223,6 +5882,11 @@ int MessageOptions::ByteSize() const { total_size += 1 + 1; } + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + total_size += 1 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -5267,6 +5931,9 @@ void MessageOptions::MergeFrom(const MessageOptions& from) { if (from.has_no_standard_descriptor_accessor()) { set_no_standard_descriptor_accessor(from.no_standard_descriptor_accessor()); } + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -5286,9 +5953,7 @@ void MessageOptions::CopyFrom(const MessageOptions& from) { bool MessageOptions::IsInitialized() const { - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; if (!_extensions_.IsInitialized()) return false; return true; } @@ -5297,6 +5962,7 @@ void MessageOptions::Swap(MessageOptions* other) { if (other != this) { std::swap(message_set_wire_format_, other->message_set_wire_format_); std::swap(no_standard_descriptor_accessor_, other->no_standard_descriptor_accessor_); + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -5352,6 +6018,7 @@ const int FieldOptions::kUninterpretedOptionFieldNumber; FieldOptions::FieldOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.FieldOptions) } void FieldOptions::InitAsDefaultInstance() { @@ -5361,25 +6028,28 @@ FieldOptions::FieldOptions(const FieldOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions) } void FieldOptions::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; ctype_ = 0; packed_ = false; lazy_ = false; deprecated_ = false; - experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); weak_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } FieldOptions::~FieldOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.FieldOptions) SharedDtor(); } void FieldOptions::SharedDtor() { - if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete experimental_map_key_; } if (this != default_instance_) { @@ -5409,18 +6079,28 @@ FieldOptions* FieldOptions::New() const { void FieldOptions::Clear() { _extensions_.Clear(); - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - ctype_ = 0; - packed_ = false; - lazy_ = false; - deprecated_ = false; +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + if (_has_bits_[0 / 32] & 63) { + ZR_(ctype_, weak_); if (has_experimental_map_key()) { - if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_->clear(); } } - weak_ = false; } + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -5428,14 +6108,17 @@ void FieldOptions::Clear() { bool FieldOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.FieldOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 8) { int value; DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( @@ -5446,7 +6129,7 @@ bool FieldOptions::MergePartialFromCodedStream( mutable_unknown_fields()->AddVarint(1, value); } } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_packed; break; @@ -5454,15 +6137,14 @@ bool FieldOptions::MergePartialFromCodedStream( // optional bool packed = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_packed: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &packed_))); set_has_packed(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(24)) goto parse_deprecated; break; @@ -5470,15 +6152,14 @@ bool FieldOptions::MergePartialFromCodedStream( // optional bool deprecated = 3 [default = false]; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 24) { parse_deprecated: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &deprecated_))); set_has_deprecated(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(40)) goto parse_lazy; break; @@ -5486,15 +6167,14 @@ bool FieldOptions::MergePartialFromCodedStream( // optional bool lazy = 5 [default = false]; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 40) { parse_lazy: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &lazy_))); set_has_lazy(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(74)) goto parse_experimental_map_key; break; @@ -5502,16 +6182,16 @@ bool FieldOptions::MergePartialFromCodedStream( // optional string experimental_map_key = 9; case 9: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 74) { parse_experimental_map_key: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_experimental_map_key())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->experimental_map_key().data(), this->experimental_map_key().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "experimental_map_key"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(80)) goto parse_weak; break; @@ -5519,15 +6199,14 @@ bool FieldOptions::MergePartialFromCodedStream( // optional bool weak = 10 [default = false]; case 10: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 80) { parse_weak: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &weak_))); set_has_weak(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; @@ -5535,24 +6214,24 @@ bool FieldOptions::MergePartialFromCodedStream( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -5565,12 +6244,18 @@ bool FieldOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.FieldOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.FieldOptions) + return false; #undef DO_ } void FieldOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.FieldOptions) // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (has_ctype()) { ::google::protobuf::internal::WireFormatLite::WriteEnum( @@ -5594,10 +6279,11 @@ void FieldOptions::SerializeWithCachedSizes( // optional string experimental_map_key = 9; if (has_experimental_map_key()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->experimental_map_key().data(), this->experimental_map_key().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "experimental_map_key"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 9, this->experimental_map_key(), output); } @@ -5620,10 +6306,12 @@ void FieldOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.FieldOptions) } ::google::protobuf::uint8* FieldOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions) // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING]; if (has_ctype()) { target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( @@ -5647,9 +6335,10 @@ void FieldOptions::SerializeWithCachedSizes( // optional string experimental_map_key = 9; if (has_experimental_map_key()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->experimental_map_key().data(), this->experimental_map_key().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "experimental_map_key"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 9, this->experimental_map_key(), target); @@ -5675,6 +6364,7 @@ void FieldOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.FieldOptions) return target; } @@ -5790,9 +6480,7 @@ void FieldOptions::CopyFrom(const FieldOptions& from) { bool FieldOptions::IsInitialized() const { - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; if (!_extensions_.IsInitialized()) return false; return true; } @@ -5826,12 +6514,14 @@ void FieldOptions::Swap(FieldOptions* other) { #ifndef _MSC_VER const int EnumOptions::kAllowAliasFieldNumber; +const int EnumOptions::kDeprecatedFieldNumber; const int EnumOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER EnumOptions::EnumOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.EnumOptions) } void EnumOptions::InitAsDefaultInstance() { @@ -5841,15 +6531,18 @@ EnumOptions::EnumOptions(const EnumOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions) } void EnumOptions::SharedCtor() { _cached_size_ = 0; - allow_alias_ = true; + allow_alias_ = false; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } EnumOptions::~EnumOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumOptions) SharedDtor(); } @@ -5881,9 +6574,21 @@ EnumOptions* EnumOptions::New() const { void EnumOptions::Clear() { _extensions_.Clear(); - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - allow_alias_ = true; - } +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + ZR_(allow_alias_, deprecated_); + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -5891,20 +6596,38 @@ void EnumOptions::Clear() { bool EnumOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.EnumOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { - // optional bool allow_alias = 2 [default = true]; + // optional bool allow_alias = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &allow_alias_))); set_has_allow_alias(); } else { - goto handle_uninterpreted; + goto handle_unusual; + } + if (input->ExpectTag(24)) goto parse_deprecated; + break; + } + + // optional bool deprecated = 3 [default = false]; + case 3: { + if (tag == 24) { + parse_deprecated: + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; break; @@ -5912,24 +6635,24 @@ bool EnumOptions::MergePartialFromCodedStream( // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -5942,17 +6665,28 @@ bool EnumOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.EnumOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.EnumOptions) + return false; #undef DO_ } void EnumOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { - // optional bool allow_alias = 2 [default = true]; + // @@protoc_insertion_point(serialize_start:google.protobuf.EnumOptions) + // optional bool allow_alias = 2; if (has_allow_alias()) { ::google::protobuf::internal::WireFormatLite::WriteBool(2, this->allow_alias(), output); } + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(3, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -5967,15 +6701,22 @@ void EnumOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.EnumOptions) } ::google::protobuf::uint8* EnumOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { - // optional bool allow_alias = 2 [default = true]; + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions) + // optional bool allow_alias = 2; if (has_allow_alias()) { target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(2, this->allow_alias(), target); } + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(3, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -5991,6 +6732,7 @@ void EnumOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumOptions) return target; } @@ -5998,11 +6740,16 @@ int EnumOptions::ByteSize() const { int total_size = 0; if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { - // optional bool allow_alias = 2 [default = true]; + // optional bool allow_alias = 2; if (has_allow_alias()) { total_size += 1 + 1; } + // optional bool deprecated = 3 [default = false]; + if (has_deprecated()) { + total_size += 1 + 1; + } + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); @@ -6044,6 +6791,9 @@ void EnumOptions::MergeFrom(const EnumOptions& from) { if (from.has_allow_alias()) { set_allow_alias(from.allow_alias()); } + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); @@ -6063,9 +6813,7 @@ void EnumOptions::CopyFrom(const EnumOptions& from) { bool EnumOptions::IsInitialized() const { - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; if (!_extensions_.IsInitialized()) return false; return true; } @@ -6073,6 +6821,7 @@ bool EnumOptions::IsInitialized() const { void EnumOptions::Swap(EnumOptions* other) { if (other != this) { std::swap(allow_alias_, other->allow_alias_); + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -6093,12 +6842,14 @@ void EnumOptions::Swap(EnumOptions* other) { // =================================================================== #ifndef _MSC_VER +const int EnumValueOptions::kDeprecatedFieldNumber; const int EnumValueOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER EnumValueOptions::EnumValueOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.EnumValueOptions) } void EnumValueOptions::InitAsDefaultInstance() { @@ -6108,14 +6859,17 @@ EnumValueOptions::EnumValueOptions(const EnumValueOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumValueOptions) } void EnumValueOptions::SharedCtor() { _cached_size_ = 0; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } EnumValueOptions::~EnumValueOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.EnumValueOptions) SharedDtor(); } @@ -6147,6 +6901,7 @@ EnumValueOptions* EnumValueOptions::New() const { void EnumValueOptions::Clear() { _extensions_.Clear(); + deprecated_ = false; uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -6154,30 +6909,48 @@ void EnumValueOptions::Clear() { bool EnumValueOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.EnumValueOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool deprecated = 1 [default = false]; + case 1: { + if (tag == 8) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -6190,12 +6963,23 @@ bool EnumValueOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.EnumValueOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.EnumValueOptions) + return false; #undef DO_ } void EnumValueOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.EnumValueOptions) + // optional bool deprecated = 1 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(1, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -6210,10 +6994,17 @@ void EnumValueOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.EnumValueOptions) } ::google::protobuf::uint8* EnumValueOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions) + // optional bool deprecated = 1 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(1, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -6229,12 +7020,20 @@ void EnumValueOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.EnumValueOptions) return target; } int EnumValueOptions::ByteSize() const { int total_size = 0; + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool deprecated = 1 [default = false]; + if (has_deprecated()) { + total_size += 1 + 1; + } + + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { @@ -6271,6 +7070,11 @@ void EnumValueOptions::MergeFrom(const ::google::protobuf::Message& from) { void EnumValueOptions::MergeFrom(const EnumValueOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } + } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -6289,15 +7093,14 @@ void EnumValueOptions::CopyFrom(const EnumValueOptions& from) { bool EnumValueOptions::IsInitialized() const { - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; if (!_extensions_.IsInitialized()) return false; return true; } void EnumValueOptions::Swap(EnumValueOptions* other) { if (other != this) { + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -6318,12 +7121,14 @@ void EnumValueOptions::Swap(EnumValueOptions* other) { // =================================================================== #ifndef _MSC_VER +const int ServiceOptions::kDeprecatedFieldNumber; const int ServiceOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER ServiceOptions::ServiceOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.ServiceOptions) } void ServiceOptions::InitAsDefaultInstance() { @@ -6333,14 +7138,17 @@ ServiceOptions::ServiceOptions(const ServiceOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceOptions) } void ServiceOptions::SharedCtor() { _cached_size_ = 0; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } ServiceOptions::~ServiceOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.ServiceOptions) SharedDtor(); } @@ -6372,6 +7180,7 @@ ServiceOptions* ServiceOptions::New() const { void ServiceOptions::Clear() { _extensions_.Clear(); + deprecated_ = false; uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -6379,30 +7188,48 @@ void ServiceOptions::Clear() { bool ServiceOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.ServiceOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool deprecated = 33 [default = false]; + case 33: { + if (tag == 264) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -6415,12 +7242,23 @@ bool ServiceOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.ServiceOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.ServiceOptions) + return false; #undef DO_ } void ServiceOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.ServiceOptions) + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(33, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -6435,10 +7273,17 @@ void ServiceOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.ServiceOptions) } ::google::protobuf::uint8* ServiceOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions) + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(33, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -6454,12 +7299,20 @@ void ServiceOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ServiceOptions) return target; } int ServiceOptions::ByteSize() const { int total_size = 0; + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + total_size += 2 + 1; + } + + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { @@ -6496,6 +7349,11 @@ void ServiceOptions::MergeFrom(const ::google::protobuf::Message& from) { void ServiceOptions::MergeFrom(const ServiceOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } + } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -6514,15 +7372,14 @@ void ServiceOptions::CopyFrom(const ServiceOptions& from) { bool ServiceOptions::IsInitialized() const { - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; if (!_extensions_.IsInitialized()) return false; return true; } void ServiceOptions::Swap(ServiceOptions* other) { if (other != this) { + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -6543,12 +7400,14 @@ void ServiceOptions::Swap(ServiceOptions* other) { // =================================================================== #ifndef _MSC_VER +const int MethodOptions::kDeprecatedFieldNumber; const int MethodOptions::kUninterpretedOptionFieldNumber; #endif // !_MSC_VER MethodOptions::MethodOptions() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.MethodOptions) } void MethodOptions::InitAsDefaultInstance() { @@ -6558,14 +7417,17 @@ MethodOptions::MethodOptions(const MethodOptions& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions) } void MethodOptions::SharedCtor() { _cached_size_ = 0; + deprecated_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } MethodOptions::~MethodOptions() { + // @@protoc_insertion_point(destructor:google.protobuf.MethodOptions) SharedDtor(); } @@ -6597,6 +7459,7 @@ MethodOptions* MethodOptions::New() const { void MethodOptions::Clear() { _extensions_.Clear(); + deprecated_ = false; uninterpreted_option_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -6604,30 +7467,48 @@ void MethodOptions::Clear() { bool MethodOptions::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.MethodOptions) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(16383); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // optional bool deprecated = 33 [default = false]; + case 33: { + if (tag == 264) { + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &deprecated_))); + set_has_deprecated(); + } else { + goto handle_unusual; + } + if (input->ExpectTag(7994)) goto parse_uninterpreted_option; + break; + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; case 999: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 7994) { parse_uninterpreted_option: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_uninterpreted_option())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(7994)) goto parse_uninterpreted_option; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } if ((8000u <= tag)) { DO_(_extensions_.ParseField(tag, input, default_instance_, @@ -6640,12 +7521,23 @@ bool MethodOptions::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.MethodOptions) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.MethodOptions) + return false; #undef DO_ } void MethodOptions::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.MethodOptions) + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(33, this->deprecated(), output); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -6660,10 +7552,17 @@ void MethodOptions::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.MethodOptions) } ::google::protobuf::uint8* MethodOptions::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions) + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(33, this->deprecated(), target); + } + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; for (int i = 0; i < this->uninterpreted_option_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -6679,12 +7578,20 @@ void MethodOptions::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.MethodOptions) return target; } int MethodOptions::ByteSize() const { int total_size = 0; + if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + // optional bool deprecated = 33 [default = false]; + if (has_deprecated()) { + total_size += 2 + 1; + } + + } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; total_size += 2 * this->uninterpreted_option_size(); for (int i = 0; i < this->uninterpreted_option_size(); i++) { @@ -6721,6 +7628,11 @@ void MethodOptions::MergeFrom(const ::google::protobuf::Message& from) { void MethodOptions::MergeFrom(const MethodOptions& from) { GOOGLE_CHECK_NE(&from, this); uninterpreted_option_.MergeFrom(from.uninterpreted_option_); + if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (from.has_deprecated()) { + set_deprecated(from.deprecated()); + } + } _extensions_.MergeFrom(from._extensions_); mutable_unknown_fields()->MergeFrom(from.unknown_fields()); } @@ -6739,15 +7651,14 @@ void MethodOptions::CopyFrom(const MethodOptions& from) { bool MethodOptions::IsInitialized() const { - for (int i = 0; i < uninterpreted_option_size(); i++) { - if (!this->uninterpreted_option(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->uninterpreted_option())) return false; if (!_extensions_.IsInitialized()) return false; return true; } void MethodOptions::Swap(MethodOptions* other) { if (other != this) { + std::swap(deprecated_, other->deprecated_); uninterpreted_option_.Swap(&other->uninterpreted_option_); std::swap(_has_bits_[0], other->_has_bits_[0]); _unknown_fields_.Swap(&other->_unknown_fields_); @@ -6775,6 +7686,7 @@ const int UninterpretedOption_NamePart::kIsExtensionFieldNumber; UninterpretedOption_NamePart::UninterpretedOption_NamePart() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption.NamePart) } void UninterpretedOption_NamePart::InitAsDefaultInstance() { @@ -6784,21 +7696,24 @@ UninterpretedOption_NamePart::UninterpretedOption_NamePart(const UninterpretedOp : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption.NamePart) } void UninterpretedOption_NamePart::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); is_extension_ = false; ::memset(_has_bits_, 0, sizeof(_has_bits_)); } UninterpretedOption_NamePart::~UninterpretedOption_NamePart() { + // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption.NamePart) SharedDtor(); } void UninterpretedOption_NamePart::SharedDtor() { - if (name_part_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_part_; } if (this != default_instance_) { @@ -6827,9 +7742,9 @@ UninterpretedOption_NamePart* UninterpretedOption_NamePart::New() const { } void UninterpretedOption_NamePart::Clear() { - if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) { + if (_has_bits_[0 / 32] & 3) { if (has_name_part()) { - if (name_part_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_->clear(); } } @@ -6841,21 +7756,25 @@ void UninterpretedOption_NamePart::Clear() { bool UninterpretedOption_NamePart::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption.NamePart) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // required string name_part = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_name_part())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name_part().data(), this->name_part().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "name_part"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(16)) goto parse_is_extension; break; @@ -6863,25 +7782,25 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream( // required bool is_extension = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 16) { parse_is_extension: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( input, &is_extension_))); set_has_is_extension(); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -6889,18 +7808,25 @@ bool UninterpretedOption_NamePart::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.UninterpretedOption.NamePart) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.UninterpretedOption.NamePart) + return false; #undef DO_ } void UninterpretedOption_NamePart::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.UninterpretedOption.NamePart) // required string name_part = 1; if (has_name_part()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name_part().data(), this->name_part().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name_part"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 1, this->name_part(), output); } @@ -6913,15 +7839,18 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption.NamePart) } ::google::protobuf::uint8* UninterpretedOption_NamePart::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart) // required string name_part = 1; if (has_name_part()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->name_part().data(), this->name_part().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "name_part"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 1, this->name_part(), target); @@ -6936,6 +7865,7 @@ void UninterpretedOption_NamePart::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption.NamePart) return target; } @@ -7044,6 +7974,7 @@ const int UninterpretedOption::kAggregateValueFieldNumber; UninterpretedOption::UninterpretedOption() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.UninterpretedOption) } void UninterpretedOption::InitAsDefaultInstance() { @@ -7053,31 +7984,34 @@ UninterpretedOption::UninterpretedOption(const UninterpretedOption& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption) } void UninterpretedOption::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); positive_int_value_ = GOOGLE_ULONGLONG(0); negative_int_value_ = GOOGLE_LONGLONG(0); double_value_ = 0; - string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } UninterpretedOption::~UninterpretedOption() { + // @@protoc_insertion_point(destructor:google.protobuf.UninterpretedOption) SharedDtor(); } void UninterpretedOption::SharedDtor() { - if (identifier_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete identifier_value_; } - if (string_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete string_value_; } - if (aggregate_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete aggregate_value_; } if (this != default_instance_) { @@ -7106,26 +8040,38 @@ UninterpretedOption* UninterpretedOption::New() const { } void UninterpretedOption::Clear() { - if (_has_bits_[1 / 32] & (0xffu << (1 % 32))) { +#define OFFSET_OF_FIELD_(f) (reinterpret_cast( \ + &reinterpret_cast(16)->f) - \ + reinterpret_cast(16)) + +#define ZR_(first, last) do { \ + size_t f = OFFSET_OF_FIELD_(first); \ + size_t n = OFFSET_OF_FIELD_(last) - f + sizeof(last); \ + ::memset(&first, 0, n); \ + } while (0) + + if (_has_bits_[0 / 32] & 126) { + ZR_(positive_int_value_, double_value_); if (has_identifier_value()) { - if (identifier_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_->clear(); } } - positive_int_value_ = GOOGLE_ULONGLONG(0); - negative_int_value_ = GOOGLE_LONGLONG(0); - double_value_ = 0; if (has_string_value()) { - if (string_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_->clear(); } } if (has_aggregate_value()) { - if (aggregate_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { aggregate_value_->clear(); } } } + +#undef OFFSET_OF_FIELD_ +#undef ZR_ + name_.Clear(); ::memset(_has_bits_, 0, sizeof(_has_bits_)); mutable_unknown_fields()->Clear(); @@ -7133,19 +8079,22 @@ void UninterpretedOption::Clear() { bool UninterpretedOption::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.UninterpretedOption) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_name: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_name())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_name; if (input->ExpectTag(26)) goto parse_identifier_value; @@ -7154,16 +8103,16 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional string identifier_value = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_identifier_value: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_identifier_value())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->identifier_value().data(), this->identifier_value().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "identifier_value"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(32)) goto parse_positive_int_value; break; @@ -7171,15 +8120,14 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional uint64 positive_int_value = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 32) { parse_positive_int_value: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::uint64, ::google::protobuf::internal::WireFormatLite::TYPE_UINT64>( input, &positive_int_value_))); set_has_positive_int_value(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(40)) goto parse_negative_int_value; break; @@ -7187,15 +8135,14 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional int64 negative_int_value = 5; case 5: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) { + if (tag == 40) { parse_negative_int_value: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( input, &negative_int_value_))); set_has_negative_int_value(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(49)) goto parse_double_value; break; @@ -7203,15 +8150,14 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional double double_value = 6; case 6: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_FIXED64) { + if (tag == 49) { parse_double_value: DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( input, &double_value_))); set_has_double_value(); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(58)) goto parse_string_value; break; @@ -7219,13 +8165,12 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional bytes string_value = 7; case 7: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 58) { parse_string_value: DO_(::google::protobuf::internal::WireFormatLite::ReadBytes( input, this->mutable_string_value())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(66)) goto parse_aggregate_value; break; @@ -7233,26 +8178,27 @@ bool UninterpretedOption::MergePartialFromCodedStream( // optional string aggregate_value = 8; case 8: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 66) { parse_aggregate_value: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_aggregate_value())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->aggregate_value().data(), this->aggregate_value().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "aggregate_value"); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -7260,12 +8206,18 @@ bool UninterpretedOption::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.UninterpretedOption) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.UninterpretedOption) + return false; #undef DO_ } void UninterpretedOption::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.UninterpretedOption) // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; for (int i = 0; i < this->name_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -7274,10 +8226,11 @@ void UninterpretedOption::SerializeWithCachedSizes( // optional string identifier_value = 3; if (has_identifier_value()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->identifier_value().data(), this->identifier_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "identifier_value"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 3, this->identifier_value(), output); } @@ -7298,16 +8251,17 @@ void UninterpretedOption::SerializeWithCachedSizes( // optional bytes string_value = 7; if (has_string_value()) { - ::google::protobuf::internal::WireFormatLite::WriteBytes( + ::google::protobuf::internal::WireFormatLite::WriteBytesMaybeAliased( 7, this->string_value(), output); } // optional string aggregate_value = 8; if (has_aggregate_value()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->aggregate_value().data(), this->aggregate_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "aggregate_value"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 8, this->aggregate_value(), output); } @@ -7315,10 +8269,12 @@ void UninterpretedOption::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.UninterpretedOption) } ::google::protobuf::uint8* UninterpretedOption::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption) // repeated .google.protobuf.UninterpretedOption.NamePart name = 2; for (int i = 0; i < this->name_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -7328,9 +8284,10 @@ void UninterpretedOption::SerializeWithCachedSizes( // optional string identifier_value = 3; if (has_identifier_value()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->identifier_value().data(), this->identifier_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "identifier_value"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 3, this->identifier_value(), target); @@ -7360,9 +8317,10 @@ void UninterpretedOption::SerializeWithCachedSizes( // optional string aggregate_value = 8; if (has_aggregate_value()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->aggregate_value().data(), this->aggregate_value().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "aggregate_value"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 8, this->aggregate_value(), target); @@ -7372,6 +8330,7 @@ void UninterpretedOption::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.UninterpretedOption) return target; } @@ -7491,9 +8450,7 @@ void UninterpretedOption::CopyFrom(const UninterpretedOption& from) { bool UninterpretedOption::IsInitialized() const { - for (int i = 0; i < name_size(); i++) { - if (!this->name(i).IsInitialized()) return false; - } + if (!::google::protobuf::internal::AllAreInitialized(this->name())) return false; return true; } @@ -7533,6 +8490,7 @@ const int SourceCodeInfo_Location::kTrailingCommentsFieldNumber; SourceCodeInfo_Location::SourceCodeInfo_Location() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo.Location) } void SourceCodeInfo_Location::InitAsDefaultInstance() { @@ -7542,24 +8500,27 @@ SourceCodeInfo_Location::SourceCodeInfo_Location(const SourceCodeInfo_Location& : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo.Location) } void SourceCodeInfo_Location::SharedCtor() { + ::google::protobuf::internal::GetEmptyString(); _cached_size_ = 0; - leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); - trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); ::memset(_has_bits_, 0, sizeof(_has_bits_)); } SourceCodeInfo_Location::~SourceCodeInfo_Location() { + // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo.Location) SharedDtor(); } void SourceCodeInfo_Location::SharedDtor() { - if (leading_comments_ != &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete leading_comments_; } - if (trailing_comments_ != &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete trailing_comments_; } if (this != default_instance_) { @@ -7588,14 +8549,14 @@ SourceCodeInfo_Location* SourceCodeInfo_Location::New() const { } void SourceCodeInfo_Location::Clear() { - if (_has_bits_[2 / 32] & (0xffu << (2 % 32))) { + if (_has_bits_[0 / 32] & 12) { if (has_leading_comments()) { - if (leading_comments_ != &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { leading_comments_->clear(); } } if (has_trailing_comments()) { - if (trailing_comments_ != &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { trailing_comments_->clear(); } } @@ -7608,25 +8569,26 @@ void SourceCodeInfo_Location::Clear() { bool SourceCodeInfo_Location::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo.Location) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated int32 path = 1 [packed = true]; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, this->mutable_path()))); - } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) - == ::google::protobuf::internal::WireFormatLite:: - WIRETYPE_VARINT) { + } else if (tag == 8) { DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( 1, 10, input, this->mutable_path()))); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(18)) goto parse_span; break; @@ -7634,20 +8596,17 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream( // repeated int32 span = 2 [packed = true]; case 2: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 18) { parse_span: DO_((::google::protobuf::internal::WireFormatLite::ReadPackedPrimitive< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( input, this->mutable_span()))); - } else if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) - == ::google::protobuf::internal::WireFormatLite:: - WIRETYPE_VARINT) { + } else if (tag == 16) { DO_((::google::protobuf::internal::WireFormatLite::ReadRepeatedPrimitiveNoInline< ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( 1, 18, input, this->mutable_span()))); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(26)) goto parse_leading_comments; break; @@ -7655,16 +8614,16 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream( // optional string leading_comments = 3; case 3: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 26) { parse_leading_comments: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_leading_comments())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->leading_comments().data(), this->leading_comments().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "leading_comments"); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(34)) goto parse_trailing_comments; break; @@ -7672,26 +8631,27 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream( // optional string trailing_comments = 4; case 4: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 34) { parse_trailing_comments: DO_(::google::protobuf::internal::WireFormatLite::ReadString( input, this->mutable_trailing_comments())); - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->trailing_comments().data(), this->trailing_comments().length(), - ::google::protobuf::internal::WireFormat::PARSE); + ::google::protobuf::internal::WireFormat::PARSE, + "trailing_comments"); } else { - goto handle_uninterpreted; + goto handle_unusual; } - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -7699,12 +8659,18 @@ bool SourceCodeInfo_Location::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.SourceCodeInfo.Location) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.SourceCodeInfo.Location) + return false; #undef DO_ } void SourceCodeInfo_Location::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.SourceCodeInfo.Location) // repeated int32 path = 1 [packed = true]; if (this->path_size() > 0) { ::google::protobuf::internal::WireFormatLite::WriteTag(1, ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED, output); @@ -7727,19 +8693,21 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( // optional string leading_comments = 3; if (has_leading_comments()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->leading_comments().data(), this->leading_comments().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "leading_comments"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 3, this->leading_comments(), output); } // optional string trailing_comments = 4; if (has_trailing_comments()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->trailing_comments().data(), this->trailing_comments().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); - ::google::protobuf::internal::WireFormatLite::WriteString( + ::google::protobuf::internal::WireFormat::SERIALIZE, + "trailing_comments"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( 4, this->trailing_comments(), output); } @@ -7747,10 +8715,12 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo.Location) } ::google::protobuf::uint8* SourceCodeInfo_Location::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location) // repeated int32 path = 1 [packed = true]; if (this->path_size() > 0) { target = ::google::protobuf::internal::WireFormatLite::WriteTagToArray( @@ -7781,9 +8751,10 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( // optional string leading_comments = 3; if (has_leading_comments()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->leading_comments().data(), this->leading_comments().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "leading_comments"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 3, this->leading_comments(), target); @@ -7791,9 +8762,10 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( // optional string trailing_comments = 4; if (has_trailing_comments()) { - ::google::protobuf::internal::WireFormat::VerifyUTF8String( + ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField( this->trailing_comments().data(), this->trailing_comments().length(), - ::google::protobuf::internal::WireFormat::SERIALIZE); + ::google::protobuf::internal::WireFormat::SERIALIZE, + "trailing_comments"); target = ::google::protobuf::internal::WireFormatLite::WriteStringToArray( 4, this->trailing_comments(), target); @@ -7803,6 +8775,7 @@ void SourceCodeInfo_Location::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo.Location) return target; } @@ -7944,6 +8917,7 @@ const int SourceCodeInfo::kLocationFieldNumber; SourceCodeInfo::SourceCodeInfo() : ::google::protobuf::Message() { SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.SourceCodeInfo) } void SourceCodeInfo::InitAsDefaultInstance() { @@ -7953,6 +8927,7 @@ SourceCodeInfo::SourceCodeInfo(const SourceCodeInfo& from) : ::google::protobuf::Message() { SharedCtor(); MergeFrom(from); + // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceCodeInfo) } void SourceCodeInfo::SharedCtor() { @@ -7961,6 +8936,7 @@ void SourceCodeInfo::SharedCtor() { } SourceCodeInfo::~SourceCodeInfo() { + // @@protoc_insertion_point(destructor:google.protobuf.SourceCodeInfo) SharedDtor(); } @@ -7998,30 +8974,34 @@ void SourceCodeInfo::Clear() { bool SourceCodeInfo::MergePartialFromCodedStream( ::google::protobuf::io::CodedInputStream* input) { -#define DO_(EXPRESSION) if (!(EXPRESSION)) return false +#define DO_(EXPRESSION) if (!(EXPRESSION)) goto failure ::google::protobuf::uint32 tag; - while ((tag = input->ReadTag()) != 0) { + // @@protoc_insertion_point(parse_start:google.protobuf.SourceCodeInfo) + for (;;) { + ::std::pair< ::google::protobuf::uint32, bool> p = input->ReadTagWithCutoff(127); + tag = p.first; + if (!p.second) goto handle_unusual; switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { // repeated .google.protobuf.SourceCodeInfo.Location location = 1; case 1: { - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == - ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) { + if (tag == 10) { parse_location: DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( input, add_location())); } else { - goto handle_uninterpreted; + goto handle_unusual; } if (input->ExpectTag(10)) goto parse_location; - if (input->ExpectAtEnd()) return true; + if (input->ExpectAtEnd()) goto success; break; } default: { - handle_uninterpreted: - if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == + handle_unusual: + if (tag == 0 || + ::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) == ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) { - return true; + goto success; } DO_(::google::protobuf::internal::WireFormat::SkipField( input, tag, mutable_unknown_fields())); @@ -8029,12 +9009,18 @@ bool SourceCodeInfo::MergePartialFromCodedStream( } } } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.SourceCodeInfo) return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.SourceCodeInfo) + return false; #undef DO_ } void SourceCodeInfo::SerializeWithCachedSizes( ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.SourceCodeInfo) // repeated .google.protobuf.SourceCodeInfo.Location location = 1; for (int i = 0; i < this->location_size(); i++) { ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( @@ -8045,10 +9031,12 @@ void SourceCodeInfo::SerializeWithCachedSizes( ::google::protobuf::internal::WireFormat::SerializeUnknownFields( unknown_fields(), output); } + // @@protoc_insertion_point(serialize_end:google.protobuf.SourceCodeInfo) } ::google::protobuf::uint8* SourceCodeInfo::SerializeWithCachedSizesToArray( ::google::protobuf::uint8* target) const { + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo) // repeated .google.protobuf.SourceCodeInfo.Location location = 1; for (int i = 0; i < this->location_size(); i++) { target = ::google::protobuf::internal::WireFormatLite:: @@ -8060,6 +9048,7 @@ void SourceCodeInfo::SerializeWithCachedSizes( target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( unknown_fields(), target); } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceCodeInfo) return target; } diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h index cfed2883..36d4d1b7 100644 --- a/src/google/protobuf/descriptor.pb.h +++ b/src/google/protobuf/descriptor.pb.h @@ -40,6 +40,7 @@ class FileDescriptorProto; class DescriptorProto; class DescriptorProto_ExtensionRange; class FieldDescriptorProto; +class OneofDescriptorProto; class EnumDescriptorProto; class EnumValueDescriptorProto; class ServiceDescriptorProto; @@ -200,7 +201,6 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -224,11 +224,9 @@ class LIBPROTOBUF_EXPORT FileDescriptorSet : public ::google::protobuf::Message ::google::protobuf::UnknownFieldSet _unknown_fields_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_; - + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - + ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto > file_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -285,7 +283,6 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -435,6 +432,8 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_; ::std::string* package_; ::google::protobuf::RepeatedPtrField< ::std::string> dependency_; @@ -446,10 +445,6 @@ class LIBPROTOBUF_EXPORT FileDescriptorProto : public ::google::protobuf::Messag ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_; ::google::protobuf::FileOptions* options_; ::google::protobuf::SourceCodeInfo* source_code_info_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(11 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -506,7 +501,6 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -536,12 +530,10 @@ class LIBPROTOBUF_EXPORT DescriptorProto_ExtensionRange : public ::google::proto ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::google::protobuf::int32 start_; ::google::protobuf::int32 end_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -598,7 +590,6 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -679,6 +670,18 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* mutable_extension_range(); + // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; + inline int oneof_decl_size() const; + inline void clear_oneof_decl(); + static const int kOneofDeclFieldNumber = 8; + inline const ::google::protobuf::OneofDescriptorProto& oneof_decl(int index) const; + inline ::google::protobuf::OneofDescriptorProto* mutable_oneof_decl(int index); + inline ::google::protobuf::OneofDescriptorProto* add_oneof_decl(); + inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& + oneof_decl() const; + inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* + mutable_oneof_decl(); + // optional .google.protobuf.MessageOptions options = 7; inline bool has_options() const; inline void clear_options(); @@ -697,17 +700,16 @@ class LIBPROTOBUF_EXPORT DescriptorProto : public ::google::protobuf::Message { ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > field_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto > extension_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto > nested_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto > enum_type_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange > extension_range_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto > oneof_decl_; ::google::protobuf::MessageOptions* options_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -764,7 +766,6 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -905,6 +906,13 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline ::std::string* release_default_value(); inline void set_allocated_default_value(::std::string* default_value); + // optional int32 oneof_index = 9; + inline bool has_oneof_index() const; + inline void clear_oneof_index(); + static const int kOneofIndexFieldNumber = 9; + inline ::google::protobuf::int32 oneof_index() const; + inline void set_oneof_index(::google::protobuf::int32 value); + // optional .google.protobuf.FieldOptions options = 8; inline bool has_options() const; inline void clear_options(); @@ -930,29 +938,114 @@ class LIBPROTOBUF_EXPORT FieldDescriptorProto : public ::google::protobuf::Messa inline void clear_has_extendee(); inline void set_has_default_value(); inline void clear_has_default_value(); + inline void set_has_oneof_index(); + inline void clear_has_oneof_index(); inline void set_has_options(); inline void clear_has_options(); ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_; ::google::protobuf::int32 number_; int label_; ::std::string* type_name_; ::std::string* extendee_; + int type_; + ::google::protobuf::int32 oneof_index_; ::std::string* default_value_; ::google::protobuf::FieldOptions* options_; - int type_; + friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); + friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(8 + 31) / 32]; + void InitAsDefaultInstance(); + static FieldDescriptorProto* default_instance_; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT OneofDescriptorProto : public ::google::protobuf::Message { + public: + OneofDescriptorProto(); + virtual ~OneofDescriptorProto(); + + OneofDescriptorProto(const OneofDescriptorProto& from); + + inline OneofDescriptorProto& operator=(const OneofDescriptorProto& from) { + CopyFrom(from); + return *this; + } + + inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const { + return _unknown_fields_; + } + + inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() { + return &_unknown_fields_; + } + + static const ::google::protobuf::Descriptor* descriptor(); + static const OneofDescriptorProto& default_instance(); + + void Swap(OneofDescriptorProto* other); + + // implements Message ---------------------------------------------- + + OneofDescriptorProto* New() const; + void CopyFrom(const ::google::protobuf::Message& from); + void MergeFrom(const ::google::protobuf::Message& from); + void CopyFrom(const OneofDescriptorProto& from); + void MergeFrom(const OneofDescriptorProto& from); + void Clear(); + bool IsInitialized() const; + + int ByteSize() const; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input); + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const; + ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const; + int GetCachedSize() const { return _cached_size_; } + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const; + public: + ::google::protobuf::Metadata GetMetadata() const; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // optional string name = 1; + inline bool has_name() const; + inline void clear_name(); + static const int kNameFieldNumber = 1; + inline const ::std::string& name() const; + inline void set_name(const ::std::string& value); + inline void set_name(const char* value); + inline void set_name(const char* value, size_t size); + inline ::std::string* mutable_name(); + inline ::std::string* release_name(); + inline void set_allocated_name(::std::string* name); + + // @@protoc_insertion_point(class_scope:google.protobuf.OneofDescriptorProto) + private: + inline void set_has_name(); + inline void clear_has_name(); + + ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; + ::std::string* name_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); void InitAsDefaultInstance(); - static FieldDescriptorProto* default_instance_; + static OneofDescriptorProto* default_instance_; }; // ------------------------------------------------------------------- @@ -1003,7 +1096,6 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1052,13 +1144,11 @@ class LIBPROTOBUF_EXPORT EnumDescriptorProto : public ::google::protobuf::Messag ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto > value_; ::google::protobuf::EnumOptions* options_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -1115,7 +1205,6 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1161,13 +1250,11 @@ class LIBPROTOBUF_EXPORT EnumValueDescriptorProto : public ::google::protobuf::M ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_; ::google::protobuf::EnumValueOptions* options_; ::google::protobuf::int32 number_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -1224,7 +1311,6 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1273,13 +1359,11 @@ class LIBPROTOBUF_EXPORT ServiceDescriptorProto : public ::google::protobuf::Mes ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto > method_; ::google::protobuf::ServiceOptions* options_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -1336,7 +1420,6 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1401,14 +1484,12 @@ class LIBPROTOBUF_EXPORT MethodDescriptorProto : public ::google::protobuf::Mess ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_; ::std::string* input_type_; ::std::string* output_type_; ::google::protobuf::MethodOptions* options_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -1465,7 +1546,6 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1535,6 +1615,13 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline bool java_generate_equals_and_hash() const; inline void set_java_generate_equals_and_hash(bool value); + // optional bool java_string_check_utf8 = 27 [default = false]; + inline bool has_java_string_check_utf8() const; + inline void clear_java_string_check_utf8(); + static const int kJavaStringCheckUtf8FieldNumber = 27; + inline bool java_string_check_utf8() const; + inline void set_java_string_check_utf8(bool value); + // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; inline bool has_optimize_for() const; inline void clear_optimize_for(); @@ -1575,6 +1662,13 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline bool py_generic_services() const; inline void set_py_generic_services(bool value); + // optional bool deprecated = 23 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 23; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -1598,6 +1692,8 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void clear_has_java_multiple_files(); inline void set_has_java_generate_equals_and_hash(); inline void clear_has_java_generate_equals_and_hash(); + inline void set_has_java_string_check_utf8(); + inline void clear_has_java_string_check_utf8(); inline void set_has_optimize_for(); inline void clear_has_optimize_for(); inline void set_has_go_package(); @@ -1608,25 +1704,27 @@ class LIBPROTOBUF_EXPORT FileOptions : public ::google::protobuf::Message { inline void clear_has_java_generic_services(); inline void set_has_py_generic_services(); inline void clear_has_py_generic_services(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* java_package_; ::std::string* java_outer_classname_; - int optimize_for_; bool java_multiple_files_; bool java_generate_equals_and_hash_; + bool java_string_check_utf8_; bool cc_generic_services_; - bool java_generic_services_; + int optimize_for_; ::std::string* go_package_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool java_generic_services_; bool py_generic_services_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(10 + 31) / 32]; - + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -1683,7 +1781,6 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1704,6 +1801,13 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { inline bool no_standard_descriptor_accessor() const; inline void set_no_standard_descriptor_accessor(bool value); + // optional bool deprecated = 3 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 3; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -1723,18 +1827,19 @@ class LIBPROTOBUF_EXPORT MessageOptions : public ::google::protobuf::Message { inline void clear_has_message_set_wire_format(); inline void set_has_no_standard_descriptor_accessor(); inline void clear_has_no_standard_descriptor_accessor(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool message_set_wire_format_; bool no_standard_descriptor_accessor_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32]; - + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -1791,7 +1896,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -1902,6 +2006,8 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; int ctype_; bool packed_; bool lazy_; @@ -1909,10 +2015,6 @@ class LIBPROTOBUF_EXPORT FieldOptions : public ::google::protobuf::Message { bool weak_; ::std::string* experimental_map_key_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -1969,20 +2071,26 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- - // optional bool allow_alias = 2 [default = true]; + // optional bool allow_alias = 2; inline bool has_allow_alias() const; inline void clear_allow_alias(); static const int kAllowAliasFieldNumber = 2; inline bool allow_alias() const; inline void set_allow_alias(bool value); + // optional bool deprecated = 3 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 3; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -2000,17 +2108,18 @@ class LIBPROTOBUF_EXPORT EnumOptions : public ::google::protobuf::Message { private: inline void set_has_allow_alias(); inline void clear_has_allow_alias(); + inline void set_has_deprecated(); + inline void clear_has_deprecated(); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; bool allow_alias_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2067,13 +2176,19 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + // optional bool deprecated = 1 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 1; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -2089,16 +2204,17 @@ class LIBPROTOBUF_EXPORT EnumValueOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(EnumValueOptions) // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueOptions) private: + inline void set_has_deprecated(); + inline void clear_has_deprecated(); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::UnknownFieldSet _unknown_fields_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2155,13 +2271,19 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + // optional bool deprecated = 33 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 33; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -2177,16 +2299,17 @@ class LIBPROTOBUF_EXPORT ServiceOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(ServiceOptions) // @@protoc_insertion_point(class_scope:google.protobuf.ServiceOptions) private: + inline void set_has_deprecated(); + inline void clear_has_deprecated(); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::UnknownFieldSet _unknown_fields_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2243,13 +2366,19 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- // accessors ------------------------------------------------------- + // optional bool deprecated = 33 [default = false]; + inline bool has_deprecated() const; + inline void clear_deprecated(); + static const int kDeprecatedFieldNumber = 33; + inline bool deprecated() const; + inline void set_deprecated(bool value); + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int uninterpreted_option_size() const; inline void clear_uninterpreted_option(); @@ -2265,16 +2394,17 @@ class LIBPROTOBUF_EXPORT MethodOptions : public ::google::protobuf::Message { GOOGLE_PROTOBUF_EXTENSION_ACCESSORS(MethodOptions) // @@protoc_insertion_point(class_scope:google.protobuf.MethodOptions) private: + inline void set_has_deprecated(); + inline void clear_has_deprecated(); ::google::protobuf::internal::ExtensionSet _extensions_; ::google::protobuf::UnknownFieldSet _unknown_fields_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; - + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - + ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption > uninterpreted_option_; + bool deprecated_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2331,7 +2461,6 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2366,12 +2495,10 @@ class LIBPROTOBUF_EXPORT UninterpretedOption_NamePart : public ::google::protobu ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::std::string* name_part_; bool is_extension_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2428,7 +2555,6 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2523,6 +2649,8 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart > name_; ::std::string* identifier_value_; ::google::protobuf::uint64 positive_int_value_; @@ -2530,10 +2658,6 @@ class LIBPROTOBUF_EXPORT UninterpretedOption : public ::google::protobuf::Messag double double_value_; ::std::string* string_value_; ::std::string* aggregate_value_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(7 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2590,7 +2714,6 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2654,16 +2777,14 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo_Location : public ::google::protobuf::Me ::google::protobuf::UnknownFieldSet _unknown_fields_; + ::google::protobuf::uint32 _has_bits_[1]; + mutable int _cached_size_; ::google::protobuf::RepeatedField< ::google::protobuf::int32 > path_; mutable int _path_cached_byte_size_; ::google::protobuf::RepeatedField< ::google::protobuf::int32 > span_; mutable int _span_cached_byte_size_; ::std::string* leading_comments_; ::std::string* trailing_comments_; - - mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32]; - friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2720,7 +2841,6 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { void SharedDtor(); void SetCachedSize(int size) const; public: - ::google::protobuf::Metadata GetMetadata() const; // nested types ---------------------------------------------------- @@ -2746,11 +2866,9 @@ class LIBPROTOBUF_EXPORT SourceCodeInfo : public ::google::protobuf::Message { ::google::protobuf::UnknownFieldSet _unknown_fields_; - ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_; - + ::google::protobuf::uint32 _has_bits_[1]; mutable int _cached_size_; - ::google::protobuf::uint32 _has_bits_[(1 + 31) / 32]; - + ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location > location_; friend void LIBPROTOBUF_EXPORT protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_AssignDesc_google_2fprotobuf_2fdescriptor_2eproto(); friend void protobuf_ShutdownFile_google_2fprotobuf_2fdescriptor_2eproto(); @@ -2773,20 +2891,25 @@ inline void FileDescriptorSet::clear_file() { file_.Clear(); } inline const ::google::protobuf::FileDescriptorProto& FileDescriptorSet::file(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorSet.file) return file_.Get(index); } inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::mutable_file(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorSet.file) return file_.Mutable(index); } inline ::google::protobuf::FileDescriptorProto* FileDescriptorSet::add_file() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorSet.file) return file_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >& FileDescriptorSet::file() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorSet.file) return file_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FileDescriptorProto >* FileDescriptorSet::mutable_file() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorSet.file) return &file_; } @@ -2805,54 +2928,59 @@ inline void FileDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } inline void FileDescriptorProto::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } clear_has_name(); } inline const ::std::string& FileDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.name) return *name_; } inline void FileDescriptorProto::set_name(const ::std::string& value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.name) } inline void FileDescriptorProto::set_name(const char* value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.name) } inline void FileDescriptorProto::set_name(const char* value, size_t size) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.name) } inline ::std::string* FileDescriptorProto::mutable_name() { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.name) return name_; } inline ::std::string* FileDescriptorProto::release_name() { clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FileDescriptorProto::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (name) { @@ -2860,8 +2988,9 @@ inline void FileDescriptorProto::set_allocated_name(::std::string* name) { name_ = name; } else { clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.name) } // optional string package = 2; @@ -2875,54 +3004,59 @@ inline void FileDescriptorProto::clear_has_package() { _has_bits_[0] &= ~0x00000002u; } inline void FileDescriptorProto::clear_package() { - if (package_ != &::google::protobuf::internal::GetEmptyString()) { + if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_->clear(); } clear_has_package(); } inline const ::std::string& FileDescriptorProto::package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.package) return *package_; } inline void FileDescriptorProto::set_package(const ::std::string& value) { set_has_package(); - if (package_ == &::google::protobuf::internal::GetEmptyString()) { + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_ = new ::std::string; } package_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.package) } inline void FileDescriptorProto::set_package(const char* value) { set_has_package(); - if (package_ == &::google::protobuf::internal::GetEmptyString()) { + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_ = new ::std::string; } package_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.package) } inline void FileDescriptorProto::set_package(const char* value, size_t size) { set_has_package(); - if (package_ == &::google::protobuf::internal::GetEmptyString()) { + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_ = new ::std::string; } package_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.package) } inline ::std::string* FileDescriptorProto::mutable_package() { set_has_package(); - if (package_ == &::google::protobuf::internal::GetEmptyString()) { + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { package_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.package) return package_; } inline ::std::string* FileDescriptorProto::release_package() { clear_has_package(); - if (package_ == &::google::protobuf::internal::GetEmptyString()) { + if (package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = package_; - package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FileDescriptorProto::set_allocated_package(::std::string* package) { - if (package_ != &::google::protobuf::internal::GetEmptyString()) { + if (package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete package_; } if (package) { @@ -2930,8 +3064,9 @@ inline void FileDescriptorProto::set_allocated_package(::std::string* package) { package_ = package; } else { clear_has_package(); - package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.package) } // repeated string dependency = 3; @@ -2942,39 +3077,49 @@ inline void FileDescriptorProto::clear_dependency() { dependency_.Clear(); } inline const ::std::string& FileDescriptorProto::dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.dependency) return dependency_.Get(index); } inline ::std::string* FileDescriptorProto::mutable_dependency(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.dependency) return dependency_.Mutable(index); } inline void FileDescriptorProto::set_dependency(int index, const ::std::string& value) { + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency) dependency_.Mutable(index)->assign(value); } inline void FileDescriptorProto::set_dependency(int index, const char* value) { dependency_.Mutable(index)->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency) } inline void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) { dependency_.Mutable(index)->assign( reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency) } inline ::std::string* FileDescriptorProto::add_dependency() { return dependency_.Add(); } inline void FileDescriptorProto::add_dependency(const ::std::string& value) { dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency) } inline void FileDescriptorProto::add_dependency(const char* value) { dependency_.Add()->assign(value); + // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency) } inline void FileDescriptorProto::add_dependency(const char* value, size_t size) { dependency_.Add()->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency) } inline const ::google::protobuf::RepeatedPtrField< ::std::string>& FileDescriptorProto::dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.dependency) return dependency_; } inline ::google::protobuf::RepeatedPtrField< ::std::string>* FileDescriptorProto::mutable_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.dependency) return &dependency_; } @@ -2986,20 +3131,25 @@ inline void FileDescriptorProto::clear_public_dependency() { public_dependency_.Clear(); } inline ::google::protobuf::int32 FileDescriptorProto::public_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency) return public_dependency_.Get(index); } inline void FileDescriptorProto::set_public_dependency(int index, ::google::protobuf::int32 value) { public_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency) } inline void FileDescriptorProto::add_public_dependency(::google::protobuf::int32 value) { public_dependency_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency) } inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& FileDescriptorProto::public_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency) return public_dependency_; } inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* FileDescriptorProto::mutable_public_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency) return &public_dependency_; } @@ -3011,20 +3161,25 @@ inline void FileDescriptorProto::clear_weak_dependency() { weak_dependency_.Clear(); } inline ::google::protobuf::int32 FileDescriptorProto::weak_dependency(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency) return weak_dependency_.Get(index); } inline void FileDescriptorProto::set_weak_dependency(int index, ::google::protobuf::int32 value) { weak_dependency_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency) } inline void FileDescriptorProto::add_weak_dependency(::google::protobuf::int32 value) { weak_dependency_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency) } inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& FileDescriptorProto::weak_dependency() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency) return weak_dependency_; } inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* FileDescriptorProto::mutable_weak_dependency() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency) return &weak_dependency_; } @@ -3036,20 +3191,25 @@ inline void FileDescriptorProto::clear_message_type() { message_type_.Clear(); } inline const ::google::protobuf::DescriptorProto& FileDescriptorProto::message_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.message_type) return message_type_.Get(index); } inline ::google::protobuf::DescriptorProto* FileDescriptorProto::mutable_message_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.message_type) return message_type_.Mutable(index); } inline ::google::protobuf::DescriptorProto* FileDescriptorProto::add_message_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.message_type) return message_type_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& FileDescriptorProto::message_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.message_type) return message_type_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* FileDescriptorProto::mutable_message_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.message_type) return &message_type_; } @@ -3061,20 +3221,25 @@ inline void FileDescriptorProto::clear_enum_type() { enum_type_.Clear(); } inline const ::google::protobuf::EnumDescriptorProto& FileDescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.enum_type) return enum_type_.Get(index); } inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.enum_type) return enum_type_.Mutable(index); } inline ::google::protobuf::EnumDescriptorProto* FileDescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.enum_type) return enum_type_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& FileDescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.enum_type) return enum_type_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* FileDescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.enum_type) return &enum_type_; } @@ -3086,20 +3251,25 @@ inline void FileDescriptorProto::clear_service() { service_.Clear(); } inline const ::google::protobuf::ServiceDescriptorProto& FileDescriptorProto::service(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.service) return service_.Get(index); } inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::mutable_service(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.service) return service_.Mutable(index); } inline ::google::protobuf::ServiceDescriptorProto* FileDescriptorProto::add_service() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.service) return service_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >& FileDescriptorProto::service() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.service) return service_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::ServiceDescriptorProto >* FileDescriptorProto::mutable_service() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.service) return &service_; } @@ -3111,20 +3281,25 @@ inline void FileDescriptorProto::clear_extension() { extension_.Clear(); } inline const ::google::protobuf::FieldDescriptorProto& FileDescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.extension) return extension_.Get(index); } inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.extension) return extension_.Mutable(index); } inline ::google::protobuf::FieldDescriptorProto* FileDescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.extension) return extension_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& FileDescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.extension) return extension_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* FileDescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.extension) return &extension_; } @@ -3143,11 +3318,13 @@ inline void FileDescriptorProto::clear_options() { clear_has_options(); } inline const ::google::protobuf::FileOptions& FileDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::FileOptions* FileDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::FileOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.options) return options_; } inline ::google::protobuf::FileOptions* FileDescriptorProto::release_options() { @@ -3164,6 +3341,7 @@ inline void FileDescriptorProto::set_allocated_options(::google::protobuf::FileO } else { clear_has_options(); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options) } // optional .google.protobuf.SourceCodeInfo source_code_info = 9; @@ -3181,11 +3359,13 @@ inline void FileDescriptorProto::clear_source_code_info() { clear_has_source_code_info(); } inline const ::google::protobuf::SourceCodeInfo& FileDescriptorProto::source_code_info() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.source_code_info) return source_code_info_ != NULL ? *source_code_info_ : *default_instance_->source_code_info_; } inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::mutable_source_code_info() { set_has_source_code_info(); if (source_code_info_ == NULL) source_code_info_ = new ::google::protobuf::SourceCodeInfo; + // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.source_code_info) return source_code_info_; } inline ::google::protobuf::SourceCodeInfo* FileDescriptorProto::release_source_code_info() { @@ -3202,6 +3382,7 @@ inline void FileDescriptorProto::set_allocated_source_code_info(::google::protob } else { clear_has_source_code_info(); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info) } // ------------------------------------------------------------------- @@ -3223,11 +3404,13 @@ inline void DescriptorProto_ExtensionRange::clear_start() { clear_has_start(); } inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::start() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start) return start_; } inline void DescriptorProto_ExtensionRange::set_start(::google::protobuf::int32 value) { set_has_start(); start_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start) } // optional int32 end = 2; @@ -3245,11 +3428,13 @@ inline void DescriptorProto_ExtensionRange::clear_end() { clear_has_end(); } inline ::google::protobuf::int32 DescriptorProto_ExtensionRange::end() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end) return end_; } inline void DescriptorProto_ExtensionRange::set_end(::google::protobuf::int32 value) { set_has_end(); end_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end) } // ------------------------------------------------------------------- @@ -3267,54 +3452,59 @@ inline void DescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } inline void DescriptorProto::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } clear_has_name(); } inline const ::std::string& DescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.name) return *name_; } inline void DescriptorProto::set_name(const ::std::string& value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.name) } inline void DescriptorProto::set_name(const char* value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.name) } inline void DescriptorProto::set_name(const char* value, size_t size) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.name) } inline ::std::string* DescriptorProto::mutable_name() { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.name) return name_; } inline ::std::string* DescriptorProto::release_name() { clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void DescriptorProto::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (name) { @@ -3322,8 +3512,9 @@ inline void DescriptorProto::set_allocated_name(::std::string* name) { name_ = name; } else { clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.name) } // repeated .google.protobuf.FieldDescriptorProto field = 2; @@ -3334,20 +3525,25 @@ inline void DescriptorProto::clear_field() { field_.Clear(); } inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::field(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.field) return field_.Get(index); } inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_field(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.field) return field_.Mutable(index); } inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_field() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.field) return field_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& DescriptorProto::field() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.field) return field_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* DescriptorProto::mutable_field() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.field) return &field_; } @@ -3359,20 +3555,25 @@ inline void DescriptorProto::clear_extension() { extension_.Clear(); } inline const ::google::protobuf::FieldDescriptorProto& DescriptorProto::extension(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension) return extension_.Get(index); } inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::mutable_extension(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension) return extension_.Mutable(index); } inline ::google::protobuf::FieldDescriptorProto* DescriptorProto::add_extension() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension) return extension_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >& DescriptorProto::extension() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension) return extension_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::FieldDescriptorProto >* DescriptorProto::mutable_extension() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension) return &extension_; } @@ -3384,20 +3585,25 @@ inline void DescriptorProto::clear_nested_type() { nested_type_.Clear(); } inline const ::google::protobuf::DescriptorProto& DescriptorProto::nested_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.nested_type) return nested_type_.Get(index); } inline ::google::protobuf::DescriptorProto* DescriptorProto::mutable_nested_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.nested_type) return nested_type_.Mutable(index); } inline ::google::protobuf::DescriptorProto* DescriptorProto::add_nested_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.nested_type) return nested_type_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >& DescriptorProto::nested_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.nested_type) return nested_type_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto >* DescriptorProto::mutable_nested_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.nested_type) return &nested_type_; } @@ -3409,20 +3615,25 @@ inline void DescriptorProto::clear_enum_type() { enum_type_.Clear(); } inline const ::google::protobuf::EnumDescriptorProto& DescriptorProto::enum_type(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.enum_type) return enum_type_.Get(index); } inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::mutable_enum_type(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.enum_type) return enum_type_.Mutable(index); } inline ::google::protobuf::EnumDescriptorProto* DescriptorProto::add_enum_type() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.enum_type) return enum_type_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >& DescriptorProto::enum_type() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.enum_type) return enum_type_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumDescriptorProto >* DescriptorProto::mutable_enum_type() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.enum_type) return &enum_type_; } @@ -3434,43 +3645,80 @@ inline void DescriptorProto::clear_extension_range() { extension_range_.Clear(); } inline const ::google::protobuf::DescriptorProto_ExtensionRange& DescriptorProto::extension_range(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.extension_range) return extension_range_.Get(index); } inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::mutable_extension_range(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.extension_range) return extension_range_.Mutable(index); } inline ::google::protobuf::DescriptorProto_ExtensionRange* DescriptorProto::add_extension_range() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.extension_range) return extension_range_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >& DescriptorProto::extension_range() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.extension_range) return extension_range_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::DescriptorProto_ExtensionRange >* DescriptorProto::mutable_extension_range() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.extension_range) return &extension_range_; } +// repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8; +inline int DescriptorProto::oneof_decl_size() const { + return oneof_decl_.size(); +} +inline void DescriptorProto::clear_oneof_decl() { + oneof_decl_.Clear(); +} +inline const ::google::protobuf::OneofDescriptorProto& DescriptorProto::oneof_decl(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Get(index); +} +inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::mutable_oneof_decl(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Mutable(index); +} +inline ::google::protobuf::OneofDescriptorProto* DescriptorProto::add_oneof_decl() { + // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >& +DescriptorProto::oneof_decl() const { + // @@protoc_insertion_point(field_list:google.protobuf.DescriptorProto.oneof_decl) + return oneof_decl_; +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::OneofDescriptorProto >* +DescriptorProto::mutable_oneof_decl() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.DescriptorProto.oneof_decl) + return &oneof_decl_; +} + // optional .google.protobuf.MessageOptions options = 7; inline bool DescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000040u) != 0; + return (_has_bits_[0] & 0x00000080u) != 0; } inline void DescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000040u; + _has_bits_[0] |= 0x00000080u; } inline void DescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000040u; + _has_bits_[0] &= ~0x00000080u; } inline void DescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::MessageOptions::Clear(); clear_has_options(); } inline const ::google::protobuf::MessageOptions& DescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::MessageOptions* DescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::MessageOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.DescriptorProto.options) return options_; } inline ::google::protobuf::MessageOptions* DescriptorProto::release_options() { @@ -3487,6 +3735,7 @@ inline void DescriptorProto::set_allocated_options(::google::protobuf::MessageOp } else { clear_has_options(); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.DescriptorProto.options) } // ------------------------------------------------------------------- @@ -3504,54 +3753,59 @@ inline void FieldDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } inline void FieldDescriptorProto::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } clear_has_name(); } inline const ::std::string& FieldDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.name) return *name_; } inline void FieldDescriptorProto::set_name(const ::std::string& value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.name) } inline void FieldDescriptorProto::set_name(const char* value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.name) } inline void FieldDescriptorProto::set_name(const char* value, size_t size) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.name) } inline ::std::string* FieldDescriptorProto::mutable_name() { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.name) return name_; } inline ::std::string* FieldDescriptorProto::release_name() { clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FieldDescriptorProto::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (name) { @@ -3559,8 +3813,9 @@ inline void FieldDescriptorProto::set_allocated_name(::std::string* name) { name_ = name; } else { clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.name) } // optional int32 number = 3; @@ -3578,11 +3833,13 @@ inline void FieldDescriptorProto::clear_number() { clear_has_number(); } inline ::google::protobuf::int32 FieldDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number) return number_; } inline void FieldDescriptorProto::set_number(::google::protobuf::int32 value) { set_has_number(); number_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number) } // optional .google.protobuf.FieldDescriptorProto.Label label = 4; @@ -3600,12 +3857,14 @@ inline void FieldDescriptorProto::clear_label() { clear_has_label(); } inline ::google::protobuf::FieldDescriptorProto_Label FieldDescriptorProto::label() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.label) return static_cast< ::google::protobuf::FieldDescriptorProto_Label >(label_); } inline void FieldDescriptorProto::set_label(::google::protobuf::FieldDescriptorProto_Label value) { assert(::google::protobuf::FieldDescriptorProto_Label_IsValid(value)); set_has_label(); label_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.label) } // optional .google.protobuf.FieldDescriptorProto.Type type = 5; @@ -3623,12 +3882,14 @@ inline void FieldDescriptorProto::clear_type() { clear_has_type(); } inline ::google::protobuf::FieldDescriptorProto_Type FieldDescriptorProto::type() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type) return static_cast< ::google::protobuf::FieldDescriptorProto_Type >(type_); } inline void FieldDescriptorProto::set_type(::google::protobuf::FieldDescriptorProto_Type value) { assert(::google::protobuf::FieldDescriptorProto_Type_IsValid(value)); set_has_type(); type_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type) } // optional string type_name = 6; @@ -3642,54 +3903,59 @@ inline void FieldDescriptorProto::clear_has_type_name() { _has_bits_[0] &= ~0x00000010u; } inline void FieldDescriptorProto::clear_type_name() { - if (type_name_ != &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_->clear(); } clear_has_type_name(); } inline const ::std::string& FieldDescriptorProto::type_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.type_name) return *type_name_; } inline void FieldDescriptorProto::set_type_name(const ::std::string& value) { set_has_type_name(); - if (type_name_ == &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_ = new ::std::string; } type_name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.type_name) } inline void FieldDescriptorProto::set_type_name(const char* value) { set_has_type_name(); - if (type_name_ == &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_ = new ::std::string; } type_name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.type_name) } inline void FieldDescriptorProto::set_type_name(const char* value, size_t size) { set_has_type_name(); - if (type_name_ == &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_ = new ::std::string; } type_name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.type_name) } inline ::std::string* FieldDescriptorProto::mutable_type_name() { set_has_type_name(); - if (type_name_ == &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { type_name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.type_name) return type_name_; } inline ::std::string* FieldDescriptorProto::release_type_name() { clear_has_type_name(); - if (type_name_ == &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = type_name_; - type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_name) { - if (type_name_ != &::google::protobuf::internal::GetEmptyString()) { + if (type_name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete type_name_; } if (type_name) { @@ -3697,8 +3963,9 @@ inline void FieldDescriptorProto::set_allocated_type_name(::std::string* type_na type_name_ = type_name; } else { clear_has_type_name(); - type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + type_name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.type_name) } // optional string extendee = 2; @@ -3712,54 +3979,59 @@ inline void FieldDescriptorProto::clear_has_extendee() { _has_bits_[0] &= ~0x00000020u; } inline void FieldDescriptorProto::clear_extendee() { - if (extendee_ != &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_->clear(); } clear_has_extendee(); } inline const ::std::string& FieldDescriptorProto::extendee() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.extendee) return *extendee_; } inline void FieldDescriptorProto::set_extendee(const ::std::string& value) { set_has_extendee(); - if (extendee_ == &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_ = new ::std::string; } extendee_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.extendee) } inline void FieldDescriptorProto::set_extendee(const char* value) { set_has_extendee(); - if (extendee_ == &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_ = new ::std::string; } extendee_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.extendee) } inline void FieldDescriptorProto::set_extendee(const char* value, size_t size) { set_has_extendee(); - if (extendee_ == &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_ = new ::std::string; } extendee_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.extendee) } inline ::std::string* FieldDescriptorProto::mutable_extendee() { set_has_extendee(); - if (extendee_ == &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { extendee_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.extendee) return extendee_; } inline ::std::string* FieldDescriptorProto::release_extendee() { clear_has_extendee(); - if (extendee_ == &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = extendee_; - extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee) { - if (extendee_ != &::google::protobuf::internal::GetEmptyString()) { + if (extendee_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete extendee_; } if (extendee) { @@ -3767,8 +4039,9 @@ inline void FieldDescriptorProto::set_allocated_extendee(::std::string* extendee extendee_ = extendee; } else { clear_has_extendee(); - extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + extendee_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.extendee) } // optional string default_value = 7; @@ -3782,54 +4055,59 @@ inline void FieldDescriptorProto::clear_has_default_value() { _has_bits_[0] &= ~0x00000040u; } inline void FieldDescriptorProto::clear_default_value() { - if (default_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_->clear(); } clear_has_default_value(); } inline const ::std::string& FieldDescriptorProto::default_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.default_value) return *default_value_; } inline void FieldDescriptorProto::set_default_value(const ::std::string& value) { set_has_default_value(); - if (default_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_ = new ::std::string; } default_value_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.default_value) } inline void FieldDescriptorProto::set_default_value(const char* value) { set_has_default_value(); - if (default_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_ = new ::std::string; } default_value_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldDescriptorProto.default_value) } inline void FieldDescriptorProto::set_default_value(const char* value, size_t size) { set_has_default_value(); - if (default_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_ = new ::std::string; } default_value_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldDescriptorProto.default_value) } inline ::std::string* FieldDescriptorProto::mutable_default_value() { set_has_default_value(); - if (default_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { default_value_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.default_value) return default_value_; } inline ::std::string* FieldDescriptorProto::release_default_value() { clear_has_default_value(); - if (default_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = default_value_; - default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FieldDescriptorProto::set_allocated_default_value(::std::string* default_value) { - if (default_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (default_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete default_value_; } if (default_value) { @@ -3837,30 +4115,57 @@ inline void FieldDescriptorProto::set_allocated_default_value(::std::string* def default_value_ = default_value; } else { clear_has_default_value(); - default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + default_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.default_value) +} + +// optional int32 oneof_index = 9; +inline bool FieldDescriptorProto::has_oneof_index() const { + return (_has_bits_[0] & 0x00000080u) != 0; +} +inline void FieldDescriptorProto::set_has_oneof_index() { + _has_bits_[0] |= 0x00000080u; +} +inline void FieldDescriptorProto::clear_has_oneof_index() { + _has_bits_[0] &= ~0x00000080u; +} +inline void FieldDescriptorProto::clear_oneof_index() { + oneof_index_ = 0; + clear_has_oneof_index(); +} +inline ::google::protobuf::int32 FieldDescriptorProto::oneof_index() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index) + return oneof_index_; +} +inline void FieldDescriptorProto::set_oneof_index(::google::protobuf::int32 value) { + set_has_oneof_index(); + oneof_index_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index) } // optional .google.protobuf.FieldOptions options = 8; inline bool FieldDescriptorProto::has_options() const { - return (_has_bits_[0] & 0x00000080u) != 0; + return (_has_bits_[0] & 0x00000100u) != 0; } inline void FieldDescriptorProto::set_has_options() { - _has_bits_[0] |= 0x00000080u; + _has_bits_[0] |= 0x00000100u; } inline void FieldDescriptorProto::clear_has_options() { - _has_bits_[0] &= ~0x00000080u; + _has_bits_[0] &= ~0x00000100u; } inline void FieldDescriptorProto::clear_options() { if (options_ != NULL) options_->::google::protobuf::FieldOptions::Clear(); clear_has_options(); } inline const ::google::protobuf::FieldOptions& FieldDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::FieldOptions* FieldDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::FieldOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldDescriptorProto.options) return options_; } inline ::google::protobuf::FieldOptions* FieldDescriptorProto::release_options() { @@ -3877,6 +4182,87 @@ inline void FieldDescriptorProto::set_allocated_options(::google::protobuf::Fiel } else { clear_has_options(); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldDescriptorProto.options) +} + +// ------------------------------------------------------------------- + +// OneofDescriptorProto + +// optional string name = 1; +inline bool OneofDescriptorProto::has_name() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void OneofDescriptorProto::set_has_name() { + _has_bits_[0] |= 0x00000001u; +} +inline void OneofDescriptorProto::clear_has_name() { + _has_bits_[0] &= ~0x00000001u; +} +inline void OneofDescriptorProto::clear_name() { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_->clear(); + } + clear_has_name(); +} +inline const ::std::string& OneofDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.OneofDescriptorProto.name) + return *name_; +} +inline void OneofDescriptorProto::set_name(const ::std::string& value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_ = new ::std::string; + } + name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.OneofDescriptorProto.name) +} +inline void OneofDescriptorProto::set_name(const char* value) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_ = new ::std::string; + } + name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.OneofDescriptorProto.name) +} +inline void OneofDescriptorProto::set_name(const char* value, size_t size) { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_ = new ::std::string; + } + name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.OneofDescriptorProto.name) +} +inline ::std::string* OneofDescriptorProto::mutable_name() { + set_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + name_ = new ::std::string; + } + // @@protoc_insertion_point(field_mutable:google.protobuf.OneofDescriptorProto.name) + return name_; +} +inline ::std::string* OneofDescriptorProto::release_name() { + clear_has_name(); + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + return NULL; + } else { + ::std::string* temp = name_; + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + return temp; + } +} +inline void OneofDescriptorProto::set_allocated_name(::std::string* name) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { + delete name_; + } + if (name) { + set_has_name(); + name_ = name; + } else { + clear_has_name(); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.OneofDescriptorProto.name) } // ------------------------------------------------------------------- @@ -3894,54 +4280,59 @@ inline void EnumDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } inline void EnumDescriptorProto::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } clear_has_name(); } inline const ::std::string& EnumDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.name) return *name_; } inline void EnumDescriptorProto::set_name(const ::std::string& value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.name) } inline void EnumDescriptorProto::set_name(const char* value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.name) } inline void EnumDescriptorProto::set_name(const char* value, size_t size) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.name) } inline ::std::string* EnumDescriptorProto::mutable_name() { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.name) return name_; } inline ::std::string* EnumDescriptorProto::release_name() { clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void EnumDescriptorProto::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (name) { @@ -3949,8 +4340,9 @@ inline void EnumDescriptorProto::set_allocated_name(::std::string* name) { name_ = name; } else { clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.name) } // repeated .google.protobuf.EnumValueDescriptorProto value = 2; @@ -3961,20 +4353,25 @@ inline void EnumDescriptorProto::clear_value() { value_.Clear(); } inline const ::google::protobuf::EnumValueDescriptorProto& EnumDescriptorProto::value(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.value) return value_.Get(index); } inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::mutable_value(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.value) return value_.Mutable(index); } inline ::google::protobuf::EnumValueDescriptorProto* EnumDescriptorProto::add_value() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.value) return value_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >& EnumDescriptorProto::value() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumDescriptorProto.value) return value_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::EnumValueDescriptorProto >* EnumDescriptorProto::mutable_value() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumDescriptorProto.value) return &value_; } @@ -3993,11 +4390,13 @@ inline void EnumDescriptorProto::clear_options() { clear_has_options(); } inline const ::google::protobuf::EnumOptions& EnumDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::EnumOptions* EnumDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::EnumOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumDescriptorProto.options) return options_; } inline ::google::protobuf::EnumOptions* EnumDescriptorProto::release_options() { @@ -4014,6 +4413,7 @@ inline void EnumDescriptorProto::set_allocated_options(::google::protobuf::EnumO } else { clear_has_options(); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumDescriptorProto.options) } // ------------------------------------------------------------------- @@ -4031,54 +4431,59 @@ inline void EnumValueDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } inline void EnumValueDescriptorProto::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } clear_has_name(); } inline const ::std::string& EnumValueDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.name) return *name_; } inline void EnumValueDescriptorProto::set_name(const ::std::string& value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.name) } inline void EnumValueDescriptorProto::set_name(const char* value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.EnumValueDescriptorProto.name) } inline void EnumValueDescriptorProto::set_name(const char* value, size_t size) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumValueDescriptorProto.name) } inline ::std::string* EnumValueDescriptorProto::mutable_name() { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.name) return name_; } inline ::std::string* EnumValueDescriptorProto::release_name() { clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (name) { @@ -4086,8 +4491,9 @@ inline void EnumValueDescriptorProto::set_allocated_name(::std::string* name) { name_ = name; } else { clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.name) } // optional int32 number = 2; @@ -4105,11 +4511,13 @@ inline void EnumValueDescriptorProto::clear_number() { clear_has_number(); } inline ::google::protobuf::int32 EnumValueDescriptorProto::number() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number) return number_; } inline void EnumValueDescriptorProto::set_number(::google::protobuf::int32 value) { set_has_number(); number_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number) } // optional .google.protobuf.EnumValueOptions options = 3; @@ -4127,11 +4535,13 @@ inline void EnumValueDescriptorProto::clear_options() { clear_has_options(); } inline const ::google::protobuf::EnumValueOptions& EnumValueDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::EnumValueOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueDescriptorProto.options) return options_; } inline ::google::protobuf::EnumValueOptions* EnumValueDescriptorProto::release_options() { @@ -4148,6 +4558,7 @@ inline void EnumValueDescriptorProto::set_allocated_options(::google::protobuf:: } else { clear_has_options(); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.EnumValueDescriptorProto.options) } // ------------------------------------------------------------------- @@ -4165,54 +4576,59 @@ inline void ServiceDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } inline void ServiceDescriptorProto::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } clear_has_name(); } inline const ::std::string& ServiceDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.name) return *name_; } inline void ServiceDescriptorProto::set_name(const ::std::string& value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.ServiceDescriptorProto.name) } inline void ServiceDescriptorProto::set_name(const char* value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.ServiceDescriptorProto.name) } inline void ServiceDescriptorProto::set_name(const char* value, size_t size) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.ServiceDescriptorProto.name) } inline ::std::string* ServiceDescriptorProto::mutable_name() { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.name) return name_; } inline ::std::string* ServiceDescriptorProto::release_name() { clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (name) { @@ -4220,8 +4636,9 @@ inline void ServiceDescriptorProto::set_allocated_name(::std::string* name) { name_ = name; } else { clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.name) } // repeated .google.protobuf.MethodDescriptorProto method = 2; @@ -4232,20 +4649,25 @@ inline void ServiceDescriptorProto::clear_method() { method_.Clear(); } inline const ::google::protobuf::MethodDescriptorProto& ServiceDescriptorProto::method(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.method) return method_.Get(index); } inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::mutable_method(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.method) return method_.Mutable(index); } inline ::google::protobuf::MethodDescriptorProto* ServiceDescriptorProto::add_method() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceDescriptorProto.method) return method_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >& ServiceDescriptorProto::method() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceDescriptorProto.method) return method_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::MethodDescriptorProto >* ServiceDescriptorProto::mutable_method() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceDescriptorProto.method) return &method_; } @@ -4264,11 +4686,13 @@ inline void ServiceDescriptorProto::clear_options() { clear_has_options(); } inline const ::google::protobuf::ServiceOptions& ServiceDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::ServiceOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceDescriptorProto.options) return options_; } inline ::google::protobuf::ServiceOptions* ServiceDescriptorProto::release_options() { @@ -4285,6 +4709,7 @@ inline void ServiceDescriptorProto::set_allocated_options(::google::protobuf::Se } else { clear_has_options(); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.ServiceDescriptorProto.options) } // ------------------------------------------------------------------- @@ -4302,54 +4727,59 @@ inline void MethodDescriptorProto::clear_has_name() { _has_bits_[0] &= ~0x00000001u; } inline void MethodDescriptorProto::clear_name() { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_->clear(); } clear_has_name(); } inline const ::std::string& MethodDescriptorProto::name() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.name) return *name_; } inline void MethodDescriptorProto::set_name(const ::std::string& value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.name) } inline void MethodDescriptorProto::set_name(const char* value) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.name) } inline void MethodDescriptorProto::set_name(const char* value, size_t size) { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } name_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.name) } inline ::std::string* MethodDescriptorProto::mutable_name() { set_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.name) return name_; } inline ::std::string* MethodDescriptorProto::release_name() { clear_has_name(); - if (name_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_; - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void MethodDescriptorProto::set_allocated_name(::std::string* name) { - if (name_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_; } if (name) { @@ -4357,8 +4787,9 @@ inline void MethodDescriptorProto::set_allocated_name(::std::string* name) { name_ = name; } else { clear_has_name(); - name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.name) } // optional string input_type = 2; @@ -4372,54 +4803,59 @@ inline void MethodDescriptorProto::clear_has_input_type() { _has_bits_[0] &= ~0x00000002u; } inline void MethodDescriptorProto::clear_input_type() { - if (input_type_ != &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_->clear(); } clear_has_input_type(); } inline const ::std::string& MethodDescriptorProto::input_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.input_type) return *input_type_; } inline void MethodDescriptorProto::set_input_type(const ::std::string& value) { set_has_input_type(); - if (input_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_ = new ::std::string; } input_type_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.input_type) } inline void MethodDescriptorProto::set_input_type(const char* value) { set_has_input_type(); - if (input_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_ = new ::std::string; } input_type_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.input_type) } inline void MethodDescriptorProto::set_input_type(const char* value, size_t size) { set_has_input_type(); - if (input_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_ = new ::std::string; } input_type_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.input_type) } inline ::std::string* MethodDescriptorProto::mutable_input_type() { set_has_input_type(); - if (input_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { input_type_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.input_type) return input_type_; } inline ::std::string* MethodDescriptorProto::release_input_type() { clear_has_input_type(); - if (input_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = input_type_; - input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input_type) { - if (input_type_ != &::google::protobuf::internal::GetEmptyString()) { + if (input_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete input_type_; } if (input_type) { @@ -4427,8 +4863,9 @@ inline void MethodDescriptorProto::set_allocated_input_type(::std::string* input input_type_ = input_type; } else { clear_has_input_type(); - input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + input_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.input_type) } // optional string output_type = 3; @@ -4442,54 +4879,59 @@ inline void MethodDescriptorProto::clear_has_output_type() { _has_bits_[0] &= ~0x00000004u; } inline void MethodDescriptorProto::clear_output_type() { - if (output_type_ != &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_->clear(); } clear_has_output_type(); } inline const ::std::string& MethodDescriptorProto::output_type() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.output_type) return *output_type_; } inline void MethodDescriptorProto::set_output_type(const ::std::string& value) { set_has_output_type(); - if (output_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_ = new ::std::string; } output_type_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.MethodDescriptorProto.output_type) } inline void MethodDescriptorProto::set_output_type(const char* value) { set_has_output_type(); - if (output_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_ = new ::std::string; } output_type_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.MethodDescriptorProto.output_type) } inline void MethodDescriptorProto::set_output_type(const char* value, size_t size) { set_has_output_type(); - if (output_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_ = new ::std::string; } output_type_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.MethodDescriptorProto.output_type) } inline ::std::string* MethodDescriptorProto::mutable_output_type() { set_has_output_type(); - if (output_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { output_type_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.output_type) return output_type_; } inline ::std::string* MethodDescriptorProto::release_output_type() { clear_has_output_type(); - if (output_type_ == &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = output_type_; - output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void MethodDescriptorProto::set_allocated_output_type(::std::string* output_type) { - if (output_type_ != &::google::protobuf::internal::GetEmptyString()) { + if (output_type_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete output_type_; } if (output_type) { @@ -4497,8 +4939,9 @@ inline void MethodDescriptorProto::set_allocated_output_type(::std::string* outp output_type_ = output_type; } else { clear_has_output_type(); - output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + output_type_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.output_type) } // optional .google.protobuf.MethodOptions options = 4; @@ -4516,11 +4959,13 @@ inline void MethodDescriptorProto::clear_options() { clear_has_options(); } inline const ::google::protobuf::MethodOptions& MethodDescriptorProto::options() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodDescriptorProto.options) return options_ != NULL ? *options_ : *default_instance_->options_; } inline ::google::protobuf::MethodOptions* MethodDescriptorProto::mutable_options() { set_has_options(); if (options_ == NULL) options_ = new ::google::protobuf::MethodOptions; + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodDescriptorProto.options) return options_; } inline ::google::protobuf::MethodOptions* MethodDescriptorProto::release_options() { @@ -4537,6 +4982,7 @@ inline void MethodDescriptorProto::set_allocated_options(::google::protobuf::Met } else { clear_has_options(); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.MethodDescriptorProto.options) } // ------------------------------------------------------------------- @@ -4554,54 +5000,59 @@ inline void FileOptions::clear_has_java_package() { _has_bits_[0] &= ~0x00000001u; } inline void FileOptions::clear_java_package() { - if (java_package_ != &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_->clear(); } clear_has_java_package(); } inline const ::std::string& FileOptions::java_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_package) return *java_package_; } inline void FileOptions::set_java_package(const ::std::string& value) { set_has_java_package(); - if (java_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_ = new ::std::string; } java_package_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_package) } inline void FileOptions::set_java_package(const char* value) { set_has_java_package(); - if (java_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_ = new ::std::string; } java_package_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_package) } inline void FileOptions::set_java_package(const char* value, size_t size) { set_has_java_package(); - if (java_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_ = new ::std::string; } java_package_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_package) } inline ::std::string* FileOptions::mutable_java_package() { set_has_java_package(); - if (java_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_package_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_package) return java_package_; } inline ::std::string* FileOptions::release_java_package() { clear_has_java_package(); - if (java_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = java_package_; - java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FileOptions::set_allocated_java_package(::std::string* java_package) { - if (java_package_ != &::google::protobuf::internal::GetEmptyString()) { + if (java_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete java_package_; } if (java_package) { @@ -4609,8 +5060,9 @@ inline void FileOptions::set_allocated_java_package(::std::string* java_package) java_package_ = java_package; } else { clear_has_java_package(); - java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + java_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_package) } // optional string java_outer_classname = 8; @@ -4624,54 +5076,59 @@ inline void FileOptions::clear_has_java_outer_classname() { _has_bits_[0] &= ~0x00000002u; } inline void FileOptions::clear_java_outer_classname() { - if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_->clear(); } clear_has_java_outer_classname(); } inline const ::std::string& FileOptions::java_outer_classname() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_outer_classname) return *java_outer_classname_; } inline void FileOptions::set_java_outer_classname(const ::std::string& value) { set_has_java_outer_classname(); - if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_outer_classname) } inline void FileOptions::set_java_outer_classname(const char* value) { set_has_java_outer_classname(); - if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.java_outer_classname) } inline void FileOptions::set_java_outer_classname(const char* value, size_t size) { set_has_java_outer_classname(); - if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_ = new ::std::string; } java_outer_classname_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.java_outer_classname) } inline ::std::string* FileOptions::mutable_java_outer_classname() { set_has_java_outer_classname(); - if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { java_outer_classname_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.java_outer_classname) return java_outer_classname_; } inline ::std::string* FileOptions::release_java_outer_classname() { clear_has_java_outer_classname(); - if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = java_outer_classname_; - java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_outer_classname) { - if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyString()) { + if (java_outer_classname_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete java_outer_classname_; } if (java_outer_classname) { @@ -4679,8 +5136,9 @@ inline void FileOptions::set_allocated_java_outer_classname(::std::string* java_ java_outer_classname_ = java_outer_classname; } else { clear_has_java_outer_classname(); - java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + java_outer_classname_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.java_outer_classname) } // optional bool java_multiple_files = 10 [default = false]; @@ -4698,11 +5156,13 @@ inline void FileOptions::clear_java_multiple_files() { clear_has_java_multiple_files(); } inline bool FileOptions::java_multiple_files() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_multiple_files) return java_multiple_files_; } inline void FileOptions::set_java_multiple_files(bool value) { set_has_java_multiple_files(); java_multiple_files_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_multiple_files) } // optional bool java_generate_equals_and_hash = 20 [default = false]; @@ -4720,95 +5180,128 @@ inline void FileOptions::clear_java_generate_equals_and_hash() { clear_has_java_generate_equals_and_hash(); } inline bool FileOptions::java_generate_equals_and_hash() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generate_equals_and_hash) return java_generate_equals_and_hash_; } inline void FileOptions::set_java_generate_equals_and_hash(bool value) { set_has_java_generate_equals_and_hash(); java_generate_equals_and_hash_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generate_equals_and_hash) +} + +// optional bool java_string_check_utf8 = 27 [default = false]; +inline bool FileOptions::has_java_string_check_utf8() const { + return (_has_bits_[0] & 0x00000010u) != 0; +} +inline void FileOptions::set_has_java_string_check_utf8() { + _has_bits_[0] |= 0x00000010u; +} +inline void FileOptions::clear_has_java_string_check_utf8() { + _has_bits_[0] &= ~0x00000010u; +} +inline void FileOptions::clear_java_string_check_utf8() { + java_string_check_utf8_ = false; + clear_has_java_string_check_utf8(); +} +inline bool FileOptions::java_string_check_utf8() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_string_check_utf8) + return java_string_check_utf8_; +} +inline void FileOptions::set_java_string_check_utf8(bool value) { + set_has_java_string_check_utf8(); + java_string_check_utf8_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_string_check_utf8) } // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED]; inline bool FileOptions::has_optimize_for() const { - return (_has_bits_[0] & 0x00000010u) != 0; + return (_has_bits_[0] & 0x00000020u) != 0; } inline void FileOptions::set_has_optimize_for() { - _has_bits_[0] |= 0x00000010u; + _has_bits_[0] |= 0x00000020u; } inline void FileOptions::clear_has_optimize_for() { - _has_bits_[0] &= ~0x00000010u; + _has_bits_[0] &= ~0x00000020u; } inline void FileOptions::clear_optimize_for() { optimize_for_ = 1; clear_has_optimize_for(); } inline ::google::protobuf::FileOptions_OptimizeMode FileOptions::optimize_for() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.optimize_for) return static_cast< ::google::protobuf::FileOptions_OptimizeMode >(optimize_for_); } inline void FileOptions::set_optimize_for(::google::protobuf::FileOptions_OptimizeMode value) { assert(::google::protobuf::FileOptions_OptimizeMode_IsValid(value)); set_has_optimize_for(); optimize_for_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.optimize_for) } // optional string go_package = 11; inline bool FileOptions::has_go_package() const { - return (_has_bits_[0] & 0x00000020u) != 0; + return (_has_bits_[0] & 0x00000040u) != 0; } inline void FileOptions::set_has_go_package() { - _has_bits_[0] |= 0x00000020u; + _has_bits_[0] |= 0x00000040u; } inline void FileOptions::clear_has_go_package() { - _has_bits_[0] &= ~0x00000020u; + _has_bits_[0] &= ~0x00000040u; } inline void FileOptions::clear_go_package() { - if (go_package_ != &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { go_package_->clear(); } clear_has_go_package(); } inline const ::std::string& FileOptions::go_package() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.go_package) return *go_package_; } inline void FileOptions::set_go_package(const ::std::string& value) { set_has_go_package(); - if (go_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { go_package_ = new ::std::string; } go_package_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.go_package) } inline void FileOptions::set_go_package(const char* value) { set_has_go_package(); - if (go_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { go_package_ = new ::std::string; } go_package_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FileOptions.go_package) } inline void FileOptions::set_go_package(const char* value, size_t size) { set_has_go_package(); - if (go_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { go_package_ = new ::std::string; } go_package_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileOptions.go_package) } inline ::std::string* FileOptions::mutable_go_package() { set_has_go_package(); - if (go_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { go_package_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.go_package) return go_package_; } inline ::std::string* FileOptions::release_go_package() { clear_has_go_package(); - if (go_package_ == &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = go_package_; - go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FileOptions::set_allocated_go_package(::std::string* go_package) { - if (go_package_ != &::google::protobuf::internal::GetEmptyString()) { + if (go_package_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete go_package_; } if (go_package) { @@ -4816,74 +5309,105 @@ inline void FileOptions::set_allocated_go_package(::std::string* go_package) { go_package_ = go_package; } else { clear_has_go_package(); - go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + go_package_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileOptions.go_package) } // optional bool cc_generic_services = 16 [default = false]; inline bool FileOptions::has_cc_generic_services() const { - return (_has_bits_[0] & 0x00000040u) != 0; + return (_has_bits_[0] & 0x00000080u) != 0; } inline void FileOptions::set_has_cc_generic_services() { - _has_bits_[0] |= 0x00000040u; + _has_bits_[0] |= 0x00000080u; } inline void FileOptions::clear_has_cc_generic_services() { - _has_bits_[0] &= ~0x00000040u; + _has_bits_[0] &= ~0x00000080u; } inline void FileOptions::clear_cc_generic_services() { cc_generic_services_ = false; clear_has_cc_generic_services(); } inline bool FileOptions::cc_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.cc_generic_services) return cc_generic_services_; } inline void FileOptions::set_cc_generic_services(bool value) { set_has_cc_generic_services(); cc_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.cc_generic_services) } // optional bool java_generic_services = 17 [default = false]; inline bool FileOptions::has_java_generic_services() const { - return (_has_bits_[0] & 0x00000080u) != 0; + return (_has_bits_[0] & 0x00000100u) != 0; } inline void FileOptions::set_has_java_generic_services() { - _has_bits_[0] |= 0x00000080u; + _has_bits_[0] |= 0x00000100u; } inline void FileOptions::clear_has_java_generic_services() { - _has_bits_[0] &= ~0x00000080u; + _has_bits_[0] &= ~0x00000100u; } inline void FileOptions::clear_java_generic_services() { java_generic_services_ = false; clear_has_java_generic_services(); } inline bool FileOptions::java_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.java_generic_services) return java_generic_services_; } inline void FileOptions::set_java_generic_services(bool value) { set_has_java_generic_services(); java_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.java_generic_services) } // optional bool py_generic_services = 18 [default = false]; inline bool FileOptions::has_py_generic_services() const { - return (_has_bits_[0] & 0x00000100u) != 0; + return (_has_bits_[0] & 0x00000200u) != 0; } inline void FileOptions::set_has_py_generic_services() { - _has_bits_[0] |= 0x00000100u; + _has_bits_[0] |= 0x00000200u; } inline void FileOptions::clear_has_py_generic_services() { - _has_bits_[0] &= ~0x00000100u; + _has_bits_[0] &= ~0x00000200u; } inline void FileOptions::clear_py_generic_services() { py_generic_services_ = false; clear_has_py_generic_services(); } inline bool FileOptions::py_generic_services() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.py_generic_services) return py_generic_services_; } inline void FileOptions::set_py_generic_services(bool value) { set_has_py_generic_services(); py_generic_services_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.py_generic_services) +} + +// optional bool deprecated = 23 [default = false]; +inline bool FileOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000400u) != 0; +} +inline void FileOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000400u; +} +inline void FileOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000400u; +} +inline void FileOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool FileOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.deprecated) + return deprecated_; +} +inline void FileOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FileOptions.deprecated) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; @@ -4894,20 +5418,25 @@ inline void FileOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& FileOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* FileOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* FileOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& FileOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FileOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* FileOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -4930,11 +5459,13 @@ inline void MessageOptions::clear_message_set_wire_format() { clear_has_message_set_wire_format(); } inline bool MessageOptions::message_set_wire_format() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.message_set_wire_format) return message_set_wire_format_; } inline void MessageOptions::set_message_set_wire_format(bool value) { set_has_message_set_wire_format(); message_set_wire_format_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.message_set_wire_format) } // optional bool no_standard_descriptor_accessor = 2 [default = false]; @@ -4952,11 +5483,37 @@ inline void MessageOptions::clear_no_standard_descriptor_accessor() { clear_has_no_standard_descriptor_accessor(); } inline bool MessageOptions::no_standard_descriptor_accessor() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.no_standard_descriptor_accessor) return no_standard_descriptor_accessor_; } inline void MessageOptions::set_no_standard_descriptor_accessor(bool value) { set_has_no_standard_descriptor_accessor(); no_standard_descriptor_accessor_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.no_standard_descriptor_accessor) +} + +// optional bool deprecated = 3 [default = false]; +inline bool MessageOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000004u) != 0; +} +inline void MessageOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000004u; +} +inline void MessageOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000004u; +} +inline void MessageOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool MessageOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.deprecated) + return deprecated_; +} +inline void MessageOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MessageOptions.deprecated) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; @@ -4967,20 +5524,25 @@ inline void MessageOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& MessageOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* MessageOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* MessageOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& MessageOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MessageOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* MessageOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MessageOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -5003,12 +5565,14 @@ inline void FieldOptions::clear_ctype() { clear_has_ctype(); } inline ::google::protobuf::FieldOptions_CType FieldOptions::ctype() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.ctype) return static_cast< ::google::protobuf::FieldOptions_CType >(ctype_); } inline void FieldOptions::set_ctype(::google::protobuf::FieldOptions_CType value) { assert(::google::protobuf::FieldOptions_CType_IsValid(value)); set_has_ctype(); ctype_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.ctype) } // optional bool packed = 2; @@ -5026,11 +5590,13 @@ inline void FieldOptions::clear_packed() { clear_has_packed(); } inline bool FieldOptions::packed() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.packed) return packed_; } inline void FieldOptions::set_packed(bool value) { set_has_packed(); packed_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.packed) } // optional bool lazy = 5 [default = false]; @@ -5048,11 +5614,13 @@ inline void FieldOptions::clear_lazy() { clear_has_lazy(); } inline bool FieldOptions::lazy() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.lazy) return lazy_; } inline void FieldOptions::set_lazy(bool value) { set_has_lazy(); lazy_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.lazy) } // optional bool deprecated = 3 [default = false]; @@ -5070,11 +5638,13 @@ inline void FieldOptions::clear_deprecated() { clear_has_deprecated(); } inline bool FieldOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.deprecated) return deprecated_; } inline void FieldOptions::set_deprecated(bool value) { set_has_deprecated(); deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.deprecated) } // optional string experimental_map_key = 9; @@ -5088,54 +5658,59 @@ inline void FieldOptions::clear_has_experimental_map_key() { _has_bits_[0] &= ~0x00000010u; } inline void FieldOptions::clear_experimental_map_key() { - if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_->clear(); } clear_has_experimental_map_key(); } inline const ::std::string& FieldOptions::experimental_map_key() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.experimental_map_key) return *experimental_map_key_; } inline void FieldOptions::set_experimental_map_key(const ::std::string& value) { set_has_experimental_map_key(); - if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.experimental_map_key) } inline void FieldOptions::set_experimental_map_key(const char* value) { set_has_experimental_map_key(); - if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.FieldOptions.experimental_map_key) } inline void FieldOptions::set_experimental_map_key(const char* value, size_t size) { set_has_experimental_map_key(); - if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_ = new ::std::string; } experimental_map_key_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldOptions.experimental_map_key) } inline ::std::string* FieldOptions::mutable_experimental_map_key() { set_has_experimental_map_key(); - if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { experimental_map_key_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.experimental_map_key) return experimental_map_key_; } inline ::std::string* FieldOptions::release_experimental_map_key() { clear_has_experimental_map_key(); - if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = experimental_map_key_; - experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void FieldOptions::set_allocated_experimental_map_key(::std::string* experimental_map_key) { - if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyString()) { + if (experimental_map_key_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete experimental_map_key_; } if (experimental_map_key) { @@ -5143,8 +5718,9 @@ inline void FieldOptions::set_allocated_experimental_map_key(::std::string* expe experimental_map_key_ = experimental_map_key; } else { clear_has_experimental_map_key(); - experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + experimental_map_key_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.FieldOptions.experimental_map_key) } // optional bool weak = 10 [default = false]; @@ -5162,11 +5738,13 @@ inline void FieldOptions::clear_weak() { clear_has_weak(); } inline bool FieldOptions::weak() const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.weak) return weak_; } inline void FieldOptions::set_weak(bool value) { set_has_weak(); weak_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.FieldOptions.weak) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; @@ -5177,20 +5755,25 @@ inline void FieldOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& FieldOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* FieldOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* FieldOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& FieldOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.FieldOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* FieldOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.FieldOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -5198,7 +5781,7 @@ FieldOptions::mutable_uninterpreted_option() { // EnumOptions -// optional bool allow_alias = 2 [default = true]; +// optional bool allow_alias = 2; inline bool EnumOptions::has_allow_alias() const { return (_has_bits_[0] & 0x00000001u) != 0; } @@ -5209,15 +5792,41 @@ inline void EnumOptions::clear_has_allow_alias() { _has_bits_[0] &= ~0x00000001u; } inline void EnumOptions::clear_allow_alias() { - allow_alias_ = true; + allow_alias_ = false; clear_has_allow_alias(); } inline bool EnumOptions::allow_alias() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.allow_alias) return allow_alias_; } inline void EnumOptions::set_allow_alias(bool value) { set_has_allow_alias(); allow_alias_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.allow_alias) +} + +// optional bool deprecated = 3 [default = false]; +inline bool EnumOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000002u) != 0; +} +inline void EnumOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000002u; +} +inline void EnumOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000002u; +} +inline void EnumOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool EnumOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.deprecated) + return deprecated_; +} +inline void EnumOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumOptions.deprecated) } // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; @@ -5228,20 +5837,25 @@ inline void EnumOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& EnumOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* EnumOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* EnumOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& EnumOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* EnumOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -5249,6 +5863,30 @@ EnumOptions::mutable_uninterpreted_option() { // EnumValueOptions +// optional bool deprecated = 1 [default = false]; +inline bool EnumValueOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void EnumValueOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} +inline void EnumValueOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} +inline void EnumValueOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool EnumValueOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.deprecated) + return deprecated_; +} +inline void EnumValueOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.EnumValueOptions.deprecated) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int EnumValueOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -5257,20 +5895,25 @@ inline void EnumValueOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& EnumValueOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* EnumValueOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* EnumValueOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& EnumValueOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.EnumValueOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* EnumValueOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.EnumValueOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -5278,6 +5921,30 @@ EnumValueOptions::mutable_uninterpreted_option() { // ServiceOptions +// optional bool deprecated = 33 [default = false]; +inline bool ServiceOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void ServiceOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} +inline void ServiceOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} +inline void ServiceOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool ServiceOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.deprecated) + return deprecated_; +} +inline void ServiceOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.ServiceOptions.deprecated) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int ServiceOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -5286,20 +5953,25 @@ inline void ServiceOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& ServiceOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* ServiceOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* ServiceOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& ServiceOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.ServiceOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* ServiceOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ServiceOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -5307,6 +5979,30 @@ ServiceOptions::mutable_uninterpreted_option() { // MethodOptions +// optional bool deprecated = 33 [default = false]; +inline bool MethodOptions::has_deprecated() const { + return (_has_bits_[0] & 0x00000001u) != 0; +} +inline void MethodOptions::set_has_deprecated() { + _has_bits_[0] |= 0x00000001u; +} +inline void MethodOptions::clear_has_deprecated() { + _has_bits_[0] &= ~0x00000001u; +} +inline void MethodOptions::clear_deprecated() { + deprecated_ = false; + clear_has_deprecated(); +} +inline bool MethodOptions::deprecated() const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.deprecated) + return deprecated_; +} +inline void MethodOptions::set_deprecated(bool value) { + set_has_deprecated(); + deprecated_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.MethodOptions.deprecated) +} + // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999; inline int MethodOptions::uninterpreted_option_size() const { return uninterpreted_option_.size(); @@ -5315,20 +6011,25 @@ inline void MethodOptions::clear_uninterpreted_option() { uninterpreted_option_.Clear(); } inline const ::google::protobuf::UninterpretedOption& MethodOptions::uninterpreted_option(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_.Get(index); } inline ::google::protobuf::UninterpretedOption* MethodOptions::mutable_uninterpreted_option(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_.Mutable(index); } inline ::google::protobuf::UninterpretedOption* MethodOptions::add_uninterpreted_option() { + // @@protoc_insertion_point(field_add:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >& MethodOptions::uninterpreted_option() const { + // @@protoc_insertion_point(field_list:google.protobuf.MethodOptions.uninterpreted_option) return uninterpreted_option_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption >* MethodOptions::mutable_uninterpreted_option() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.MethodOptions.uninterpreted_option) return &uninterpreted_option_; } @@ -5347,54 +6048,59 @@ inline void UninterpretedOption_NamePart::clear_has_name_part() { _has_bits_[0] &= ~0x00000001u; } inline void UninterpretedOption_NamePart::clear_name_part() { - if (name_part_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_->clear(); } clear_has_name_part(); } inline const ::std::string& UninterpretedOption_NamePart::name_part() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.name_part) return *name_part_; } inline void UninterpretedOption_NamePart::set_name_part(const ::std::string& value) { set_has_name_part(); - if (name_part_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_ = new ::std::string; } name_part_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.name_part) } inline void UninterpretedOption_NamePart::set_name_part(const char* value) { set_has_name_part(); - if (name_part_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_ = new ::std::string; } name_part_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.NamePart.name_part) } inline void UninterpretedOption_NamePart::set_name_part(const char* value, size_t size) { set_has_name_part(); - if (name_part_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_ = new ::std::string; } name_part_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.NamePart.name_part) } inline ::std::string* UninterpretedOption_NamePart::mutable_name_part() { set_has_name_part(); - if (name_part_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { name_part_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.NamePart.name_part) return name_part_; } inline ::std::string* UninterpretedOption_NamePart::release_name_part() { clear_has_name_part(); - if (name_part_ == &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = name_part_; - name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part) { - if (name_part_ != &::google::protobuf::internal::GetEmptyString()) { + if (name_part_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete name_part_; } if (name_part) { @@ -5402,8 +6108,9 @@ inline void UninterpretedOption_NamePart::set_allocated_name_part(::std::string* name_part_ = name_part; } else { clear_has_name_part(); - name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + name_part_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.NamePart.name_part) } // required bool is_extension = 2; @@ -5421,11 +6128,13 @@ inline void UninterpretedOption_NamePart::clear_is_extension() { clear_has_is_extension(); } inline bool UninterpretedOption_NamePart::is_extension() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.NamePart.is_extension) return is_extension_; } inline void UninterpretedOption_NamePart::set_is_extension(bool value) { set_has_is_extension(); is_extension_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.NamePart.is_extension) } // ------------------------------------------------------------------- @@ -5440,20 +6149,25 @@ inline void UninterpretedOption::clear_name() { name_.Clear(); } inline const ::google::protobuf::UninterpretedOption_NamePart& UninterpretedOption::name(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.name) return name_.Get(index); } inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::mutable_name(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.name) return name_.Mutable(index); } inline ::google::protobuf::UninterpretedOption_NamePart* UninterpretedOption::add_name() { + // @@protoc_insertion_point(field_add:google.protobuf.UninterpretedOption.name) return name_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >& UninterpretedOption::name() const { + // @@protoc_insertion_point(field_list:google.protobuf.UninterpretedOption.name) return name_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::UninterpretedOption_NamePart >* UninterpretedOption::mutable_name() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.UninterpretedOption.name) return &name_; } @@ -5468,54 +6182,59 @@ inline void UninterpretedOption::clear_has_identifier_value() { _has_bits_[0] &= ~0x00000002u; } inline void UninterpretedOption::clear_identifier_value() { - if (identifier_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_->clear(); } clear_has_identifier_value(); } inline const ::std::string& UninterpretedOption::identifier_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.identifier_value) return *identifier_value_; } inline void UninterpretedOption::set_identifier_value(const ::std::string& value) { set_has_identifier_value(); - if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_ = new ::std::string; } identifier_value_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.identifier_value) } inline void UninterpretedOption::set_identifier_value(const char* value) { set_has_identifier_value(); - if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_ = new ::std::string; } identifier_value_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.identifier_value) } inline void UninterpretedOption::set_identifier_value(const char* value, size_t size) { set_has_identifier_value(); - if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_ = new ::std::string; } identifier_value_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.identifier_value) } inline ::std::string* UninterpretedOption::mutable_identifier_value() { set_has_identifier_value(); - if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { identifier_value_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.identifier_value) return identifier_value_; } inline ::std::string* UninterpretedOption::release_identifier_value() { clear_has_identifier_value(); - if (identifier_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = identifier_value_; - identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void UninterpretedOption::set_allocated_identifier_value(::std::string* identifier_value) { - if (identifier_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (identifier_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete identifier_value_; } if (identifier_value) { @@ -5523,8 +6242,9 @@ inline void UninterpretedOption::set_allocated_identifier_value(::std::string* i identifier_value_ = identifier_value; } else { clear_has_identifier_value(); - identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + identifier_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.identifier_value) } // optional uint64 positive_int_value = 4; @@ -5542,11 +6262,13 @@ inline void UninterpretedOption::clear_positive_int_value() { clear_has_positive_int_value(); } inline ::google::protobuf::uint64 UninterpretedOption::positive_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value) return positive_int_value_; } inline void UninterpretedOption::set_positive_int_value(::google::protobuf::uint64 value) { set_has_positive_int_value(); positive_int_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value) } // optional int64 negative_int_value = 5; @@ -5564,11 +6286,13 @@ inline void UninterpretedOption::clear_negative_int_value() { clear_has_negative_int_value(); } inline ::google::protobuf::int64 UninterpretedOption::negative_int_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value) return negative_int_value_; } inline void UninterpretedOption::set_negative_int_value(::google::protobuf::int64 value) { set_has_negative_int_value(); negative_int_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value) } // optional double double_value = 6; @@ -5586,11 +6310,13 @@ inline void UninterpretedOption::clear_double_value() { clear_has_double_value(); } inline double UninterpretedOption::double_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.double_value) return double_value_; } inline void UninterpretedOption::set_double_value(double value) { set_has_double_value(); double_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.double_value) } // optional bytes string_value = 7; @@ -5604,54 +6330,59 @@ inline void UninterpretedOption::clear_has_string_value() { _has_bits_[0] &= ~0x00000020u; } inline void UninterpretedOption::clear_string_value() { - if (string_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_->clear(); } clear_has_string_value(); } inline const ::std::string& UninterpretedOption::string_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.string_value) return *string_value_; } inline void UninterpretedOption::set_string_value(const ::std::string& value) { set_has_string_value(); - if (string_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_ = new ::std::string; } string_value_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.string_value) } inline void UninterpretedOption::set_string_value(const char* value) { set_has_string_value(); - if (string_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_ = new ::std::string; } string_value_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.string_value) } inline void UninterpretedOption::set_string_value(const void* value, size_t size) { set_has_string_value(); - if (string_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_ = new ::std::string; } string_value_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.string_value) } inline ::std::string* UninterpretedOption::mutable_string_value() { set_has_string_value(); - if (string_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { string_value_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.string_value) return string_value_; } inline ::std::string* UninterpretedOption::release_string_value() { clear_has_string_value(); - if (string_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = string_value_; - string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void UninterpretedOption::set_allocated_string_value(::std::string* string_value) { - if (string_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (string_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete string_value_; } if (string_value) { @@ -5659,8 +6390,9 @@ inline void UninterpretedOption::set_allocated_string_value(::std::string* strin string_value_ = string_value; } else { clear_has_string_value(); - string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + string_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.string_value) } // optional string aggregate_value = 8; @@ -5674,54 +6406,59 @@ inline void UninterpretedOption::clear_has_aggregate_value() { _has_bits_[0] &= ~0x00000040u; } inline void UninterpretedOption::clear_aggregate_value() { - if (aggregate_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { aggregate_value_->clear(); } clear_has_aggregate_value(); } inline const ::std::string& UninterpretedOption::aggregate_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.aggregate_value) return *aggregate_value_; } inline void UninterpretedOption::set_aggregate_value(const ::std::string& value) { set_has_aggregate_value(); - if (aggregate_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { aggregate_value_ = new ::std::string; } aggregate_value_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.aggregate_value) } inline void UninterpretedOption::set_aggregate_value(const char* value) { set_has_aggregate_value(); - if (aggregate_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { aggregate_value_ = new ::std::string; } aggregate_value_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.UninterpretedOption.aggregate_value) } inline void UninterpretedOption::set_aggregate_value(const char* value, size_t size) { set_has_aggregate_value(); - if (aggregate_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { aggregate_value_ = new ::std::string; } aggregate_value_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.UninterpretedOption.aggregate_value) } inline ::std::string* UninterpretedOption::mutable_aggregate_value() { set_has_aggregate_value(); - if (aggregate_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { aggregate_value_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.UninterpretedOption.aggregate_value) return aggregate_value_; } inline ::std::string* UninterpretedOption::release_aggregate_value() { clear_has_aggregate_value(); - if (aggregate_value_ == &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = aggregate_value_; - aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* aggregate_value) { - if (aggregate_value_ != &::google::protobuf::internal::GetEmptyString()) { + if (aggregate_value_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete aggregate_value_; } if (aggregate_value) { @@ -5729,8 +6466,9 @@ inline void UninterpretedOption::set_allocated_aggregate_value(::std::string* ag aggregate_value_ = aggregate_value; } else { clear_has_aggregate_value(); - aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + aggregate_value_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.UninterpretedOption.aggregate_value) } // ------------------------------------------------------------------- @@ -5745,20 +6483,25 @@ inline void SourceCodeInfo_Location::clear_path() { path_.Clear(); } inline ::google::protobuf::int32 SourceCodeInfo_Location::path(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path) return path_.Get(index); } inline void SourceCodeInfo_Location::set_path(int index, ::google::protobuf::int32 value) { path_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path) } inline void SourceCodeInfo_Location::add_path(::google::protobuf::int32 value) { path_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path) } inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& SourceCodeInfo_Location::path() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path) return path_; } inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* SourceCodeInfo_Location::mutable_path() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path) return &path_; } @@ -5770,20 +6513,25 @@ inline void SourceCodeInfo_Location::clear_span() { span_.Clear(); } inline ::google::protobuf::int32 SourceCodeInfo_Location::span(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span) return span_.Get(index); } inline void SourceCodeInfo_Location::set_span(int index, ::google::protobuf::int32 value) { span_.Set(index, value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span) } inline void SourceCodeInfo_Location::add_span(::google::protobuf::int32 value) { span_.Add(value); + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span) } inline const ::google::protobuf::RepeatedField< ::google::protobuf::int32 >& SourceCodeInfo_Location::span() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span) return span_; } inline ::google::protobuf::RepeatedField< ::google::protobuf::int32 >* SourceCodeInfo_Location::mutable_span() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span) return &span_; } @@ -5798,54 +6546,59 @@ inline void SourceCodeInfo_Location::clear_has_leading_comments() { _has_bits_[0] &= ~0x00000004u; } inline void SourceCodeInfo_Location::clear_leading_comments() { - if (leading_comments_ != &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { leading_comments_->clear(); } clear_has_leading_comments(); } inline const ::std::string& SourceCodeInfo_Location::leading_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.leading_comments) return *leading_comments_; } inline void SourceCodeInfo_Location::set_leading_comments(const ::std::string& value) { set_has_leading_comments(); - if (leading_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { leading_comments_ = new ::std::string; } leading_comments_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.leading_comments) } inline void SourceCodeInfo_Location::set_leading_comments(const char* value) { set_has_leading_comments(); - if (leading_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { leading_comments_ = new ::std::string; } leading_comments_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_comments) } inline void SourceCodeInfo_Location::set_leading_comments(const char* value, size_t size) { set_has_leading_comments(); - if (leading_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { leading_comments_ = new ::std::string; } leading_comments_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_comments) } inline ::std::string* SourceCodeInfo_Location::mutable_leading_comments() { set_has_leading_comments(); - if (leading_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { leading_comments_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.leading_comments) return leading_comments_; } inline ::std::string* SourceCodeInfo_Location::release_leading_comments() { clear_has_leading_comments(); - if (leading_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = leading_comments_; - leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::string* leading_comments) { - if (leading_comments_ != &::google::protobuf::internal::GetEmptyString()) { + if (leading_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete leading_comments_; } if (leading_comments) { @@ -5853,8 +6606,9 @@ inline void SourceCodeInfo_Location::set_allocated_leading_comments(::std::strin leading_comments_ = leading_comments; } else { clear_has_leading_comments(); - leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + leading_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.leading_comments) } // optional string trailing_comments = 4; @@ -5868,54 +6622,59 @@ inline void SourceCodeInfo_Location::clear_has_trailing_comments() { _has_bits_[0] &= ~0x00000008u; } inline void SourceCodeInfo_Location::clear_trailing_comments() { - if (trailing_comments_ != &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { trailing_comments_->clear(); } clear_has_trailing_comments(); } inline const ::std::string& SourceCodeInfo_Location::trailing_comments() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.trailing_comments) return *trailing_comments_; } inline void SourceCodeInfo_Location::set_trailing_comments(const ::std::string& value) { set_has_trailing_comments(); - if (trailing_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { trailing_comments_ = new ::std::string; } trailing_comments_->assign(value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.trailing_comments) } inline void SourceCodeInfo_Location::set_trailing_comments(const char* value) { set_has_trailing_comments(); - if (trailing_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { trailing_comments_ = new ::std::string; } trailing_comments_->assign(value); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.trailing_comments) } inline void SourceCodeInfo_Location::set_trailing_comments(const char* value, size_t size) { set_has_trailing_comments(); - if (trailing_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { trailing_comments_ = new ::std::string; } trailing_comments_->assign(reinterpret_cast(value), size); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.trailing_comments) } inline ::std::string* SourceCodeInfo_Location::mutable_trailing_comments() { set_has_trailing_comments(); - if (trailing_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { trailing_comments_ = new ::std::string; } + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.Location.trailing_comments) return trailing_comments_; } inline ::std::string* SourceCodeInfo_Location::release_trailing_comments() { clear_has_trailing_comments(); - if (trailing_comments_ == &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ == &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { return NULL; } else { ::std::string* temp = trailing_comments_; - trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); return temp; } } inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::string* trailing_comments) { - if (trailing_comments_ != &::google::protobuf::internal::GetEmptyString()) { + if (trailing_comments_ != &::google::protobuf::internal::GetEmptyStringAlreadyInited()) { delete trailing_comments_; } if (trailing_comments) { @@ -5923,8 +6682,9 @@ inline void SourceCodeInfo_Location::set_allocated_trailing_comments(::std::stri trailing_comments_ = trailing_comments; } else { clear_has_trailing_comments(); - trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyString()); + trailing_comments_ = const_cast< ::std::string*>(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceCodeInfo.Location.trailing_comments) } // ------------------------------------------------------------------- @@ -5939,20 +6699,25 @@ inline void SourceCodeInfo::clear_location() { location_.Clear(); } inline const ::google::protobuf::SourceCodeInfo_Location& SourceCodeInfo::location(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.location) return location_.Get(index); } inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::mutable_location(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceCodeInfo.location) return location_.Mutable(index); } inline ::google::protobuf::SourceCodeInfo_Location* SourceCodeInfo::add_location() { + // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.location) return location_.Add(); } inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >& SourceCodeInfo::location() const { + // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.location) return location_; } inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::SourceCodeInfo_Location >* SourceCodeInfo::mutable_location() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.location) return &location_; } @@ -5966,18 +6731,22 @@ SourceCodeInfo::mutable_location() { namespace google { namespace protobuf { +template <> struct is_proto_enum< ::google::protobuf::FieldDescriptorProto_Type> : ::google::protobuf::internal::true_type {}; template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Type>() { return ::google::protobuf::FieldDescriptorProto_Type_descriptor(); } +template <> struct is_proto_enum< ::google::protobuf::FieldDescriptorProto_Label> : ::google::protobuf::internal::true_type {}; template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldDescriptorProto_Label>() { return ::google::protobuf::FieldDescriptorProto_Label_descriptor(); } +template <> struct is_proto_enum< ::google::protobuf::FileOptions_OptimizeMode> : ::google::protobuf::internal::true_type {}; template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FileOptions_OptimizeMode>() { return ::google::protobuf::FileOptions_OptimizeMode_descriptor(); } +template <> struct is_proto_enum< ::google::protobuf::FieldOptions_CType> : ::google::protobuf::internal::true_type {}; template <> inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::FieldOptions_CType>() { return ::google::protobuf::FieldOptions_CType_descriptor(); diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto index a785f79f..45141646 100644 --- a/src/google/protobuf/descriptor.proto +++ b/src/google/protobuf/descriptor.proto @@ -96,6 +96,8 @@ message DescriptorProto { } repeated ExtensionRange extension_range = 5; + repeated OneofDescriptorProto oneof_decl = 8; + optional MessageOptions options = 7; } @@ -143,7 +145,7 @@ message FieldDescriptorProto { optional Label label = 4; // If type_name is set, this need not be set. If both this and type_name - // are set, this must be either TYPE_ENUM or TYPE_MESSAGE. + // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. optional Type type = 5; // For message and enum types, this is the name of the type. If the name @@ -164,9 +166,20 @@ message FieldDescriptorProto { // TODO(kenton): Base-64 encode? optional string default_value = 7; + // If set, gives the index of a oneof in the containing type's oneof_decl + // list. This field is a member of that oneof. Extensions of a oneof should + // not set this since the oneof to which they belong will be inferred based + // on the extension range containing the extension's field number. + optional int32 oneof_index = 9; + optional FieldOptions options = 8; } +// Describes a oneof. +message OneofDescriptorProto { + optional string name = 1; +} + // Describes an enum type. message EnumDescriptorProto { optional string name = 1; @@ -263,11 +276,26 @@ message FileOptions { optional bool java_multiple_files = 10 [default=false]; // If set true, then the Java code generator will generate equals() and - // hashCode() methods for all messages defined in the .proto file. This is - // purely a speed optimization, as the AbstractMessage base class includes - // reflection-based implementations of these methods. + // hashCode() methods for all messages defined in the .proto file. + // - In the full runtime, this is purely a speed optimization, as the + // AbstractMessage base class includes reflection-based implementations of + // these methods. + //- In the lite runtime, setting this option changes the semantics of + // equals() and hashCode() to more closely match those of the full runtime; + // the generated methods compute their results based on field values rather + // than object identity. (Implementations should not assume that hashcodes + // will be consistent across runtimes or versions of the protocol compiler.) optional bool java_generate_equals_and_hash = 20 [default=false]; + // If set true, then the Java2 code generator will generate code that + // throws an exception whenever an attempt is made to assign a non-UTF-8 + // byte sequence to a string field. + // Message reflection will do the same. + // However, an extension field still accepts non-UTF-8 byte sequences. + // This option has no effect on when used with the lite runtime. + optional bool java_string_check_utf8 = 27 [default=false]; + + // Generated classes can be optimized for speed or code size. enum OptimizeMode { SPEED = 1; // Generate complete code for parsing, serialization, @@ -297,6 +325,13 @@ message FileOptions { optional bool java_generic_services = 17 [default=false]; optional bool py_generic_services = 18 [default=false]; + // Is this file deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for everything in the file, or it will be completely ignored; in the very + // least, this is a formalization for deprecating files. + optional bool deprecated = 23 [default=false]; + + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -330,6 +365,12 @@ message MessageOptions { // from proto1 easier; new code should avoid fields named "descriptor". optional bool no_standard_descriptor_accessor = 2 [default=false]; + // Is this message deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the message, or it will be completely ignored; in the very least, + // this is a formalization for deprecating messages. + optional bool deprecated = 3 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -412,6 +453,8 @@ message FieldOptions { // For Google-internal migration only. Do not use. optional bool weak = 10 [default=false]; + + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -421,9 +464,15 @@ message FieldOptions { message EnumOptions { - // Set this option to false to disallow mapping different tag names to a same + // Set this option to true to allow mapping different tag names to the same // value. - optional bool allow_alias = 2 [default=true]; + optional bool allow_alias = 2; + + // Is this enum deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum, or it will be completely ignored; in the very least, this + // is a formalization for deprecating enums. + optional bool deprecated = 3 [default=false]; // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -433,6 +482,12 @@ message EnumOptions { } message EnumValueOptions { + // Is this enum value deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the enum value, or it will be completely ignored; in the very least, + // this is a formalization for deprecating enum values. + optional bool deprecated = 1 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -447,6 +502,12 @@ message ServiceOptions { // we were already using them long before we decided to release Protocol // Buffers. + // Is this service deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the service, or it will be completely ignored; in the very least, + // this is a formalization for deprecating services. + optional bool deprecated = 33 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; @@ -461,6 +522,12 @@ message MethodOptions { // we were already using them long before we decided to release Protocol // Buffers. + // Is this method deprecated? + // Depending on the target platform, this can emit Deprecated annotations + // for the method, or it will be completely ignored; in the very least, + // this is a formalization for deprecating methods. + optional bool deprecated = 33 [default=false]; + // The parser stores options it doesn't recognize here. See above. repeated UninterpretedOption uninterpreted_option = 999; diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc index 35e459d5..e5c25366 100644 --- a/src/google/protobuf/descriptor_database.cc +++ b/src/google/protobuf/descriptor_database.cc @@ -40,7 +40,7 @@ #include #include #include -#include +#include namespace google { namespace protobuf { @@ -289,6 +289,7 @@ bool SimpleDescriptorDatabase::FindAllExtensionNumbers( return index_.FindAllExtensionNumbers(extendee_type, output); } + bool SimpleDescriptorDatabase::MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output) { if (file == NULL) return false; @@ -537,5 +538,6 @@ bool MergedDescriptorDatabase::FindAllExtensionNumbers( return success; } + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h index 604648f8..c35e4785 100644 --- a/src/google/protobuf/descriptor_database.h +++ b/src/google/protobuf/descriptor_database.h @@ -101,6 +101,7 @@ class LIBPROTOBUF_EXPORT DescriptorDatabase { return false; } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase); }; @@ -356,6 +357,7 @@ class LIBPROTOBUF_EXPORT MergedDescriptorDatabase : public DescriptorDatabase { bool FindAllExtensionNumbers(const string& extendee_type, vector* output); + private: vector sources_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase); diff --git a/src/google/protobuf/descriptor_pb2_test.py b/src/google/protobuf/descriptor_pb2_test.py new file mode 100644 index 00000000..1c222288 --- /dev/null +++ b/src/google/protobuf/descriptor_pb2_test.py @@ -0,0 +1,54 @@ +#! /usr/bin/python +# +# Protocol Buffers - Google's data interchange format +# Copyright 2008 Google Inc. All rights reserved. +# http://code.google.com/p/protobuf/ +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Verify that prebuild and checkedin version of descriptor_pb2.py is up to date. + +from google3.pyglib import resources +import unittest + +_DESC = 'google3/net/proto2/proto/descriptor_pb2.' +_OLD = _DESC + 'py-prebuilt' +_NEW = _DESC + 'compiled' + + +class PregeneratedFileChanged(unittest.TestCase): + + def testSameText(self): + generated = resources.GetResource(_NEW) + checkedin = resources.GetResource(_OLD) + self.assertMultiLineEqual( + generated, checkedin, 'It seems that protoc _pb2 generator changed. ' + 'Please run google/protobuf/generate_descriptor_proto.sh to ' + 'regnerate a new version of %s and add it to your CL' % _OLD) + +if __name__ == '__main__': + unittest.main() diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc index 86e6a49d..9b77fbe8 100644 --- a/src/google/protobuf/descriptor_unittest.cc +++ b/src/google/protobuf/descriptor_unittest.cc @@ -646,6 +646,104 @@ TEST_F(DescriptorTest, FieldEnumType) { // =================================================================== +// Test simple flat messages and fields. +class OneofDescriptorTest : public testing::Test { + protected: + virtual void SetUp() { + // Build descriptors for the following definitions: + // + // package garply; + // message TestOneof { + // optional int32 a = 1; + // oneof foo { + // string b = 2; + // TestOneof c = 3; + // } + // oneof bar { + // float d = 4; + // } + // } + + FileDescriptorProto baz_file; + baz_file.set_name("baz.proto"); + baz_file.set_package("garply"); + + DescriptorProto* oneof_message = AddMessage(&baz_file, "TestOneof"); + oneof_message->add_oneof_decl()->set_name("foo"); + oneof_message->add_oneof_decl()->set_name("bar"); + + AddField(oneof_message, "a", 1, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + AddField(oneof_message, "b", 2, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_STRING); + oneof_message->mutable_field(1)->set_oneof_index(0); + AddField(oneof_message, "c", 3, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_MESSAGE); + oneof_message->mutable_field(2)->set_oneof_index(0); + oneof_message->mutable_field(2)->set_type_name("TestOneof"); + + AddField(oneof_message, "d", 4, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_FLOAT); + oneof_message->mutable_field(3)->set_oneof_index(1); + + // Build the descriptors and get the pointers. + baz_file_ = pool_.BuildFile(baz_file); + ASSERT_TRUE(baz_file_ != NULL); + + ASSERT_EQ(1, baz_file_->message_type_count()); + oneof_message_ = baz_file_->message_type(0); + + ASSERT_EQ(2, oneof_message_->oneof_decl_count()); + oneof_ = oneof_message_->oneof_decl(0); + oneof2_ = oneof_message_->oneof_decl(1); + + ASSERT_EQ(4, oneof_message_->field_count()); + a_ = oneof_message_->field(0); + b_ = oneof_message_->field(1); + c_ = oneof_message_->field(2); + d_ = oneof_message_->field(3); + } + + DescriptorPool pool_; + + const FileDescriptor* baz_file_; + + const Descriptor* oneof_message_; + + const OneofDescriptor* oneof_; + const OneofDescriptor* oneof2_; + const FieldDescriptor* a_; + const FieldDescriptor* b_; + const FieldDescriptor* c_; + const FieldDescriptor* d_; + const FieldDescriptor* e_; + const FieldDescriptor* f_; +}; + +TEST_F(OneofDescriptorTest, Normal) { + EXPECT_EQ("foo", oneof_->name()); + EXPECT_EQ("garply.TestOneof.foo", oneof_->full_name()); + EXPECT_EQ(0, oneof_->index()); + ASSERT_EQ(2, oneof_->field_count()); + EXPECT_EQ(b_, oneof_->field(0)); + EXPECT_EQ(c_, oneof_->field(1)); + EXPECT_TRUE(a_->containing_oneof() == NULL); + EXPECT_EQ(oneof_, b_->containing_oneof()); + EXPECT_EQ(oneof_, c_->containing_oneof()); +} + +TEST_F(OneofDescriptorTest, FindByName) { + EXPECT_EQ(oneof_, oneof_message_->FindOneofByName("foo")); + EXPECT_EQ(oneof2_, oneof_message_->FindOneofByName("bar")); + EXPECT_TRUE(oneof_message_->FindOneofByName("no_such_oneof") == NULL); +} + +// =================================================================== + class StylizedFieldNamesTest : public testing::Test { protected: void SetUp() { @@ -1516,6 +1614,40 @@ TEST_F(ExtensionDescriptorTest, FindAllExtensions) { EXPECT_EQ(39, extensions[3]->number()); } +TEST_F(ExtensionDescriptorTest, DuplicateFieldNumber) { + DescriptorPool pool; + FileDescriptorProto file_proto; + // Add "google/protobuf/descriptor.proto". + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + // Add "foo.proto": + // import "google/protobuf/descriptor.proto"; + // extend google.protobuf.FieldOptions { + // optional int32 option1 = 1000; + // } + file_proto.Clear(); + file_proto.set_name("foo.proto"); + file_proto.add_dependency("google/protobuf/descriptor.proto"); + AddExtension(&file_proto, "google.protobuf.FieldOptions", "option1", 1000, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + // Add "bar.proto": + // import "google/protobuf/descriptor.proto"; + // extend google.protobuf.FieldOptions { + // optional int32 option2 = 1000; + // } + file_proto.Clear(); + file_proto.set_name("bar.proto"); + file_proto.add_dependency("google/protobuf/descriptor.proto"); + AddExtension(&file_proto, "google.protobuf.FieldOptions", "option2", 1000, + FieldDescriptorProto::LABEL_OPTIONAL, + FieldDescriptorProto::TYPE_INT32); + // Currently we only generate a warning for conflicting extension numbers. + // TODO(xiaofeng): Change it to an error. + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); +} + // =================================================================== class MiscTest : public testing::Test { @@ -1567,6 +1699,18 @@ class MiscTest : public testing::Test { return field != NULL ? field->cpp_type_name() : ""; } + const Descriptor* GetMessageDescriptorForFieldType( + FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->message_type() : NULL; + } + + const EnumDescriptor* GetEnumDescriptorForFieldType( + FieldDescriptor::Type type) { + const FieldDescriptor* field = GetFieldDescriptorOfType(type); + return field != NULL ? field->enum_type() : NULL; + } + scoped_ptr pool_; }; @@ -1595,6 +1739,31 @@ TEST_F(MiscTest, TypeNames) { EXPECT_STREQ("sint64" , GetTypeNameForFieldType(FD::TYPE_SINT64 )); } +TEST_F(MiscTest, StaticTypeNames) { + // Test that correct type names are returned. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_STREQ("double" , FD::TypeName(FD::TYPE_DOUBLE )); + EXPECT_STREQ("float" , FD::TypeName(FD::TYPE_FLOAT )); + EXPECT_STREQ("int64" , FD::TypeName(FD::TYPE_INT64 )); + EXPECT_STREQ("uint64" , FD::TypeName(FD::TYPE_UINT64 )); + EXPECT_STREQ("int32" , FD::TypeName(FD::TYPE_INT32 )); + EXPECT_STREQ("fixed64" , FD::TypeName(FD::TYPE_FIXED64 )); + EXPECT_STREQ("fixed32" , FD::TypeName(FD::TYPE_FIXED32 )); + EXPECT_STREQ("bool" , FD::TypeName(FD::TYPE_BOOL )); + EXPECT_STREQ("string" , FD::TypeName(FD::TYPE_STRING )); + EXPECT_STREQ("group" , FD::TypeName(FD::TYPE_GROUP )); + EXPECT_STREQ("message" , FD::TypeName(FD::TYPE_MESSAGE )); + EXPECT_STREQ("bytes" , FD::TypeName(FD::TYPE_BYTES )); + EXPECT_STREQ("uint32" , FD::TypeName(FD::TYPE_UINT32 )); + EXPECT_STREQ("enum" , FD::TypeName(FD::TYPE_ENUM )); + EXPECT_STREQ("sfixed32", FD::TypeName(FD::TYPE_SFIXED32)); + EXPECT_STREQ("sfixed64", FD::TypeName(FD::TYPE_SFIXED64)); + EXPECT_STREQ("sint32" , FD::TypeName(FD::TYPE_SINT32 )); + EXPECT_STREQ("sint64" , FD::TypeName(FD::TYPE_SINT64 )); +} + TEST_F(MiscTest, CppTypes) { // Test that CPP types are assigned correctly. @@ -1645,6 +1814,74 @@ TEST_F(MiscTest, CppTypeNames) { EXPECT_STREQ("int64" , GetCppTypeNameForFieldType(FD::TYPE_SINT64 )); } +TEST_F(MiscTest, StaticCppTypeNames) { + // Test that correct CPP type names are returned. + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_STREQ("int32" , FD::CppTypeName(FD::CPPTYPE_INT32 )); + EXPECT_STREQ("int64" , FD::CppTypeName(FD::CPPTYPE_INT64 )); + EXPECT_STREQ("uint32" , FD::CppTypeName(FD::CPPTYPE_UINT32 )); + EXPECT_STREQ("uint64" , FD::CppTypeName(FD::CPPTYPE_UINT64 )); + EXPECT_STREQ("double" , FD::CppTypeName(FD::CPPTYPE_DOUBLE )); + EXPECT_STREQ("float" , FD::CppTypeName(FD::CPPTYPE_FLOAT )); + EXPECT_STREQ("bool" , FD::CppTypeName(FD::CPPTYPE_BOOL )); + EXPECT_STREQ("enum" , FD::CppTypeName(FD::CPPTYPE_ENUM )); + EXPECT_STREQ("string" , FD::CppTypeName(FD::CPPTYPE_STRING )); + EXPECT_STREQ("message", FD::CppTypeName(FD::CPPTYPE_MESSAGE)); +} + +TEST_F(MiscTest, MessageType) { + // Test that message_type() is NULL for non-aggregate fields + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_DOUBLE )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FLOAT )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT64 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT64 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_INT32 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED64 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_FIXED32 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BOOL )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_STRING )); + EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_GROUP )); + EXPECT_TRUE(NULL != GetMessageDescriptorForFieldType(FD::TYPE_MESSAGE )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_BYTES )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_UINT32 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_ENUM )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED32)); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SFIXED64)); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT32 )); + EXPECT_TRUE(NULL == GetMessageDescriptorForFieldType(FD::TYPE_SINT64 )); +} + +TEST_F(MiscTest, EnumType) { + // Test that enum_type() is NULL for non-enum fields + + typedef FieldDescriptor FD; // avoid ugly line wrapping + + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_DOUBLE )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FLOAT )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT64 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT64 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_INT32 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED64 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_FIXED32 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BOOL )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_STRING )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_GROUP )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_MESSAGE )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_BYTES )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_UINT32 )); + EXPECT_TRUE(NULL != GetEnumDescriptorForFieldType(FD::TYPE_ENUM )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED32)); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SFIXED64)); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT32 )); + EXPECT_TRUE(NULL == GetEnumDescriptorForFieldType(FD::TYPE_SINT64 )); +} + + TEST_F(MiscTest, DefaultValues) { // Test that setting default values works. FileDescriptorProto file_proto; @@ -1910,10 +2147,12 @@ class AllowUnknownDependenciesTest TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) { ASSERT_EQ(2, foo_file_->dependency_count()); EXPECT_EQ(bar_file_, foo_file_->dependency(0)); + EXPECT_FALSE(bar_file_->is_placeholder()); const FileDescriptor* baz_file = foo_file_->dependency(1); EXPECT_EQ("baz.proto", baz_file->name()); EXPECT_EQ(0, baz_file->message_type_count()); + EXPECT_TRUE(baz_file->is_placeholder()); // Placeholder files should not be findable. EXPECT_EQ(bar_file_, pool_->FindFileByName(bar_file_->name())); @@ -1923,19 +2162,20 @@ TEST_P(AllowUnknownDependenciesTest, PlaceholderFile) { TEST_P(AllowUnknownDependenciesTest, PlaceholderTypes) { ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, bar_field_->type()); EXPECT_EQ(bar_type_, bar_field_->message_type()); + EXPECT_FALSE(bar_type_->is_placeholder()); ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, baz_field_->type()); const Descriptor* baz_type = baz_field_->message_type(); EXPECT_EQ("Baz", baz_type->name()); EXPECT_EQ("Baz", baz_type->full_name()); - EXPECT_EQ("Baz.placeholder.proto", baz_type->file()->name()); EXPECT_EQ(0, baz_type->extension_range_count()); + EXPECT_TRUE(baz_type->is_placeholder()); ASSERT_EQ(FieldDescriptor::TYPE_ENUM, qux_field_->type()); const EnumDescriptor* qux_type = qux_field_->enum_type(); EXPECT_EQ("Qux", qux_type->name()); EXPECT_EQ("corge.Qux", qux_type->full_name()); - EXPECT_EQ("corge.Qux.placeholder.proto", qux_type->file()->name()); + EXPECT_TRUE(qux_type->is_placeholder()); // Placeholder types should not be findable. EXPECT_EQ(bar_type_, pool_->FindMessageTypeByName(bar_type_->full_name())); @@ -1993,6 +2233,7 @@ TEST_P(AllowUnknownDependenciesTest, UnknownExtendee) { ASSERT_EQ(1, file->extension_count()); const Descriptor* extendee = file->extension(0)->containing_type(); EXPECT_EQ("UnknownType", extendee->name()); + EXPECT_TRUE(extendee->is_placeholder()); ASSERT_EQ(1, extendee->extension_range_count()); EXPECT_EQ(1, extendee->extension_range(0)->start); EXPECT_EQ(FieldDescriptor::kMaxNumber + 1, extendee->extension_range(0)->end); @@ -2111,13 +2352,13 @@ TEST_P(AllowUnknownDependenciesTest, const Descriptor* corge_desc = file->message_type(0); ASSERT_EQ("Corge", corge_desc->name()); ASSERT_EQ(1, corge_desc->field_count()); + EXPECT_FALSE(corge_desc->is_placeholder()); const FieldDescriptor* quux_field = corge_desc->field(0); ASSERT_EQ(FieldDescriptor::TYPE_MESSAGE, quux_field->type()); ASSERT_EQ("Quux", quux_field->message_type()->name()); ASSERT_EQ("undeclared.Quux", quux_field->message_type()->full_name()); - EXPECT_EQ("undeclared.Quux.placeholder.proto", - quux_field->message_type()->file()->name()); + EXPECT_TRUE(quux_field->message_type()->is_placeholder()); // The place holder type should not be findable. ASSERT_TRUE(pool_->FindMessageTypeByName("undeclared.Quux") == NULL); } @@ -2167,7 +2408,7 @@ TEST(CustomOptions, OptionTypes) { options = &protobuf_unittest::CustomOptionMinIntegerValues::descriptor()->options(); - EXPECT_FALSE( options->GetExtension(protobuf_unittest::bool_opt)); + EXPECT_EQ(false , options->GetExtension(protobuf_unittest::bool_opt)); EXPECT_EQ(kint32min, options->GetExtension(protobuf_unittest::int32_opt)); EXPECT_EQ(kint64min, options->GetExtension(protobuf_unittest::int64_opt)); EXPECT_EQ(0 , options->GetExtension(protobuf_unittest::uint32_opt)); @@ -2181,7 +2422,7 @@ TEST(CustomOptions, OptionTypes) { options = &protobuf_unittest::CustomOptionMaxIntegerValues::descriptor()->options(); - EXPECT_TRUE( options->GetExtension(protobuf_unittest::bool_opt)); + EXPECT_EQ(true , options->GetExtension(protobuf_unittest::bool_opt)); EXPECT_EQ(kint32max , options->GetExtension(protobuf_unittest::int32_opt)); EXPECT_EQ(kint64max , options->GetExtension(protobuf_unittest::int64_opt)); EXPECT_EQ(kuint32max, options->GetExtension(protobuf_unittest::uint32_opt)); @@ -2389,6 +2630,170 @@ TEST(CustomOptions, MessageOptionThreeFieldsSet) { EXPECT_EQ(1234, options.GetExtension(protobuf_unittest::complex_opt1).foo()); } +TEST(CustomOptions, MessageOptionRepeatedLeafFieldSet) { + // This test verifies that repeated fields in custom options can be + // given multiple values by repeating the option with a different value. + // This test checks repeated leaf values. Each repeated custom value + // appears in a different uninterpreted_option, which will be concatenated + // when they are merged into the final option value. + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + // The following represents the definition: + // + // import "google/protobuf/unittest_custom_options.proto" + // package protobuf_unittest; + // message Foo { + // option (complex_opt1).foo4 = 12; + // option (complex_opt1).foo4 = 34; + // option (complex_opt1).foo4 = 56; + // } + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 12 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 34 " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt1\" " + " is_extension: true " + " } " + " name { " + " name_part: \"foo4\" " + " is_extension: false " + " } " + " positive_int_value: 56 " + " } " + " } " + "}", + &file_proto)); + + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + ASSERT_EQ(1, file->message_type_count()); + + const MessageOptions& options = file->message_type(0)->options(); + EXPECT_EQ(3, options.GetExtension(protobuf_unittest::complex_opt1).foo4_size()); + EXPECT_EQ(12, options.GetExtension(protobuf_unittest::complex_opt1).foo4(0)); + EXPECT_EQ(34, options.GetExtension(protobuf_unittest::complex_opt1).foo4(1)); + EXPECT_EQ(56, options.GetExtension(protobuf_unittest::complex_opt1).foo4(2)); +} + +TEST(CustomOptions, MessageOptionRepeatedMsgFieldSet) { + // This test verifies that repeated fields in custom options can be + // given multiple values by repeating the option with a different value. + // This test checks repeated message values. Each repeated custom value + // appears in a different uninterpreted_option, which will be concatenated + // when they are merged into the final option value. + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + // The following represents the definition: + // + // import "google/protobuf/unittest_custom_options.proto" + // package protobuf_unittest; + // message Foo { + // option (complex_opt2).barney = {waldo: 1}; + // option (complex_opt2).barney = {waldo: 10}; + // option (complex_opt2).barney = {waldo: 100}; + // } + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" " + "message_type { " + " name: \"Foo\" " + " options { " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 1\" " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 10\" " + " } " + " uninterpreted_option { " + " name { " + " name_part: \"complex_opt2\" " + " is_extension: true " + " } " + " name { " + " name_part: \"barney\" " + " is_extension: false " + " } " + " aggregate_value: \"waldo: 100\" " + " } " + " } " + "}", + &file_proto)); + + const FileDescriptor* file = pool.BuildFile(file_proto); + ASSERT_TRUE(file != NULL); + ASSERT_EQ(1, file->message_type_count()); + + const MessageOptions& options = file->message_type(0)->options(); + EXPECT_EQ(3, options.GetExtension( + protobuf_unittest::complex_opt2).barney_size()); + EXPECT_EQ(1,options.GetExtension( + protobuf_unittest::complex_opt2).barney(0).waldo()); + EXPECT_EQ(10, options.GetExtension( + protobuf_unittest::complex_opt2).barney(1).waldo()); + EXPECT_EQ(100, options.GetExtension( + protobuf_unittest::complex_opt2).barney(2).waldo()); +} + // Check that aggregate options were parsed and saved correctly in // the appropriate descriptors. TEST(CustomOptions, AggregateOptions) { @@ -2429,6 +2834,27 @@ TEST(CustomOptions, AggregateOptions) { method->options().GetExtension(protobuf_unittest::methodopt).s()); } +TEST(CustomOptions, UnusedImportWarning) { + DescriptorPool pool; + + FileDescriptorProto file_proto; + FileDescriptorProto::descriptor()->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + protobuf_unittest::TestMessageWithCustomOptions::descriptor() + ->file()->CopyTo(&file_proto); + ASSERT_TRUE(pool.BuildFile(file_proto) != NULL); + + + pool.AddUnusedImportTrackFile("custom_options_import.proto"); + ASSERT_TRUE(TextFormat::ParseFromString( + "name: \"custom_options_import.proto\" " + "package: \"protobuf_unittest\" " + "dependency: \"google/protobuf/unittest_custom_options.proto\" ", + &file_proto)); + pool.BuildFile(file_proto); +} + // =================================================================== // The tests below trigger every unique call to AddError() in descriptor.cc, @@ -2442,6 +2868,7 @@ class MockErrorCollector : public DescriptorPool::ErrorCollector { ~MockErrorCollector() {} string text_; + string warning_text_; // implements ErrorCollector --------------------------------------- void AddError(const string& filename, @@ -2465,6 +2892,29 @@ class MockErrorCollector : public DescriptorPool::ErrorCollector { &text_, "$0: $1: $2: $3\n", filename, element_name, location_name, message); } + + // implements ErrorCollector --------------------------------------- + void AddWarning(const string& filename, const string& element_name, + const Message* descriptor, ErrorLocation location, + const string& message) { + const char* location_name = NULL; + switch (location) { + case NAME : location_name = "NAME" ; break; + case NUMBER : location_name = "NUMBER" ; break; + case TYPE : location_name = "TYPE" ; break; + case EXTENDEE : location_name = "EXTENDEE" ; break; + case DEFAULT_VALUE: location_name = "DEFAULT_VALUE"; break; + case OPTION_NAME : location_name = "OPTION_NAME" ; break; + case OPTION_VALUE : location_name = "OPTION_VALUE" ; break; + case INPUT_TYPE : location_name = "INPUT_TYPE" ; break; + case OUTPUT_TYPE : location_name = "OUTPUT_TYPE" ; break; + case OTHER : location_name = "OTHER" ; break; + } + + strings::SubstituteAndAppend( + &warning_text_, "$0: $1: $2: $3\n", + filename, element_name, location_name, message); + } }; class ValidationErrorTest : public testing::Test { @@ -2491,6 +2941,19 @@ class ValidationErrorTest : public testing::Test { EXPECT_EQ(expected_errors, error_collector.text_); } + // Parse file_text as a FileDescriptorProto in text format and add it + // to the DescriptorPool. Expect errors to be produced which match the + // given warning text. + void BuildFileWithWarnings(const string& file_text, + const string& expected_warnings) { + FileDescriptorProto file_proto; + ASSERT_TRUE(TextFormat::ParseFromString(file_text, &file_proto)); + + MockErrorCollector error_collector; + EXPECT_TRUE(pool_.BuildFileCollectingErrors(file_proto, &error_collector)); + EXPECT_EQ(expected_warnings, error_collector.warning_text_); + } + // Builds some already-parsed file in our test pool. void BuildFileInTestPool(const FileDescriptor* file) { FileDescriptorProto file_proto; @@ -2744,8 +3207,8 @@ TEST_F(ValidationErrorTest, InvalidDefaults) { " default_value: \"1\" }" "}", - "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value.\n" - "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value.\n" + "foo.proto: Foo.foo: DEFAULT_VALUE: Couldn't parse default value \"abc\".\n" + "foo.proto: Foo.bar: DEFAULT_VALUE: Couldn't parse default value \"\".\n" "foo.proto: Foo.baz: DEFAULT_VALUE: Boolean default must be true or " "false.\n" "foo.proto: Foo.qux: DEFAULT_VALUE: Messages can't have default values.\n" @@ -2828,6 +3291,38 @@ TEST_F(ValidationErrorTest, NonExtensionWithExtendee) { "non-extension field.\n"); } +TEST_F(ValidationErrorTest, FieldOneofIndexTooLarge) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 1 }" + " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index 1 is out of " + "range for type \"Foo\".\n"); +} + +TEST_F(ValidationErrorTest, FieldOneofIndexNegative) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: -1 }" + " field { name:\"dummy\" number:2 label:LABEL_OPTIONAL type:TYPE_INT32 " + " oneof_index: 0 }" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.foo: OTHER: FieldDescriptorProto.oneof_index -1 is out of " + "range for type \"Foo\".\n"); +} + TEST_F(ValidationErrorTest, FieldNumberConflict) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -2988,6 +3483,28 @@ TEST_F(ValidationErrorTest, NotAnExtensionNumber) { "number.\n"); } +TEST_F(ValidationErrorTest, RequiredExtension) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Bar\"" + " extension_range { start: 1000 end: 10000 }" + "}" + "message_type {" + " name: \"Foo\"" + " extension {" + " name:\"foo\"" + " number:1000" + " label:LABEL_REQUIRED" + " type:TYPE_INT32" + " extendee: \"Bar\"" + " }" + "}", + + "foo.proto: Foo.foo: TYPE: Message extensions cannot have required " + "fields.\n"); +} + TEST_F(ValidationErrorTest, UndefinedFieldType) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -2999,6 +3516,36 @@ TEST_F(ValidationErrorTest, UndefinedFieldType) { "foo.proto: Foo.foo: TYPE: \"Bar\" is not defined.\n"); } +TEST_F(ValidationErrorTest, UndefinedFieldTypeWithDefault) { + // See b/12533582. Previously this failed because the default value was not + // accepted by the parser, which assumed an enum type, leading to an unclear + // error message. We want this input to yield a validation error instead, + // since the unknown type is the primary problem. + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"int\" " + " default_value:\"1\" }" + "}", + + "foo.proto: Foo.foo: TYPE: \"int\" is not defined.\n"); +} + +TEST_F(ValidationErrorTest, UndefinedNestedFieldType) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " nested_type { name:\"Baz\" }" + " field { name:\"foo\" number:1" + " label:LABEL_OPTIONAL" + " type_name:\"Foo.Baz.Bar\" }" + "}", + + "foo.proto: Foo.foo: TYPE: \"Foo.Baz.Bar\" is not defined.\n"); +} + TEST_F(ValidationErrorTest, FieldTypeDefinedInUndeclaredDependency) { BuildFile( "name: \"bar.proto\" " @@ -3174,7 +3721,8 @@ TEST_F(ValidationErrorTest, TEST_F(ValidationErrorTest, SearchMostLocalFirst) { - // The following should produce an error that Bar.Baz is not defined: + // The following should produce an error that Bar.Baz is resolved but + // not defined: // message Bar { message Baz {} } // message Foo { // message Bar { @@ -3200,7 +3748,10 @@ TEST_F(ValidationErrorTest, SearchMostLocalFirst) { " type_name:\"Bar.Baz\" }" "}", - "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is not defined.\n"); + "foo.proto: Foo.baz: TYPE: \"Bar.Baz\" is resolved to \"Foo.Bar.Baz\"," + " which is not defined. The innermost scope is searched first in name " + "resolution. Consider using a leading '.'(i.e., \".Bar.Baz\") to start " + "from the outermost scope.\n"); } TEST_F(ValidationErrorTest, SearchMostLocalFirst2) { @@ -3342,6 +3893,20 @@ TEST_F(ValidationErrorTest, BadEnumDefaultValue) { "\"NO_SUCH_VALUE\".\n"); } +TEST_F(ValidationErrorTest, EnumDefaultValueIsInteger) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "enum_type { name: \"Bar\" value { name:\"DUMMY\" number:0 } } " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_OPTIONAL type_name:\"Bar\"" + " default_value:\"0\" }" + "}", + + "foo.proto: Foo.foo: DEFAULT_VALUE: Default value for an enum field must " + "be an identifier.\n"); +} + TEST_F(ValidationErrorTest, PrimitiveWithTypeName) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -3366,6 +3931,31 @@ TEST_F(ValidationErrorTest, NonPrimitiveWithoutTypeName) { "type_name.\n"); } +TEST_F(ValidationErrorTest, OneofWithNoFields) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.bar: NAME: Oneof must have at least one field.\n"); +} + +TEST_F(ValidationErrorTest, OneofLabelMismatch) { + BuildFileWithErrors( + "name: \"foo.proto\" " + "message_type {" + " name: \"Foo\"" + " field { name:\"foo\" number:1 label:LABEL_REPEATED type:TYPE_INT32 " + " oneof_index:0 }" + " oneof_decl { name:\"bar\" }" + "}", + + "foo.proto: Foo.foo: NAME: Fields of oneofs must themselves have label " + "LABEL_OPTIONAL.\n"); +} + TEST_F(ValidationErrorTest, InputTypeNotDefined) { BuildFileWithErrors( "name: \"foo.proto\" " @@ -3527,20 +4117,85 @@ TEST_F(ValidationErrorTest, InvalidOptionName) { "reserved name \"uninterpreted_option\".\n"); } -TEST_F(ValidationErrorTest, RepeatedOption) { +TEST_F(ValidationErrorTest, RepeatedMessageOption) { BuildDescriptorMessagesInTestPool(); BuildFileWithErrors( "name: \"foo.proto\" " "dependency: \"google/protobuf/descriptor.proto\" " - "extension { name: \"foo\" number: 7672757 label: LABEL_REPEATED " - " type: TYPE_FLOAT extendee: \"google.protobuf.FileOptions\" }" - "options { uninterpreted_option { name { name_part: \"foo\" " + "message_type: { name: \"Bar\" field: { " + " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " + "} " + "extension { name: \"bar\" number: 7672757 label: LABEL_REPEATED " + " type: TYPE_MESSAGE type_name: \"Bar\" " + " extendee: \"google.protobuf.FileOptions\" }" + "options { uninterpreted_option { name { name_part: \"bar\" " " is_extension: true } " - " double_value: 1.2 } }", + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", - "foo.proto: foo.proto: OPTION_NAME: Option field \"(foo)\" is repeated. " - "Repeated options are not supported.\n"); + "foo.proto: foo.proto: OPTION_NAME: Option field \"(bar)\" is a " + "repeated message. Repeated message options must be initialized " + "using an aggregate value.\n"); +} + +TEST_F(ValidationErrorTest, ResolveUndefinedOption) { + // The following should produce an eror that baz.bar is resolved but not + // defined. + // foo.proto: + // package baz + // import google/protobuf/descriptor.proto + // message Bar { optional int32 foo = 1; } + // extend FileOptions { optional Bar bar = 7672757; } + // + // qux.proto: + // package qux.baz + // option (baz.bar).foo = 1; + // + // Although "baz.bar" is already defined, the lookup code will try + // "qux.baz.bar", since it's the match from the innermost scope, which will + // cause a symbol not defined error. + BuildDescriptorMessagesInTestPool(); + + BuildFile( + "name: \"foo.proto\" " + "package: \"baz\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "message_type: { name: \"Bar\" field: { " + " name: \"foo\" number: 1 label: LABEL_OPTIONAL type: TYPE_INT32 } " + "} " + "extension { name: \"bar\" number: 7672757 label: LABEL_OPTIONAL " + " type: TYPE_MESSAGE type_name: \"Bar\" " + " extendee: \"google.protobuf.FileOptions\" }"); + + BuildFileWithErrors( + "name: \"qux.proto\" " + "package: \"qux.baz\" " + "options { uninterpreted_option { name { name_part: \"baz.bar\" " + " is_extension: true } " + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", + + "qux.proto: qux.proto: OPTION_NAME: Option \"(baz.bar)\" is resolved to " + "\"(qux.baz.bar)\"," + " which is not defined. The innermost scope is searched first in name " + "resolution. Consider using a leading '.'(i.e., \"(.baz.bar)\") to start " + "from the outermost scope.\n"); +} + +TEST_F(ValidationErrorTest, UnknownOption) { + BuildFileWithErrors( + "name: \"qux.proto\" " + "package: \"qux.baz\" " + "options { uninterpreted_option { name { name_part: \"baaz.bar\" " + " is_extension: true } " + " name { name_part: \"foo\" " + " is_extension: false } " + " positive_int_value: 1 } }", + + "qux.proto: qux.proto: OPTION_NAME: Option \"(baaz.bar)\" unknown.\n"); } TEST_F(ValidationErrorTest, CustomOptionConflictingFieldNumber) { @@ -3813,6 +4468,25 @@ TEST_F(ValidationErrorTest, StringOptionValueIsNotString) { "string option \"foo\".\n"); } +TEST_F(ValidationErrorTest, DuplicateExtensionFieldNumber) { + BuildDescriptorMessagesInTestPool(); + + BuildFile( + "name: \"foo.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"option1\" number: 1000 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }"); + + BuildFileWithWarnings( + "name: \"bar.proto\" " + "dependency: \"google/protobuf/descriptor.proto\" " + "extension { name: \"option2\" number: 1000 label: LABEL_OPTIONAL " + " type: TYPE_INT32 extendee: \"google.protobuf.FileOptions\" }", + "bar.proto: option2: NUMBER: Extension number 1000 has already been used " + "in \"google.protobuf.FileOptions\" by extension \"option1\" defined in " + "foo.proto.\n"); +} + // Helper function for tests that check for aggregate value parsing // errors. The "value" argument is embedded inside the // "uninterpreted_option" portion of the result. @@ -3998,7 +4672,6 @@ TEST_F(ValidationErrorTest, DisallowEnumAlias) { " name: \"Bar\"" " value { name:\"ENUM_A\" number:0 }" " value { name:\"ENUM_B\" number:0 }" - " options { allow_alias: false }" "}", "foo.proto: Bar: NUMBER: " "\"ENUM_B\" uses the same enum value as \"ENUM_A\". " @@ -4006,6 +4679,64 @@ TEST_F(ValidationErrorTest, DisallowEnumAlias) { "definition.\n"); } +TEST_F(ValidationErrorTest, AllowEnumAlias) { + BuildFile( + "name: \"foo.proto\" " + "enum_type {" + " name: \"Bar\"" + " value { name:\"ENUM_A\" number:0 }" + " value { name:\"ENUM_B\" number:0 }" + " options { allow_alias: true }" + "}"); +} + +TEST_F(ValidationErrorTest, UnusedImportWarning) { + + pool_.AddUnusedImportTrackFile("bar.proto"); + BuildFile( + "name: \"bar.proto\" " + "message_type { name: \"Bar\" }"); + + pool_.AddUnusedImportTrackFile("base.proto"); + BuildFile( + "name: \"base.proto\" " + "message_type { name: \"Base\" }"); + + pool_.AddUnusedImportTrackFile("baz.proto"); + BuildFile( + "name: \"baz.proto\" " + "message_type { name: \"Baz\" }"); + + pool_.AddUnusedImportTrackFile("public.proto"); + BuildFile( + "name: \"public.proto\" " + "dependency: \"bar.proto\"" + "public_dependency: 0"); + + // // forward.proto + // import "base.proto" // No warning: Base message is used. + // import "bar.proto" // Will log a warning. + // import public "baz.proto" // No warning: Do not track import public. + // import "public.proto" // No warning: public.proto has import public. + // message Forward { + // optional Base base = 1; + // } + // + pool_.AddUnusedImportTrackFile("forward.proto"); + BuildFile( + "name: \"forward.proto\"" + "dependency: \"base.proto\"" + "dependency: \"bar.proto\"" + "dependency: \"baz.proto\"" + "dependency: \"public.proto\"" + "public_dependency: 2 " + "message_type {" + " name: \"Forward\"" + " field { name:\"base\" number:1 label:LABEL_OPTIONAL type_name:\"Base\" }" + "}"); +} + + // =================================================================== // DescriptorDatabase @@ -4328,6 +5059,10 @@ TEST_F(DatabaseBackedPoolTest, UnittestProto) { EXPECT_EQ(original_file_proto.DebugString(), file_from_database_proto.DebugString()); + + // Also verify that CopyTo() did not omit any information. + EXPECT_EQ(original_file->DebugString(), + file_from_database->DebugString()); } TEST_F(DatabaseBackedPoolTest, DoesntRetryDbUnnecessarily) { @@ -4396,15 +5131,93 @@ TEST_F(DatabaseBackedPoolTest, DoesntReloadFilesUncesessarily) { EXPECT_EQ("", error_collector.text_); } +// DescriptorDatabase that attempts to induce exponentially-bad performance +// in DescriptorPool. For every positive N, the database contains a file +// fileN.proto, which defines a message MessageN, which contains fields of +// type MessageK for all K in [0,N). Message0 is not defined anywhere +// (file0.proto exists, but is empty), so every other file and message type +// will fail to build. +// +// If the DescriptorPool is not careful to memoize errors, an attempt to +// build a descriptor for MessageN can require O(2^N) time. +class ExponentialErrorDatabase : public DescriptorDatabase { + public: + ExponentialErrorDatabase() {} + ~ExponentialErrorDatabase() {} + + // implements DescriptorDatabase --------------------------------- + bool FindFileByName(const string& filename, + FileDescriptorProto* output) { + int file_num = -1; + FullMatch(filename, "file", ".proto", &file_num); + if (file_num > -1) { + return PopulateFile(file_num, output); + } else { + return false; + } + } + bool FindFileContainingSymbol(const string& symbol_name, + FileDescriptorProto* output) { + int file_num = -1; + FullMatch(symbol_name, "Message", "", &file_num); + if (file_num > 0) { + return PopulateFile(file_num, output); + } else { + return false; + } + } + bool FindFileContainingExtension(const string& containing_type, + int field_number, + FileDescriptorProto* output) { + return false; + } + + private: + void FullMatch(const string& name, + const string& begin_with, + const string& end_with, + int* file_num) { + int begin_size = begin_with.size(); + int end_size = end_with.size(); + if (name.substr(0, begin_size) != begin_with || + name.substr(name.size()- end_size, end_size) != end_with) { + return; + } + safe_strto32(name.substr(begin_size, name.size() - end_size - begin_size), + file_num); + } + + bool PopulateFile(int file_num, FileDescriptorProto* output) { + using strings::Substitute; + GOOGLE_CHECK_GE(file_num, 0); + output->Clear(); + output->set_name(Substitute("file$0.proto", file_num)); + // file0.proto doesn't define Message0 + if (file_num > 0) { + DescriptorProto* message = output->add_message_type(); + message->set_name(Substitute("Message$0", file_num)); + for (int i = 0; i < file_num; ++i) { + output->add_dependency(Substitute("file$0.proto", i)); + FieldDescriptorProto* field = message->add_field(); + field->set_name(Substitute("field$0", i)); + field->set_number(i); + field->set_label(FieldDescriptorProto::LABEL_OPTIONAL); + field->set_type(FieldDescriptorProto::TYPE_MESSAGE); + field->set_type_name(Substitute("Message$0", i)); + } + } + return true; + } +}; + TEST_F(DatabaseBackedPoolTest, DoesntReloadKnownBadFiles) { - ErrorDescriptorDatabase error_database; - MockErrorCollector error_collector; - DescriptorPool pool(&error_database, &error_collector); + ExponentialErrorDatabase error_database; + DescriptorPool pool(&error_database); - EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); - error_collector.text_.clear(); - EXPECT_TRUE(pool.FindFileByName("error.proto") == NULL); - EXPECT_EQ("", error_collector.text_); + GOOGLE_LOG(INFO) << "A timeout in this test probably indicates a real bug."; + + EXPECT_TRUE(pool.FindFileByName("file40.proto") == NULL); + EXPECT_TRUE(pool.FindMessageTypeByName("Message40") == NULL); } TEST_F(DatabaseBackedPoolTest, DoesntFallbackOnWrongType) { @@ -4489,6 +5302,17 @@ const char *const kSourceLocationTestInput = " rpc Method(A) returns (A.B);\n" // Put an empty line here to make the source location range match. "\n" + "}\n" + "message MessageWithExtensions {\n" + " extensions 1000 to max;\n" + "}\n" + "extend MessageWithExtensions {\n" + " optional int32 int32_extension = 1001;\n" + "}\n" + "message C {\n" + " extend MessageWithExtensions {\n" + " optional C message_extension = 1002;\n" + " }\n" "}\n"; class SourceLocationTest : public testing::Test { @@ -4550,6 +5374,27 @@ TEST_F(SourceLocationTest, GetSourceLocation) { } +TEST_F(SourceLocationTest, ExtensionSourceLocation) { + SourceLocation loc; + + const FileDescriptor *file_desc = + GOOGLE_CHECK_NOTNULL(pool_.FindFileByName("/test/test.proto")); + + const FieldDescriptor *int32_extension_desc = + file_desc->FindExtensionByName("int32_extension"); + EXPECT_TRUE(int32_extension_desc->GetSourceLocation(&loc)); + EXPECT_EQ("21:3-21:41", PrintSourceLocation(loc)); + + const Descriptor *c_desc = file_desc->FindMessageTypeByName("C"); + EXPECT_TRUE(c_desc->GetSourceLocation(&loc)); + EXPECT_EQ("23:1-27:2", PrintSourceLocation(loc)); + + const FieldDescriptor *message_extension_desc = + c_desc->FindExtensionByName("message_extension"); + EXPECT_TRUE(message_extension_desc->GetSourceLocation(&loc)); + EXPECT_EQ("25:5-25:41", PrintSourceLocation(loc)); +} + // Missing SourceCodeInfo doesn't cause crash: TEST_F(SourceLocationTest, GetSourceLocation_MissingSourceCodeInfo) { SourceLocation loc; diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc index 09bec543..d3d52113 100644 --- a/src/google/protobuf/dynamic_message.cc +++ b/src/google/protobuf/dynamic_message.cc @@ -141,11 +141,42 @@ int FieldSpaceUsed(const FieldDescriptor* field) { return 0; } +// Compute the byte size of in-memory representation of the oneof fields +// in default oneof instance. +int OneofFieldSpaceUsed(const FieldDescriptor* field) { + typedef FieldDescriptor FD; // avoid line wrapping + switch (field->cpp_type()) { + case FD::CPPTYPE_INT32 : return sizeof(int32 ); + case FD::CPPTYPE_INT64 : return sizeof(int64 ); + case FD::CPPTYPE_UINT32 : return sizeof(uint32 ); + case FD::CPPTYPE_UINT64 : return sizeof(uint64 ); + case FD::CPPTYPE_DOUBLE : return sizeof(double ); + case FD::CPPTYPE_FLOAT : return sizeof(float ); + case FD::CPPTYPE_BOOL : return sizeof(bool ); + case FD::CPPTYPE_ENUM : return sizeof(int ); + + case FD::CPPTYPE_MESSAGE: + return sizeof(Message*); + + case FD::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + return sizeof(string*); + } + break; + } + + GOOGLE_LOG(DFATAL) << "Can't get here."; + return 0; +} + inline int DivideRoundingUp(int i, int j) { return (i + (j - 1)) / j; } static const int kSafeAlignment = sizeof(uint64); +static const int kMaxOneofUnionSize = sizeof(uint64); inline int AlignTo(int offset, int alignment) { return DivideRoundingUp(offset, alignment) * alignment; @@ -168,6 +199,7 @@ class DynamicMessage : public Message { struct TypeInfo { int size; int has_bits_offset; + int oneof_case_offset; int unknown_fields_offset; int extensions_offset; @@ -185,11 +217,13 @@ class DynamicMessage : public Message { // looking back at this field. This would assume details about the // implementation of scoped_ptr. const DynamicMessage* prototype; + void* default_oneof_instance; - TypeInfo() : prototype(NULL) {} + TypeInfo() : prototype(NULL), default_oneof_instance(NULL) {} ~TypeInfo() { delete prototype; + operator delete(default_oneof_instance); } }; @@ -208,6 +242,7 @@ class DynamicMessage : public Message { Metadata GetMetadata() const; + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage); @@ -245,6 +280,12 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info) const Descriptor* descriptor = type_info_->type; + // Initialize oneof cases. + for (int i = 0 ; i < descriptor->oneof_decl_count(); ++i) { + new(OffsetToPointer(type_info_->oneof_case_offset + sizeof(uint32) * i)) + uint32(0); + } + new(OffsetToPointer(type_info_->unknown_fields_offset)) UnknownFieldSet; if (type_info_->extensions_offset != -1) { @@ -254,6 +295,9 @@ DynamicMessage::DynamicMessage(const TypeInfo* type_info) for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); void* field_ptr = OffsetToPointer(type_info_->offsets[i]); + if (field->containing_oneof()) { + continue; + } switch (field->cpp_type()) { #define HANDLE_TYPE(CPPTYPE, TYPE) \ case FieldDescriptor::CPPTYPE_##CPPTYPE: \ @@ -327,12 +371,35 @@ DynamicMessage::~DynamicMessage() { // We need to manually run the destructors for repeated fields and strings, // just as we ran their constructors in the the DynamicMessage constructor. + // We also need to manually delete oneof fields if it is set and is string + // or message. // Additionally, if any singular embedded messages have been allocated, we // need to delete them, UNLESS we are the prototype message of this type, // in which case any embedded messages are other prototypes and shouldn't // be touched. for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); + if (field->containing_oneof()) { + void* field_ptr = OffsetToPointer( + type_info_->oneof_case_offset + + sizeof(uint32) * field->containing_oneof()->index()); + if (*(reinterpret_cast(field_ptr)) == + field->number()) { + field_ptr = OffsetToPointer(type_info_->offsets[ + descriptor->field_count() + field->containing_oneof()->index()]); + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + delete *reinterpret_cast(field_ptr); + break; + } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + delete *reinterpret_cast(field_ptr); + } + } + continue; + } void* field_ptr = OffsetToPointer(type_info_->offsets[i]); if (field->is_repeated()) { @@ -402,6 +469,10 @@ void DynamicMessage::CrossLinkPrototypes() { for (int i = 0; i < descriptor->field_count(); i++) { const FieldDescriptor* field = descriptor->field(i); void* field_ptr = OffsetToPointer(type_info_->offsets[i]); + if (field->containing_oneof()) { + field_ptr = reinterpret_cast( + type_info_->default_oneof_instance) + type_info_->offsets[i]; + } if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE && !field->is_repeated()) { @@ -429,7 +500,9 @@ void DynamicMessage::SetCachedSize(int size) const { // This is theoretically not thread-compatible, but in practice it works // because if multiple threads write this simultaneously, they will be // writing the exact same value. + GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN(); cached_byte_size_ = size; + GOOGLE_SAFE_CONCURRENT_WRITES_END(); } Metadata DynamicMessage::GetMetadata() const { @@ -459,6 +532,9 @@ DynamicMessageFactory::DynamicMessageFactory(const DescriptorPool* pool) DynamicMessageFactory::~DynamicMessageFactory() { for (PrototypeMap::Map::iterator iter = prototypes_->map_.begin(); iter != prototypes_->map_.end(); ++iter) { + DeleteDefaultOneofInstance(iter->second->type, + iter->second->offsets.get(), + iter->second->default_oneof_instance); delete iter->second; } } @@ -497,7 +573,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( // or not that field is set. // Compute size and offsets. - int* offsets = new int[type->field_count()]; + int* offsets = new int[type->field_count() + type->oneof_decl_count()]; type_info->offsets.reset(offsets); // Decide all field offsets by packing in order. @@ -513,6 +589,13 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( size += has_bits_array_size * sizeof(uint32); size = AlignOffset(size); + // The oneof_case, if any. It is an array of uint32s. + if (type->oneof_decl_count() > 0) { + type_info->oneof_case_offset = size; + size += type->oneof_decl_count() * sizeof(uint32); + size = AlignOffset(size); + } + // The ExtensionSet, if any. if (type->extension_range_count() > 0) { type_info->extensions_offset = size; @@ -526,10 +609,20 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( // All the fields. for (int i = 0; i < type->field_count(); i++) { // Make sure field is aligned to avoid bus errors. - int field_size = FieldSpaceUsed(type->field(i)); - size = AlignTo(size, min(kSafeAlignment, field_size)); - offsets[i] = size; - size += field_size; + // Oneof fields do not use any space. + if (!type->field(i)->containing_oneof()) { + int field_size = FieldSpaceUsed(type->field(i)); + size = AlignTo(size, min(kSafeAlignment, field_size)); + offsets[i] = size; + size += field_size; + } + } + + // The oneofs. + for (int i = 0; i < type->oneof_decl_count(); i++) { + size = AlignTo(size, kSafeAlignment); + offsets[type->field_count() + i] = size; + size += kMaxOneofUnionSize; } // Add the UnknownFieldSet to the end. @@ -549,23 +642,125 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock( type_info->prototype = prototype; // Construct the reflection object. - type_info->reflection.reset( - new GeneratedMessageReflection( - type_info->type, - type_info->prototype, - type_info->offsets.get(), - type_info->has_bits_offset, - type_info->unknown_fields_offset, - type_info->extensions_offset, - type_info->pool, - this, - type_info->size)); - + if (type->oneof_decl_count() > 0) { + // Compute the size of default oneof instance and offsets of default + // oneof fields. + int oneof_size = 0; + for (int i = 0; i < type->oneof_decl_count(); i++) { + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = type->oneof_decl(i)->field(j); + int field_size = OneofFieldSpaceUsed(field); + oneof_size = AlignTo(oneof_size, min(kSafeAlignment, field_size)); + offsets[field->index()] = oneof_size; + oneof_size += field_size; + } + } + // Construct default oneof instance. + type_info->default_oneof_instance = ::operator new(oneof_size); + ConstructDefaultOneofInstance(type_info->type, + type_info->offsets.get(), + type_info->default_oneof_instance); + type_info->reflection.reset( + new GeneratedMessageReflection( + type_info->type, + type_info->prototype, + type_info->offsets.get(), + type_info->has_bits_offset, + type_info->unknown_fields_offset, + type_info->extensions_offset, + type_info->default_oneof_instance, + type_info->oneof_case_offset, + type_info->pool, + this, + type_info->size)); + } else { + type_info->reflection.reset( + new GeneratedMessageReflection( + type_info->type, + type_info->prototype, + type_info->offsets.get(), + type_info->has_bits_offset, + type_info->unknown_fields_offset, + type_info->extensions_offset, + type_info->pool, + this, + type_info->size)); + } // Cross link prototypes. prototype->CrossLinkPrototypes(); return prototype; } +void DynamicMessageFactory::ConstructDefaultOneofInstance( + const Descriptor* type, + const int offsets[], + void* default_oneof_instance) { + for (int i = 0; i < type->oneof_decl_count(); i++) { + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = type->oneof_decl(i)->field(j); + void* field_ptr = reinterpret_cast( + default_oneof_instance) + offsets[field->index()]; + switch (field->cpp_type()) { +#define HANDLE_TYPE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + new(field_ptr) TYPE(field->default_value_##TYPE()); \ + break; + + HANDLE_TYPE(INT32 , int32 ); + HANDLE_TYPE(INT64 , int64 ); + HANDLE_TYPE(UINT32, uint32); + HANDLE_TYPE(UINT64, uint64); + HANDLE_TYPE(DOUBLE, double); + HANDLE_TYPE(FLOAT , float ); + HANDLE_TYPE(BOOL , bool ); +#undef HANDLE_TYPE + + case FieldDescriptor::CPPTYPE_ENUM: + new(field_ptr) int(field->default_value_enum()->number()); + break; + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + if (field->has_default_value()) { + new(field_ptr) const string*(&field->default_value_string()); + } else { + new(field_ptr) string*( + const_cast(&internal::GetEmptyString())); + } + break; + } + break; + + case FieldDescriptor::CPPTYPE_MESSAGE: { + new(field_ptr) Message*(NULL); + break; + } + } + } + } +} + +void DynamicMessageFactory::DeleteDefaultOneofInstance( + const Descriptor* type, + const int offsets[], + void* default_oneof_instance) { + for (int i = 0; i < type->oneof_decl_count(); i++) { + for (int j = 0; j < type->oneof_decl(i)->field_count(); j++) { + const FieldDescriptor* field = type->oneof_decl(i)->field(j); + void* field_ptr = reinterpret_cast( + default_oneof_instance) + offsets[field->index()]; + if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) { + switch (field->options().ctype()) { + default: + case FieldOptions::STRING: + break; + } + } + } + } +} + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h index b3d1e5d2..a09593c3 100644 --- a/src/google/protobuf/dynamic_message.h +++ b/src/google/protobuf/dynamic_message.h @@ -38,6 +38,8 @@ #ifndef GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ #define GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__ +#include + #include #include @@ -127,6 +129,16 @@ class LIBPROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory { friend class DynamicMessage; const Message* GetPrototypeNoLock(const Descriptor* type); + // Construct default oneof instance for reflection usage if oneof + // is defined. + static void ConstructDefaultOneofInstance(const Descriptor* type, + const int offsets[], + void* default_oneof_instance); + // Delete default oneof instance. Called by ~DynamicMessageFactory. + static void DeleteDefaultOneofInstance(const Descriptor* type, + const int offsets[], + void* default_oneof_instance); + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory); }; diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc index e4615970..a7866d9c 100644 --- a/src/google/protobuf/dynamic_message_unittest.cc +++ b/src/google/protobuf/dynamic_message_unittest.cc @@ -63,6 +63,8 @@ class DynamicMessageTest : public testing::Test { const Message* extensions_prototype_; const Descriptor* packed_descriptor_; const Message* packed_prototype_; + const Descriptor* oneof_descriptor_; + const Message* oneof_prototype_; DynamicMessageTest(): factory_(&pool_) {} @@ -98,6 +100,11 @@ class DynamicMessageTest : public testing::Test { pool_.FindMessageTypeByName("protobuf_unittest.TestPackedTypes"); ASSERT_TRUE(packed_descriptor_ != NULL); packed_prototype_ = factory_.GetPrototype(packed_descriptor_); + + oneof_descriptor_ = + pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2"); + ASSERT_TRUE(oneof_descriptor_ != NULL); + oneof_prototype_ = factory_.GetPrototype(oneof_descriptor_); } }; @@ -147,6 +154,63 @@ TEST_F(DynamicMessageTest, PackedFields) { reflection_tester.ExpectPackedFieldsSetViaReflection(*message); } +TEST_F(DynamicMessageTest, Oneof) { + // Check that oneof fields work properly. + scoped_ptr message(oneof_prototype_->New()); + + // Check default values. + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* reflection = message->GetReflection(); + EXPECT_EQ(0, reflection->GetInt32( + *message, descriptor->FindFieldByName("foo_int"))); + EXPECT_EQ("", reflection->GetString( + *message, descriptor->FindFieldByName("foo_string"))); + EXPECT_EQ("", reflection->GetString( + *message, descriptor->FindFieldByName("foo_cord"))); + EXPECT_EQ("", reflection->GetString( + *message, descriptor->FindFieldByName("foo_string_piece"))); + EXPECT_EQ("", reflection->GetString( + *message, descriptor->FindFieldByName("foo_bytes"))); + EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum( + *message, descriptor->FindFieldByName("foo_enum"))->number()); + const Descriptor* nested_descriptor; + const Message* nested_prototype; + nested_descriptor = + pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.NestedMessage"); + nested_prototype = factory_.GetPrototype(nested_descriptor); + EXPECT_EQ(nested_prototype, + &reflection->GetMessage( + *message, descriptor->FindFieldByName("foo_message"))); + const Descriptor* foogroup_descriptor; + const Message* foogroup_prototype; + foogroup_descriptor = + pool_.FindMessageTypeByName("protobuf_unittest.TestOneof2.FooGroup"); + foogroup_prototype = factory_.GetPrototype(foogroup_descriptor); + EXPECT_EQ(foogroup_prototype, + &reflection->GetMessage( + *message, descriptor->FindFieldByName("foogroup"))); + EXPECT_NE(foogroup_prototype, + &reflection->GetMessage( + *message, descriptor->FindFieldByName("foo_lazy_message"))); + EXPECT_EQ(5, reflection->GetInt32( + *message, descriptor->FindFieldByName("bar_int"))); + EXPECT_EQ("STRING", reflection->GetString( + *message, descriptor->FindFieldByName("bar_string"))); + EXPECT_EQ("CORD", reflection->GetString( + *message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("SPIECE", reflection->GetString( + *message, descriptor->FindFieldByName("bar_string_piece"))); + EXPECT_EQ("BYTES", reflection->GetString( + *message, descriptor->FindFieldByName("bar_bytes"))); + EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum( + *message, descriptor->FindFieldByName("bar_enum"))->number()); + + // Check set functions. + TestUtil::ReflectionTester reflection_tester(oneof_descriptor_); + reflection_tester.SetOneofViaReflection(message.get()); + reflection_tester.ExpectOneofSetViaReflection(*message); +} + TEST_F(DynamicMessageTest, SpaceUsed) { // Test that SpaceUsed() works properly diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc index 2cbba8f5..81ff89fe 100644 --- a/src/google/protobuf/extension_set.cc +++ b/src/google/protobuf/extension_set.cc @@ -38,10 +38,9 @@ #include #include #include -#include #include #include -#include +#include namespace google { namespace protobuf { @@ -58,6 +57,22 @@ inline WireFormatLite::CppType cpp_type(FieldType type) { return WireFormatLite::FieldTypeToCppType(real_type(type)); } +inline bool is_packable(WireFormatLite::WireType type) { + switch (type) { + case WireFormatLite::WIRETYPE_VARINT: + case WireFormatLite::WIRETYPE_FIXED64: + case WireFormatLite::WIRETYPE_FIXED32: + return true; + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: + case WireFormatLite::WIRETYPE_START_GROUP: + case WireFormatLite::WIRETYPE_END_GROUP: + return false; + + // Do not add a default statement. Let the compiler complain when someone + // adds a new wire type. + } +} + // Registry stuff. typedef hash_map, ExtensionInfo> ExtensionRegistry; @@ -304,14 +319,80 @@ PRIMITIVE_ACCESSORS( BOOL, bool, Bool) #undef PRIMITIVE_ACCESSORS +const void* ExtensionSet::GetRawRepeatedField(int number, + const void* default_value) const { + map::const_iterator iter = extensions_.find(number); + if (iter == extensions_.end()) { + return default_value; + } + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + return iter->second.repeated_int32_value; +} + +void* ExtensionSet::MutableRawRepeatedField(int number, FieldType field_type, + bool packed, + const FieldDescriptor* desc) { + Extension* extension; + + // We instantiate an empty Repeated{,Ptr}Field if one doesn't exist for this + // extension. + if (MaybeNewExtension(number, desc, &extension)) { + extension->is_repeated = true; + extension->type = field_type; + extension->is_packed = packed; + + switch (WireFormatLite::FieldTypeToCppType( + static_cast(field_type))) { + case WireFormatLite::CPPTYPE_INT32: + extension->repeated_int32_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_INT64: + extension->repeated_int64_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_UINT32: + extension->repeated_uint32_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_UINT64: + extension->repeated_uint64_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_DOUBLE: + extension->repeated_double_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_FLOAT: + extension->repeated_float_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_BOOL: + extension->repeated_bool_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_ENUM: + extension->repeated_enum_value = new RepeatedField(); + break; + case WireFormatLite::CPPTYPE_STRING: + extension->repeated_string_value = new RepeatedPtrField< ::std::string>(); + break; + case WireFormatLite::CPPTYPE_MESSAGE: + extension->repeated_message_value = new RepeatedPtrField(); + break; + } + } + + // We assume that all the RepeatedField<>* pointers have the same + // size and alignment within the anonymous union in Extension. + return extension->repeated_int32_value; +} + +// Compatible version using old call signature. Does not create extensions when +// the don't already exist; instead, just GOOGLE_CHECK-fails. void* ExtensionSet::MutableRawRepeatedField(int number) { + map::iterator iter = extensions_.find(number); + GOOGLE_CHECK(iter == extensions_.end()) << "Extension not found."; // We assume that all the RepeatedField<>* pointers have the same // size and alignment within the anonymous union in Extension. - map::const_iterator iter = extensions_.find(number); - GOOGLE_CHECK(iter != extensions_.end()) << "no extension numbered " << number; return iter->second.repeated_int32_value; } + // ------------------------------------------------------------------- // Enums @@ -826,6 +907,36 @@ void ExtensionSet::Swap(ExtensionSet* x) { extensions_.swap(x->extensions_); } +void ExtensionSet::SwapExtension(ExtensionSet* other, + int number) { + if (this == other) return; + map::iterator this_iter = extensions_.find(number); + map::iterator other_iter = other->extensions_.find(number); + + if (this_iter == extensions_.end() && + other_iter == other->extensions_.end()) { + return; + } + + if (this_iter != extensions_.end() && + other_iter != other->extensions_.end()) { + std::swap(this_iter->second, other_iter->second); + return; + } + + if (this_iter == extensions_.end()) { + extensions_.insert(make_pair(number, other_iter->second)); + other->extensions_.erase(number); + return; + } + + if (other_iter == other->extensions_.end()) { + other->extensions_.insert(make_pair(number, this_iter->second)); + extensions_.erase(number); + return; + } +} + bool ExtensionSet::IsInitialized() const { // Extensions are never required. However, we need to check that all // embedded messages are initialized. @@ -855,41 +966,59 @@ bool ExtensionSet::IsInitialized() const { } bool ExtensionSet::FindExtensionInfoFromTag( - uint32 tag, ExtensionFinder* extension_finder, - int* field_number, ExtensionInfo* extension) { + uint32 tag, ExtensionFinder* extension_finder, int* field_number, + ExtensionInfo* extension, bool* was_packed_on_wire) { *field_number = WireFormatLite::GetTagFieldNumber(tag); WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + return FindExtensionInfoFromFieldNumber(wire_type, *field_number, + extension_finder, extension, + was_packed_on_wire); +} - bool is_unknown; - if (!extension_finder->Find(*field_number, extension)) { - is_unknown = true; - } else if (extension->is_packed) { - is_unknown = (wire_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED); - } else { - WireFormatLite::WireType expected_wire_type = - WireFormatLite::WireTypeForFieldType(real_type(extension->type)); - is_unknown = (wire_type != expected_wire_type); +bool ExtensionSet::FindExtensionInfoFromFieldNumber( + int wire_type, int field_number, ExtensionFinder* extension_finder, + ExtensionInfo* extension, bool* was_packed_on_wire) { + if (!extension_finder->Find(field_number, extension)) { + return false; + } + + WireFormatLite::WireType expected_wire_type = + WireFormatLite::WireTypeForFieldType(real_type(extension->type)); + + // Check if this is a packed field. + *was_packed_on_wire = false; + if (extension->is_repeated && + wire_type == WireFormatLite::WIRETYPE_LENGTH_DELIMITED && + is_packable(expected_wire_type)) { + *was_packed_on_wire = true; + return true; } - return !is_unknown; + // Otherwise the wire type must match. + return expected_wire_type == wire_type; } bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, ExtensionFinder* extension_finder, FieldSkipper* field_skipper) { int number; + bool was_packed_on_wire; ExtensionInfo extension; - if (!FindExtensionInfoFromTag(tag, extension_finder, &number, &extension)) { + if (!FindExtensionInfoFromTag( + tag, extension_finder, &number, &extension, &was_packed_on_wire)) { return field_skipper->SkipField(input, tag); } else { - return ParseFieldWithExtensionInfo(number, extension, input, field_skipper); + return ParseFieldWithExtensionInfo( + number, was_packed_on_wire, extension, input, field_skipper); } } bool ExtensionSet::ParseFieldWithExtensionInfo( - int number, const ExtensionInfo& extension, + int number, bool was_packed_on_wire, const ExtensionInfo& extension, io::CodedInputStream* input, FieldSkipper* field_skipper) { - if (extension.is_packed) { + // Explicitly not read extension.is_packed, instead check whether the field + // was encoded in packed form on the wire. + if (was_packed_on_wire) { uint32 size; if (!input->ReadVarint32(&size)) return false; io::CodedInputStream::Limit limit = input->PushLimit(size); @@ -903,7 +1032,8 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ input, &value)) return false; \ Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ - true, value, extension.descriptor); \ + extension.is_packed, value, \ + extension.descriptor); \ } \ break @@ -929,8 +1059,8 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( input, &value)) return false; if (extension.enum_validity_check.func( extension.enum_validity_check.arg, value)) { - AddEnum(number, WireFormatLite::TYPE_ENUM, true, value, - extension.descriptor); + AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, + value, extension.descriptor); } } break; @@ -952,9 +1082,10 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( if (!WireFormatLite::ReadPrimitive< \ CPP_LOWERCASE, WireFormatLite::TYPE_##UPPERCASE>( \ input, &value)) return false; \ - if (extension.is_repeated) { \ + if (extension.is_repeated) { \ Add##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, \ - false, value, extension.descriptor); \ + extension.is_packed, value, \ + extension.descriptor); \ } else { \ Set##CPP_CAMELCASE(number, WireFormatLite::TYPE_##UPPERCASE, value, \ extension.descriptor); \ @@ -986,7 +1117,7 @@ bool ExtensionSet::ParseFieldWithExtensionInfo( // Invalid value. Treat as unknown. field_skipper->SkipUnknownEnum(number, value); } else if (extension.is_repeated) { - AddEnum(number, WireFormatLite::TYPE_ENUM, false, value, + AddEnum(number, WireFormatLite::TYPE_ENUM, extension.is_packed, value, extension.descriptor); } else { SetEnum(number, WireFormatLite::TYPE_ENUM, value, @@ -1045,6 +1176,14 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, return ParseField(tag, input, &finder, &skipper); } +bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type, + io::CodedOutputStream* unknown_fields) { + CodedOutputStreamFieldSkipper skipper(unknown_fields); + GeneratedExtensionFinder finder(containing_type); + return ParseField(tag, input, &finder, &skipper); +} + // Defined in extension_set_heavy.cc. // bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, // const MessageLite* containing_type, @@ -1456,6 +1595,56 @@ void ExtensionSet::Extension::Free() { // Defined in extension_set_heavy.cc. // int ExtensionSet::Extension::SpaceUsedExcludingSelf() const +// ================================================================== +// Default repeated field instances for iterator-compatible accessors + +const RepeatedStringTypeTraits::RepeatedFieldType* +RepeatedStringTypeTraits::default_repeated_field_ = NULL; + +const RepeatedMessageGenericTypeTraits::RepeatedFieldType* +RepeatedMessageGenericTypeTraits::default_repeated_field_ = NULL; + +#define PROTOBUF_DEFINE_DEFAULT_REPEATED(TYPE) \ + const RepeatedField* \ + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_##TYPE##_ = NULL; + +PROTOBUF_DEFINE_DEFAULT_REPEATED(int32) +PROTOBUF_DEFINE_DEFAULT_REPEATED(int64) +PROTOBUF_DEFINE_DEFAULT_REPEATED(uint32) +PROTOBUF_DEFINE_DEFAULT_REPEATED(uint64) +PROTOBUF_DEFINE_DEFAULT_REPEATED(double) +PROTOBUF_DEFINE_DEFAULT_REPEATED(float) +PROTOBUF_DEFINE_DEFAULT_REPEATED(bool) + +#undef PROTOBUF_DEFINE_DEFAULT_REPEATED + +struct StaticDefaultRepeatedFieldsInitializer { + StaticDefaultRepeatedFieldsInitializer() { + InitializeDefaultRepeatedFields(); + } +} static_repeated_fields_initializer; + +void InitializeDefaultRepeatedFields() { + RepeatedStringTypeTraits::default_repeated_field_ = + new RepeatedStringTypeTraits::RepeatedFieldType; + RepeatedMessageGenericTypeTraits::default_repeated_field_ = + new RepeatedMessageGenericTypeTraits::RepeatedFieldType; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int32_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_int64_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint32_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_uint64_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_double_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_float_ = + new RepeatedField; + RepeatedPrimitiveGenericTypeTraits::default_repeated_field_bool_ = + new RepeatedField; +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h index 73529e52..6bdb3d6e 100644 --- a/src/google/protobuf/extension_set.h +++ b/src/google/protobuf/extension_set.h @@ -46,6 +46,8 @@ #include +#include + namespace google { namespace protobuf { @@ -62,10 +64,7 @@ namespace protobuf { } namespace internal { class FieldSkipper; // wire_format_lite.h - class RepeatedPtrFieldBase; // repeated_field.h } - template class RepeatedField; // repeated_field.h - template class RepeatedPtrField; // repeated_field.h } namespace protobuf { @@ -138,6 +137,9 @@ class LIBPROTOBUF_EXPORT GeneratedExtensionFinder : public ExtensionFinder { const MessageLite* containing_type_; }; +// A FieldSkipper used for parsing MessageSet. +class MessageSetFieldSkipper; + // Note: extension_set_heavy.cc defines DescriptorPoolExtensionFinder for // finding extensions from a DescriptorPool. @@ -265,6 +267,20 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // repeated fields ------------------------------------------------- + // Fetches a RepeatedField extension by number; returns |default_value| + // if no such extension exists. User should not touch this directly; it is + // used by the GetRepeatedExtension() method. + const void* GetRawRepeatedField(int number, const void* default_value) const; + // Fetches a mutable version of a RepeatedField extension by number, + // instantiating one if none exists. Similar to above, user should not use + // this directly; it underlies MutableRepeatedExtension(). + void* MutableRawRepeatedField(int number, FieldType field_type, + bool packed, const FieldDescriptor* desc); + + // This is an overload of MutableRawRepeatedField to maintain compatibility + // with old code using a previous API. This version of + // MutableRawRepeatedField() will GOOGLE_CHECK-fail on a missing extension. + // (E.g.: borg/clients/internal/proto1/proto2_reflection.cc.) void* MutableRawRepeatedField(int number); int32 GetRepeatedInt32 (int number, int index) const; @@ -323,6 +339,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { void Clear(); void MergeFrom(const ExtensionSet& other); void Swap(ExtensionSet* other); + void SwapExtension(ExtensionSet* other, int number); bool IsInitialized() const; // Parses a single extension from the input. The input should start out @@ -342,12 +359,15 @@ class LIBPROTOBUF_EXPORT ExtensionSet { bool ParseField(uint32 tag, io::CodedInputStream* input, const Message* containing_type, UnknownFieldSet* unknown_fields); + bool ParseField(uint32 tag, io::CodedInputStream* input, + const MessageLite* containing_type, + io::CodedOutputStream* unknown_fields); // Parse an entire message in MessageSet format. Such messages have no // fields, only extensions. bool ParseMessageSet(io::CodedInputStream* input, ExtensionFinder* extension_finder, - FieldSkipper* field_skipper); + MessageSetFieldSkipper* field_skipper); // Specific versions for lite or full messages (constructs the appropriate // FieldSkipper automatically). @@ -505,23 +525,38 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // Returns true and fills field_number and extension if extension is found. + // Note to support packed repeated field compatibility, it also fills whether + // the tag on wire is packed, which can be different from + // extension->is_packed (whether packed=true is specified). bool FindExtensionInfoFromTag(uint32 tag, ExtensionFinder* extension_finder, - int* field_number, ExtensionInfo* extension); + int* field_number, ExtensionInfo* extension, + bool* was_packed_on_wire); + + // Returns true and fills extension if extension is found. + // Note to support packed repeated field compatibility, it also fills whether + // the tag on wire is packed, which can be different from + // extension->is_packed (whether packed=true is specified). + bool FindExtensionInfoFromFieldNumber(int wire_type, int field_number, + ExtensionFinder* extension_finder, + ExtensionInfo* extension, + bool* was_packed_on_wire); // Parses a single extension from the input. The input should start out // positioned immediately after the wire tag. This method is called in - // ParseField() after field number is extracted from the wire tag and - // ExtensionInfo is found by the field number. + // ParseField() after field number and was_packed_on_wire is extracted from + // the wire tag and ExtensionInfo is found by the field number. bool ParseFieldWithExtensionInfo(int field_number, + bool was_packed_on_wire, const ExtensionInfo& extension, io::CodedInputStream* input, FieldSkipper* field_skipper); // Like ParseField(), but this method may parse singular message extensions // lazily depending on the value of FLAGS_eagerly_parse_message_sets. - bool ParseFieldMaybeLazily(uint32 tag, io::CodedInputStream* input, + bool ParseFieldMaybeLazily(int wire_type, int field_number, + io::CodedInputStream* input, ExtensionFinder* extension_finder, - FieldSkipper* field_skipper); + MessageSetFieldSkipper* field_skipper); // Gets the extension with the given number, creating it if it does not // already exist. Returns true if the extension did not already exist. @@ -532,7 +567,7 @@ class LIBPROTOBUF_EXPORT ExtensionSet { // tag has been read. bool ParseMessageSetItem(io::CodedInputStream* input, ExtensionFinder* extension_finder, - FieldSkipper* field_skipper); + MessageSetFieldSkipper* field_skipper); // Hack: RepeatedPtrFieldBase declares ExtensionSet as a friend. This @@ -587,6 +622,16 @@ inline void ExtensionSet::AddString(int number, FieldType type, // public: // typedef ? ConstType; // typedef ? MutableType; +// // TypeTraits for singular fields and repeated fields will define the +// // symbol "Singular" or "Repeated" respectively. These two symbols will +// // be used in extension accessors to distinguish between singular +// // extensions and repeated extensions. If the TypeTraits for the passed +// // in extension doesn't have the expected symbol defined, it means the +// // user is passing a repeated extension to a singular accessor, or the +// // opposite. In that case the C++ compiler will generate an error +// // message "no matching member function" to inform the user. +// typedef ? Singular +// typedef ? Repeated // // static inline ConstType Get(int number, const ExtensionSet& set); // static inline void Set(int number, ConstType value, ExtensionSet* set); @@ -625,6 +670,8 @@ template class PrimitiveTypeTraits { public: typedef Type ConstType; + typedef Type MutableType; + typedef PrimitiveTypeTraits Singular; static inline ConstType Get(int number, const ExtensionSet& set, ConstType default_value); @@ -636,11 +683,39 @@ template class RepeatedPrimitiveTypeTraits { public: typedef Type ConstType; + typedef Type MutableType; + typedef RepeatedPrimitiveTypeTraits Repeated; + + typedef RepeatedField RepeatedFieldType; static inline Type Get(int number, const ExtensionSet& set, int index); static inline void Set(int number, int index, Type value, ExtensionSet* set); static inline void Add(int number, FieldType field_type, bool is_packed, Type value, ExtensionSet* set); + + static inline const RepeatedField& + GetRepeated(int number, const ExtensionSet& set); + static inline RepeatedField* + MutableRepeated(int number, FieldType field_type, + bool is_packed, ExtensionSet* set); + + static const RepeatedFieldType* GetDefaultRepeatedField(); +}; + +// Declared here so that this can be friended below. +void InitializeDefaultRepeatedFields(); + +class LIBPROTOBUF_EXPORT RepeatedPrimitiveGenericTypeTraits { + private: + template friend class RepeatedPrimitiveTypeTraits; + friend void InitializeDefaultRepeatedFields(); + static const RepeatedField* default_repeated_field_int32_; + static const RepeatedField* default_repeated_field_int64_; + static const RepeatedField* default_repeated_field_uint32_; + static const RepeatedField* default_repeated_field_uint64_; + static const RepeatedField* default_repeated_field_double_; + static const RepeatedField* default_repeated_field_float_; + static const RepeatedField* default_repeated_field_bool_; }; #define PROTOBUF_DEFINE_PRIMITIVE_TYPE(TYPE, METHOD) \ @@ -665,6 +740,26 @@ template<> inline void RepeatedPrimitiveTypeTraits::Add( \ int number, FieldType field_type, bool is_packed, \ TYPE value, ExtensionSet* set) { \ set->Add##METHOD(number, field_type, is_packed, value, NULL); \ +} \ +template<> inline const RepeatedField* \ + RepeatedPrimitiveTypeTraits::GetDefaultRepeatedField() { \ + return RepeatedPrimitiveGenericTypeTraits:: \ + default_repeated_field_##TYPE##_; \ +} \ +template<> inline const RepeatedField& \ + RepeatedPrimitiveTypeTraits::GetRepeated(int number, \ + const ExtensionSet& set) { \ + return *reinterpret_cast*>( \ + set.GetRawRepeatedField( \ + number, GetDefaultRepeatedField())); \ +} \ +template<> inline RepeatedField* \ + RepeatedPrimitiveTypeTraits::MutableRepeated(int number, \ + FieldType field_type, \ + bool is_packed, \ + ExtensionSet* set) { \ + return reinterpret_cast*>( \ + set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); \ } PROTOBUF_DEFINE_PRIMITIVE_TYPE( int32, Int32) @@ -685,6 +780,7 @@ class LIBPROTOBUF_EXPORT StringTypeTraits { public: typedef const string& ConstType; typedef string* MutableType; + typedef StringTypeTraits Singular; static inline const string& Get(int number, const ExtensionSet& set, ConstType default_value) { @@ -704,6 +800,9 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { public: typedef const string& ConstType; typedef string* MutableType; + typedef RepeatedStringTypeTraits Repeated; + + typedef RepeatedPtrField RepeatedFieldType; static inline const string& Get(int number, const ExtensionSet& set, int index) { @@ -725,6 +824,27 @@ class LIBPROTOBUF_EXPORT RepeatedStringTypeTraits { ExtensionSet* set) { return set->AddString(number, field_type, NULL); } + static inline const RepeatedPtrField& + GetRepeated(int number, const ExtensionSet& set) { + return *reinterpret_cast*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + + static inline RepeatedPtrField* + MutableRepeated(int number, FieldType field_type, + bool is_packed, ExtensionSet* set) { + return reinterpret_cast*>( + set->MutableRawRepeatedField(number, field_type, + is_packed, NULL)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField() { + return default_repeated_field_; + } + + private: + friend void InitializeDefaultRepeatedFields(); + static const RepeatedFieldType *default_repeated_field_; }; // ------------------------------------------------------------------- @@ -736,6 +856,8 @@ template class EnumTypeTraits { public: typedef Type ConstType; + typedef Type MutableType; + typedef EnumTypeTraits Singular; static inline ConstType Get(int number, const ExtensionSet& set, ConstType default_value) { @@ -752,6 +874,10 @@ template class RepeatedEnumTypeTraits { public: typedef Type ConstType; + typedef Type MutableType; + typedef RepeatedEnumTypeTraits Repeated; + + typedef RepeatedField RepeatedFieldType; static inline ConstType Get(int number, const ExtensionSet& set, int index) { return static_cast(set.GetRepeatedEnum(number, index)); @@ -766,6 +892,35 @@ class RepeatedEnumTypeTraits { GOOGLE_DCHECK(IsValid(value)); set->AddEnum(number, field_type, is_packed, value, NULL); } + static inline const RepeatedField& GetRepeated(int number, + const ExtensionSet& + set) { + // Hack: the `Extension` struct stores a RepeatedField for enums. + // RepeatedField cannot implicitly convert to RepeatedField + // so we need to do some casting magic. See message.h for similar + // contortions for non-extension fields. + return *reinterpret_cast*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + + static inline RepeatedField* MutableRepeated(int number, + FieldType field_type, + bool is_packed, + ExtensionSet* set) { + return reinterpret_cast*>( + set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField() { + // Hack: as noted above, repeated enum fields are internally stored as a + // RepeatedField. We need to be able to instantiate global static + // objects to return as default (empty) repeated fields on non-existent + // extensions. We would not be able to know a-priori all of the enum types + // (values of |Type|) to instantiate all of these, so we just re-use int32's + // default repeated field object. + return reinterpret_cast*>( + RepeatedPrimitiveTypeTraits::GetDefaultRepeatedField()); + } }; // ------------------------------------------------------------------- @@ -779,6 +934,7 @@ class MessageTypeTraits { public: typedef const Type& ConstType; typedef Type* MutableType; + typedef MessageTypeTraits Singular; static inline ConstType Get(int number, const ExtensionSet& set, ConstType default_value) { @@ -801,11 +957,17 @@ class MessageTypeTraits { } }; +// forward declaration +class RepeatedMessageGenericTypeTraits; + template class RepeatedMessageTypeTraits { public: typedef const Type& ConstType; typedef Type* MutableType; + typedef RepeatedMessageTypeTraits Repeated; + + typedef RepeatedPtrField RepeatedFieldType; static inline ConstType Get(int number, const ExtensionSet& set, int index) { return static_cast(set.GetRepeatedMessage(number, index)); @@ -818,8 +980,46 @@ class RepeatedMessageTypeTraits { return static_cast( set->AddMessage(number, field_type, Type::default_instance(), NULL)); } + static inline const RepeatedPtrField& GetRepeated(int number, + const ExtensionSet& + set) { + // See notes above in RepeatedEnumTypeTraits::GetRepeated(): same + // casting hack applies here, because a RepeatedPtrField + // cannot naturally become a RepeatedPtrType even though Type is + // presumably a message. google::protobuf::Message goes through similar contortions + // with a reinterpret_cast<>. + return *reinterpret_cast*>( + set.GetRawRepeatedField(number, GetDefaultRepeatedField())); + } + static inline RepeatedPtrField* MutableRepeated(int number, + FieldType field_type, + bool is_packed, + ExtensionSet* set) { + return reinterpret_cast*>( + set->MutableRawRepeatedField(number, field_type, is_packed, NULL)); + } + + static const RepeatedFieldType* GetDefaultRepeatedField(); +}; + +// This class exists only to hold a generic default empty repeated field for all +// message-type repeated field extensions. +class LIBPROTOBUF_EXPORT RepeatedMessageGenericTypeTraits { + public: + typedef RepeatedPtrField< ::google::protobuf::MessageLite*> RepeatedFieldType; + private: + template friend class RepeatedMessageTypeTraits; + friend void InitializeDefaultRepeatedFields(); + static const RepeatedFieldType* default_repeated_field_; }; +template inline + const typename RepeatedMessageTypeTraits::RepeatedFieldType* + RepeatedMessageTypeTraits::GetDefaultRepeatedField() { + return reinterpret_cast( + RepeatedMessageGenericTypeTraits::default_repeated_field_); +} + // ------------------------------------------------------------------- // ExtensionIdentifier @@ -902,7 +1102,7 @@ class ExtensionIdentifier { template \ - inline typename _proto_TypeTraits::ConstType GetExtension( \ + inline typename _proto_TypeTraits::Singular::ConstType GetExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) const { \ return _proto_TypeTraits::Get(id.number(), _extensions_, \ @@ -912,7 +1112,7 @@ class ExtensionIdentifier { template \ - inline typename _proto_TypeTraits::MutableType MutableExtension( \ + inline typename _proto_TypeTraits::Singular::MutableType MutableExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ return _proto_TypeTraits::Mutable(id.number(), _field_type, \ @@ -925,7 +1125,7 @@ class ExtensionIdentifier { inline void SetExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ - typename _proto_TypeTraits::ConstType value) { \ + typename _proto_TypeTraits::Singular::ConstType value) { \ _proto_TypeTraits::Set(id.number(), _field_type, value, &_extensions_); \ } \ \ @@ -935,14 +1135,14 @@ class ExtensionIdentifier { inline void SetAllocatedExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ - typename _proto_TypeTraits::MutableType value) { \ + typename _proto_TypeTraits::Singular::MutableType value) { \ _proto_TypeTraits::SetAllocated(id.number(), _field_type, \ value, &_extensions_); \ } \ template \ - inline typename _proto_TypeTraits::MutableType ReleaseExtension( \ + inline typename _proto_TypeTraits::Singular::MutableType ReleaseExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ return _proto_TypeTraits::Release(id.number(), _field_type, \ @@ -953,7 +1153,7 @@ class ExtensionIdentifier { template \ - inline typename _proto_TypeTraits::ConstType GetExtension( \ + inline typename _proto_TypeTraits::Repeated::ConstType GetExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ int index) const { \ @@ -963,7 +1163,7 @@ class ExtensionIdentifier { template \ - inline typename _proto_TypeTraits::MutableType MutableExtension( \ + inline typename _proto_TypeTraits::Repeated::MutableType MutableExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ int index) { \ @@ -976,14 +1176,14 @@ class ExtensionIdentifier { inline void SetExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ - int index, typename _proto_TypeTraits::ConstType value) { \ + int index, typename _proto_TypeTraits::Repeated::ConstType value) { \ _proto_TypeTraits::Set(id.number(), index, value, &_extensions_); \ } \ \ template \ - inline typename _proto_TypeTraits::MutableType AddExtension( \ + inline typename _proto_TypeTraits::Repeated::MutableType AddExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id) { \ return _proto_TypeTraits::Add(id.number(), _field_type, &_extensions_); \ @@ -995,9 +1195,32 @@ class ExtensionIdentifier { inline void AddExtension( \ const ::google::protobuf::internal::ExtensionIdentifier< \ CLASSNAME, _proto_TypeTraits, _field_type, _is_packed>& id, \ - typename _proto_TypeTraits::ConstType value) { \ + typename _proto_TypeTraits::Repeated::ConstType value) { \ _proto_TypeTraits::Add(id.number(), _field_type, _is_packed, \ value, &_extensions_); \ + } \ + \ + template \ + inline const typename _proto_TypeTraits::Repeated::RepeatedFieldType& \ + GetRepeatedExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, \ + _is_packed>& id) const { \ + return _proto_TypeTraits::GetRepeated(id.number(), _extensions_); \ + } \ + \ + template \ + inline typename _proto_TypeTraits::Repeated::RepeatedFieldType* \ + MutableRepeatedExtension( \ + const ::google::protobuf::internal::ExtensionIdentifier< \ + CLASSNAME, _proto_TypeTraits, _field_type, \ + _is_packed>& id) { \ + return _proto_TypeTraits::MutableRepeated(id.number(), _field_type, \ + _is_packed, &_extensions_); \ } } // namespace internal diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc index 483d7055..a58c99d2 100644 --- a/src/google/protobuf/extension_set_heavy.cc +++ b/src/google/protobuf/extension_set_heavy.cc @@ -48,6 +48,29 @@ namespace google { namespace protobuf { namespace internal { +// A FieldSkipper used to store unknown MessageSet fields into UnknownFieldSet. +class MessageSetFieldSkipper + : public UnknownFieldSetFieldSkipper { + public: + explicit MessageSetFieldSkipper(UnknownFieldSet* unknown_fields) + : UnknownFieldSetFieldSkipper(unknown_fields) {} + virtual ~MessageSetFieldSkipper() {} + + virtual bool SkipMessageSetField(io::CodedInputStream* input, + int field_number); +}; +bool MessageSetFieldSkipper::SkipMessageSetField( + io::CodedInputStream* input, int field_number) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + if (unknown_fields_ == NULL) { + return input->Skip(length); + } else { + return input->ReadString( + unknown_fields_->AddLengthDelimited(field_number), length); + } +} + // Implementation of ExtensionFinder which finds extensions in a given // DescriptorPool, using the given MessageFactory to construct sub-objects. @@ -172,7 +195,7 @@ MessageLite* ExtensionSet::ReleaseMessage(const FieldDescriptor* descriptor, MessageLite* ret = NULL; if (iter->second.is_lazy) { ret = iter->second.lazymessage_value->ReleaseMessage( - *factory->GetPrototype(descriptor->message_type())); + *factory->GetPrototype(descriptor->message_type())); delete iter->second.lazymessage_value; } else { ret = iter->second.message_value; @@ -261,7 +284,7 @@ bool ExtensionSet::ParseField(uint32 tag, io::CodedInputStream* input, bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, const Message* containing_type, UnknownFieldSet* unknown_fields) { - UnknownFieldSetFieldSkipper skipper(unknown_fields); + MessageSetFieldSkipper skipper(unknown_fields); if (input->GetExtensionPool() == NULL) { GeneratedExtensionFinder finder(containing_type); return ParseMessageSet(input, &finder, &skipper); @@ -511,17 +534,19 @@ uint8* ExtensionSet::Extension::SerializeMessageSetItemWithCachedSizesToArray( bool ExtensionSet::ParseFieldMaybeLazily( - uint32 tag, io::CodedInputStream* input, + int wire_type, int field_number, io::CodedInputStream* input, ExtensionFinder* extension_finder, - FieldSkipper* field_skipper) { - return ParseField(tag, input, extension_finder, field_skipper); + MessageSetFieldSkipper* field_skipper) { + return ParseField(WireFormatLite::MakeTag( + field_number, static_cast(wire_type)), + input, extension_finder, field_skipper); } bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, ExtensionFinder* extension_finder, - FieldSkipper* field_skipper) { + MessageSetFieldSkipper* field_skipper) { while (true) { - uint32 tag = input->ReadTag(); + const uint32 tag = input->ReadTag(); switch (tag) { case 0: return true; @@ -541,14 +566,14 @@ bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, bool ExtensionSet::ParseMessageSet(io::CodedInputStream* input, const MessageLite* containing_type) { - FieldSkipper skipper; + MessageSetFieldSkipper skipper(NULL); GeneratedExtensionFinder finder(containing_type); return ParseMessageSet(input, &finder, &skipper); } bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, ExtensionFinder* extension_finder, - FieldSkipper* field_skipper) { + MessageSetFieldSkipper* field_skipper) { // TODO(kenton): It would be nice to share code between this and // WireFormatLite::ParseAndMergeMessageSetItem(), but I think the // differences would be hard to factor out. @@ -557,25 +582,21 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, // required int32 type_id = 2; // required data message = 3; - // Once we see a type_id, we'll construct a fake tag for this extension - // which is the tag it would have had under the proto2 extensions wire - // format. - uint32 fake_tag = 0; + uint32 last_type_id = 0; // If we see message data before the type_id, we'll append it to this so // we can parse it later. string message_data; while (true) { - uint32 tag = input->ReadTag(); + const uint32 tag = input->ReadTag(); if (tag == 0) return false; switch (tag) { case WireFormatLite::kMessageSetTypeIdTag: { uint32 type_id; if (!input->ReadVarint32(&type_id)) return false; - fake_tag = WireFormatLite::MakeTag(type_id, - WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + last_type_id = type_id; if (!message_data.empty()) { // We saw some message data before the type_id. Have to parse it @@ -583,7 +604,8 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, io::CodedInputStream sub_input( reinterpret_cast(message_data.data()), message_data.size()); - if (!ParseFieldMaybeLazily(fake_tag, &sub_input, + if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + last_type_id, &sub_input, extension_finder, field_skipper)) { return false; } @@ -594,7 +616,7 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, } case WireFormatLite::kMessageSetMessageTag: { - if (fake_tag == 0) { + if (last_type_id == 0) { // We haven't seen a type_id yet. Append this data to message_data. string temp; uint32 length; @@ -606,7 +628,8 @@ bool ExtensionSet::ParseMessageSetItem(io::CodedInputStream* input, coded_output.WriteString(temp); } else { // Already saw type_id, so we can parse this directly. - if (!ParseFieldMaybeLazily(fake_tag, input, + if (!ParseFieldMaybeLazily(WireFormatLite::WIRETYPE_LENGTH_DELIMITED, + last_type_id, input, extension_finder, field_skipper)) { return false; } @@ -689,8 +712,8 @@ int ExtensionSet::Extension::MessageSetItemByteSize(int number) const { void ExtensionSet::SerializeMessageSetWithCachedSizes( io::CodedOutputStream* output) const { - map::const_iterator iter; - for (iter = extensions_.begin(); iter != extensions_.end(); ++iter) { + for (map::const_iterator iter = extensions_.begin(); + iter != extensions_.end(); ++iter) { iter->second.SerializeMessageSetItemWithCachedSizes(iter->first, output); } } diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc index 559de6e1..52e551cd 100644 --- a/src/google/protobuf/extension_set_unittest.cc +++ b/src/google/protobuf/extension_set_unittest.cc @@ -142,7 +142,7 @@ TEST(ExtensionSetTest, ClearOneField) { TestUtil::ExpectAllExtensionsSet(message); } -TEST(ExtensionSetTest, SetAllocatedExtensin) { +TEST(ExtensionSetTest, SetAllocatedExtension) { unittest::TestAllExtensions message; EXPECT_FALSE(message.HasExtension( unittest::optional_foreign_message_extension)); @@ -162,11 +162,11 @@ TEST(ExtensionSetTest, SetAllocatedExtensin) { // SetAllocatedExtension should delete the previously existing extension. // (We reply on unittest to check memory leaks for this case) message.SetAllocatedExtension(unittest::optional_foreign_message_extension, - new unittest::ForeignMessage()); + new unittest::ForeignMessage()); // SetAllocatedExtension with a NULL parameter is equivalent to ClearExtenion. message.SetAllocatedExtension(unittest::optional_foreign_message_extension, - NULL); + NULL); EXPECT_FALSE(message.HasExtension( unittest::optional_foreign_message_extension)); } @@ -186,7 +186,7 @@ TEST(ExtensionSetTest, ReleaseExtension) { // Release the extension using ReleaseExtension unittest::TestMessageSetExtension1* released_extension = message.ReleaseExtension( - unittest::TestMessageSetExtension1::message_set_extension); + unittest::TestMessageSetExtension1::message_set_extension); EXPECT_EQ(extension, released_extension); EXPECT_FALSE(message.HasExtension( unittest::TestMessageSetExtension1::message_set_extension)); @@ -198,7 +198,7 @@ TEST(ExtensionSetTest, ReleaseExtension) { message.ClearExtension( unittest::TestMessageSetExtension1::message_set_extension); released_extension = message.ReleaseExtension( - unittest::TestMessageSetExtension1::message_set_extension); + unittest::TestMessageSetExtension1::message_set_extension); EXPECT_TRUE(released_extension != NULL); delete released_extension; } @@ -256,6 +256,82 @@ TEST(ExtensionSetTest, SwapWithSelf) { TestUtil::ExpectAllExtensionsSet(message); } +TEST(ExtensionSetTest, SwapExtension) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + + TestUtil::SetAllExtensions(&message1); + vector fields; + + // Swap empty fields. + const Reflection* reflection = message1.GetReflection(); + reflection->SwapFields(&message1, &message2, fields); + TestUtil::ExpectAllExtensionsSet(message1); + TestUtil::ExpectExtensionsClear(message2); + + // Swap two extensions. + fields.push_back( + reflection->FindKnownExtensionByNumber(12)); + fields.push_back( + reflection->FindKnownExtensionByNumber(25)); + reflection->SwapFields(&message1, &message2, fields); + + EXPECT_TRUE(message1.HasExtension(unittest::optional_int32_extension)); + EXPECT_FALSE(message1.HasExtension(unittest::optional_double_extension)); + EXPECT_FALSE(message1.HasExtension(unittest::optional_cord_extension)); + + EXPECT_FALSE(message2.HasExtension(unittest::optional_int32_extension)); + EXPECT_TRUE(message2.HasExtension(unittest::optional_double_extension)); + EXPECT_TRUE(message2.HasExtension(unittest::optional_cord_extension)); +} + +TEST(ExtensionSetTest, SwapExtensionWithEmpty) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + unittest::TestAllExtensions message3; + + TestUtil::SetAllExtensions(&message3); + + const Reflection* reflection = message3.GetReflection(); + vector fields; + reflection->ListFields(message3, &fields); + + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectExtensionsClear(message1); + TestUtil::ExpectExtensionsClear(message2); +} + +TEST(ExtensionSetTest, SwapExtensionBothFull) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + + TestUtil::SetAllExtensions(&message1); + TestUtil::SetAllExtensions(&message2); + + const Reflection* reflection = message1.GetReflection(); + vector fields; + reflection->ListFields(message1, &fields); + + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectAllExtensionsSet(message1); + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(ExtensionSetTest, SwapExtensionWithSelf) { + unittest::TestAllExtensions message1; + + TestUtil::SetAllExtensions(&message1); + + vector fields; + const Reflection* reflection = message1.GetReflection(); + reflection->ListFields(message1, &fields); + reflection->SwapFields(&message1, &message1, fields); + + TestUtil::ExpectAllExtensionsSet(message1); +} + TEST(ExtensionSetTest, SerializationToArray) { // Serialize as TestAllExtensions and parse as TestAllTypes to insure wire // compatibility of extensions. @@ -353,6 +429,7 @@ TEST(ExtensionSetTest, Parsing) { TestUtil::SetAllFields(&source); source.SerializeToString(&data); EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::SetOneofFields(&destination); TestUtil::ExpectAllExtensionsSet(destination); } @@ -368,6 +445,48 @@ TEST(ExtensionSetTest, PackedParsing) { TestUtil::ExpectPackedExtensionsSet(destination); } +TEST(ExtensionSetTest, PackedToUnpackedParsing) { + unittest::TestPackedTypes source; + unittest::TestUnpackedExtensions destination; + string data; + + TestUtil::SetPackedFields(&source); + source.SerializeToString(&data); + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectUnpackedExtensionsSet(destination); + + // Reserialize + unittest::TestUnpackedTypes unpacked; + TestUtil::SetUnpackedFields(&unpacked); + EXPECT_TRUE(unpacked.SerializeAsString() == destination.SerializeAsString()); + + // Make sure we can add extensions. + destination.AddExtension(unittest::unpacked_int32_extension, 1); + destination.AddExtension(unittest::unpacked_enum_extension, + protobuf_unittest::FOREIGN_BAR); +} + +TEST(ExtensionSetTest, UnpackedToPackedParsing) { + unittest::TestUnpackedTypes source; + unittest::TestPackedExtensions destination; + string data; + + TestUtil::SetUnpackedFields(&source); + source.SerializeToString(&data); + EXPECT_TRUE(destination.ParseFromString(data)); + TestUtil::ExpectPackedExtensionsSet(destination); + + // Reserialize + unittest::TestPackedTypes packed; + TestUtil::SetPackedFields(&packed); + EXPECT_TRUE(packed.SerializeAsString() == destination.SerializeAsString()); + + // Make sure we can add extensions. + destination.AddExtension(unittest::packed_int32_extension, 1); + destination.AddExtension(unittest::packed_enum_extension, + protobuf_unittest::FOREIGN_BAR); +} + TEST(ExtensionSetTest, IsInitialized) { // Test that IsInitialized() returns false if required fields in nested // extensions are missing. @@ -550,6 +669,256 @@ TEST(ExtensionSetTest, SpaceUsedExcludingSelf) { } } +// N.B.: We do not test range-based for here because we remain C++03 compatible. +template +inline T SumAllExtensions(const M& message, ID extension, T zero) { + T sum = zero; + typename RepeatedField::const_iterator iter = + message.GetRepeatedExtension(extension).begin(); + typename RepeatedField::const_iterator end = + message.GetRepeatedExtension(extension).end(); + for (; iter != end; ++iter) { + sum += *iter; + } + return sum; +} + +template +inline void IncAllExtensions(M* message, ID extension, + T val) { + typename RepeatedField::iterator iter = + message->MutableRepeatedExtension(extension)->begin(); + typename RepeatedField::iterator end = + message->MutableRepeatedExtension(extension)->end(); + for (; iter != end; ++iter) { + *iter += val; + } +} + +TEST(ExtensionSetTest, RepeatedFields) { + unittest::TestAllExtensions message; + + // Test empty repeated-field case (b/12926163) + ASSERT_EQ(0, message.GetRepeatedExtension( + unittest::repeated_int32_extension).size()); + ASSERT_EQ(0, message.GetRepeatedExtension( + unittest::repeated_nested_enum_extension).size()); + ASSERT_EQ(0, message.GetRepeatedExtension( + unittest::repeated_string_extension).size()); + ASSERT_EQ(0, message.GetRepeatedExtension( + unittest::repeated_nested_message_extension).size()); + + unittest::TestAllTypes::NestedMessage nested_message; + nested_message.set_bb(42); + unittest::TestAllTypes::NestedEnum nested_enum = + unittest::TestAllTypes::NestedEnum_MIN; + + for (int i = 0; i < 10; ++i) { + message.AddExtension(unittest::repeated_int32_extension, 1); + message.AddExtension(unittest::repeated_int64_extension, 2); + message.AddExtension(unittest::repeated_uint32_extension, 3); + message.AddExtension(unittest::repeated_uint64_extension, 4); + message.AddExtension(unittest::repeated_sint32_extension, 5); + message.AddExtension(unittest::repeated_sint64_extension, 6); + message.AddExtension(unittest::repeated_fixed32_extension, 7); + message.AddExtension(unittest::repeated_fixed64_extension, 8); + message.AddExtension(unittest::repeated_sfixed32_extension, 7); + message.AddExtension(unittest::repeated_sfixed64_extension, 8); + message.AddExtension(unittest::repeated_float_extension, 9.0); + message.AddExtension(unittest::repeated_double_extension, 10.0); + message.AddExtension(unittest::repeated_bool_extension, true); + message.AddExtension(unittest::repeated_nested_enum_extension, nested_enum); + message.AddExtension(unittest::repeated_string_extension, + ::std::string("test")); + message.AddExtension(unittest::repeated_bytes_extension, + ::std::string("test\xFF")); + message.AddExtension( + unittest::repeated_nested_message_extension)->CopyFrom(nested_message); + message.AddExtension(unittest::repeated_nested_enum_extension, + nested_enum); + } + + ASSERT_EQ(10, SumAllExtensions( + message, unittest::repeated_int32_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_int32_extension, 1); + ASSERT_EQ(20, SumAllExtensions( + message, unittest::repeated_int32_extension, 0)); + + ASSERT_EQ(20, SumAllExtensions( + message, unittest::repeated_int64_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_int64_extension, 1); + ASSERT_EQ(30, SumAllExtensions( + message, unittest::repeated_int64_extension, 0)); + + ASSERT_EQ(30, SumAllExtensions( + message, unittest::repeated_uint32_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_uint32_extension, 1); + ASSERT_EQ(40, SumAllExtensions( + message, unittest::repeated_uint32_extension, 0)); + + ASSERT_EQ(40, SumAllExtensions( + message, unittest::repeated_uint64_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_uint64_extension, 1); + ASSERT_EQ(50, SumAllExtensions( + message, unittest::repeated_uint64_extension, 0)); + + ASSERT_EQ(50, SumAllExtensions( + message, unittest::repeated_sint32_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_sint32_extension, 1); + ASSERT_EQ(60, SumAllExtensions( + message, unittest::repeated_sint32_extension, 0)); + + ASSERT_EQ(60, SumAllExtensions( + message, unittest::repeated_sint64_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_sint64_extension, 1); + ASSERT_EQ(70, SumAllExtensions( + message, unittest::repeated_sint64_extension, 0)); + + ASSERT_EQ(70, SumAllExtensions( + message, unittest::repeated_fixed32_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_fixed32_extension, 1); + ASSERT_EQ(80, SumAllExtensions( + message, unittest::repeated_fixed32_extension, 0)); + + ASSERT_EQ(80, SumAllExtensions( + message, unittest::repeated_fixed64_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_fixed64_extension, 1); + ASSERT_EQ(90, SumAllExtensions( + message, unittest::repeated_fixed64_extension, 0)); + + // Usually, floating-point arithmetic cannot be trusted to be exact, so it is + // a Bad Idea to assert equality in a test like this. However, we're dealing + // with integers with a small number of significant mantissa bits, so we + // should actually have exact precision here. + ASSERT_EQ(90, SumAllExtensions( + message, unittest::repeated_float_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_float_extension, 1); + ASSERT_EQ(100, SumAllExtensions( + message, unittest::repeated_float_extension, 0)); + + ASSERT_EQ(100, SumAllExtensions( + message, unittest::repeated_double_extension, 0)); + IncAllExtensions( + &message, unittest::repeated_double_extension, 1); + ASSERT_EQ(110, SumAllExtensions( + message, unittest::repeated_double_extension, 0)); + + typename RepeatedPtrField< ::std::string>::iterator string_iter; + typename RepeatedPtrField< ::std::string>::iterator string_end; + for (string_iter = message.MutableRepeatedExtension( + unittest::repeated_string_extension)->begin(), + string_end = message.MutableRepeatedExtension( + unittest::repeated_string_extension)->end(); + string_iter != string_end; ++string_iter) { + *string_iter += "test"; + } + typename RepeatedPtrField< ::std::string>::const_iterator string_const_iter; + typename RepeatedPtrField< ::std::string>::const_iterator string_const_end; + for (string_const_iter = message.GetRepeatedExtension( + unittest::repeated_string_extension).begin(), + string_const_end = message.GetRepeatedExtension( + unittest::repeated_string_extension).end(); + string_iter != string_end; ++string_iter) { + ASSERT_TRUE(*string_iter == "testtest"); + } + + typename RepeatedField::iterator enum_iter; + typename RepeatedField::iterator enum_end; + for (enum_iter = message.MutableRepeatedExtension( + unittest::repeated_nested_enum_extension)->begin(), + enum_end = message.MutableRepeatedExtension( + unittest::repeated_nested_enum_extension)->end(); + enum_iter != enum_end; ++enum_iter) { + *enum_iter = unittest::TestAllTypes::NestedEnum_MAX; + } + typename RepeatedField::const_iterator + enum_const_iter; + typename RepeatedField::const_iterator + enum_const_end; + for (enum_const_iter = message.GetRepeatedExtension( + unittest::repeated_nested_enum_extension).begin(), + enum_const_end = message.GetRepeatedExtension( + unittest::repeated_nested_enum_extension).end(); + enum_iter != enum_end; ++enum_iter) { + ASSERT_EQ(*enum_const_iter, unittest::TestAllTypes::NestedEnum_MAX); + } + + typename RepeatedPtrField::iterator + msg_iter; + typename RepeatedPtrField::iterator + msg_end; + for (msg_iter = message.MutableRepeatedExtension( + unittest::repeated_nested_message_extension)->begin(), + msg_end = message.MutableRepeatedExtension( + unittest::repeated_nested_message_extension)->end(); + msg_iter != msg_end; ++msg_iter) { + msg_iter->set_bb(1234); + } + typename RepeatedPtrField:: + const_iterator msg_const_iter; + typename RepeatedPtrField:: + const_iterator msg_const_end; + for (msg_const_iter = message.GetRepeatedExtension( + unittest::repeated_nested_message_extension).begin(), + msg_const_end = message.GetRepeatedExtension( + unittest::repeated_nested_message_extension).end(); + msg_const_iter != msg_const_end; ++msg_const_iter) { + ASSERT_EQ(msg_const_iter->bb(), 1234); + } + + // Test range-based for as well, but only if compiled as C++11. +#if __cplusplus >= 201103L + // Test one primitive field. + for (auto& x : *message.MutableRepeatedExtension( + unittest::repeated_int32_extension)) { + x = 4321; + } + for (const auto& x : message.GetRepeatedExtension( + unittest::repeated_int32_extension)) { + ASSERT_EQ(x, 4321); + } + // Test one string field. + for (auto& x : *message.MutableRepeatedExtension( + unittest::repeated_string_extension)) { + x = "test_range_based_for"; + } + for (const auto& x : message.GetRepeatedExtension( + unittest::repeated_string_extension)) { + ASSERT_TRUE(x == "test_range_based_for"); + } + // Test one message field. + for (auto& x : *message.MutableRepeatedExtension( + unittest::repeated_nested_message_extension)) { + x.set_bb(4321); + } + for (const auto& x : *message.MutableRepeatedExtension( + unittest::repeated_nested_message_extension)) { + ASSERT_EQ(x.bb(), 4321); + } +#endif +} + +// From b/12926163 +TEST(ExtensionSetTest, AbsentExtension) { + unittest::TestAllExtensions message; + message.MutableRepeatedExtension(unittest::repeated_nested_message_extension) + ->Add()->set_bb(123); + ASSERT_EQ(1, message.ExtensionSize( + unittest::repeated_nested_message_extension)); + EXPECT_EQ( + 123, message.GetExtension( + unittest::repeated_nested_message_extension, 0).bb()); +} + #ifdef PROTOBUF_HAS_DEATH_TEST TEST(ExtensionSetTest, InvalidEnumDeath) { diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h index a09a540b..2780a9b3 100644 --- a/src/google/protobuf/generated_enum_reflection.h +++ b/src/google/protobuf/generated_enum_reflection.h @@ -41,6 +41,8 @@ #include +#include + namespace google { namespace protobuf { class EnumDescriptor; @@ -48,6 +50,10 @@ namespace protobuf { namespace protobuf { +// This type trait can be used to cause templates to only match proto2 enum +// types. +template struct is_proto_enum : ::google::protobuf::internal::false_type {}; + // Returns the EnumDescriptor for enum type E, which must be a // proto-declared enum type. Code generated by the protocol compiler // will include specializations of this template for each enum type declared. diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index 33297ed1..853aadbf 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -33,6 +33,7 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include #include #include #include @@ -41,6 +42,8 @@ #include #include +#define GOOGLE_PROTOBUF_HAS_ONEOF + namespace google { namespace protobuf { namespace internal { @@ -49,7 +52,7 @@ int StringSpaceUsedExcludingSelf(const string& str) { const void* start = &str; const void* end = &str + 1; - if (start <= str.data() && str.data() <= end) { + if (start <= str.data() && str.data() < end) { // The string's data is stored inside the string object itself. return 0; } else { @@ -188,6 +191,33 @@ GeneratedMessageReflection::GeneratedMessageReflection( message_factory_ (factory) { } +GeneratedMessageReflection::GeneratedMessageReflection( + const Descriptor* descriptor, + const Message* default_instance, + const int offsets[], + int has_bits_offset, + int unknown_fields_offset, + int extensions_offset, + const void* default_oneof_instance, + int oneof_case_offset, + const DescriptorPool* descriptor_pool, + MessageFactory* factory, + int object_size) + : descriptor_ (descriptor), + default_instance_ (default_instance), + default_oneof_instance_ (default_oneof_instance), + offsets_ (offsets), + has_bits_offset_ (has_bits_offset), + oneof_case_offset_(oneof_case_offset), + unknown_fields_offset_(unknown_fields_offset), + extensions_offset_(extensions_offset), + object_size_ (object_size), + descriptor_pool_ ((descriptor_pool == NULL) ? + DescriptorPool::generated_pool() : + descriptor_pool), + message_factory_ (factory) { +} + GeneratedMessageReflection::~GeneratedMessageReflection() {} const UnknownFieldSet& GeneratedMessageReflection::GetUnknownFields( @@ -254,6 +284,9 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const { break; } } else { + if (field->containing_oneof() && !HasOneofField(message, field)) { + continue; + } switch (field->cpp_type()) { case FieldDescriptor::CPPTYPE_INT32 : case FieldDescriptor::CPPTYPE_INT64 : @@ -306,6 +339,195 @@ int GeneratedMessageReflection::SpaceUsed(const Message& message) const { return total_size; } +void GeneratedMessageReflection::SwapField( + Message* message1, + Message* message2, + const FieldDescriptor* field) const { + if (field->is_repeated()) { + switch (field->cpp_type()) { +#define SWAP_ARRAYS(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + MutableRaw >(message1, field)->Swap( \ + MutableRaw >(message2, field)); \ + break; + + SWAP_ARRAYS(INT32 , int32 ); + SWAP_ARRAYS(INT64 , int64 ); + SWAP_ARRAYS(UINT32, uint32); + SWAP_ARRAYS(UINT64, uint64); + SWAP_ARRAYS(FLOAT , float ); + SWAP_ARRAYS(DOUBLE, double); + SWAP_ARRAYS(BOOL , bool ); + SWAP_ARRAYS(ENUM , int ); +#undef SWAP_ARRAYS + + case FieldDescriptor::CPPTYPE_STRING: + case FieldDescriptor::CPPTYPE_MESSAGE: + MutableRaw(message1, field)->Swap( + MutableRaw(message2, field)); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } + } else { + switch (field->cpp_type()) { +#define SWAP_VALUES(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + std::swap(*MutableRaw(message1, field), \ + *MutableRaw(message2, field)); \ + break; + + SWAP_VALUES(INT32 , int32 ); + SWAP_VALUES(INT64 , int64 ); + SWAP_VALUES(UINT32, uint32); + SWAP_VALUES(UINT64, uint64); + SWAP_VALUES(FLOAT , float ); + SWAP_VALUES(DOUBLE, double); + SWAP_VALUES(BOOL , bool ); + SWAP_VALUES(ENUM , int ); +#undef SWAP_VALUES + case FieldDescriptor::CPPTYPE_MESSAGE: + std::swap(*MutableRaw(message1, field), + *MutableRaw(message2, field)); + break; + + case FieldDescriptor::CPPTYPE_STRING: + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + std::swap(*MutableRaw(message1, field), + *MutableRaw(message2, field)); + break; + } + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + } + } +} + +void GeneratedMessageReflection::SwapOneofField( + Message* message1, + Message* message2, + const OneofDescriptor* oneof_descriptor) const { + uint32 oneof_case1 = GetOneofCase(*message1, oneof_descriptor); + uint32 oneof_case2 = GetOneofCase(*message2, oneof_descriptor); + + int32 temp_int32; + int64 temp_int64; + uint32 temp_uint32; + uint64 temp_uint64; + float temp_float; + double temp_double; + bool temp_bool; + int temp_int; + Message* temp_message; + string temp_string; + + // Stores message1's oneof field to a temp variable. + const FieldDescriptor* field1; + if (oneof_case1 > 0) { + field1 = descriptor_->FindFieldByNumber(oneof_case1); + //oneof_descriptor->field(oneof_case1); + switch (field1->cpp_type()) { +#define GET_TEMP_VALUE(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + temp_##TYPE = GetField(*message1, field1); \ + break; + + GET_TEMP_VALUE(INT32 , int32 ); + GET_TEMP_VALUE(INT64 , int64 ); + GET_TEMP_VALUE(UINT32, uint32); + GET_TEMP_VALUE(UINT64, uint64); + GET_TEMP_VALUE(FLOAT , float ); + GET_TEMP_VALUE(DOUBLE, double); + GET_TEMP_VALUE(BOOL , bool ); + GET_TEMP_VALUE(ENUM , int ); +#undef GET_TEMP_VALUE + case FieldDescriptor::CPPTYPE_MESSAGE: + temp_message = ReleaseMessage(message1, field1); + break; + + case FieldDescriptor::CPPTYPE_STRING: + temp_string = GetString(*message1, field1); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type(); + } + } + + // Sets message1's oneof field from the message2's oneof field. + if (oneof_case2 > 0) { + const FieldDescriptor* field2 = + descriptor_->FindFieldByNumber(oneof_case2); + switch (field2->cpp_type()) { +#define SET_ONEOF_VALUE1(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + SetField(message1, field2, GetField(*message2, field2)); \ + break; + + SET_ONEOF_VALUE1(INT32 , int32 ); + SET_ONEOF_VALUE1(INT64 , int64 ); + SET_ONEOF_VALUE1(UINT32, uint32); + SET_ONEOF_VALUE1(UINT64, uint64); + SET_ONEOF_VALUE1(FLOAT , float ); + SET_ONEOF_VALUE1(DOUBLE, double); + SET_ONEOF_VALUE1(BOOL , bool ); + SET_ONEOF_VALUE1(ENUM , int ); +#undef SET_ONEOF_VALUE1 + case FieldDescriptor::CPPTYPE_MESSAGE: + SetAllocatedMessage(message1, + ReleaseMessage(message2, field2), + field2); + break; + + case FieldDescriptor::CPPTYPE_STRING: + SetString(message1, field2, GetString(*message2, field2)); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field2->cpp_type(); + } + } else { + ClearOneof(message1, oneof_descriptor); + } + + // Sets message2's oneof field from the temp variable. + if (oneof_case1 > 0) { + switch (field1->cpp_type()) { +#define SET_ONEOF_VALUE2(CPPTYPE, TYPE) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + SetField(message2, field1, temp_##TYPE); \ + break; + + SET_ONEOF_VALUE2(INT32 , int32 ); + SET_ONEOF_VALUE2(INT64 , int64 ); + SET_ONEOF_VALUE2(UINT32, uint32); + SET_ONEOF_VALUE2(UINT64, uint64); + SET_ONEOF_VALUE2(FLOAT , float ); + SET_ONEOF_VALUE2(DOUBLE, double); + SET_ONEOF_VALUE2(BOOL , bool ); + SET_ONEOF_VALUE2(ENUM , int ); +#undef SET_ONEOF_VALUE2 + case FieldDescriptor::CPPTYPE_MESSAGE: + SetAllocatedMessage(message2, temp_message, field1); + break; + + case FieldDescriptor::CPPTYPE_STRING: + SetString(message2, field1, temp_string); + break; + + default: + GOOGLE_LOG(FATAL) << "Unimplemented type: " << field1->cpp_type(); + } + } else { + ClearOneof(message2, oneof_descriptor); + } +} + void GeneratedMessageReflection::Swap( Message* message1, Message* message2) const { @@ -337,76 +559,69 @@ void GeneratedMessageReflection::Swap( for (int i = 0; i < descriptor_->field_count(); i++) { const FieldDescriptor* field = descriptor_->field(i); - if (field->is_repeated()) { - switch (field->cpp_type()) { -#define SWAP_ARRAYS(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - MutableRaw >(message1, field)->Swap( \ - MutableRaw >(message2, field)); \ - break; + if (!field->containing_oneof()) { + SwapField(message1, message2, field); + } + } - SWAP_ARRAYS(INT32 , int32 ); - SWAP_ARRAYS(INT64 , int64 ); - SWAP_ARRAYS(UINT32, uint32); - SWAP_ARRAYS(UINT64, uint64); - SWAP_ARRAYS(FLOAT , float ); - SWAP_ARRAYS(DOUBLE, double); - SWAP_ARRAYS(BOOL , bool ); - SWAP_ARRAYS(ENUM , int ); -#undef SWAP_ARRAYS + for (int i = 0; i < descriptor_->oneof_decl_count(); i++) { + SwapOneofField(message1, message2, descriptor_->oneof_decl(i)); + } - case FieldDescriptor::CPPTYPE_STRING: - case FieldDescriptor::CPPTYPE_MESSAGE: - MutableRaw(message1, field)->Swap( - MutableRaw(message2, field)); - break; + if (extensions_offset_ != -1) { + MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2)); + } - default: - GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); - } - } else { - switch (field->cpp_type()) { -#define SWAP_VALUES(CPPTYPE, TYPE) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - std::swap(*MutableRaw(message1, field), \ - *MutableRaw(message2, field)); \ - break; + MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2)); +} - SWAP_VALUES(INT32 , int32 ); - SWAP_VALUES(INT64 , int64 ); - SWAP_VALUES(UINT32, uint32); - SWAP_VALUES(UINT64, uint64); - SWAP_VALUES(FLOAT , float ); - SWAP_VALUES(DOUBLE, double); - SWAP_VALUES(BOOL , bool ); - SWAP_VALUES(ENUM , int ); -#undef SWAP_VALUES - case FieldDescriptor::CPPTYPE_MESSAGE: - std::swap(*MutableRaw(message1, field), - *MutableRaw(message2, field)); - break; +void GeneratedMessageReflection::SwapFields( + Message* message1, + Message* message2, + const vector& fields) const { + if (message1 == message2) return; - case FieldDescriptor::CPPTYPE_STRING: - switch (field->options().ctype()) { - default: // TODO(kenton): Support other string reps. - case FieldOptions::STRING: - std::swap(*MutableRaw(message1, field), - *MutableRaw(message2, field)); - break; - } - break; + // TODO(kenton): Other Reflection methods should probably check this too. + GOOGLE_CHECK_EQ(message1->GetReflection(), this) + << "First argument to SwapFields() (of type \"" + << message1->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type \"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + GOOGLE_CHECK_EQ(message2->GetReflection(), this) + << "Second argument to SwapFields() (of type \"" + << message2->GetDescriptor()->full_name() + << "\") is not compatible with this reflection object (which is for type \"" + << descriptor_->full_name() + << "\"). Note that the exact same class is required; not just the same " + "descriptor."; + + std::set swapped_oneof; - default: - GOOGLE_LOG(FATAL) << "Unimplemented type: " << field->cpp_type(); + for (int i = 0; i < fields.size(); i++) { + const FieldDescriptor* field = fields[i]; + if (field->is_extension()) { + MutableExtensionSet(message1)->SwapExtension( + MutableExtensionSet(message2), + field->number()); + } else { + if (field->containing_oneof()) { + int oneof_index = field->containing_oneof()->index(); + // Only swap the oneof field once. + if (swapped_oneof.find(oneof_index) != swapped_oneof.end()) { + continue; + } + swapped_oneof.insert(oneof_index); + SwapOneofField(message1, message2, field->containing_oneof()); + } else { + // Swap has bit. + SwapBit(message1, message2, field); + // Swap field. + SwapField(message1, message2, field); } } } - - if (extensions_offset_ != -1) { - MutableExtensionSet(message1)->Swap(MutableExtensionSet(message2)); - } - - MutableUnknownFields(message1)->Swap(MutableUnknownFields(message2)); } // ------------------------------------------------------------------- @@ -419,7 +634,11 @@ bool GeneratedMessageReflection::HasField(const Message& message, if (field->is_extension()) { return GetExtensionSet(message).Has(field->number()); } else { - return HasBit(message, field); + if (field->containing_oneof()) { + return HasOneofField(message, field); + } else { + return HasBit(message, field); + } } } @@ -463,6 +682,11 @@ void GeneratedMessageReflection::ClearField( if (field->is_extension()) { MutableExtensionSet(message)->ClearExtension(field->number()); } else if (!field->is_repeated()) { + if (field->containing_oneof()) { + ClearOneofField(message, field); + return; + } + if (HasBit(*message, field)) { ClearBit(message, field); @@ -667,7 +891,11 @@ void GeneratedMessageReflection::ListFields( output->push_back(field); } } else { - if (HasBit(message, field)) { + if (field->containing_oneof()) { + if (HasOneofField(message, field)) { + output->push_back(field); + } + } else if (HasBit(message, field)) { output->push_back(field); } } @@ -777,7 +1005,7 @@ string GeneratedMessageReflection::GetString( const string& GeneratedMessageReflection::GetStringReference( const Message& message, - const FieldDescriptor* field, string* /* scratch */) const { + const FieldDescriptor* field, string* scratch) const { USAGE_CHECK_ALL(GetStringReference, SINGULAR, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetString(field->number(), @@ -806,6 +1034,10 @@ void GeneratedMessageReflection::SetString( switch (field->options().ctype()) { default: // TODO(kenton): Support other string reps. case FieldOptions::STRING: { + if (field->containing_oneof() && !HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + *MutableField(message, field) = new string; + } string** ptr = MutableField(message, field); if (*ptr == DefaultRaw(field)) { *ptr = new string(value); @@ -838,7 +1070,7 @@ string GeneratedMessageReflection::GetRepeatedString( const string& GeneratedMessageReflection::GetRepeatedStringReference( const Message& message, const FieldDescriptor* field, - int index, string* /* scratch */) const { + int index, string* scratch) const { USAGE_CHECK_ALL(GetRepeatedStringReference, REPEATED, STRING); if (field->is_extension()) { return GetExtensionSet(message).GetRepeatedString(field->number(), index); @@ -1000,8 +1232,6 @@ const Message& GeneratedMessageReflection::GetMessage( Message* GeneratedMessageReflection::MutableMessage( Message* message, const FieldDescriptor* field, MessageFactory* factory) const { - USAGE_CHECK_ALL(MutableMessage, SINGULAR, MESSAGE); - if (factory == NULL) factory = message_factory_; if (field->is_extension()) { @@ -1009,7 +1239,19 @@ Message* GeneratedMessageReflection::MutableMessage( MutableExtensionSet(message)->MutableMessage(field, factory)); } else { Message* result; - Message** result_holder = MutableField(message, field); + Message** result_holder = MutableRaw(message, field); + + if (field->containing_oneof()) { + if (!HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + result_holder = MutableField(message, field); + const Message* default_message = DefaultRaw(field); + *result_holder = default_message->New(); + } + } else { + SetBit(message, field); + } + if (*result_holder == NULL) { const Message* default_message = DefaultRaw(field); *result_holder = default_message->New(); @@ -1019,6 +1261,38 @@ Message* GeneratedMessageReflection::MutableMessage( } } +void GeneratedMessageReflection::SetAllocatedMessage( + Message* message, + Message* sub_message, + const FieldDescriptor* field) const { + USAGE_CHECK_ALL(SetAllocatedMessage, SINGULAR, MESSAGE); + + if (field->is_extension()) { + MutableExtensionSet(message)->SetAllocatedMessage( + field->number(), field->type(), field, sub_message); + } else { + if (field->containing_oneof()) { + if (sub_message == NULL) { + ClearOneof(message, field->containing_oneof()); + return; + } + ClearOneof(message, field->containing_oneof()); + *MutableRaw(message, field) = sub_message; + SetOneofCase(message, field); + return; + } + + if (sub_message == NULL) { + ClearBit(message, field); + } else { + SetBit(message, field); + } + Message** sub_message_holder = MutableRaw(message, field); + delete *sub_message_holder; + *sub_message_holder = sub_message; + } +} + Message* GeneratedMessageReflection::ReleaseMessage( Message* message, const FieldDescriptor* field, @@ -1032,6 +1306,13 @@ Message* GeneratedMessageReflection::ReleaseMessage( MutableExtensionSet(message)->ReleaseMessage(field, factory)); } else { ClearBit(message, field); + if (field->containing_oneof()) { + if (HasOneofField(*message, field)) { + *MutableOneofCase(message, field->containing_oneof()) = 0; + } else { + return NULL; + } + } Message** result = MutableRaw(message, field); Message* ret = *result; *result = NULL; @@ -1111,11 +1392,21 @@ void* GeneratedMessageReflection::MutableRawRepeatedField( GOOGLE_CHECK_EQ(field->message_type(), desc) << "wrong submessage type"; if (field->is_extension()) return MutableExtensionSet(message)->MutableRawRepeatedField( - field->number()); + field->number(), field->type(), field->is_packed(), field); else return reinterpret_cast(message) + offsets_[field->index()]; } +const FieldDescriptor* GeneratedMessageReflection::GetOneofFieldDescriptor( + const Message& message, + const OneofDescriptor* oneof_descriptor) const { + uint32 field_number = GetOneofCase(message, oneof_descriptor); + if (field_number == 0) { + return NULL; + } + return descriptor_->FindFieldByNumber(field_number); +} + // ----------------------------------------------------------------------------- const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByName( @@ -1162,23 +1453,35 @@ const FieldDescriptor* GeneratedMessageReflection::FindKnownExtensionByNumber( template inline const Type& GeneratedMessageReflection::GetRaw( const Message& message, const FieldDescriptor* field) const { + if (field->containing_oneof() && !HasOneofField(message, field)) { + return DefaultRaw(field); + } + int index = field->containing_oneof() ? + descriptor_->field_count() + field->containing_oneof()->index() : + field->index(); const void* ptr = reinterpret_cast(&message) + - offsets_[field->index()]; + offsets_[index]; return *reinterpret_cast(ptr); } template inline Type* GeneratedMessageReflection::MutableRaw( Message* message, const FieldDescriptor* field) const { - void* ptr = reinterpret_cast(message) + offsets_[field->index()]; + int index = field->containing_oneof() ? + descriptor_->field_count() + field->containing_oneof()->index() : + field->index(); + void* ptr = reinterpret_cast(message) + offsets_[index]; return reinterpret_cast(ptr); } template inline const Type& GeneratedMessageReflection::DefaultRaw( const FieldDescriptor* field) const { - const void* ptr = reinterpret_cast(default_instance_) + - offsets_[field->index()]; + const void* ptr = field->containing_oneof() ? + reinterpret_cast(default_oneof_instance_) + + offsets_[field->index()] : + reinterpret_cast(default_instance_) + + offsets_[field->index()]; return *reinterpret_cast(ptr); } @@ -1193,6 +1496,21 @@ inline uint32* GeneratedMessageReflection::MutableHasBits( return reinterpret_cast(ptr); } +inline const uint32 GeneratedMessageReflection::GetOneofCase( + const Message& message, + const OneofDescriptor* oneof_descriptor) const { + const void* ptr = reinterpret_cast(&message) + + oneof_case_offset_; + return reinterpret_cast(ptr)[oneof_descriptor->index()]; +} + +inline uint32* GeneratedMessageReflection::MutableOneofCase( + Message* message, + const OneofDescriptor* oneof_descriptor) const { + void* ptr = reinterpret_cast(message) + oneof_case_offset_; + return &(reinterpret_cast(ptr)[oneof_descriptor->index()]); +} + inline const ExtensionSet& GeneratedMessageReflection::GetExtensionSet( const Message& message) const { GOOGLE_DCHECK_NE(extensions_offset_, -1); @@ -1224,6 +1542,73 @@ inline void GeneratedMessageReflection::ClearBit( MutableHasBits(message)[field->index() / 32] &= ~(1 << (field->index() % 32)); } +inline void GeneratedMessageReflection::SwapBit( + Message* message1, Message* message2, const FieldDescriptor* field) const { + bool temp_has_bit = HasBit(*message1, field); + if (HasBit(*message2, field)) { + SetBit(message1, field); + } else { + ClearBit(message1, field); + } + if (temp_has_bit) { + SetBit(message2, field); + } else { + ClearBit(message2, field); + } +} + +inline bool GeneratedMessageReflection::HasOneof( + const Message& message, const OneofDescriptor* oneof_descriptor) const { + return (GetOneofCase(message, oneof_descriptor) > 0); +} + +inline bool GeneratedMessageReflection::HasOneofField( + const Message& message, const FieldDescriptor* field) const { + return (GetOneofCase(message, field->containing_oneof()) == field->number()); +} + +inline void GeneratedMessageReflection::SetOneofCase( + Message* message, const FieldDescriptor* field) const { + *MutableOneofCase(message, field->containing_oneof()) = field->number(); +} + +inline void GeneratedMessageReflection::ClearOneofField( + Message* message, const FieldDescriptor* field) const { + if (HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + } +} + +inline void GeneratedMessageReflection::ClearOneof( + Message* message, const OneofDescriptor* oneof_descriptor) const { + // TODO(jieluo): Consider to cache the unused object instead of deleting + // it. It will be much faster if an aplication switches a lot from + // a few oneof fields. Time/space tradeoff + uint32 oneof_case = GetOneofCase(*message, oneof_descriptor); + if (oneof_case > 0) { + const FieldDescriptor* field = descriptor_->FindFieldByNumber(oneof_case); + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_STRING: { + switch (field->options().ctype()) { + default: // TODO(kenton): Support other string reps. + case FieldOptions::STRING: + delete *MutableRaw(message, field); + break; + } + break; + } + + case FieldDescriptor::CPPTYPE_MESSAGE: + delete *MutableRaw(message, field); + break; + default: + break; + } + + *MutableOneofCase(message, oneof_descriptor) = 0; + } +} + // Template implementations of basic accessors. Inline because each // template instance is only called from one location. These are // used for all types except messages. @@ -1236,14 +1621,19 @@ inline const Type& GeneratedMessageReflection::GetField( template inline void GeneratedMessageReflection::SetField( Message* message, const FieldDescriptor* field, const Type& value) const { + if (field->containing_oneof() && !HasOneofField(*message, field)) { + ClearOneof(message, field->containing_oneof()); + } *MutableRaw(message, field) = value; - SetBit(message, field); + field->containing_oneof() ? + SetOneofCase(message, field) : SetBit(message, field); } template inline Type* GeneratedMessageReflection::MutableField( Message* message, const FieldDescriptor* field) const { - SetBit(message, field); + field->containing_oneof() ? + SetOneofCase(message, field) : SetBit(message, field); return MutableRaw(message, field); } diff --git a/src/google/protobuf/generated_message_reflection.h b/src/google/protobuf/generated_message_reflection.h index c1c142fa..0a31057a 100644 --- a/src/google/protobuf/generated_message_reflection.h +++ b/src/google/protobuf/generated_message_reflection.h @@ -61,6 +61,7 @@ namespace protobuf { namespace protobuf { namespace internal { +class DefaultEmptyOneof; // Defined in this file. class GeneratedMessageReflection; @@ -134,6 +135,42 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const DescriptorPool* pool, MessageFactory* factory, int object_size); + + // Similar with the construction above. Call this construction if the + // message has oneof definition. + // Parameters: + // offsets: An array of ints giving the byte offsets. + // For each oneof field, the offset is relative to the + // default_oneof_instance. These can be computed at compile + // time using the + // PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET() macro. + // For each none oneof field, the offset is related to + // the start of the message object. These can be computed + // at compile time using the + // GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET() macro. + // Besides offsets for all fields, this array also contains + // offsets for oneof unions. The offset of the i-th oneof + // union is offsets[descriptor->field_count() + i]. + // default_oneof_instance: The default instance of the oneofs. It is a + // struct holding the default value of all oneof fields + // for this message. It is only used to obtain pointers + // to default instances of oneof fields, which Get + // methods will return if the field is not set. + // oneof_case_offset: Offset in the message of an array of uint32s of + // size descriptor->oneof_decl_count(). Each uint32 + // indicates what field is set for each oneof. + // other parameters are the same with the construction above. + GeneratedMessageReflection(const Descriptor* descriptor, + const Message* default_instance, + const int offsets[], + int has_bits_offset, + int unknown_fields_offset, + int extensions_offset, + const void* default_oneof_instance, + int oneof_case_offset, + const DescriptorPool* pool, + MessageFactory* factory, + int object_size); ~GeneratedMessageReflection(); // implements Reflection ------------------------------------------- @@ -146,11 +183,16 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { bool HasField(const Message& message, const FieldDescriptor* field) const; int FieldSize(const Message& message, const FieldDescriptor* field) const; void ClearField(Message* message, const FieldDescriptor* field) const; + bool HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const; + void ClearOneof(Message* message, const OneofDescriptor* field) const; void RemoveLast(Message* message, const FieldDescriptor* field) const; Message* ReleaseLast(Message* message, const FieldDescriptor* field) const; void Swap(Message* message1, Message* message2) const; + void SwapFields(Message* message1, Message* message2, + const vector& fields) const; void SwapElements(Message* message, const FieldDescriptor* field, - int index1, int index2) const; + int index1, int index2) const; void ListFields(const Message& message, vector* output) const; @@ -179,6 +221,11 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const FieldDescriptor* field, MessageFactory* factory = NULL) const; + const FieldDescriptor* GetOneofFieldDescriptor( + const Message& message, + const OneofDescriptor* oneof_descriptor) const; + + public: void SetInt32 (Message* message, const FieldDescriptor* field, int32 value) const; void SetInt64 (Message* message, @@ -200,6 +247,9 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const EnumValueDescriptor* value) const; Message* MutableMessage(Message* message, const FieldDescriptor* field, MessageFactory* factory = NULL) const; + void SetAllocatedMessage(Message* message, + Message* sub_message, + const FieldDescriptor* field) const; Message* ReleaseMessage(Message* message, const FieldDescriptor* field, MessageFactory* factory = NULL) const; @@ -293,9 +343,11 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const Descriptor* descriptor_; const Message* default_instance_; + const void* default_oneof_instance_; const int* offsets_; int has_bits_offset_; + int oneof_case_offset_; int unknown_fields_offset_; int extensions_offset_; int object_size_; @@ -311,9 +363,17 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const FieldDescriptor* field) const; template inline const Type& DefaultRaw(const FieldDescriptor* field) const; + template + inline const Type& DefaultOneofRaw(const FieldDescriptor* field) const; inline const uint32* GetHasBits(const Message& message) const; inline uint32* MutableHasBits(Message* message) const; + inline const uint32 GetOneofCase( + const Message& message, + const OneofDescriptor* oneof_descriptor) const; + inline uint32* MutableOneofCase( + Message* message, + const OneofDescriptor* oneof_descriptor) const; inline const ExtensionSet& GetExtensionSet(const Message& message) const; inline ExtensionSet* MutableExtensionSet(Message* message) const; @@ -323,6 +383,26 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { const FieldDescriptor* field) const; inline void ClearBit(Message* message, const FieldDescriptor* field) const; + inline void SwapBit(Message* message1, + Message* message2, + const FieldDescriptor* field) const; + + // This function only swaps the field. Should swap corresponding has_bit + // before or after using this function. + void SwapField(Message* message1, + Message* message2, + const FieldDescriptor* field) const; + + void SwapOneofField(Message* message1, + Message* message2, + const OneofDescriptor* oneof_descriptor) const; + + inline bool HasOneofField(const Message& message, + const FieldDescriptor* field) const; + inline void SetOneofCase(Message* message, + const FieldDescriptor* field) const; + inline void ClearOneofField(Message* message, + const FieldDescriptor* field) const; template inline const Type& GetField(const Message& message, @@ -376,9 +456,14 @@ class LIBPROTOBUF_EXPORT GeneratedMessageReflection : public Reflection { // be confused by an unaligned pointer. #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(TYPE, FIELD) \ static_cast( \ - reinterpret_cast( \ - &reinterpret_cast(16)->FIELD) - \ - reinterpret_cast(16)) + reinterpret_cast( \ + &reinterpret_cast(16)->FIELD) - \ + reinterpret_cast(16)) + +#define PROTO2_GENERATED_DEFAULT_ONEOF_FIELD_OFFSET(ONEOF, FIELD) \ + static_cast( \ + reinterpret_cast(&(ONEOF->FIELD)) \ + - reinterpret_cast(ONEOF)) // There are some places in proto2 where dynamic_cast would be useful as an // optimization. For example, take Message::MergeFrom(const Message& other). diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc index 39aa55fb..99c28188 100644 --- a/src/google/protobuf/generated_message_reflection_unittest.cc +++ b/src/google/protobuf/generated_message_reflection_unittest.cc @@ -207,6 +207,111 @@ TEST(GeneratedMessageReflectionTest, SwapUnknown) { EXPECT_EQ(1, message2.unknown_fields().field_count()); } +TEST(GeneratedMessageReflectionTest, SwapFields) { + unittest::TestAllTypes message1, message2; + message1.set_optional_double(12.3); + message1.mutable_repeated_int32()->Add(10); + message1.mutable_repeated_int32()->Add(20); + + message2.set_optional_string("hello"); + message2.mutable_repeated_int64()->Add(30); + + vector fields; + const Descriptor* descriptor = message1.GetDescriptor(); + fields.push_back(descriptor->FindFieldByName("optional_double")); + fields.push_back(descriptor->FindFieldByName("repeated_int32")); + fields.push_back(descriptor->FindFieldByName("optional_string")); + fields.push_back(descriptor->FindFieldByName("optional_uint64")); + + const Reflection* reflection = message1.GetReflection(); + reflection->SwapFields(&message1, &message2, fields); + + EXPECT_FALSE(message1.has_optional_double()); + EXPECT_EQ(0, message1.repeated_int32_size()); + EXPECT_TRUE(message1.has_optional_string()); + EXPECT_EQ("hello", message1.optional_string()); + EXPECT_EQ(0, message1.repeated_int64_size()); + EXPECT_FALSE(message1.has_optional_uint64()); + + EXPECT_TRUE(message2.has_optional_double()); + EXPECT_EQ(12.3, message2.optional_double()); + EXPECT_EQ(2, message2.repeated_int32_size()); + EXPECT_EQ(10, message2.repeated_int32(0)); + EXPECT_EQ(20, message2.repeated_int32(1)); + EXPECT_FALSE(message2.has_optional_string()); + EXPECT_EQ(1, message2.repeated_int64_size()); + EXPECT_FALSE(message2.has_optional_uint64()); +} + +TEST(GeneratedMessageReflectionTest, SwapFieldsAll) { + unittest::TestAllTypes message1; + unittest::TestAllTypes message2; + + TestUtil::SetAllFields(&message2); + + vector fields; + const Reflection* reflection = message1.GetReflection(); + reflection->ListFields(message2, &fields); + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectAllFieldsSet(message1); + TestUtil::ExpectClear(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapFieldsAllExtension) { + unittest::TestAllExtensions message1; + unittest::TestAllExtensions message2; + + TestUtil::SetAllExtensions(&message1); + + vector fields; + const Reflection* reflection = message1.GetReflection(); + reflection->ListFields(message1, &fields); + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectExtensionsClear(message1); + TestUtil::ExpectAllExtensionsSet(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapOneof) { + unittest::TestOneof2 message1, message2; + TestUtil::SetOneof1(&message1); + + const Reflection* reflection = message1.GetReflection(); + reflection->Swap(&message1, &message2); + + TestUtil::ExpectOneofClear(message1); + TestUtil::ExpectOneofSet1(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapOneofBothSet) { + unittest::TestOneof2 message1, message2; + TestUtil::SetOneof1(&message1); + TestUtil::SetOneof2(&message2); + + const Reflection* reflection = message1.GetReflection(); + reflection->Swap(&message1, &message2); + + TestUtil::ExpectOneofSet2(message1); + TestUtil::ExpectOneofSet1(message2); +} + +TEST(GeneratedMessageReflectionTest, SwapFieldsOneof) { + unittest::TestOneof2 message1, message2; + TestUtil::SetOneof1(&message1); + + vector fields; + const Descriptor* descriptor = message1.GetDescriptor(); + for (int i = 0; i < descriptor->field_count(); i++) { + fields.push_back(descriptor->field(i)); + } + const Reflection* reflection = message1.GetReflection(); + reflection->SwapFields(&message1, &message2, fields); + + TestUtil::ExpectOneofClear(message1); + TestUtil::ExpectOneofSet1(message2); +} + TEST(GeneratedMessageReflectionTest, RemoveLast) { unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( @@ -375,6 +480,192 @@ TEST(GeneratedMessageReflectionTest, FindKnownExtensionByName) { FindKnownExtensionByName(extension1->full_name()) == NULL); } +TEST(GeneratedMessageReflectionTest, SetAllocatedMessageTest) { + unittest::TestAllTypes from_message1; + unittest::TestAllTypes from_message2; + unittest::TestAllTypes to_message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllTypes::descriptor()); + reflection_tester.SetAllFieldsViaReflection(&from_message1); + reflection_tester.SetAllFieldsViaReflection(&from_message2); + + // Before moving fields, we expect the nested messages to be NULL. + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::IS_NULL); + + // After fields are moved we should get non-NULL releases. + reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message1, &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::NOT_NULL); + + // Another move to make sure that we can SetAllocated several times. + reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message2, &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::NOT_NULL); + + // After SetAllocatedOptionalMessageFieldsToNullViaReflection() we expect the + // releases to be NULL again. + reflection_tester.SetAllocatedOptionalMessageFieldsToNullViaReflection( + &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::IS_NULL); +} + +TEST(GeneratedMessageReflectionTest, SetAllocatedExtensionMessageTest) { + unittest::TestAllExtensions from_message1; + unittest::TestAllExtensions from_message2; + unittest::TestAllExtensions to_message; + TestUtil::ReflectionTester reflection_tester( + unittest::TestAllExtensions::descriptor()); + reflection_tester.SetAllFieldsViaReflection(&from_message1); + reflection_tester.SetAllFieldsViaReflection(&from_message2); + + // Before moving fields, we expect the nested messages to be NULL. + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::IS_NULL); + + // After fields are moved we should get non-NULL releases. + reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message1, &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::NOT_NULL); + + // Another move to make sure that we can SetAllocated several times. + reflection_tester.SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message2, &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::NOT_NULL); + + // After SetAllocatedOptionalMessageFieldsToNullViaReflection() we expect the + // releases to be NULL again. + reflection_tester.SetAllocatedOptionalMessageFieldsToNullViaReflection( + &to_message); + reflection_tester.ExpectMessagesReleasedViaReflection( + &to_message, TestUtil::ReflectionTester::IS_NULL); +} + +TEST(GeneratedMessageReflectionTest, ListFieldsOneOf) { + unittest::TestOneof2 message; + TestUtil::SetOneof1(&message); + + const Reflection* reflection = message.GetReflection(); + vector fields; + reflection->ListFields(message, &fields); + EXPECT_EQ(4, fields.size()); +} + +TEST(GeneratedMessageReflectionTest, Oneof) { + unittest::TestOneof2 message; + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = message.GetReflection(); + + // Check default values. + EXPECT_EQ(0, reflection->GetInt32( + message, descriptor->FindFieldByName("foo_int"))); + EXPECT_EQ("", reflection->GetString( + message, descriptor->FindFieldByName("foo_string"))); + EXPECT_EQ("", reflection->GetString( + message, descriptor->FindFieldByName("foo_cord"))); + EXPECT_EQ("", reflection->GetString( + message, descriptor->FindFieldByName("foo_string_piece"))); + EXPECT_EQ("", reflection->GetString( + message, descriptor->FindFieldByName("foo_bytes"))); + EXPECT_EQ(unittest::TestOneof2::FOO, reflection->GetEnum( + message, descriptor->FindFieldByName("foo_enum"))->number()); + EXPECT_EQ(&unittest::TestOneof2::NestedMessage::default_instance(), + &reflection->GetMessage( + message, descriptor->FindFieldByName("foo_message"))); + EXPECT_EQ(&unittest::TestOneof2::FooGroup::default_instance(), + &reflection->GetMessage( + message, descriptor->FindFieldByName("foogroup"))); + EXPECT_NE(&unittest::TestOneof2::FooGroup::default_instance(), + &reflection->GetMessage( + message, descriptor->FindFieldByName("foo_lazy_message"))); + EXPECT_EQ(5, reflection->GetInt32( + message, descriptor->FindFieldByName("bar_int"))); + EXPECT_EQ("STRING", reflection->GetString( + message, descriptor->FindFieldByName("bar_string"))); + EXPECT_EQ("CORD", reflection->GetString( + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("SPIECE", reflection->GetString( + message, descriptor->FindFieldByName("bar_string_piece"))); + EXPECT_EQ("BYTES", reflection->GetString( + message, descriptor->FindFieldByName("bar_bytes"))); + EXPECT_EQ(unittest::TestOneof2::BAR, reflection->GetEnum( + message, descriptor->FindFieldByName("bar_enum"))->number()); + + // Check Set functions. + reflection->SetInt32( + &message, descriptor->FindFieldByName("foo_int"), 123); + EXPECT_EQ(123, reflection->GetInt32( + message, descriptor->FindFieldByName("foo_int"))); + reflection->SetString( + &message, descriptor->FindFieldByName("foo_string"), "abc"); + EXPECT_EQ("abc", reflection->GetString( + message, descriptor->FindFieldByName("foo_string"))); + reflection->SetString( + &message, descriptor->FindFieldByName("foo_bytes"), "bytes"); + EXPECT_EQ("bytes", reflection->GetString( + message, descriptor->FindFieldByName("foo_bytes"))); + reflection->SetString( + &message, descriptor->FindFieldByName("bar_cord"), "change_cord"); + EXPECT_EQ("change_cord", reflection->GetString( + message, descriptor->FindFieldByName("bar_cord"))); + reflection->SetString( + &message, descriptor->FindFieldByName("bar_string_piece"), + "change_spiece"); + EXPECT_EQ("change_spiece", reflection->GetString( + message, descriptor->FindFieldByName("bar_string_piece"))); +} + +TEST(GeneratedMessageReflectionTest, SetAllocatedOneofMessageTest) { + unittest::TestOneof2 from_message1; + unittest::TestOneof2 from_message2; + unittest::TestOneof2 to_message; + const Descriptor* descriptor = unittest::TestOneof2::descriptor(); + const Reflection* reflection = to_message.GetReflection(); + + Message* released = reflection->ReleaseMessage( + &to_message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_TRUE(released == NULL); + released = reflection->ReleaseMessage( + &to_message, descriptor->FindFieldByName("foo_message")); + EXPECT_TRUE(released == NULL); + + TestUtil::ReflectionTester::SetOneofViaReflection(&from_message1); + TestUtil::ReflectionTester::ExpectOneofSetViaReflection(from_message1); + + TestUtil::ReflectionTester:: + SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message1, &to_message); + const Message& sub_message = reflection->GetMessage( + to_message, descriptor->FindFieldByName("foo_lazy_message")); + released = reflection->ReleaseMessage( + &to_message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_TRUE(released != NULL); + EXPECT_EQ(&sub_message, released); + delete released; + + TestUtil::ReflectionTester::SetOneofViaReflection(&from_message2); + + reflection->MutableMessage( + &from_message2, descriptor->FindFieldByName("foo_message")); + + TestUtil::ReflectionTester:: + SetAllocatedOptionalMessageFieldsToMessageViaReflection( + &from_message2, &to_message); + + const Message& sub_message2 = reflection->GetMessage( + to_message, descriptor->FindFieldByName("foo_message")); + released = reflection->ReleaseMessage( + &to_message, descriptor->FindFieldByName("foo_message")); + EXPECT_TRUE(released != NULL); + EXPECT_EQ(&sub_message2, released); + delete released; +} + TEST(GeneratedMessageReflectionTest, ReleaseMessageTest) { unittest::TestAllTypes message; TestUtil::ReflectionTester reflection_tester( @@ -427,6 +718,26 @@ TEST(GeneratedMessageReflectionTest, ReleaseExtensionMessageTest) { TestUtil::ExpectAllExtensionsSet(message); } +TEST(GeneratedMessageReflectionTest, ReleaseOneofMessageTest) { + unittest::TestOneof2 message; + TestUtil::ReflectionTester::SetOneofViaReflection(&message); + + const Descriptor* descriptor = unittest::TestOneof2::descriptor(); + const Reflection* reflection = message.GetReflection(); + const Message& sub_message = reflection->GetMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + Message* released = reflection->ReleaseMessage( + &message, descriptor->FindFieldByName("foo_lazy_message")); + + EXPECT_TRUE(released != NULL); + EXPECT_EQ(&sub_message, released); + delete released; + + released = reflection->ReleaseMessage( + &message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_TRUE(released == NULL); +} + #ifdef PROTOBUF_HAS_DEATH_TEST TEST(GeneratedMessageReflectionTest, UsageErrors) { diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc index 58d6bce4..c0726a67 100644 --- a/src/google/protobuf/generated_message_util.cc +++ b/src/google/protobuf/generated_message_util.cc @@ -36,6 +36,7 @@ #include + namespace google { namespace protobuf { namespace internal { @@ -48,12 +49,13 @@ double NaN() { } const ::std::string* empty_string_; -ProtobufOnceType empty_string_once_init_; +GOOGLE_PROTOBUF_DECLARE_ONCE(empty_string_once_init_); void InitEmptyString() { - empty_string_ = new std::string; + empty_string_ = new string; } + } // 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 098f3219..b6c0cf92 100644 --- a/src/google/protobuf/generated_message_util.h +++ b/src/google/protobuf/generated_message_util.h @@ -38,14 +38,18 @@ #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__ +#include #include -#include #include + +#include namespace google { + namespace protobuf { namespace internal { + // Annotation for the compiler to emit a deprecation message if a field marked // with option 'deprecated=true' is used in the code, or for other things in // generated code which are deprecated. @@ -60,17 +64,26 @@ namespace internal { LIBPROTOBUF_EXPORT double Infinity(); LIBPROTOBUF_EXPORT double NaN(); +// TODO(jieluo): Change to template. We have tried to use template, +// but it causes net/rpc/python:rpcutil_test fail (the empty string will +// init twice). It may related to swig. Change to template after we +// found the solution. + // Default empty string object. Don't use the pointer directly. Instead, call // GetEmptyString() to get the reference. LIBPROTOBUF_EXPORT extern const ::std::string* empty_string_; LIBPROTOBUF_EXPORT extern ProtobufOnceType empty_string_once_init_; - LIBPROTOBUF_EXPORT void InitEmptyString(); -LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() { - GoogleOnceInit(&empty_string_once_init_, &InitEmptyString); + +LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyStringAlreadyInited() { + assert(empty_string_ != NULL); return *empty_string_; } +LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() { + ::google::protobuf::GoogleOnceInit(&empty_string_once_init_, &InitEmptyString); + return GetEmptyStringAlreadyInited(); +} // Defined in generated_message_reflection.cc -- not actually part of the lite // library. @@ -80,6 +93,19 @@ LIBPROTOBUF_EXPORT inline const ::std::string& GetEmptyString() { // get the declaration from this file. LIBPROTOBUF_EXPORT int StringSpaceUsedExcludingSelf(const string& str); + +// True if IsInitialized() is true for all elements of t. Type is expected +// to be a RepeatedPtrField. It's useful to have this +// helper here to keep the protobuf compiler from ever having to emit loops in +// IsInitialized() methods. We want the C++ compiler to inline this or not +// as it sees fit. +template bool AllAreInitialized(const Type& t) { + for (int i = t.size(); --i >= 0; ) { + if (!t.Get(i).IsInitialized()) return false; + } + return true; +} + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 36add8c3..f6a84533 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -83,6 +83,10 @@ CodedInputStream::~CodedInputStream() { int CodedInputStream::default_recursion_limit_ = 100; +void CodedOutputStream::EnableAliasing(bool enabled) { + aliasing_enabled_ = enabled && output_->AllowsAliasing(); +} + void CodedInputStream::BackUpInputToCurrentPosition() { int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_; if (backup_bytes > 0) { @@ -167,6 +171,11 @@ void CodedInputStream::SetTotalBytesLimit( RecomputeBufferLimits(); } +int CodedInputStream::BytesUntilTotalBytesLimit() const { + if (total_bytes_limit_ == INT_MAX) return -1; + return total_bytes_limit_ - CurrentPosition(); +} + void CodedInputStream::PrintTotalBytesLimitError() { GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too " "big (more than " << total_bytes_limit_ @@ -247,6 +256,14 @@ bool CodedInputStream::ReadStringFallback(string* buffer, int size) { buffer->clear(); } + int closest_limit = min(current_limit_, total_bytes_limit_); + if (closest_limit != INT_MAX) { + int bytes_to_limit = closest_limit - CurrentPosition(); + if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) { + buffer->reserve(size); + } + } + int current_buffer_size; while ((current_buffer_size = BufferSize()) < size) { // Some STL implementations "helpfully" crash on buffer->append(NULL, 0). @@ -313,11 +330,16 @@ inline const uint8* ReadVarint32FromArray(const uint8* buffer, uint32* value) { uint32 b; uint32 result; - b = *(ptr++); result = (b & 0x7F) ; if (!(b & 0x80)) goto done; - b = *(ptr++); result |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; - b = *(ptr++); result |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; - b = *(ptr++); result |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; - b = *(ptr++); result |= b << 28; if (!(b & 0x80)) goto done; + b = *(ptr++); result = b ; if (!(b & 0x80)) goto done; + result -= 0x80; + b = *(ptr++); result += b << 7; if (!(b & 0x80)) goto done; + result -= 0x80 << 7; + b = *(ptr++); result += b << 14; if (!(b & 0x80)) goto done; + result -= 0x80 << 14; + b = *(ptr++); result += b << 21; if (!(b & 0x80)) goto done; + result -= 0x80 << 21; + b = *(ptr++); result += b << 28; if (!(b & 0x80)) goto done; + // "result -= 0x80 << 28" is irrevelant. // If the input is larger than 32 bits, we still need to read it all // and discard the high-order bits. @@ -347,8 +369,8 @@ bool CodedInputStream::ReadVarint32Slow(uint32* value) { bool CodedInputStream::ReadVarint32Fallback(uint32* value) { if (BufferSize() >= kMaxVarintBytes || - // Optimization: If the varint ends at exactly the end of the buffer, - // we can detect that and still use the fast path. + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { const uint8* end = ReadVarint32FromArray(buffer_, value); if (end == NULL) return false; @@ -391,8 +413,8 @@ uint32 CodedInputStream::ReadTagSlow() { uint32 CodedInputStream::ReadTagFallback() { const int buf_size = BufferSize(); if (buf_size >= kMaxVarintBytes || - // Optimization: If the varint ends at exactly the end of the buffer, - // we can detect that and still use the fast path. + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. (buf_size > 0 && !(buffer_end_[-1] & 0x80))) { uint32 tag; const uint8* end = ReadVarint32FromArray(buffer_, &tag); @@ -444,8 +466,8 @@ bool CodedInputStream::ReadVarint64Slow(uint64* value) { bool CodedInputStream::ReadVarint64Fallback(uint64* value) { if (BufferSize() >= kMaxVarintBytes || - // Optimization: If the varint ends at exactly the end of the buffer, - // we can detect that and still use the fast path. + // Optimization: We're also safe if the buffer is non-empty and it ends + // with a byte that would terminate a varint. (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { // Fast path: We have enough bytes left in the buffer to guarantee that // this read won't cross the end, so we can skip the checks. @@ -457,16 +479,26 @@ bool CodedInputStream::ReadVarint64Fallback(uint64* value) { // processors. uint32 part0 = 0, part1 = 0, part2 = 0; - b = *(ptr++); part0 = (b & 0x7F) ; if (!(b & 0x80)) goto done; - b = *(ptr++); part0 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; - b = *(ptr++); part0 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; - b = *(ptr++); part0 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; - b = *(ptr++); part1 = (b & 0x7F) ; if (!(b & 0x80)) goto done; - b = *(ptr++); part1 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; - b = *(ptr++); part1 |= (b & 0x7F) << 14; if (!(b & 0x80)) goto done; - b = *(ptr++); part1 |= (b & 0x7F) << 21; if (!(b & 0x80)) goto done; - b = *(ptr++); part2 = (b & 0x7F) ; if (!(b & 0x80)) goto done; - b = *(ptr++); part2 |= (b & 0x7F) << 7; if (!(b & 0x80)) goto done; + b = *(ptr++); part0 = b ; if (!(b & 0x80)) goto done; + part0 -= 0x80; + b = *(ptr++); part0 += b << 7; if (!(b & 0x80)) goto done; + part0 -= 0x80 << 7; + b = *(ptr++); part0 += b << 14; if (!(b & 0x80)) goto done; + part0 -= 0x80 << 14; + b = *(ptr++); part0 += b << 21; if (!(b & 0x80)) goto done; + part0 -= 0x80 << 21; + b = *(ptr++); part1 = b ; if (!(b & 0x80)) goto done; + part1 -= 0x80; + b = *(ptr++); part1 += b << 7; if (!(b & 0x80)) goto done; + part1 -= 0x80 << 7; + b = *(ptr++); part1 += b << 14; if (!(b & 0x80)) goto done; + part1 -= 0x80 << 14; + b = *(ptr++); part1 += b << 21; if (!(b & 0x80)) goto done; + part1 -= 0x80 << 21; + b = *(ptr++); part2 = b ; if (!(b & 0x80)) goto done; + part2 -= 0x80; + b = *(ptr++); part2 += b << 7; if (!(b & 0x80)) goto done; + // "part2 -= 0x80 << 7" is irrelevant because (0x80 << 7) << 56 is 0. // We have overrun the maximum size of a varint (10 bytes). The data // must be corrupt. @@ -555,7 +587,8 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) buffer_(NULL), buffer_size_(0), total_bytes_(0), - had_error_(false) { + had_error_(false), + aliasing_enabled_(false) { // Eagerly Refresh() so buffer space is immediately available. Refresh(); // The Refresh() may have failed. If the client doesn't write any data, @@ -609,6 +642,23 @@ uint8* CodedOutputStream::WriteRawToArray( } +void CodedOutputStream::WriteAliasedRaw(const void* data, int size) { + if (size < buffer_size_ + ) { + WriteRaw(data, size); + } else { + if (buffer_size_ > 0) { + output_->BackUp(buffer_size_); + total_bytes_ -= buffer_size_; + buffer_ = NULL; + buffer_size_ = 0; + } + + total_bytes_ += size; + had_error_ |= !output_->WriteAliasedRaw(data, size); + } +} + void CodedOutputStream::WriteLittleEndian32(uint32 value) { uint8 bytes[sizeof(value)]; @@ -852,6 +902,13 @@ int CodedOutputStream::VarintSize64(uint64 value) { } } +uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str, + uint8* target) { + GOOGLE_DCHECK_LE(str.size(), kuint32max); + target = WriteVarint32ToArray(str.size(), target); + return WriteStringToArray(str, target); +} + } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/coded_stream.h b/src/google/protobuf/io/coded_stream.h index 66cbee00..50a03a11 100644 --- a/src/google/protobuf/io/coded_stream.h +++ b/src/google/protobuf/io/coded_stream.h @@ -233,11 +233,22 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // Read a tag. This calls ReadVarint32() and returns the result, or returns // zero (which is not a valid tag) if ReadVarint32() fails. Also, it updates // the last tag value, which can be checked with LastTagWas(). - // Always inline because this is only called in once place per parse loop + // Always inline because this is only called in one place per parse loop // but it is called for every iteration of said loop, so it should be fast. // GCC doesn't want to inline this by default. uint32 ReadTag() GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + // This usually a faster alternative to ReadTag() when cutoff is a manifest + // constant. It does particularly well for cutoff >= 127. The first part + // of the return value is the tag that was read, though it can also be 0 in + // the cases where ReadTag() would return 0. If the second part is true + // then the tag is known to be in [0, cutoff]. If not, the tag either is + // above cutoff or is 0. (There's intentional wiggle room when tag is 0, + // because that can arise in several ways, and for best performance we want + // to avoid an extra "is tag == 0?" check here.) + inline std::pair ReadTagWithCutoff(uint32 cutoff) + GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + // Usually returns true if calling ReadVarint32() now would produce the given // value. Will always return false if ReadVarint32() would not return the // given value. If ExpectTag() returns true, it also advances past @@ -264,8 +275,8 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // zero, and ConsumedEntireMessage() will return true. bool ExpectAtEnd(); - // If the last call to ReadTag() returned the given value, returns true. - // Otherwise, returns false; + // If the last call to ReadTag() or ReadTagWithCutoff() returned the + // given value, returns true. Otherwise, returns false; // // This is needed because parsers for some types of embedded messages // (with field type TYPE_GROUP) don't actually know that they've reached the @@ -333,7 +344,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // cause integer overflows is 512MB. The default limit is 64MB. Apps // should set shorter limits if possible. If warning_threshold is not -1, // a warning will be printed to stderr after warning_threshold bytes are - // read. For backwards compatibility all negative values get squached to -1, + // read. For backwards compatibility all negative values get squashed to -1, // as other negative values might have special internal meanings. // An error will always be printed to stderr if the limit is reached. // @@ -356,6 +367,10 @@ class LIBPROTOBUF_EXPORT CodedInputStream { // something unusual. void SetTotalBytesLimit(int total_bytes_limit, int warning_threshold); + // The Total Bytes Limit minus the Current Position, or -1 if there + // is no Total Bytes Limit. + int BytesUntilTotalBytesLimit() const; + // Recursion Limit ------------------------------------------------- // To prevent corrupt or malicious messages from causing stack overflows, // we must keep track of the depth of recursion when parsing embedded @@ -466,7 +481,7 @@ class LIBPROTOBUF_EXPORT CodedInputStream { int overflow_bytes_; // LastTagWas() stuff. - uint32 last_tag_; // result of last ReadTag(). + uint32 last_tag_; // result of last ReadTag() or ReadTagWithCutoff(). // This is set true by ReadTag{Fallback/Slow}() if it is called when exactly // at EOF, or by ExpectAtEnd() when it returns true. This happens when we @@ -638,6 +653,9 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // Write raw bytes, copying them from the given buffer. void WriteRaw(const void* buffer, int size); + // Like WriteRaw() but will try to write aliased data if aliasing is + // turned on. + void WriteRawMaybeAliased(const void* data, int size); // Like WriteRaw() but writing directly to the target array. // This is _not_ inlined, as the compiler often optimizes memcpy into inline // copy loops. Since this gets called by every field with string or bytes @@ -649,8 +667,21 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { void WriteString(const string& str); // Like WriteString() but writing directly to the target array. static uint8* WriteStringToArray(const string& str, uint8* target); + // Write the varint-encoded size of str followed by str. + static uint8* WriteStringWithSizeToArray(const string& str, uint8* target); + // Instructs the CodedOutputStream to allow the underlying + // ZeroCopyOutputStream to hold pointers to the original structure instead of + // copying, if it supports it (i.e. output->AllowsAliasing() is true). If the + // underlying stream does not support aliasing, then enabling it has no + // affect. For now, this only affects the behavior of + // WriteRawMaybeAliased(). + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + void EnableAliasing(bool enabled); + // Write a 32-bit little-endian integer. void WriteLittleEndian32(uint32 value); // Like WriteLittleEndian32() but writing directly to the target array. @@ -725,6 +756,7 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { int buffer_size_; 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(). // Advance the buffer by a given number of bytes. void Advance(int amount); @@ -733,6 +765,10 @@ class LIBPROTOBUF_EXPORT CodedOutputStream { // Advance(buffer_size_). bool Refresh(); + // Like WriteRaw() but may avoid copying if the underlying + // ZeroCopyOutputStream supports it. + void WriteAliasedRaw(const void* buffer, int size); + static uint8* WriteVarint32FallbackToArray(uint32 value, uint8* target); // Always-inlined versions of WriteVarint* functions so that code can be @@ -850,6 +886,45 @@ inline uint32 CodedInputStream::ReadTag() { } } +inline std::pair CodedInputStream::ReadTagWithCutoff( + uint32 cutoff) { + // In performance-sensitive code we can expect cutoff to be a compile-time + // constant, and things like "cutoff >= kMax1ByteVarint" to be evaluated at + // compile time. + if (GOOGLE_PREDICT_TRUE(buffer_ < buffer_end_)) { + // Hot case: buffer_ non_empty, buffer_[0] in [1, 128). + // TODO(gpike): Is it worth rearranging this? E.g., if the number of fields + // is large enough then is it better to check for the two-byte case first? + if (static_cast(buffer_[0]) > 0) { + const uint32 kMax1ByteVarint = 0x7f; + uint32 tag = last_tag_ = buffer_[0]; + Advance(1); + return make_pair(tag, cutoff >= kMax1ByteVarint || tag <= cutoff); + } + // Other hot case: cutoff >= 0x80, buffer_ has at least two bytes available, + // and tag is two bytes. The latter is tested by bitwise-and-not of the + // first byte and the second byte. + if (cutoff >= 0x80 && + GOOGLE_PREDICT_TRUE(buffer_ + 1 < buffer_end_) && + GOOGLE_PREDICT_TRUE((buffer_[0] & ~buffer_[1]) >= 0x80)) { + const uint32 kMax2ByteVarint = (0x7f << 7) + 0x7f; + uint32 tag = last_tag_ = (1u << 7) * buffer_[1] + (buffer_[0] - 0x80); + Advance(2); + // It might make sense to test for tag == 0 now, but it is so rare that + // that we don't bother. A varint-encoded 0 should be one byte unless + // the encoder lost its mind. The second part of the return value of + // this function is allowed to be either true or false if the tag is 0, + // so we don't have to check for tag == 0. We may need to check whether + // it exceeds cutoff. + bool at_or_below_cutoff = cutoff >= kMax2ByteVarint || tag <= cutoff; + return make_pair(tag, at_or_below_cutoff); + } + } + // Slow path + last_tag_ = ReadTagFallback(); + return make_pair(last_tag_, static_cast(last_tag_ - 1) < cutoff); +} + inline bool CodedInputStream::LastTagWas(uint32 expected) { return last_tag_ == expected; } @@ -1029,6 +1104,15 @@ inline void CodedOutputStream::WriteString(const string& str) { WriteRaw(str.data(), static_cast(str.size())); } +inline void CodedOutputStream::WriteRawMaybeAliased( + const void* data, int size) { + if (aliasing_enabled_) { + WriteAliasedRaw(data, size); + } else { + WriteRaw(data, size); + } +} + inline uint8* CodedOutputStream::WriteStringToArray( const string& str, uint8* target) { return WriteRawToArray(str.data(), static_cast(str.size()), target); diff --git a/src/google/protobuf/io/coded_stream_inl.h b/src/google/protobuf/io/coded_stream_inl.h index 144f44f0..41dc10e3 100644 --- a/src/google/protobuf/io/coded_stream_inl.h +++ b/src/google/protobuf/io/coded_stream_inl.h @@ -37,6 +37,7 @@ #define GOOGLE_PROTOBUF_IO_CODED_STREAM_INL_H__ #include +#include #include #include @@ -53,7 +54,7 @@ inline bool CodedInputStream::InternalReadStringInline(string* buffer, // When buffer is empty, string_as_array(buffer) will return NULL but memcpy // requires non-NULL pointers even when size is 0. Hench this check. if (size > 0) { - memcpy(string_as_array(buffer), buffer_, size); + memcpy(mutable_string_data(buffer), buffer_, size); Advance(size); } return true; diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc index 2daab194..b39987ca 100644 --- a/src/google/protobuf/io/coded_stream_unittest.cc +++ b/src/google/protobuf/io/coded_stream_unittest.cc @@ -144,6 +144,10 @@ uint8 CodedStreamTest::buffer_[CodedStreamTest::kBufferSize]; // checks. const int kBlockSizes[] = {1, 2, 3, 5, 7, 13, 32, 1024}; +// In several ReadCord test functions, we either clear the Cord before ReadCord +// calls or not. +const bool kResetCords[] = {false, true}; + // ------------------------------------------------------------------- // Varint tests. @@ -682,6 +686,191 @@ TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnHeap) { EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); } +TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnTotalLimit, kBlockSizes) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + coded_input.SetTotalBytesLimit(sizeof(kRawBytes), sizeof(kRawBytes)); + EXPECT_EQ(sizeof(kRawBytes), coded_input.BytesUntilTotalBytesLimit()); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); + EXPECT_EQ(sizeof(kRawBytes) - strlen(kRawBytes), + coded_input.BytesUntilTotalBytesLimit()); + EXPECT_EQ(kRawBytes, str); + // TODO(liujisi): Replace with a more meaningful test (see cl/60966023). + EXPECT_GE(str.capacity(), strlen(kRawBytes)); + } + + EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); +} + +TEST_1D(CodedStreamTest, ReadStringReservesMemoryOnPushedLimit, kBlockSizes) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + ArrayInputStream input(buffer_, sizeof(buffer_), kBlockSizes_case); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(sizeof(buffer_)); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); + EXPECT_EQ(kRawBytes, str); + // TODO(liujisi): Replace with a more meaningful test (see cl/60966023). + EXPECT_GE(str.capacity(), strlen(kRawBytes)); + } + + EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); +} + +TEST_F(CodedStreamTest, ReadStringNoReservationIfLimitsNotSet) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + + string str; + EXPECT_TRUE(coded_input.ReadString(&str, strlen(kRawBytes))); + EXPECT_EQ(kRawBytes, str); + // Note: this check depends on string class implementation. It + // expects that string will allocate more than strlen(kRawBytes) + // if the content of kRawBytes is appended to string in small + // chunks. + // TODO(liujisi): Replace with a more meaningful test (see cl/60966023). + EXPECT_GE(str.capacity(), strlen(kRawBytes)); + } + + EXPECT_EQ(strlen(kRawBytes), input.ByteCount()); +} + +TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsNegative) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(sizeof(buffer_)); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, -1)); + // Note: this check depends on string class implementation. It + // expects that string will always allocate the same amount of + // memory for an empty string. + EXPECT_EQ(string().capacity(), str.capacity()); + } +} + +TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsLarge) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(sizeof(buffer_)); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30)); + EXPECT_GT(1 << 30, str.capacity()); + } +} + +TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheLimit) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(16); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); + // Note: this check depends on string class implementation. It + // expects that string will allocate less than strlen(kRawBytes) + // for an empty string. + EXPECT_GT(strlen(kRawBytes), str.capacity()); + } +} + +TEST_F(CodedStreamTest, ReadStringNoReservationSizeIsOverTheTotalBytesLimit) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.SetTotalBytesLimit(16, 16); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); + // Note: this check depends on string class implementation. It + // expects that string will allocate less than strlen(kRawBytes) + // for an empty string. + EXPECT_GT(strlen(kRawBytes), str.capacity()); + } +} + +TEST_F(CodedStreamTest, + ReadStringNoReservationSizeIsOverTheClosestLimit_GlobalLimitIsCloser) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(sizeof(buffer_)); + coded_input.SetTotalBytesLimit(16, 16); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); + // Note: this check depends on string class implementation. It + // expects that string will allocate less than strlen(kRawBytes) + // for an empty string. + EXPECT_GT(strlen(kRawBytes), str.capacity()); + } +} + +TEST_F(CodedStreamTest, + ReadStringNoReservationSizeIsOverTheClosestLimit_LocalLimitIsCloser) { + memcpy(buffer_, kRawBytes, sizeof(kRawBytes)); + // Buffer size in the input must be smaller than sizeof(kRawBytes), + // otherwise check against capacity will fail as ReadStringInline() + // will handle the reading and will reserve the memory as needed. + ArrayInputStream input(buffer_, sizeof(buffer_), 32); + + { + CodedInputStream coded_input(&input); + coded_input.PushLimit(16); + coded_input.SetTotalBytesLimit(sizeof(buffer_), sizeof(buffer_)); + EXPECT_EQ(sizeof(buffer_), coded_input.BytesUntilTotalBytesLimit()); + + string str; + EXPECT_FALSE(coded_input.ReadString(&str, strlen(kRawBytes))); + // Note: this check depends on string class implementation. It + // expects that string will allocate less than strlen(kRawBytes) + // for an empty string. + EXPECT_GT(strlen(kRawBytes), str.capacity()); + } +} + // ------------------------------------------------------------------- // Skip @@ -980,9 +1169,11 @@ TEST_F(CodedStreamTest, TotalBytesLimit) { ArrayInputStream input(buffer_, sizeof(buffer_)); CodedInputStream coded_input(&input); coded_input.SetTotalBytesLimit(16, -1); + EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit()); string str; EXPECT_TRUE(coded_input.ReadString(&str, 16)); + EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit()); vector errors; @@ -997,7 +1188,9 @@ TEST_F(CodedStreamTest, TotalBytesLimit) { "A protocol message was rejected because it was too big", errors[0]); coded_input.SetTotalBytesLimit(32, -1); + EXPECT_EQ(16, coded_input.BytesUntilTotalBytesLimit()); EXPECT_TRUE(coded_input.ReadString(&str, 16)); + EXPECT_EQ(0, coded_input.BytesUntilTotalBytesLimit()); } TEST_F(CodedStreamTest, TotalBytesLimitNotValidMessageEnd) { diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h index 365e9ea5..7ee24bc3 100644 --- a/src/google/protobuf/io/gzip_stream.h +++ b/src/google/protobuf/io/gzip_stream.h @@ -118,7 +118,7 @@ class LIBPROTOBUF_EXPORT GzipOutputStream : public ZeroCopyOutputStream { ZLIB = 2, }; - struct LIBPROTOBUF_EXPORT Options { + struct Options { // Defaults to GZIP. Format format; diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc index c9b30359..76fb9442 100644 --- a/src/google/protobuf/io/printer_unittest.cc +++ b/src/google/protobuf/io/printer_unittest.cc @@ -231,7 +231,7 @@ TEST(Printer, Death) { EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name"); EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent"); } -#endif // PROTOBUF__HAS_DEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST TEST(Printer, WriteFailurePartial) { char buffer[17]; diff --git a/src/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc new file mode 100644 index 00000000..cf0c6e10 --- /dev/null +++ b/src/google/protobuf/io/strtod.cc @@ -0,0 +1,113 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace io { + +// ---------------------------------------------------------------------- +// NoLocaleStrtod() +// This code will make you cry. +// ---------------------------------------------------------------------- + +namespace { + +// Returns a string identical to *input except that the character pointed to +// by radix_pos (which should be '.') is replaced with the locale-specific +// radix character. +string LocalizeRadix(const char* input, const char* radix_pos) { + // Determine the locale-specific radix character by calling sprintf() to + // print the number 1.5, then stripping off the digits. As far as I can + // tell, this is the only portable, thread-safe way to get the C library + // to divuldge the locale's radix character. No, localeconv() is NOT + // thread-safe. + char temp[16]; + int size = sprintf(temp, "%.1f", 1.5); + GOOGLE_CHECK_EQ(temp[0], '1'); + GOOGLE_CHECK_EQ(temp[size-1], '5'); + GOOGLE_CHECK_LE(size, 6); + + // Now replace the '.' in the input with it. + string result; + result.reserve(strlen(input) + size - 3); + result.append(input, radix_pos); + result.append(temp + 1, size - 2); + result.append(radix_pos + 1); + return result; +} + +} // namespace + +double NoLocaleStrtod(const char* text, char** original_endptr) { + // We cannot simply set the locale to "C" temporarily with setlocale() + // as this is not thread-safe. Instead, we try to parse in the current + // locale first. If parsing stops at a '.' character, then this is a + // pretty good hint that we're actually in some other locale in which + // '.' is not the radix character. + + char* temp_endptr; + double result = strtod(text, &temp_endptr); + if (original_endptr != NULL) *original_endptr = temp_endptr; + if (*temp_endptr != '.') return result; + + // Parsing halted on a '.'. Perhaps we're in a different locale? Let's + // try to replace the '.' with a locale-specific radix character and + // try again. + string localized = LocalizeRadix(text, temp_endptr); + const char* localized_cstr = localized.c_str(); + char* localized_endptr; + result = strtod(localized_cstr, &localized_endptr); + if ((localized_endptr - localized_cstr) > + (temp_endptr - text)) { + // This attempt got further, so replacing the decimal must have helped. + // Update original_endptr to point at the right location. + if (original_endptr != NULL) { + // size_diff is non-zero if the localized radix has multiple bytes. + int size_diff = localized.size() - strlen(text); + // const_cast is necessary to match the strtod() interface. + *original_endptr = const_cast( + text + (localized_endptr - localized_cstr - size_diff)); + } + } + + return result; +} + +} // namespace io +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/io/strtod.h b/src/google/protobuf/io/strtod.h new file mode 100644 index 00000000..2be3c43d --- /dev/null +++ b/src/google/protobuf/io/strtod.h @@ -0,0 +1,50 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// A locale-independent version of strtod(), used to parse floating +// point default values in .proto files, where the decimal separator +// is always a dot. + +#ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__ +#define GOOGLE_PROTOBUF_IO_STRTOD_H__ + +namespace google { +namespace protobuf { +namespace io { + +// A locale-independent version of the standard strtod(), which always +// uses a dot as the decimal separator. +double NoLocaleStrtod(const char* str, char** endptr); + +} // namespace io +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_IO_STRTOD_H__ diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc index a022b71d..d149305a 100644 --- a/src/google/protobuf/io/tokenizer.cc +++ b/src/google/protobuf/io/tokenizer.cc @@ -91,6 +91,7 @@ #include #include #include +#include #include #include #include @@ -195,7 +196,9 @@ Tokenizer::Tokenizer(ZeroCopyInputStream* input, record_target_(NULL), record_start_(-1), allow_f_after_float_(false), - comment_style_(CPP_COMMENT_STYLE) { + comment_style_(CPP_COMMENT_STYLE), + require_space_after_number_(true), + allow_multiline_strings_(false) { current_.line = 0; current_.column = 0; @@ -350,9 +353,16 @@ void Tokenizer::ConsumeString(char delimiter) { while (true) { switch (current_char_) { case '\0': - case '\n': { - AddError("String literals cannot cross line boundaries."); + AddError("Unexpected end of string."); return; + + case '\n': { + if (!allow_multiline_strings_) { + AddError("String literals cannot cross line boundaries."); + return; + } + NextChar(); + break; } case '\\': { @@ -449,7 +459,7 @@ Tokenizer::TokenType Tokenizer::ConsumeNumber(bool started_with_zero, } } - if (LookingAt()) { + if (LookingAt() && require_space_after_number_) { AddError("Need space between number and identifier."); } else if (current_char_ == '.') { if (is_float) { @@ -618,6 +628,12 @@ bool Tokenizer::Next() { ConsumeString('\''); current_.type = TYPE_STRING; } else { + // Check if the high order bit is set. + if (current_char_ & 0x80) { + error_collector_->AddError(line_, column_, + StringPrintf("Interpreting non ascii codepoint %d.", + static_cast(current_char_))); + } NextChar(); current_.type = TYPE_SYMBOL; } @@ -1086,6 +1102,26 @@ void Tokenizer::ParseStringAppend(const string& text, string* output) { } } +template +static bool AllInClass(const string& s) { + for (int i = 0; i < s.size(); ++i) { + if (!CharacterClass::InClass(s[i])) + return false; + } + return true; +} + +bool Tokenizer::IsIdentifier(const string& text) { + // Mirrors IDENTIFIER definition in Tokenizer::Next() above. + if (text.size() == 0) + return false; + if (!Letter::InClass(text.at(0))) + return false; + if (!AllInClass(text.substr(1))) + return false; + return true; +} + } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h index 6b727d9f..2f07116e 100644 --- a/src/google/protobuf/io/tokenizer.h +++ b/src/google/protobuf/io/tokenizer.h @@ -229,6 +229,21 @@ class LIBPROTOBUF_EXPORT Tokenizer { // Sets the comment style. void set_comment_style(CommentStyle style) { comment_style_ = style; } + // Whether to require whitespace between a number and a field name. + // Default is true. Do not use this; for Google-internal cleanup only. + void set_require_space_after_number(bool require) { + require_space_after_number_ = require; + } + + // Whether to allow string literals to span multiple lines. Default is false. + // Do not use this; for Google-internal cleanup only. + void set_allow_multiline_strings(bool allow) { + allow_multiline_strings_ = allow; + } + + // External helper: validate an identifier. + static bool IsIdentifier(const string& text); + // ----------------------------------------------------------------- private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer); @@ -259,6 +274,8 @@ class LIBPROTOBUF_EXPORT Tokenizer { // Options. bool allow_f_after_float_; CommentStyle comment_style_; + bool require_space_after_number_; + bool allow_multiline_strings_; // Since we count columns we need to interpret tabs somehow. We'll take // the standard 8-character definition for lack of any way to do better. diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc index dbb5be4f..b39279b7 100644 --- a/src/google/protobuf/io/tokenizer_unittest.cc +++ b/src/google/protobuf/io/tokenizer_unittest.cc @@ -411,12 +411,6 @@ MultiTokenCase kMultiTokenCases[] = { { Tokenizer::TYPE_END , "" , 1, 3, 3 }, }}, - // Bytes with the high-order bit set should not be seen as control characters. - { "\300", { - { Tokenizer::TYPE_SYMBOL, "\300", 0, 0, 1 }, - { Tokenizer::TYPE_END , "" , 0, 1, 1 }, - }}, - // Test all whitespace chars { "foo\n\t\r\v\fbar", { { Tokenizer::TYPE_IDENTIFIER, "foo", 0, 0, 3 }, @@ -741,7 +735,7 @@ TEST_F(TokenizerTest, ParseInteger) { EXPECT_EQ(0, ParseInteger("0x")); uint64 i; -#ifdef PROTOBUF_HASDEATH_TEST // death tests do not work on Windows yet +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet // Test invalid integers that will never be tokenized as integers. EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("zxy", kuint64max, &i), "passed text that could not have been tokenized as an integer"); @@ -753,7 +747,7 @@ TEST_F(TokenizerTest, ParseInteger) { "passed text that could not have been tokenized as an integer"); EXPECT_DEBUG_DEATH(Tokenizer::ParseInteger("-1", kuint64max, &i), "passed text that could not have been tokenized as an integer"); -#endif // PROTOBUF_HASDEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST // Test overflows. EXPECT_TRUE (Tokenizer::ParseInteger("0", 0, &i)); @@ -796,7 +790,7 @@ TEST_F(TokenizerTest, ParseFloat) { EXPECT_EQ( 0.0, Tokenizer::ParseFloat("1e-9999999999999999999999999999")); EXPECT_EQ(HUGE_VAL, Tokenizer::ParseFloat("1e+9999999999999999999999999999")); -#ifdef PROTOBUF_HASDEATH_TEST // death tests do not work on Windows yet +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet // Test invalid integers that will never be tokenized as integers. EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("zxy"), "passed text that could not have been tokenized as a float"); @@ -804,7 +798,7 @@ TEST_F(TokenizerTest, ParseFloat) { "passed text that could not have been tokenized as a float"); EXPECT_DEBUG_DEATH(Tokenizer::ParseFloat("-1.0"), "passed text that could not have been tokenized as a float"); -#endif // PROTOBUF_HASDEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST } TEST_F(TokenizerTest, ParseString) { @@ -843,10 +837,10 @@ TEST_F(TokenizerTest, ParseString) { EXPECT_EQ("u0", output); // Test invalid strings that will never be tokenized as strings. -#ifdef PROTOBUF_HASDEATH_TEST // death tests do not work on Windows yet +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet EXPECT_DEBUG_DEATH(Tokenizer::ParseString("", &output), "passed text that could not have been tokenized as a string"); -#endif // PROTOBUF_HASDEATH_TEST +#endif // PROTOBUF_HAS_DEATH_TEST } TEST_F(TokenizerTest, ParseStringAppend) { @@ -883,7 +877,7 @@ ErrorCase kErrorCases[] = { { "'\\x' foo", true, "0:3: Expected hex digits for escape sequence.\n" }, { "'foo", false, - "0:4: String literals cannot cross line boundaries.\n" }, + "0:4: Unexpected end of string.\n" }, { "'bar\nfoo", true, "0:4: String literals cannot cross line boundaries.\n" }, { "'\\u01' foo", true, @@ -951,6 +945,10 @@ ErrorCase kErrorCases[] = { "0:0: Invalid control characters encountered in text.\n" }, { string("\0\0foo", 5), true, "0:0: Invalid control characters encountered in text.\n" }, + + // Check error from high order bits set + { "\300foo", true, + "0:0: Interpreting non ascii codepoint 192.\n" }, }; TEST_2D(TokenizerTest, Errors, kErrorCases, kBlockSizes) { diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc index dad6ff14..4d53f29b 100644 --- a/src/google/protobuf/io/zero_copy_stream.cc +++ b/src/google/protobuf/io/zero_copy_stream.cc @@ -34,6 +34,7 @@ #include +#include namespace google { namespace protobuf { @@ -43,6 +44,14 @@ ZeroCopyInputStream::~ZeroCopyInputStream() {} ZeroCopyOutputStream::~ZeroCopyOutputStream() {} +bool ZeroCopyOutputStream::WriteAliasedRaw(const void* /* data */, + int /* size */) { + GOOGLE_LOG(FATAL) << "This ZeroCopyOutputStream doesn't support aliasing. " + "Reaching here usually means a ZeroCopyOutputStream " + "implementation bug."; + return false; +} + } // namespace io } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/io/zero_copy_stream.h b/src/google/protobuf/io/zero_copy_stream.h index db5326f7..f8921228 100644 --- a/src/google/protobuf/io/zero_copy_stream.h +++ b/src/google/protobuf/io/zero_copy_stream.h @@ -226,6 +226,16 @@ class LIBPROTOBUF_EXPORT ZeroCopyOutputStream { // Returns the total number of bytes written since this object was created. virtual int64 ByteCount() const = 0; + // Write a given chunk of data to the output. Some output streams may + // implement this in a way that avoids copying. Check AllowsAliasing() before + // calling WriteAliasedRaw(). It will GOOGLE_CHECK fail if WriteAliasedRaw() is + // called on a stream that does not allow aliasing. + // + // NOTE: It is caller's responsibility to ensure that the chunk of memory + // remains live until all of the data has been consumed from the stream. + virtual bool WriteAliasedRaw(const void* data, int size); + virtual bool AllowsAliasing() const { return false; } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream); diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc index 9fcbb622..7829a29f 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl.cc @@ -413,7 +413,9 @@ int64 ConcatenatingInputStream::ByteCount() const { LimitingInputStream::LimitingInputStream(ZeroCopyInputStream* input, int64 limit) - : input_(input), limit_(limit) {} + : input_(input), limit_(limit) { + prior_bytes_read_ = input_->ByteCount(); +} LimitingInputStream::~LimitingInputStream() { // If we overshot the limit, back up. @@ -457,9 +459,9 @@ bool LimitingInputStream::Skip(int count) { int64 LimitingInputStream::ByteCount() const { if (limit_ < 0) { - return input_->ByteCount() + limit_; + return input_->ByteCount() + limit_ - prior_bytes_read_; } else { - return input_->ByteCount(); + return input_->ByteCount() - prior_bytes_read_; } } diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h index 9fedb005..83827097 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl.h +++ b/src/google/protobuf/io/zero_copy_stream_impl.h @@ -344,6 +344,7 @@ class LIBPROTOBUF_EXPORT LimitingInputStream : public ZeroCopyInputStream { private: ZeroCopyInputStream* input_; int64 limit_; // Decreases as we go, becomes negative if we overshoot. + int64 prior_bytes_read_; // Bytes read on underlying stream at construction GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream); }; diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc index b3a71ce3..d186a98b 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc @@ -33,10 +33,12 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include -#include -#include #include +#include + +#include +#include namespace google { namespace protobuf { @@ -161,15 +163,23 @@ bool StringOutputStream::Next(void** data, int* size) { // without a memory allocation this way. STLStringResizeUninitialized(target_, target_->capacity()); } else { - // Size has reached capacity, so double the size. Also make sure - // that the new size is at least kMinimumSize. + // Size has reached capacity, try to double the size. + if (old_size > std::numeric_limits::max() / 2) { + // Can not double the size otherwise it is going to cause integer + // overflow in the expression below: old_size * 2 "; + GOOGLE_LOG(ERROR) << "Cannot allocate buffer larger than kint32max for " + << "StringOutputStream."; + return false; + } + // Double the size, also make sure that the new size is at least + // kMinimumSize. STLStringResizeUninitialized( target_, max(old_size * 2, kMinimumSize + 0)); // "+ 0" works around GCC4 weirdness. } - *data = string_as_array(target_) + old_size; + *data = mutable_string_data(target_) + old_size; *size = target_->size() - old_size; return true; } diff --git a/src/google/protobuf/io/zero_copy_stream_impl_lite.h b/src/google/protobuf/io/zero_copy_stream_impl_lite.h index 153f543e..b980143e 100644 --- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h +++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h @@ -48,6 +48,7 @@ #include #include #include +#include namespace google { @@ -333,6 +334,19 @@ class LIBPROTOBUF_EXPORT CopyingOutputStreamAdaptor : public ZeroCopyOutputStrea // =================================================================== +// Return a pointer to mutable characters underlying the given string. The +// return value is valid until the next time the string is resized. We +// trust the caller to treat the return value as an array of length s->size(). +inline char* mutable_string_data(string* s) { +#ifdef LANG_CXX11 + // This should be simpler & faster than string_as_array() because the latter + // is guaranteed to return NULL when *s is empty, so it has to check for that. + return &(*s)[0]; +#else + return string_as_array(s); +#endif +} + } // namespace io } // namespace protobuf diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc index 6f155df7..75eb2a43 100644 --- a/src/google/protobuf/io/zero_copy_stream_unittest.cc +++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc @@ -560,9 +560,10 @@ TEST_F(IoTest, CompressionOptions) { // Some ad-hoc testing of compression options. string golden; - File::ReadFileToStringOrDie( - TestSourceDir() + "/google/protobuf/testdata/golden_message", - &golden); + GOOGLE_CHECK_OK(File::GetContents( + TestSourceDir() + + "/google/protobuf/testdata/golden_message", + &golden, true)); GzipOutputStream::Options options; string gzip_compressed = Compress(golden, options); @@ -923,6 +924,26 @@ TEST_F(IoTest, LimitingInputStream) { ReadStuff(&input); } +// Checks that ByteCount works correctly for LimitingInputStreams where the +// underlying stream has already been read. +TEST_F(IoTest, LimitingInputStreamByteCount) { + const int kHalfBufferSize = 128; + const int kBufferSize = kHalfBufferSize * 2; + uint8 buffer[kBufferSize]; + + // Set up input. Only allow half to be read at once. + ArrayInputStream array_input(buffer, kBufferSize, kHalfBufferSize); + const void* data; + int size; + EXPECT_TRUE(array_input.Next(&data, &size)); + EXPECT_EQ(kHalfBufferSize, array_input.ByteCount()); + // kHalfBufferSize - 1 to test limiting logic as well. + LimitingInputStream input(&array_input, kHalfBufferSize - 1); + EXPECT_EQ(0, input.ByteCount()); + EXPECT_TRUE(input.Next(&data, &size)); + EXPECT_EQ(kHalfBufferSize - 1 , input.ByteCount()); +} + // Check that a zero-size array doesn't confuse the code. TEST(ZeroSizeArray, Input) { ArrayInputStream input(NULL, 0); diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc index 7a0a57b7..6f385bd3 100644 --- a/src/google/protobuf/lite_unittest.cc +++ b/src/google/protobuf/lite_unittest.cc @@ -36,6 +36,10 @@ #include #include #include +#include +#include +#include +#include using namespace std; @@ -57,10 +61,31 @@ void AssignParsingMergeMessages( msg3->set_optional_string("hello"); } +void SetAllTypesInEmptyMessageUnknownFields( + google::protobuf::unittest::TestEmptyMessageLite* empty_message) { + protobuf_unittest::TestAllTypesLite message; + google::protobuf::TestUtilLite::ExpectClear(message); + google::protobuf::TestUtilLite::SetAllFields(&message); + string data = message.SerializeAsString(); + empty_message->ParseFromString(data); +} + +void SetSomeTypesInEmptyMessageUnknownFields( + google::protobuf::unittest::TestEmptyMessageLite* empty_message) { + protobuf_unittest::TestAllTypesLite message; + google::protobuf::TestUtilLite::ExpectClear(message); + message.set_optional_int32(101); + message.set_optional_int64(102); + message.set_optional_uint32(103); + message.set_optional_uint64(104); + string data = message.SerializeAsString(); + empty_message->ParseFromString(data); +} + } // namespace int main(int argc, char* argv[]) { - string data, packed_data; + string data, data2, packed_data; { protobuf_unittest::TestAllTypesLite message, message2, message3; @@ -84,7 +109,6 @@ int main(int argc, char* argv[]) { google::protobuf::TestUtilLite::SetAllExtensions(&message); message2.CopyFrom(message); string extensions_data = message.SerializeAsString(); - GOOGLE_CHECK(extensions_data == data); message3.ParseFromString(extensions_data); google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message); google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2); @@ -180,6 +204,147 @@ int main(int argc, char* argv[]) { google::protobuf::unittest::TestParsingMergeLite::repeated_ext) == 3); } + // Test unknown fields support for lite messages. + { + protobuf_unittest::TestAllTypesLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message; + google::protobuf::TestUtilLite::ExpectClear(message); + google::protobuf::TestUtilLite::SetAllFields(&message); + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data.clear(); + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + data = message2.SerializeAsString(); + google::protobuf::TestUtilLite::ExpectAllFieldsSet(message2); + message.Clear(); + google::protobuf::TestUtilLite::ExpectClear(message); + } + + { + protobuf_unittest::TestAllExtensionsLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message; + google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + google::protobuf::TestUtilLite::SetAllExtensions(&message); + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data.clear(); + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + data = message2.SerializeAsString(); + google::protobuf::TestUtilLite::ExpectAllExtensionsSet(message2); + message.Clear(); + google::protobuf::TestUtilLite::ExpectExtensionsClear(message); + } + + { + protobuf_unittest::TestPackedTypesLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message; + google::protobuf::TestUtilLite::ExpectPackedClear(message); + google::protobuf::TestUtilLite::SetPackedFields(&message); + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data.clear(); + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + data = message2.SerializeAsString(); + google::protobuf::TestUtilLite::ExpectPackedFieldsSet(message2); + message.Clear(); + google::protobuf::TestUtilLite::ExpectPackedClear(message); + } + + { + protobuf_unittest::TestPackedExtensionsLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message; + google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + google::protobuf::TestUtilLite::SetPackedExtensions(&message); + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data.clear(); + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + data = message2.SerializeAsString(); + google::protobuf::TestUtilLite::ExpectPackedExtensionsSet(message2); + message.Clear(); + google::protobuf::TestUtilLite::ExpectPackedExtensionsClear(message); + } + + { + // Test Unknown fields swap + protobuf_unittest::TestEmptyMessageLite empty_message, empty_message2; + SetAllTypesInEmptyMessageUnknownFields(&empty_message); + SetSomeTypesInEmptyMessageUnknownFields(&empty_message2); + data = empty_message.SerializeAsString(); + data2 = empty_message2.SerializeAsString(); + empty_message.Swap(&empty_message2); + GOOGLE_CHECK_EQ(data, empty_message2.SerializeAsString()); + GOOGLE_CHECK_EQ(data2, empty_message.SerializeAsString()); + } + + { + // Test unknown fields swap with self + protobuf_unittest::TestEmptyMessageLite empty_message; + SetAllTypesInEmptyMessageUnknownFields(&empty_message); + data = empty_message.SerializeAsString(); + empty_message.Swap(&empty_message); + GOOGLE_CHECK_EQ(data, empty_message.SerializeAsString()); + } + + { + // Test MergeFrom with unknown fields + protobuf_unittest::TestAllTypesLite message, message2; + protobuf_unittest::TestEmptyMessageLite empty_message, empty_message2; + message.set_optional_int32(101); + message.add_repeated_int32(201); + message.set_optional_nested_enum(google::protobuf::unittest::TestAllTypesLite::BAZ); + message2.set_optional_int64(102); + message2.add_repeated_int64(202); + message2.set_optional_foreign_enum(google::protobuf::unittest::FOREIGN_LITE_BAZ); + + data = message.SerializeAsString(); + empty_message.ParseFromString(data); + data = message2.SerializeAsString(); + empty_message2.ParseFromString(data); + message.MergeFrom(message2); + empty_message.MergeFrom(empty_message2); + + data = empty_message.SerializeAsString(); + message2.ParseFromString(data); + // We do not compare the serialized output of a normal message and a lite + // message because the order of fields do not match. We convert lite message + // back into normal message, then compare. + GOOGLE_CHECK_EQ(message.SerializeAsString(), message2.SerializeAsString()); + } + + { + // Test unknown enum value + protobuf_unittest::TestAllTypesLite message; + string buffer; + { + google::protobuf::io::StringOutputStream output_stream(&buffer); + google::protobuf::io::CodedOutputStream coded_output(&output_stream); + google::protobuf::internal::WireFormatLite::WriteTag( + protobuf_unittest::TestAllTypesLite::kOptionalNestedEnumFieldNumber, + google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT, &coded_output); + coded_output.WriteVarint32(10); + google::protobuf::internal::WireFormatLite::WriteTag( + protobuf_unittest::TestAllTypesLite::kRepeatedNestedEnumFieldNumber, + google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT, &coded_output); + coded_output.WriteVarint32(20); + } + message.ParseFromString(buffer); + data = message.SerializeAsString(); + GOOGLE_CHECK_EQ(data, buffer); + } + + { + // Test Clear with unknown fields + protobuf_unittest::TestEmptyMessageLite empty_message; + SetAllTypesInEmptyMessageUnknownFields(&empty_message); + empty_message.Clear(); + GOOGLE_CHECK_EQ(0, empty_message.unknown_fields().size()); + } + cout << "PASS" << endl; return 0; } diff --git a/src/google/protobuf/message.cc b/src/google/protobuf/message.cc index 0c305d56..e838d30c 100644 --- a/src/google/protobuf/message.cc +++ b/src/google/protobuf/message.cc @@ -32,7 +32,6 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. -#include #include #include @@ -48,7 +47,7 @@ #include #include #include -#include +#include #include namespace google { @@ -75,7 +74,7 @@ void Message::CheckTypeAndMergeFrom(const MessageLite& other) { void Message::CopyFrom(const Message& from) { const Descriptor* descriptor = GetDescriptor(); GOOGLE_CHECK_EQ(from.GetDescriptor(), descriptor) - << ": Tried to copy from a message with a different type." + << ": Tried to copy from a message with a different type. " "to: " << descriptor->full_name() << ", " "from:" << from.GetDescriptor()->full_name(); ReflectionOps::Copy(from, this); @@ -100,7 +99,7 @@ void Message::FindInitializationErrors(vector* errors) const { string Message::InitializationErrorString() const { vector errors; FindInitializationErrors(&errors); - return JoinStrings(errors, ", "); + return Join(errors, ", "); } void Message::CheckInitialized() const { @@ -216,8 +215,7 @@ HANDLE_TYPE(bool, FieldDescriptor::CPPTYPE_BOOL, -1); #undef HANDLE_TYPE void* Reflection::MutableRawRepeatedString( - Message* message, const FieldDescriptor* field, - bool /* is_string */) const { + Message* message, const FieldDescriptor* field, bool is_string) const { return MutableRawRepeatedField(message, field, FieldDescriptor::CPPTYPE_STRING, FieldOptions::STRING, NULL); } diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h index 0f90bc1a..34a8dd1d 100644 --- a/src/google/protobuf/message.h +++ b/src/google/protobuf/message.h @@ -110,15 +110,9 @@ #ifndef GOOGLE_PROTOBUF_MESSAGE_H__ #define GOOGLE_PROTOBUF_MESSAGE_H__ -#include -#include - -#ifdef __DECCXX -// HP C++'s iosfwd doesn't work. -#include -#else #include -#endif +#include +#include #include @@ -126,6 +120,8 @@ #include +#define GOOGLE_PROTOBUF_HAS_ONEOF + namespace google { namespace protobuf { @@ -184,9 +180,10 @@ class LIBPROTOBUF_EXPORT Message : public MessageLite { virtual void CopyFrom(const Message& from); // Merge the fields from the given message into this message. Singular - // fields will be overwritten, except for embedded messages which will - // be merged. Repeated fields will be concatenated. The given message - // must be of the same type as this message (i.e. the exact same class). + // fields will be overwritten, if specified in from, except for embedded + // messages which will be merged. Repeated fields will be concatenated. + // The given message must be of the same type as this message (i.e. the + // exact same class). virtual void MergeFrom(const Message& from); // Verifies that IsInitialized() returns true. GOOGLE_CHECK-fails otherwise, with @@ -388,6 +385,26 @@ class LIBPROTOBUF_EXPORT Reflection { virtual void ClearField(Message* message, const FieldDescriptor* field) const = 0; + // Check if the oneof is set. Returns ture if any field in oneof + // is set, false otherwise. + // TODO(jieluo) - make it pure virtual after updating all + // the subclasses. + virtual bool HasOneof(const Message& message, + const OneofDescriptor* oneof_descriptor) const { + return false; + } + + virtual void ClearOneof(Message* message, + const OneofDescriptor* oneof_descriptor) const {} + + // Returns the field descriptor if the oneof is set. NULL otherwise. + // TODO(jieluo) - make it pure virtual. + virtual const FieldDescriptor* GetOneofFieldDescriptor( + const Message& message, + const OneofDescriptor* oneof_descriptor) const { + return NULL; + } + // Removes the last element of a repeated field. // We don't provide a way to remove any element other than the last // because it invites inefficient use, such as O(n^2) filtering loops @@ -405,11 +422,17 @@ class LIBPROTOBUF_EXPORT Reflection { // Swap the complete contents of two messages. virtual void Swap(Message* message1, Message* message2) const = 0; + // Swap fields listed in fields vector of two messages. + virtual void SwapFields(Message* message1, + Message* message2, + const vector& fields) + const = 0; + // Swap two elements of a repeated field. virtual void SwapElements(Message* message, - const FieldDescriptor* field, - int index1, - int index2) const = 0; + const FieldDescriptor* field, + int index1, + int index2) const = 0; // List all fields of the message which are currently set. This includes // extensions. Singular fields will only be listed if HasField(field) would @@ -502,6 +525,13 @@ class LIBPROTOBUF_EXPORT Reflection { virtual Message* MutableMessage(Message* message, const FieldDescriptor* field, MessageFactory* factory = NULL) const = 0; + // Replaces the message specified by 'field' with the already-allocated object + // sub_message, passing ownership to the message. If the field contained a + // message, that message is deleted. If sub_message is NULL, the field is + // cleared. + virtual void SetAllocatedMessage(Message* message, + Message* sub_message, + const FieldDescriptor* field) const = 0; // Releases the message specified by 'field' and returns the pointer, // ReleaseMessage() will return the message the message object if it exists. // Otherwise, it may or may not return NULL. In any case, if the return value @@ -699,7 +729,7 @@ class LIBPROTOBUF_EXPORT MessageFactory { // Calling this method twice with the same Descriptor returns the same // object. The returned object remains property of the factory. Also, any // objects created by calling the prototype's New() method share some data - // with the prototype, so these must be destoyed before the MessageFactory + // with the prototype, so these must be destroyed before the MessageFactory // is destroyed. // // The given descriptor must outlive the returned message, and hence must @@ -757,7 +787,6 @@ const RepeatedField& Reflection::GetRepeatedField( \ const Message& message, const FieldDescriptor* field) const; \ \ template<> \ -LIBPROTOBUF_EXPORT \ RepeatedField* Reflection::MutableRepeatedField( \ Message* message, const FieldDescriptor* field) const; diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc index 49dbe6e0..af6b301a 100644 --- a/src/google/protobuf/message_lite.cc +++ b/src/google/protobuf/message_lite.cc @@ -278,7 +278,8 @@ bool MessageLite::AppendPartialToString(string* output) const { int old_size = output->size(); int byte_size = ByteSize(); STLStringResizeUninitialized(output, old_size + byte_size); - uint8* start = reinterpret_cast(string_as_array(output) + old_size); + uint8* start = + reinterpret_cast(io::mutable_string_data(output) + old_size); uint8* end = SerializeWithCachedSizesToArray(start); if (end - start != byte_size) { ByteSizeConsistencyError(byte_size, ByteSize(), end - start); diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h index 1ec3068c..a976e5a2 100644 --- a/src/google/protobuf/message_lite.h +++ b/src/google/protobuf/message_lite.h @@ -109,7 +109,8 @@ class LIBPROTOBUF_EXPORT MessageLite { // Parsing --------------------------------------------------------- // Methods for parsing in protocol buffer format. Most of these are - // just simple wrappers around MergeFromCodedStream(). + // just simple wrappers around MergeFromCodedStream(). Clear() will be called + // before merging the input. // Fill the message with a protocol buffer parsed from the given input // stream. Returns false on a read error or if the input is in the diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc index a1449c76..8b6fd6fd 100644 --- a/src/google/protobuf/message_unittest.cc +++ b/src/google/protobuf/message_unittest.cc @@ -45,7 +45,6 @@ #include #include -#include #include #include #include @@ -53,6 +52,7 @@ #include #include +#include #include #include @@ -205,7 +205,7 @@ TEST(MessageTest, InitializationErrorString) { EXPECT_EQ("a, b, c", message.InitializationErrorString()); } -#ifdef PROTOBUF_HAS_DEATH_TEST +#ifdef PROTOBUF_HAS_DEATH_TEST // death tests do not work on Windows yet. TEST(MessageTest, SerializeFailsIfNotInitialized) { unittest::TestRequired message; @@ -222,6 +222,24 @@ TEST(MessageTest, CheckInitialized) { "fields: a, b, c"); } +TEST(MessageTest, CheckOverflow) { + unittest::TestAllTypes message; + // Create a message with size just over 2GB. This triggers integer overflow + // when computing message size. + const string data(1024, 'x'); + Cord one_megabyte; + for (int i = 0; i < 1024; i++) { + one_megabyte.Append(data); + } + + for (int i = 0; i < 2 * 1024 + 1; ++i) { + message.add_repeated_cord()->CopyFrom(one_megabyte); + } + + Cord serialized; + EXPECT_FALSE(message.AppendToCord(&serialized)); +} + #endif // PROTOBUF_HAS_DEATH_TEST TEST(MessageTest, BypassInitializationCheckOnSerialize) { @@ -329,6 +347,61 @@ TEST(MessageTest, ParsingMerge) { unittest::TestParsingMerge::repeated_ext)); } +TEST(MessageTest, MergeFrom) { + unittest::TestAllTypes source; + unittest::TestAllTypes dest; + + // Optional fields + source.set_optional_int32(1); // only source + source.set_optional_int64(2); // both source and dest + dest.set_optional_int64(3); + dest.set_optional_uint32(4); // only dest + + // Optional fields with defaults + source.set_default_int32(13); // only source + source.set_default_int64(14); // both source and dest + dest.set_default_int64(15); + dest.set_default_uint32(16); // only dest + + // Repeated fields + source.add_repeated_int32(5); // only source + source.add_repeated_int32(6); + source.add_repeated_int64(7); // both source and dest + source.add_repeated_int64(8); + dest.add_repeated_int64(9); + dest.add_repeated_int64(10); + dest.add_repeated_uint32(11); // only dest + dest.add_repeated_uint32(12); + + dest.MergeFrom(source); + + // Optional fields: source overwrites dest if source is specified + EXPECT_EQ(1, dest.optional_int32()); // only source: use source + EXPECT_EQ(2, dest.optional_int64()); // source and dest: use source + EXPECT_EQ(4, dest.optional_uint32()); // only dest: use dest + EXPECT_EQ(0, dest.optional_uint64()); // neither: use default + + // Optional fields with defaults + EXPECT_EQ(13, dest.default_int32()); // only source: use source + EXPECT_EQ(14, dest.default_int64()); // source and dest: use source + EXPECT_EQ(16, dest.default_uint32()); // only dest: use dest + EXPECT_EQ(44, dest.default_uint64()); // neither: use default + + // Repeated fields: concatenate source onto the end of dest + ASSERT_EQ(2, dest.repeated_int32_size()); + EXPECT_EQ(5, dest.repeated_int32(0)); + EXPECT_EQ(6, dest.repeated_int32(1)); + ASSERT_EQ(4, dest.repeated_int64_size()); + EXPECT_EQ(9, dest.repeated_int64(0)); + EXPECT_EQ(10, dest.repeated_int64(1)); + EXPECT_EQ(7, dest.repeated_int64(2)); + EXPECT_EQ(8, dest.repeated_int64(3)); + ASSERT_EQ(2, dest.repeated_uint32_size()); + EXPECT_EQ(11, dest.repeated_uint32(0)); + EXPECT_EQ(12, dest.repeated_uint32(1)); + ASSERT_EQ(0, dest.repeated_uint64_size()); +} + TEST(MessageFactoryTest, GeneratedFactoryLookup) { EXPECT_EQ( MessageFactory::generated_factory()->GetPrototype( diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc index f00997c6..8993a24d 100644 --- a/src/google/protobuf/reflection_ops.cc +++ b/src/google/protobuf/reflection_ops.cc @@ -56,7 +56,9 @@ void ReflectionOps::Merge(const Message& from, Message* to) { const Descriptor* descriptor = from.GetDescriptor(); GOOGLE_CHECK_EQ(to->GetDescriptor(), descriptor) - << "Tried to merge messages of different types."; + << "Tried to merge messages of different types " + << "(merge " << descriptor->full_name() + << " to " << to->GetDescriptor()->full_name() << ")"; const Reflection* from_reflection = from.GetReflection(); const Reflection* to_reflection = to->GetReflection(); diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc index 29229b5a..898c20c0 100644 --- a/src/google/protobuf/reflection_ops_unittest.cc +++ b/src/google/protobuf/reflection_ops_unittest.cc @@ -78,6 +78,18 @@ TEST(ReflectionOpsTest, CopyExtensions) { TestUtil::ExpectAllExtensionsSet(message2); } +TEST(ReflectionOpsTest, CopyOneof) { + unittest::TestOneof2 message, message2; + TestUtil::SetOneof1(&message); + ReflectionOps::Copy(message, &message2); + TestUtil::ExpectOneofSet1(message2); + + TestUtil::SetOneof2(&message); + TestUtil::ExpectOneofSet2(message); + ReflectionOps::Copy(message, &message2); + TestUtil::ExpectOneofSet2(message2); +} + TEST(ReflectionOpsTest, Merge) { // Note: Copy is implemented in terms of Merge() so technically the Copy // test already tested most of this. @@ -152,6 +164,24 @@ TEST(ReflectionOpsTest, MergeUnknown) { EXPECT_EQ(2, message1.unknown_fields().field(1).varint()); } +TEST(ReflectionOpsTest, MergeOneof) { + unittest::TestOneof2 message1, message2; + TestUtil::SetOneof1(&message1); + + // Merge to empty message + ReflectionOps::Merge(message1, &message2); + TestUtil::ExpectOneofSet1(message2); + + // Merge with the same oneof fields + ReflectionOps::Merge(message1, &message2); + TestUtil::ExpectOneofSet1(message2); + + // Merge with different oneof fields + TestUtil::SetOneof2(&message1); + ReflectionOps::Merge(message1, &message2); + TestUtil::ExpectOneofSet2(message2); +} + #ifdef PROTOBUF_HAS_DEATH_TEST TEST(ReflectionOpsTest, MergeFromSelf) { @@ -220,6 +250,23 @@ TEST(ReflectionOpsTest, ClearUnknown) { EXPECT_EQ(0, message.unknown_fields().field_count()); } +TEST(ReflectionOpsTest, ClearOneof) { + unittest::TestOneof2 message; + + TestUtil::ExpectOneofClear(message); + TestUtil::SetOneof1(&message); + TestUtil::ExpectOneofSet1(message); + ReflectionOps::Clear(&message); + TestUtil::ExpectOneofClear(message); + + TestUtil::SetOneof1(&message); + TestUtil::ExpectOneofSet1(message); + TestUtil::SetOneof2(&message); + TestUtil::ExpectOneofSet2(message); + ReflectionOps::Clear(&message); + TestUtil::ExpectOneofClear(message); +} + TEST(ReflectionOpsTest, DiscardUnknownFields) { unittest::TestAllTypes message; TestUtil::SetAllFields(&message); @@ -354,10 +401,26 @@ TEST(ReflectionOpsTest, ExtensionIsInitialized) { EXPECT_TRUE(ReflectionOps::IsInitialized(message)); } +TEST(ReflectionOpsTest, OneofIsInitialized) { + unittest::TestRequiredOneof message; + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + + message.mutable_foo_message(); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + + message.set_foo_int(1); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); + + message.mutable_foo_message(); + EXPECT_FALSE(ReflectionOps::IsInitialized(message)); + message.mutable_foo_message()->set_required_double(0.1); + EXPECT_TRUE(ReflectionOps::IsInitialized(message)); +} + static string FindInitializationErrors(const Message& message) { vector errors; ReflectionOps::FindInitializationErrors(message, "", &errors); - return JoinStrings(errors, ","); + return Join(errors, ","); } TEST(ReflectionOpsTest, FindInitializationErrors) { @@ -399,6 +462,13 @@ TEST(ReflectionOpsTest, FindExtensionInitializationErrors) { FindInitializationErrors(message)); } +TEST(ReflectionOpsTest, FindOneofInitializationErrors) { + unittest::TestRequiredOneof message; + message.mutable_foo_message(); + EXPECT_EQ("foo_message.required_double", + FindInitializationErrors(message)); +} + } // namespace } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h index ff5d1f4b..1e9728ac 100644 --- a/src/google/protobuf/repeated_field.h +++ b/src/google/protobuf/repeated_field.h @@ -46,7 +46,6 @@ #ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__ #define GOOGLE_PROTOBUF_REPEATED_FIELD_H__ -#include #include #include #include @@ -72,6 +71,22 @@ static const int kMinRepeatedFieldAllocationSize = 4; // A utility function for logging that doesn't need any template types. void LogIndexOutOfBounds(int index, int size); + +template +inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) { + return std::distance(begin, end); +} + +template +inline int CalculateReserve(Iter begin, Iter end, std::input_iterator_tag) { + return -1; +} + +template +inline int CalculateReserve(Iter begin, Iter end) { + typedef typename std::iterator_traits::iterator_category Category; + return CalculateReserve(begin, end, Category()); +} } // namespace internal @@ -90,6 +105,7 @@ class RepeatedField { RepeatedField& operator=(const RepeatedField& other); + bool empty() const; int size() const; const Element& Get(int index) const; @@ -121,6 +137,11 @@ class RepeatedField { Element* AddAlreadyReserved(); int Capacity() const; + // Like STL resize. Uses value to fill appended elements. + // Like Truncate() if new_size <= size(), otherwise this is + // O(new_size - size()). + void Resize(int new_size, const Element& value); + // Gets the underlying array. This pointer is possibly invalidated by // any add or remove operation. Element* mutable_data(); @@ -245,6 +266,7 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { template void Destroy(); + bool empty() const; int size() const; template @@ -309,8 +331,6 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { typename TypeHandler::Type* ReleaseCleared(); private: - GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); - static const int kInitialSize = 0; void** elements_; @@ -326,6 +346,8 @@ class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { static inline const typename TypeHandler::Type* cast(const void* element) { return reinterpret_cast(element); } + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); }; template @@ -410,6 +432,7 @@ class RepeatedPtrField : public internal::RepeatedPtrFieldBase { RepeatedPtrField& operator=(const RepeatedPtrField& other); + bool empty() const; int size() const; const Element& Get(int index) const; @@ -568,8 +591,16 @@ inline RepeatedField::RepeatedField(Iter begin, const Iter& end) : elements_(NULL), current_size_(0), total_size_(kInitialSize) { - for (; begin != end; ++begin) { - Add(*begin); + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + Reserve(reserve); + for (; begin != end; ++begin) { + AddAlreadyReserved(*begin); + } + } else { + for (; begin != end; ++begin) { + Add(*begin); + } } } @@ -586,6 +617,11 @@ RepeatedField::operator=(const RepeatedField& other) { return *this; } +template +inline bool RepeatedField::empty() const { + return current_size_ == 0; +} + template inline int RepeatedField::size() const { return current_size_; @@ -608,20 +644,33 @@ inline Element* RepeatedField::AddAlreadyReserved() { return &elements_[current_size_++]; } +template +inline void RepeatedField::Resize(int new_size, const Element& value) { + GOOGLE_DCHECK_GE(new_size, 0); + if (new_size > size()) { + Reserve(new_size); + std::fill(&elements_[current_size_], &elements_[new_size], value); + } + current_size_ = new_size; +} + template inline const Element& RepeatedField::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return elements_[index]; } template inline Element* RepeatedField::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return elements_ + index; } template inline void RepeatedField::Set(int index, const Element& value) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); elements_[index] = value; } @@ -672,6 +721,7 @@ inline void RepeatedField::Clear() { template inline void RepeatedField::MergeFrom(const RepeatedField& other) { + GOOGLE_CHECK_NE(&other, this); if (other.current_size_ != 0) { Reserve(current_size_ + other.current_size_); CopyArray(elements_ + current_size_, other.elements_, other.current_size_); @@ -681,6 +731,7 @@ inline void RepeatedField::MergeFrom(const RepeatedField& other) { template inline void RepeatedField::CopyFrom(const RepeatedField& other) { + if (&other == this) return; Clear(); MergeFrom(other); } @@ -714,7 +765,8 @@ void RepeatedField::Swap(RepeatedField* other) { template void RepeatedField::SwapElements(int index1, int index2) { - std::swap(elements_[index1], elements_[index2]); + using std::swap; // enable ADL with fallback + swap(elements_[index1], elements_[index2]); } template @@ -814,6 +866,10 @@ void RepeatedPtrFieldBase::Destroy() { delete [] elements_; } +inline bool RepeatedPtrFieldBase::empty() const { + return current_size_ == 0; +} + inline int RepeatedPtrFieldBase::size() const { return current_size_; } @@ -821,6 +877,7 @@ inline int RepeatedPtrFieldBase::size() const { template inline const typename TypeHandler::Type& RepeatedPtrFieldBase::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return *cast(elements_[index]); } @@ -829,6 +886,7 @@ RepeatedPtrFieldBase::Get(int index) const { template inline typename TypeHandler::Type* RepeatedPtrFieldBase::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); GOOGLE_DCHECK_LT(index, size()); return cast(elements_[index]); } @@ -861,6 +919,7 @@ void RepeatedPtrFieldBase::Clear() { template inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { + GOOGLE_CHECK_NE(&other, this); Reserve(current_size_ + other.current_size_); for (int i = 0; i < other.current_size_; i++) { TypeHandler::Merge(other.template Get(i), Add()); @@ -869,6 +928,7 @@ inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { template inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) { + if (&other == this) return; RepeatedPtrFieldBase::Clear(); RepeatedPtrFieldBase::MergeFrom(other); } @@ -901,7 +961,8 @@ RepeatedPtrFieldBase::data() const { } inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) { - std::swap(elements_[index1], elements_[index2]); + using std::swap; // enable ADL with fallback + swap(elements_[index1], elements_[index2]); } template @@ -1001,7 +1062,8 @@ inline RepeatedPtrField::RepeatedPtrField() {} template inline RepeatedPtrField::RepeatedPtrField( - const RepeatedPtrField& other) { + const RepeatedPtrField& other) + : RepeatedPtrFieldBase() { CopyFrom(other); } @@ -1009,6 +1071,10 @@ template template inline RepeatedPtrField::RepeatedPtrField( Iter begin, const Iter& end) { + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + Reserve(reserve); + } for (; begin != end; ++begin) { *Add() = *begin; } @@ -1027,6 +1093,11 @@ inline RepeatedPtrField& RepeatedPtrField::operator=( return *this; } +template +inline bool RepeatedPtrField::empty() const { + return RepeatedPtrFieldBase::empty(); +} + template inline int RepeatedPtrField::size() const { return RepeatedPtrFieldBase::size(); @@ -1182,6 +1253,10 @@ class RepeatedPtrIterator typedef std::iterator< std::random_access_iterator_tag, Element> superclass; + // Shadow the value_type in std::iterator<> because const_iterator::value_type + // needs to be T, not const T. + typedef typename remove_const::type value_type; + // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. typedef typename superclass::reference reference; @@ -1273,6 +1348,10 @@ class RepeatedPtrOverPtrsIterator typedef std::iterator< std::random_access_iterator_tag, Element*> superclass; + // Shadow the value_type in std::iterator<> because const_iterator::value_type + // needs to be T, not const T. + typedef typename remove_const::type value_type; + // Let the compiler know that these are type names, so we don't have to // write "typename" in front of them everywhere. typedef typename superclass::reference reference; diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc index 257701eb..334fdfc2 100644 --- a/src/google/protobuf/repeated_field_unittest.cc +++ b/src/google/protobuf/repeated_field_unittest.cc @@ -59,32 +59,38 @@ namespace { TEST(RepeatedField, Small) { RepeatedField field; + EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); field.Add(5); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), 5); field.Add(42); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), 5); EXPECT_EQ(field.Get(1), 42); field.Set(1, 23); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), 5); EXPECT_EQ(field.Get(1), 23); field.RemoveLast(); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), 5); field.Clear(); + EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); int expected_usage = 4 * sizeof(int); EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage); @@ -100,6 +106,7 @@ TEST(RepeatedField, Large) { field.Add(i * i); } + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 16); for (int i = 0; i < 16; i++) { @@ -118,9 +125,20 @@ TEST(RepeatedField, SwapSmallSmall) { field1.Add(5); field1.Add(42); + EXPECT_FALSE(field1.empty()); + EXPECT_EQ(field1.size(), 2); + EXPECT_EQ(field1.Get(0), 5); + EXPECT_EQ(field1.Get(1), 42); + + EXPECT_TRUE(field2.empty()); + EXPECT_EQ(field2.size(), 0); + field1.Swap(&field2); + EXPECT_TRUE(field1.empty()); EXPECT_EQ(field1.size(), 0); + + EXPECT_FALSE(field2.empty()); EXPECT_EQ(field2.size(), 2); EXPECT_EQ(field2.Get(0), 5); EXPECT_EQ(field2.Get(1), 42); @@ -212,6 +230,22 @@ TEST(RepeatedField, ReserveLessThanExisting) { EXPECT_EQ(20, ReservedSpace(&field)); } +TEST(RepeatedField, Resize) { + RepeatedField field; + field.Resize(2, 1); + EXPECT_EQ(2, field.size()); + field.Resize(5, 2); + EXPECT_EQ(5, field.size()); + field.Resize(4, 3); + ASSERT_EQ(4, field.size()); + EXPECT_EQ(1, field.Get(0)); + EXPECT_EQ(1, field.Get(1)); + EXPECT_EQ(2, field.Get(2)); + EXPECT_EQ(2, field.Get(3)); + field.Resize(0, 4); + EXPECT_TRUE(field.empty()); +} + TEST(RepeatedField, MergeFrom) { RepeatedField source, destination; source.Add(4); @@ -230,6 +264,14 @@ TEST(RepeatedField, MergeFrom) { EXPECT_EQ(5, destination.Get(4)); } +#ifdef PROTOBUF_HAS_DEATH_TEST +TEST(RepeatedField, MergeFromSelf) { + RepeatedField me; + me.Add(3); + EXPECT_DEATH(me.MergeFrom(me), ""); +} +#endif // PROTOBUF_HAS_DEATH_TEST + TEST(RepeatedField, CopyFrom) { RepeatedField source, destination; source.Add(4); @@ -245,6 +287,14 @@ TEST(RepeatedField, CopyFrom) { EXPECT_EQ(5, destination.Get(1)); } +TEST(RepeatedField, CopyFromSelf) { + RepeatedField me; + me.Add(3); + me.CopyFrom(me); + ASSERT_EQ(1, me.size()); + EXPECT_EQ(3, me.Get(0)); +} + TEST(RepeatedField, CopyConstruct) { RepeatedField source; source.Add(1); @@ -379,36 +429,41 @@ TEST(RepeatedField, ExtractSubrange) { TEST(RepeatedPtrField, Small) { RepeatedPtrField field; + EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); field.Add()->assign("foo"); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), "foo"); field.Add()->assign("bar"); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), "foo"); EXPECT_EQ(field.Get(1), "bar"); field.Mutable(1)->assign("baz"); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 2); EXPECT_EQ(field.Get(0), "foo"); EXPECT_EQ(field.Get(1), "baz"); field.RemoveLast(); + EXPECT_FALSE(field.empty()); EXPECT_EQ(field.size(), 1); EXPECT_EQ(field.Get(0), "foo"); field.Clear(); + EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); } - TEST(RepeatedPtrField, Large) { RepeatedPtrField field; @@ -431,11 +486,27 @@ TEST(RepeatedPtrField, SwapSmallSmall) { RepeatedPtrField field1; RepeatedPtrField field2; + EXPECT_TRUE(field1.empty()); + EXPECT_EQ(field1.size(), 0); + EXPECT_TRUE(field2.empty()); + EXPECT_EQ(field2.size(), 0); + field1.Add()->assign("foo"); field1.Add()->assign("bar"); + + EXPECT_FALSE(field1.empty()); + EXPECT_EQ(field1.size(), 2); + EXPECT_EQ(field1.Get(0), "foo"); + EXPECT_EQ(field1.Get(1), "bar"); + + EXPECT_TRUE(field2.empty()); + EXPECT_EQ(field2.size(), 0); + field1.Swap(&field2); + EXPECT_TRUE(field1.empty()); EXPECT_EQ(field1.size(), 0); + EXPECT_EQ(field2.size(), 2); EXPECT_EQ(field2.Get(0), "foo"); EXPECT_EQ(field2.Get(1), "bar"); @@ -639,6 +710,14 @@ TEST(RepeatedPtrField, MergeFrom) { EXPECT_EQ("5", destination.Get(4)); } +#ifdef PROTOBUF_HAS_DEATH_TEST +TEST(RepeatedPtrField, MergeFromSelf) { + RepeatedPtrField me; + me.Add()->assign("1"); + EXPECT_DEATH(me.MergeFrom(me), ""); +} +#endif // PROTOBUF_HAS_DEATH_TEST + TEST(RepeatedPtrField, CopyFrom) { RepeatedPtrField source, destination; source.Add()->assign("4"); @@ -654,6 +733,14 @@ TEST(RepeatedPtrField, CopyFrom) { EXPECT_EQ("5", destination.Get(1)); } +TEST(RepeatedPtrField, CopyFromSelf) { + RepeatedPtrField me; + me.Add()->assign("1"); + me.CopyFrom(me); + ASSERT_EQ(1, me.size()); + EXPECT_EQ("1", me.Get(0)); +} + TEST(RepeatedPtrField, CopyConstruct) { RepeatedPtrField source; source.Add()->assign("1"); @@ -1007,13 +1094,13 @@ class RepeatedPtrFieldPtrsIteratorTest : public testing::Test { TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertiblePtr) { RepeatedPtrField::pointer_iterator iter = proto_array_.pointer_begin(); - (void) iter; + static_cast(iter); } TEST_F(RepeatedPtrFieldPtrsIteratorTest, ConvertibleConstPtr) { RepeatedPtrField::const_pointer_iterator iter = const_proto_array_->pointer_begin(); - (void) iter; + static_cast(iter); } TEST_F(RepeatedPtrFieldPtrsIteratorTest, MutablePtrIteration) { @@ -1122,9 +1209,7 @@ struct StringLessThan { bool operator()(const string* z, const string& y) { return *z < y; } - bool operator()(const string* z, const string* y) { - return *z < *y; - } + bool operator()(const string* z, const string* y) const { return *z < *y; } }; TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h index c24be485..0c79fae3 100644 --- a/src/google/protobuf/stubs/common.h +++ b/src/google/protobuf/stubs/common.h @@ -685,6 +685,7 @@ class LIBPROTOBUF_EXPORT LogFinisher { #undef GOOGLE_LOG_IF #undef GOOGLE_CHECK +#undef GOOGLE_CHECK_OK #undef GOOGLE_CHECK_EQ #undef GOOGLE_CHECK_NE #undef GOOGLE_CHECK_LT @@ -711,6 +712,7 @@ class LIBPROTOBUF_EXPORT LogFinisher { #define GOOGLE_CHECK(EXPRESSION) \ GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " +#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(A) #define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) #define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) #define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) diff --git a/src/google/protobuf/stubs/map-util.h b/src/google/protobuf/stubs/map-util.h deleted file mode 100644 index 775848b9..00000000 --- a/src/google/protobuf/stubs/map-util.h +++ /dev/null @@ -1,143 +0,0 @@ -// Protocol Buffers - Google's data interchange format -// Copyright 2008 Google Inc. All rights reserved. -// http://code.google.com/p/protobuf/ -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// from google3/util/gtl/map-util.h -// Author: Anton Carver - -#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ -#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ - -#include - -namespace google { -namespace protobuf { - -// Perform a lookup in a map or hash_map. -// If the key is present in the map then the value associated with that -// key is returned, otherwise the value passed as a default is returned. -template -const typename Collection::value_type::second_type& -FindWithDefault(const Collection& collection, - const typename Collection::value_type::first_type& key, - const typename Collection::value_type::second_type& value) { - typename Collection::const_iterator it = collection.find(key); - if (it == collection.end()) { - return value; - } - return it->second; -} - -// Perform a lookup in a map or hash_map. -// If the key is present a const pointer to the associated value is returned, -// otherwise a NULL pointer is returned. -template -const typename Collection::value_type::second_type* -FindOrNull(const Collection& collection, - const typename Collection::value_type::first_type& key) { - typename Collection::const_iterator it = collection.find(key); - if (it == collection.end()) { - return 0; - } - return &it->second; -} - -// Perform a lookup in a map or hash_map, assuming that the key exists. -// Crash if it does not. -// -// This is intended as a replacement for operator[] as an rvalue (for reading) -// when the key is guaranteed to exist. -// -// operator[] is discouraged for several reasons: -// * It has a side-effect of inserting missing keys -// * It is not thread-safe (even when it is not inserting, it can still -// choose to resize the underlying storage) -// * It invalidates iterators (when it chooses to resize) -// * It default constructs a value object even if it doesn't need to -// -// This version assumes the key is printable, and includes it in the fatal log -// message. -template -const typename Collection::value_type::second_type& -FindOrDie(const Collection& collection, - const typename Collection::value_type::first_type& key) { - typename Collection::const_iterator it = collection.find(key); - GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key; - return it->second; -} - -// Perform a lookup in a map or hash_map whose values are pointers. -// If the key is present a const pointer to the associated value is returned, -// otherwise a NULL pointer is returned. -// This function does not distinguish between a missing key and a key mapped -// to a NULL value. -template -const typename Collection::value_type::second_type -FindPtrOrNull(const Collection& collection, - const typename Collection::value_type::first_type& key) { - typename Collection::const_iterator it = collection.find(key); - if (it == collection.end()) { - return 0; - } - return it->second; -} - -// Change the value associated with a particular key in a map or hash_map. -// If the key is not present in the map the key and value are inserted, -// otherwise the value is updated to be a copy of the value provided. -// True indicates that an insert took place, false indicates an update. -template -bool InsertOrUpdate(Collection * const collection, - const Key& key, const Value& value) { - pair ret = - collection->insert(typename Collection::value_type(key, value)); - if (!ret.second) { - // update - ret.first->second = value; - return false; - } - return true; -} - -// Insert a new key and value into a map or hash_map. -// If the key is not present in the map the key and value are -// inserted, otherwise nothing happens. True indicates that an insert -// took place, false indicates the key was already present. -template -bool InsertIfNotPresent(Collection * const collection, - const Key& key, const Value& value) { - pair ret = - collection->insert(typename Collection::value_type(key, value)); - return ret.second; -} - -} // namespace protobuf -} // namespace google - -#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ diff --git a/src/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h new file mode 100644 index 00000000..fb2f5f3f --- /dev/null +++ b/src/google/protobuf/stubs/map_util.h @@ -0,0 +1,771 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 Google Inc. All rights reserved. +// http://code.google.com/p/protobuf/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// from google3/util/gtl/map_util.h +// Author: Anton Carver + +#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ +#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ + +#include +#include +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace internal { +// Local implementation of RemoveConst to avoid including base/type_traits.h. +template struct RemoveConst { typedef T type; }; +template struct RemoveConst : RemoveConst {}; +} // namespace internal + +// +// Find*() +// + +// Returns a const reference to the value associated with the given key if it +// exists. Crashes otherwise. +// +// This is intended as a replacement for operator[] as an rvalue (for reading) +// when the key is guaranteed to exist. +// +// operator[] for lookup is discouraged for several reasons: +// * It has a side-effect of inserting missing keys +// * It is not thread-safe (even when it is not inserting, it can still +// choose to resize the underlying storage) +// * It invalidates iterators (when it chooses to resize) +// * It default constructs a value object even if it doesn't need to +// +// This version assumes the key is printable, and includes it in the fatal log +// message. +template +const typename Collection::value_type::second_type& +FindOrDie(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Same as above, but returns a non-const reference. +template +typename Collection::value_type::second_type& +FindOrDie(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key; + return it->second; +} + +// Same as FindOrDie above, but doesn't log the key on failure. +template +const typename Collection::value_type::second_type& +FindOrDieNoPrint(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found"; + return it->second; +} + +// Same as above, but returns a non-const reference. +template +typename Collection::value_type::second_type& +FindOrDieNoPrint(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + GOOGLE_CHECK(it != collection.end()) << "Map key not found"; + return it->second; +} + +// Returns a const reference to the value associated with the given key if it +// exists, otherwise returns a const reference to the provided default value. +// +// WARNING: If a temporary object is passed as the default "value," +// this function will return a reference to that temporary object, +// which will be destroyed at the end of the statement. A common +// example: if you have a map with string values, and you pass a char* +// as the default "value," either use the returned value immediately +// or store it in a string (not string&). +// Details: http://go/findwithdefault +template +const typename Collection::value_type::second_type& +FindWithDefault(const Collection& collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return value; + } + return it->second; +} + +// Returns a pointer to the const value associated with the given key if it +// exists, or NULL otherwise. +template +const typename Collection::value_type::second_type* +FindOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Same as above but returns a pointer to the non-const value. +template +typename Collection::value_type::second_type* +FindOrNull(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + return &it->second; +} + +// Returns the pointer value associated with the given key. If none is found, +// NULL is returned. The function is designed to be used with a map of keys to +// pointers. +// +// This function does not distinguish between a missing key and a key mapped +// to a NULL value. +template +typename Collection::value_type::second_type +FindPtrOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return typename Collection::value_type::second_type(); + } + return it->second; +} + +// Same as above, except takes non-const reference to collection. +// +// This function is needed for containers that propagate constness to the +// pointee, such as boost::ptr_map. +template +typename Collection::value_type::second_type +FindPtrOrNull(Collection& collection, // NOLINT + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection.find(key); + if (it == collection.end()) { + return typename Collection::value_type::second_type(); + } + return it->second; +} + +// Finds the pointer value associated with the given key in a map whose values +// are linked_ptrs. Returns NULL if key is not found. +template +typename Collection::value_type::second_type::element_type* +FindLinkedPtrOrNull(const Collection& collection, + const typename Collection::value_type::first_type& key) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return 0; + } + // Since linked_ptr::get() 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.get(); +} + +// Same as above, but dies if the key is not found. +template +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; + // 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; +} + +// Finds the value associated with the given key and copies it to *value (if not +// NULL). Returns false if the key was not found, true otherwise. +template +bool FindCopy(const Collection& collection, + const Key& key, + Value* const value) { + typename Collection::const_iterator it = collection.find(key); + if (it == collection.end()) { + return false; + } + if (value) { + *value = it->second; + } + return true; +} + +// +// Contains*() +// + +// Returns true if and only if the given collection contains the given key. +template +bool ContainsKey(const Collection& collection, const Key& key) { + return collection.find(key) != collection.end(); +} + +// Returns true if and only if the given collection contains the given key-value +// pair. +template +bool ContainsKeyValuePair(const Collection& collection, + const Key& key, + const Value& value) { + typedef typename Collection::const_iterator const_iterator; + std::pair range = collection.equal_range(key); + for (const_iterator it = range.first; it != range.second; ++it) { + if (it->second == value) { + return true; + } + } + return false; +} + +// +// Insert*() +// + +// Inserts the given key-value pair into the collection. Returns true if and +// only if the key from the given pair didn't previously exist. Otherwise, the +// value in the map is replaced with the value from the given pair. +template +bool InsertOrUpdate(Collection* const collection, + const typename Collection::value_type& vt) { + std::pair ret = collection->insert(vt); + if (!ret.second) { + // update + ret.first->second = vt.second; + return false; + } + return true; +} + +// Same as above, except that the key and value are passed separately. +template +bool InsertOrUpdate(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return InsertOrUpdate( + collection, typename Collection::value_type(key, value)); +} + +// Inserts/updates all the key-value pairs from the range defined by the +// iterators "first" and "last" into the given collection. +template +void InsertOrUpdateMany(Collection* const collection, + InputIterator first, InputIterator last) { + for (; first != last; ++first) { + InsertOrUpdate(collection, *first); + } +} + +// Change the value associated with a particular key in a map or hash_map +// of the form map which owns the objects pointed to by the +// value pointers. If there was an existing value for the key, it is deleted. +// True indicates an insert took place, false indicates an update + delete. +template +bool InsertAndDeleteExisting( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + std::pair ret = + collection->insert(typename Collection::value_type(key, value)); + if (!ret.second) { + delete ret.first->second; + ret.first->second = value; + return false; + } + return true; +} + +// Inserts the given key and value into the given collection if and only if the +// given key did NOT already exist in the collection. If the key previously +// existed in the collection, the value is not changed. Returns true if the +// key-value pair was inserted; returns false if the key was already present. +template +bool InsertIfNotPresent(Collection* const collection, + const typename Collection::value_type& vt) { + return collection->insert(vt).second; +} + +// Same as above except the key and value are passed separately. +template +bool InsertIfNotPresent( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return InsertIfNotPresent( + collection, typename Collection::value_type(key, value)); +} + +// Same as above except dies if the key already exists in the collection. +template +void InsertOrDie(Collection* const collection, + const typename Collection::value_type& value) { + CHECK(InsertIfNotPresent(collection, value)) << "duplicate value: " << value; +} + +// Same as above except doesn't log the value on error. +template +void InsertOrDieNoPrint(Collection* const collection, + const typename Collection::value_type& value) { + CHECK(InsertIfNotPresent(collection, value)) << "duplicate value."; +} + +// Inserts the key-value pair into the collection. Dies if key was already +// present. +template +void InsertOrDie(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + typedef typename Collection::value_type value_type; + GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) + << "duplicate key: " << key; +} + +// Same as above except doesn't log the key on error. +template +void InsertOrDieNoPrint( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + typedef typename Collection::value_type value_type; + GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key."; +} + +// Inserts a new key and default-initialized value. Dies if the key was already +// present. Returns a reference to the value. Example usage: +// +// map m; +// SomeProto& proto = InsertKeyOrDie(&m, 3); +// proto.set_field("foo"); +template +typename Collection::value_type::second_type& InsertKeyOrDie( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type value_type; + std::pair res = + collection->insert(value_type(key, typename value_type::second_type())); + GOOGLE_CHECK(res.second) << "duplicate key: " << key; + return res.first->second; +} + +// +// Lookup*() +// + +// Looks up a given key and value pair in a collection and inserts the key-value +// pair if it's not already present. Returns a reference to the value associated +// with the key. +template +typename Collection::value_type::second_type& +LookupOrInsert(Collection* const collection, + const typename Collection::value_type& vt) { + return collection->insert(vt).first->second; +} + +// Same as above except the key-value are passed separately. +template +typename Collection::value_type::second_type& +LookupOrInsert(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value) { + return LookupOrInsert( + collection, typename Collection::value_type(key, value)); +} + +// Counts the number of equivalent elements in the given "sequence", and stores +// the results in "count_map" with element as the key and count as the value. +// +// Example: +// vector v = {"a", "b", "c", "a", "b"}; +// map m; +// AddTokenCounts(v, 1, &m); +// assert(m["a"] == 2); +// assert(m["b"] == 2); +// assert(m["c"] == 1); +template +void AddTokenCounts( + const Sequence& sequence, + const typename Collection::value_type::second_type& increment, + Collection* const count_map) { + for (typename Sequence::const_iterator it = sequence.begin(); + it != sequence.end(); ++it) { + typename Collection::value_type::second_type& value = + LookupOrInsert(count_map, *it, + typename Collection::value_type::second_type()); + value += increment; + } +} + +// Returns a reference to the value associated with key. If not found, a value +// is default constructed on the heap and added to the map. +// +// This function is useful for containers of the form map, where +// inserting a new key, value pair involves constructing a new heap-allocated +// Value, and storing a pointer to that in the collection. +template +typename Collection::value_type::second_type& +LookupOrInsertNew(Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename std::iterator_traits< + typename Collection::value_type::second_type>::value_type Element; + std::pair ret = + collection->insert(typename Collection::value_type( + key, + static_cast(NULL))); + if (ret.second) { + ret.first->second = new Element(); + } + return ret.first->second; +} + +// Same as above but constructs the value using the single-argument constructor +// and the given "arg". +template +typename Collection::value_type::second_type& +LookupOrInsertNew(Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename std::iterator_traits< + typename Collection::value_type::second_type>::value_type Element; + std::pair ret = + collection->insert(typename Collection::value_type( + key, + static_cast(NULL))); + if (ret.second) { + ret.first->second = new Element(arg); + } + return ret.first->second; +} + +// Lookup of linked/shared pointers is used in two scenarios: +// +// Use LookupOrInsertNewLinkedPtr if the container owns the elements. +// In this case it is fine working with the raw pointer as long as it is +// guaranteed that no other thread can delete/update an accessed element. +// A mutex will need to lock the container operation as well as the use +// of the returned elements. Finding an element may be performed using +// FindLinkedPtr*(). +// +// Use LookupOrInsertNewSharedPtr if the container does not own the elements +// for their whole lifetime. This is typically the case when a reader allows +// parallel updates to the container. In this case a Mutex only needs to lock +// container operations, but all element operations must be performed on the +// shared pointer. Finding an element must be performed using FindPtr*() and +// cannot be done with FindLinkedPtr*() even though it compiles. + +// Lookup a key in a map or hash_map whose values are linked_ptrs. If it is +// missing, set collection[key].reset(new Value::element_type) and return that. +// Value::element_type must be default constructable. +template +typename Collection::value_type::second_type::element_type* +LookupOrInsertNewLinkedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type::second_type Value; + std::pair ret = + collection->insert(typename Collection::value_type(key, Value())); + if (ret.second) { + ret.first->second.reset(new typename Value::element_type); + } + return ret.first->second.get(); +} + +// A variant of LookupOrInsertNewLinkedPtr where the value is constructed using +// a single-parameter constructor. Note: the constructor argument is computed +// even if it will not be used, so only values cheap to compute should be passed +// here. On the other hand it does not matter how expensive the construction of +// the actual stored value is, as that only occurs if necessary. +template +typename Collection::value_type::second_type::element_type* +LookupOrInsertNewLinkedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename Collection::value_type::second_type Value; + std::pair ret = + collection->insert(typename Collection::value_type(key, Value())); + if (ret.second) { + ret.first->second.reset(new typename Value::element_type(arg)); + } + return ret.first->second.get(); +} + +// Lookup a key in a map or hash_map whose values are shared_ptrs. If it is +// missing, set collection[key].reset(new Value::element_type). Unlike +// LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of +// the raw pointer. Value::element_type must be default constructable. +template +typename Collection::value_type::second_type& +LookupOrInsertNewSharedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typedef typename Collection::value_type::second_type SharedPtr; + typedef typename Collection::value_type::second_type::element_type Element; + std::pair ret = + collection->insert(typename Collection::value_type(key, SharedPtr())); + if (ret.second) { + ret.first->second.reset(new Element()); + } + return ret.first->second; +} + +// A variant of LookupOrInsertNewSharedPtr where the value is constructed using +// a single-parameter constructor. Note: the constructor argument is computed +// even if it will not be used, so only values cheap to compute should be passed +// here. On the other hand it does not matter how expensive the construction of +// the actual stored value is, as that only occurs if necessary. +template +typename Collection::value_type::second_type& +LookupOrInsertNewSharedPtr( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const Arg& arg) { + typedef typename Collection::value_type::second_type SharedPtr; + typedef typename Collection::value_type::second_type::element_type Element; + std::pair ret = + collection->insert(typename Collection::value_type(key, SharedPtr())); + if (ret.second) { + ret.first->second.reset(new Element(arg)); + } + return ret.first->second; +} + +// +// Misc Utility Functions +// + +// Updates the value associated with the given key. If the key was not already +// present, then the key-value pair are inserted and "previous" is unchanged. If +// the key was already present, the value is updated and "*previous" will +// contain a copy of the old value. +// +// InsertOrReturnExisting has complementary behavior that returns the +// address of an already existing value, rather than updating it. +template +bool UpdateReturnCopy(Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& value, + typename Collection::value_type::second_type* previous) { + std::pair ret = + collection->insert(typename Collection::value_type(key, value)); + if (!ret.second) { + // update + if (previous) { + *previous = ret.first->second; + } + ret.first->second = value; + return true; + } + return false; +} + +// Same as above except that the key and value are passed as a pair. +template +bool UpdateReturnCopy(Collection* const collection, + const typename Collection::value_type& vt, + typename Collection::value_type::second_type* previous) { + std::pair ret = collection->insert(vt); + if (!ret.second) { + // update + if (previous) { + *previous = ret.first->second; + } + ret.first->second = vt.second; + return true; + } + return false; +} + +// Tries to insert the given key-value pair into the collection. Returns NULL if +// the insert succeeds. Otherwise, returns a pointer to the existing value. +// +// This complements UpdateReturnCopy in that it allows to update only after +// verifying the old value and still insert quickly without having to look up +// twice. Unlike UpdateReturnCopy this also does not come with the issue of an +// undefined previous* in case new data was inserted. +template +typename Collection::value_type::second_type* const +InsertOrReturnExisting(Collection* const collection, + const typename Collection::value_type& vt) { + std::pair ret = collection->insert(vt); + if (ret.second) { + return NULL; // Inserted, no existing previous value. + } else { + return &ret.first->second; // Return address of already existing value. + } +} + +// Same as above, except for explicit key and data. +template +typename Collection::value_type::second_type* const +InsertOrReturnExisting( + Collection* const collection, + const typename Collection::value_type::first_type& key, + const typename Collection::value_type::second_type& data) { + return InsertOrReturnExisting(collection, + typename Collection::value_type(key, data)); +} + +// Erases the collection item identified by the given key, and returns the value +// associated with that key. It is assumed that the value (i.e., the +// mapped_type) is a pointer. Returns NULL if the key was not found in the +// collection. +// +// Examples: +// map my_map; +// +// One line cleanup: +// delete EraseKeyReturnValuePtr(&my_map, "abc"); +// +// Use returned value: +// scoped_ptr value_ptr(EraseKeyReturnValuePtr(&my_map, "abc")); +// if (value_ptr.get()) +// value_ptr->DoSomething(); +// +template +typename Collection::value_type::second_type EraseKeyReturnValuePtr( + Collection* const collection, + const typename Collection::value_type::first_type& key) { + typename Collection::iterator it = collection->find(key); + if (it == collection->end()) { + return NULL; + } + typename Collection::value_type::second_type v = it->second; + collection->erase(it); + return v; +} + +// Inserts all the keys from map_container into key_container, which must +// support insert(MapContainer::key_type). +// +// Note: any initial contents of the key_container are not cleared. +template +void InsertKeysFromMap(const MapContainer& map_container, + KeyContainer* key_container) { + GOOGLE_CHECK(key_container != NULL); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->insert(it->first); + } +} + +// Appends all the keys from map_container into key_container, which must +// support push_back(MapContainer::key_type). +// +// Note: any initial contents of the key_container are not cleared. +template +void AppendKeysFromMap(const MapContainer& map_container, + KeyContainer* key_container) { + GOOGLE_CHECK(key_container != NULL); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->push_back(it->first); + } +} + +// A more specialized overload of AppendKeysFromMap to optimize reallocations +// for the common case in which we're appending keys to a vector and hence can +// (and sometimes should) call reserve() first. +// +// (It would be possible to play SFINAE games to call reserve() for any +// container that supports it, but this seems to get us 99% of what we need +// without the complexity of a SFINAE-based solution.) +template +void AppendKeysFromMap(const MapContainer& map_container, + vector* key_container) { + GOOGLE_CHECK(key_container != NULL); + // We now have the opportunity to call reserve(). Calling reserve() every + // time is a bad idea for some use cases: libstdc++'s implementation of + // vector<>::reserve() resizes the vector's backing store to exactly the + // given size (unless it's already at least that big). Because of this, + // the use case that involves appending a lot of small maps (total size + // N) one by one to a vector would be O(N^2). But never calling reserve() + // loses the opportunity to improve the use case of adding from a large + // map to an empty vector (this improves performance by up to 33%). A + // number of heuristics are possible; see the discussion in + // cl/34081696. Here we use the simplest one. + if (key_container->empty()) { + key_container->reserve(map_container.size()); + } + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + key_container->push_back(it->first); + } +} + +// Inserts all the values from map_container into value_container, which must +// support push_back(MapContainer::mapped_type). +// +// Note: any initial contents of the value_container are not cleared. +template +void AppendValuesFromMap(const MapContainer& map_container, + ValueContainer* value_container) { + GOOGLE_CHECK(value_container != NULL); + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + value_container->push_back(it->second); + } +} + +// A more specialized overload of AppendValuesFromMap to optimize reallocations +// for the common case in which we're appending values to a vector and hence +// can (and sometimes should) call reserve() first. +// +// (It would be possible to play SFINAE games to call reserve() for any +// container that supports it, but this seems to get us 99% of what we need +// without the complexity of a SFINAE-based solution.) +template +void AppendValuesFromMap(const MapContainer& map_container, + vector* value_container) { + GOOGLE_CHECK(value_container != NULL); + // See AppendKeysFromMap for why this is done. + if (value_container->empty()) { + value_container->reserve(map_container.size()); + } + for (typename MapContainer::const_iterator it = map_container.begin(); + it != map_container.end(); ++it) { + value_container->push_back(it->second); + } +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__ diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/stubs/once.h index 7fbc117f..86a4c01f 100644 --- a/src/google/protobuf/stubs/once.h +++ b/src/google/protobuf/stubs/once.h @@ -139,6 +139,24 @@ inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*), #endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY +class GoogleOnceDynamic { + public: + GoogleOnceDynamic() : state_(GOOGLE_PROTOBUF_ONCE_INIT) { } + + // If this->Init() has not been called before by any thread, + // execute (*func_with_arg)(arg) then return. + // Otherwise, wait until that prior invocation has finished + // executing its function, then return. + template + void Init(void (*func_with_arg)(T*), T* arg) { + GoogleOnceInit(&this->state_, + func_with_arg, + arg); + } + private: + ProtobufOnceType state_; +}; + #define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ ::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc index 917b3e9f..814d1b91 100644 --- a/src/google/protobuf/stubs/strutil.cc +++ b/src/google/protobuf/stubs/strutil.cc @@ -596,6 +596,120 @@ uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) { return static_cast(result); } +inline bool safe_parse_sign(string* text /*inout*/, + bool* negative_ptr /*output*/) { + const char* start = text->data(); + const char* end = start + text->size(); + + // Consume whitespace. + while (start < end && (start[0] == ' ')) { + ++start; + } + while (start < end && (end[-1] == ' ')) { + --end; + } + if (start >= end) { + return false; + } + + // Consume sign. + *negative_ptr = (start[0] == '-'); + if (*negative_ptr || start[0] == '+') { + ++start; + if (start >= end) { + return false; + } + } + *text = text->substr(start - text->data(), end - start); + return true; +} + +inline bool safe_parse_positive_int( + string text, int32* value_p) { + int base = 10; + int32 value = 0; + const int32 vmax = std::numeric_limits::max(); + assert(vmax > 0); + assert(vmax >= base); + const int32 vmax_over_base = vmax / base; + const char* start = text.data(); + const char* end = start + text.size(); + // loop over digits + for (; start < end; ++start) { + unsigned char c = static_cast(start[0]); + int digit = c - '0'; + if (digit >= base || digit < 0) { + *value_p = value; + return false; + } + if (value > vmax_over_base) { + *value_p = vmax; + return false; + } + value *= base; + if (value > vmax - digit) { + *value_p = vmax; + return false; + } + value += digit; + } + *value_p = value; + return true; +} + +inline bool safe_parse_negative_int( + string text, int32* value_p) { + int base = 10; + int32 value = 0; + const int32 vmin = std::numeric_limits::min(); + assert(vmin < 0); + assert(vmin <= 0 - base); + int32 vmin_over_base = vmin / base; + // 2003 c++ standard [expr.mul] + // "... the sign of the remainder is implementation-defined." + // Although (vmin/base)*base + vmin%base is always vmin. + // 2011 c++ standard tightens the spec but we cannot rely on it. + if (vmin % base > 0) { + vmin_over_base += 1; + } + const char* start = text.data(); + const char* end = start + text.size(); + // loop over digits + for (; start < end; ++start) { + unsigned char c = static_cast(start[0]); + int digit = c - '0'; + if (digit >= base || digit < 0) { + *value_p = value; + return false; + } + if (value < vmin_over_base) { + *value_p = vmin; + return false; + } + value *= base; + if (value < vmin + digit) { + *value_p = vmin; + return false; + } + value -= digit; + } + *value_p = value; + return true; +} + +bool safe_int(string text, int32* value_p) { + *value_p = 0; + bool negative; + if (!safe_parse_sign(&text, &negative)) { + return false; + } + if (!negative) { + return safe_parse_positive_int(text, value_p); + } else { + return safe_parse_negative_int(text, value_p); + } +} + // ---------------------------------------------------------------------- // FastIntToBuffer() // FastInt64ToBuffer() @@ -1143,68 +1257,22 @@ char* FloatToBuffer(float value, char* buffer) { return buffer; } -// ---------------------------------------------------------------------- -// NoLocaleStrtod() -// This code will make you cry. -// ---------------------------------------------------------------------- - -// Returns a string identical to *input except that the character pointed to -// by radix_pos (which should be '.') is replaced with the locale-specific -// radix character. -string LocalizeRadix(const char* input, const char* radix_pos) { - // Determine the locale-specific radix character by calling sprintf() to - // print the number 1.5, then stripping off the digits. As far as I can - // tell, this is the only portable, thread-safe way to get the C library - // to divuldge the locale's radix character. No, localeconv() is NOT - // thread-safe. - char temp[16]; - int size = sprintf(temp, "%.1f", 1.5); - GOOGLE_CHECK_EQ(temp[0], '1'); - GOOGLE_CHECK_EQ(temp[size-1], '5'); - GOOGLE_CHECK_LE(size, 6); - - // Now replace the '.' in the input with it. - string result; - result.reserve(strlen(input) + size - 3); - result.append(input, radix_pos); - result.append(temp + 1, size - 2); - result.append(radix_pos + 1); - return result; -} +string ToHex(uint64 num) { + if (num == 0) { + return string("0"); + } -double NoLocaleStrtod(const char* text, char** original_endptr) { - // We cannot simply set the locale to "C" temporarily with setlocale() - // as this is not thread-safe. Instead, we try to parse in the current - // locale first. If parsing stops at a '.' character, then this is a - // pretty good hint that we're actually in some other locale in which - // '.' is not the radix character. - - char* temp_endptr; - double result = strtod(text, &temp_endptr); - if (original_endptr != NULL) *original_endptr = temp_endptr; - if (*temp_endptr != '.') return result; - - // Parsing halted on a '.'. Perhaps we're in a different locale? Let's - // try to replace the '.' with a locale-specific radix character and - // try again. - string localized = LocalizeRadix(text, temp_endptr); - const char* localized_cstr = localized.c_str(); - char* localized_endptr; - result = strtod(localized_cstr, &localized_endptr); - if ((localized_endptr - localized_cstr) > - (temp_endptr - text)) { - // This attempt got further, so replacing the decimal must have helped. - // Update original_endptr to point at the right location. - if (original_endptr != NULL) { - // size_diff is non-zero if the localized radix has multiple bytes. - int size_diff = localized.size() - strlen(text); - // const_cast is necessary to match the strtod() interface. - *original_endptr = const_cast( - text + (localized_endptr - localized_cstr - size_diff)); - } + // Compute hex bytes in reverse order, writing to the back of the + // buffer. + char buf[16]; // No more than 16 hex digits needed. + char* bufptr = buf + 16; + static const char kHexChars[] = "0123456789abcdef"; + while (num != 0) { + *--bufptr = kHexChars[num & 0xf]; + num >>= 4; } - return result; + return string(bufptr, buf + 16 - bufptr); } } // namespace protobuf diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h index a401c63a..20cea2d2 100644 --- a/src/google/protobuf/stubs/strutil.h +++ b/src/google/protobuf/stubs/strutil.h @@ -126,6 +126,7 @@ LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove, // ---------------------------------------------------------------------- // LowerString() // UpperString() +// ToUpper() // Convert the characters in "s" to lowercase or uppercase. ASCII-only: // these functions intentionally ignore locale because they are applied to // identifiers used in the Protocol Buffer language, not to natural-language @@ -148,6 +149,12 @@ inline void UpperString(string * s) { } } +inline string ToUpper(const string& s) { + string out = s; + UpperString(&out); + return out; +} + // ---------------------------------------------------------------------- // StringReplace() // Give me a string and two patterns "old" and "new", and I replace @@ -180,6 +187,21 @@ LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full, const char* delim, vector* result); +// ---------------------------------------------------------------------- +// Split() +// Split a string using a character delimiter. +// ---------------------------------------------------------------------- +inline vector Split( + const string& full, const char* delim, bool skip_empty = true) { + vector result; + if (skip_empty) { + SplitStringUsing(full, delim, &result); + } else { + SplitStringAllowEmpty(full, delim, &result); + } + return result; +} + // ---------------------------------------------------------------------- // JoinStrings() // These methods concatenate a vector of strings into a C++ string, using @@ -326,6 +348,15 @@ inline uint64 strtou64(const char *nptr, char **endptr, int base) { return strtoull(nptr, endptr, base); } +// ---------------------------------------------------------------------- +// safe_strto32() +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT bool safe_int(string text, int32* value_p); + +inline bool safe_strto32(string text, int32* value) { + return safe_int(text, value); +} + // ---------------------------------------------------------------------- // FastIntToBuffer() // FastHexToBuffer() @@ -454,12 +485,76 @@ static const int kDoubleToBufferSize = 32; static const int kFloatToBufferSize = 24; // ---------------------------------------------------------------------- -// NoLocaleStrtod() -// Exactly like strtod(), except it always behaves as if in the "C" -// locale (i.e. decimal points must be '.'s). +// ToString() are internal help methods used in StrCat() and Join() +// ---------------------------------------------------------------------- +namespace internal { +inline string ToString(int i) { + return SimpleItoa(i); +} + +inline string ToString(string a) { + return a; +} +} // namespace internal + +// ---------------------------------------------------------------------- +// StrCat() +// These methods join some strings together. // ---------------------------------------------------------------------- +template +string StrCat( + const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) { + return internal::ToString(a) + internal::ToString(b) + + internal::ToString(c) + internal::ToString(d) + internal::ToString(e); +} + +template +string StrCat( + const T1& a, const T2& b, const T3& c, const T4& d) { + return internal::ToString(a) + internal::ToString(b) + + internal::ToString(c) + internal::ToString(d); +} + +template +string StrCat(const T1& a, const T2& b, const T3& c) { + return internal::ToString(a) + internal::ToString(b) + + internal::ToString(c); +} + +template +string StrCat(const T1& a, const T2& b) { + return internal::ToString(a) + internal::ToString(b); +} -LIBPROTOBUF_EXPORT double NoLocaleStrtod(const char* text, char** endptr); +// ---------------------------------------------------------------------- +// Join() +// These methods concatenate a range of components into a C++ string, using +// the C-string "delim" as a separator between components. +// ---------------------------------------------------------------------- +template +void Join(Iterator start, Iterator end, + const char* delim, string* result) { + for (Iterator it = start; it != end; ++it) { + if (it != start) { + result->append(delim); + } + result->append(internal::ToString(*it)); + } +} + +template +string Join(const Range& components, + const char* delim) { + string result; + Join(components.begin(), components.end(), delim, &result); + return result; +} + +// ---------------------------------------------------------------------- +// ToHex() +// Return a lower-case hex string representation of the given integer. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT string ToHex(uint64 num); } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc index b9c9253b..fde54f05 100644 --- a/src/google/protobuf/stubs/strutil_unittest.cc +++ b/src/google/protobuf/stubs/strutil_unittest.cc @@ -51,27 +51,17 @@ TEST(StringUtilityTest, ImmuneToLocales) { // Set the locale to "C". ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != NULL); - EXPECT_EQ(1.5, NoLocaleStrtod("1.5", NULL)); EXPECT_EQ("1.5", SimpleDtoa(1.5)); EXPECT_EQ("1.5", SimpleFtoa(1.5)); - // Verify that the endptr is set correctly even if not all text was parsed. - const char* text = "1.5f"; - char* endptr; - EXPECT_EQ(1.5, NoLocaleStrtod(text, &endptr)); - EXPECT_EQ(3, endptr - text); - if (setlocale(LC_NUMERIC, "es_ES") == NULL && setlocale(LC_NUMERIC, "es_ES.utf8") == NULL) { // Some systems may not have the desired locale available. GOOGLE_LOG(WARNING) << "Couldn't set locale to es_ES. Skipping this test."; } else { - EXPECT_EQ(1.5, NoLocaleStrtod("1.5", NULL)); EXPECT_EQ("1.5", SimpleDtoa(1.5)); EXPECT_EQ("1.5", SimpleFtoa(1.5)); - EXPECT_EQ(1.5, NoLocaleStrtod(text, &endptr)); - EXPECT_EQ(3, endptr - text); } // Return to original locale. diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc index a9666fe4..f3cf7a9a 100644 --- a/src/google/protobuf/test_util.cc +++ b/src/google/protobuf/test_util.cc @@ -54,6 +54,7 @@ void TestUtil::SetAllFields(unittest::TestAllTypes* message) { AddRepeatedFields1(message); AddRepeatedFields2(message); SetDefaultFields(message); + SetOneofFields(message); } void TestUtil::SetOptionalFields(unittest::TestAllTypes* message) { @@ -255,6 +256,14 @@ void TestUtil::ModifyRepeatedFields(unittest::TestAllTypes* message) { #endif // !PROTOBUF_TEST_NO_DESCRIPTORS } +// ------------------------------------------------------------------ +void TestUtil::SetOneofFields(unittest::TestAllTypes* message) { + message->set_oneof_uint32(601); + message->mutable_oneof_nested_message()->set_bb(602); + message->set_oneof_string("603"); + message->set_oneof_bytes("604"); +} + // ------------------------------------------------------------------- void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { @@ -454,6 +463,13 @@ void TestUtil::ExpectAllFieldsSet(const unittest::TestAllTypes& message) { EXPECT_EQ(unittest::FOREIGN_FOO , message.default_foreign_enum()); EXPECT_EQ(unittest_import::IMPORT_FOO, message.default_import_enum ()); + + EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string ()); + EXPECT_TRUE(message.has_oneof_bytes ()); + + EXPECT_EQ("604", message.oneof_bytes()); } // ------------------------------------------------------------------- @@ -600,6 +616,11 @@ void TestUtil::ExpectClear(const unittest::TestAllTypes& message) { EXPECT_EQ(unittest::FOREIGN_BAR , message.default_foreign_enum()); EXPECT_EQ(unittest_import::IMPORT_BAR, message.default_import_enum ()); + + EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string ()); + EXPECT_FALSE(message.has_oneof_bytes ()); } // ------------------------------------------------------------------- @@ -1078,6 +1099,15 @@ void TestUtil::SetAllExtensions(unittest::TestAllExtensions* message) { message->SetExtension(unittest::default_string_piece_extension, "424"); message->SetExtension(unittest::default_cord_extension, "425"); + + SetOneofFields(message); +} + +void TestUtil::SetOneofFields(unittest::TestAllExtensions* message) { + message->SetExtension(unittest::oneof_uint32_extension, 601); + message->MutableExtension(unittest::oneof_nested_message_extension)->set_bb(602); + message->SetExtension(unittest::oneof_string_extension, "603"); + message->SetExtension(unittest::oneof_bytes_extension, "604"); } // ------------------------------------------------------------------- @@ -1331,6 +1361,16 @@ void TestUtil::ExpectAllExtensionsSet( EXPECT_EQ("424", message.GetExtension(unittest::default_string_piece_extension)); EXPECT_EQ("425", message.GetExtension(unittest::default_cord_extension)); + + EXPECT_TRUE(message.HasExtension(unittest::oneof_uint32_extension)); + EXPECT_TRUE(message.GetExtension(unittest::oneof_nested_message_extension).has_bb()); + EXPECT_TRUE(message.HasExtension(unittest::oneof_string_extension)); + EXPECT_TRUE(message.HasExtension(unittest::oneof_bytes_extension)); + + EXPECT_EQ(601, message.GetExtension(unittest::oneof_uint32_extension)); + EXPECT_EQ(602, message.GetExtension(unittest::oneof_nested_message_extension).bb()); + EXPECT_EQ("603", message.GetExtension(unittest::oneof_string_extension)); + EXPECT_EQ("604", message.GetExtension(unittest::oneof_bytes_extension)); } // ------------------------------------------------------------------- @@ -1489,6 +1529,11 @@ void TestUtil::ExpectExtensionsClear( EXPECT_EQ("abc", message.GetExtension(unittest::default_string_piece_extension)); EXPECT_EQ("123", message.GetExtension(unittest::default_cord_extension)); + + EXPECT_FALSE(message.HasExtension(unittest::oneof_uint32_extension)); + EXPECT_FALSE(message.GetExtension(unittest::oneof_nested_message_extension).has_bb()); + EXPECT_FALSE(message.HasExtension(unittest::oneof_string_extension)); + EXPECT_FALSE(message.HasExtension(unittest::oneof_bytes_extension)); } // ------------------------------------------------------------------- @@ -1765,6 +1810,57 @@ void TestUtil::ExpectPackedExtensionsModified( // ------------------------------------------------------------------- +void TestUtil::ExpectUnpackedExtensionsSet( + const unittest::TestUnpackedExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_int32_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_int64_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_uint32_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_uint64_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sint32_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sint64_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_fixed32_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_fixed64_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_float_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_double_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_bool_extension )); + ASSERT_EQ(2, message.ExtensionSize(unittest::unpacked_enum_extension )); + + EXPECT_EQ(601 , message.GetExtension(unittest::unpacked_int32_extension , 0)); + EXPECT_EQ(602 , message.GetExtension(unittest::unpacked_int64_extension , 0)); + EXPECT_EQ(603 , message.GetExtension(unittest::unpacked_uint32_extension , 0)); + EXPECT_EQ(604 , message.GetExtension(unittest::unpacked_uint64_extension , 0)); + EXPECT_EQ(605 , message.GetExtension(unittest::unpacked_sint32_extension , 0)); + EXPECT_EQ(606 , message.GetExtension(unittest::unpacked_sint64_extension , 0)); + EXPECT_EQ(607 , message.GetExtension(unittest::unpacked_fixed32_extension , 0)); + EXPECT_EQ(608 , message.GetExtension(unittest::unpacked_fixed64_extension , 0)); + EXPECT_EQ(609 , message.GetExtension(unittest::unpacked_sfixed32_extension, 0)); + EXPECT_EQ(610 , message.GetExtension(unittest::unpacked_sfixed64_extension, 0)); + EXPECT_EQ(611 , message.GetExtension(unittest::unpacked_float_extension , 0)); + EXPECT_EQ(612 , message.GetExtension(unittest::unpacked_double_extension , 0)); + EXPECT_EQ(true , message.GetExtension(unittest::unpacked_bool_extension , 0)); + EXPECT_EQ(unittest::FOREIGN_BAR, + message.GetExtension(unittest::unpacked_enum_extension, 0)); + EXPECT_EQ(701 , message.GetExtension(unittest::unpacked_int32_extension , 1)); + EXPECT_EQ(702 , message.GetExtension(unittest::unpacked_int64_extension , 1)); + EXPECT_EQ(703 , message.GetExtension(unittest::unpacked_uint32_extension , 1)); + EXPECT_EQ(704 , message.GetExtension(unittest::unpacked_uint64_extension , 1)); + EXPECT_EQ(705 , message.GetExtension(unittest::unpacked_sint32_extension , 1)); + EXPECT_EQ(706 , message.GetExtension(unittest::unpacked_sint64_extension , 1)); + EXPECT_EQ(707 , message.GetExtension(unittest::unpacked_fixed32_extension , 1)); + EXPECT_EQ(708 , message.GetExtension(unittest::unpacked_fixed64_extension , 1)); + EXPECT_EQ(709 , message.GetExtension(unittest::unpacked_sfixed32_extension, 1)); + EXPECT_EQ(710 , message.GetExtension(unittest::unpacked_sfixed64_extension, 1)); + EXPECT_EQ(711 , message.GetExtension(unittest::unpacked_float_extension , 1)); + EXPECT_EQ(712 , message.GetExtension(unittest::unpacked_double_extension , 1)); + EXPECT_EQ(false, message.GetExtension(unittest::unpacked_bool_extension , 1)); + EXPECT_EQ(unittest::FOREIGN_BAZ, + message.GetExtension(unittest::unpacked_enum_extension, 1)); +} + +// ------------------------------------------------------------------- + void TestUtil::ExpectAllFieldsAndExtensionsInOrder(const string& serialized) { // We set each field individually, serialize separately, and concatenate all // the strings in canonical order to determine the expected serialization. @@ -2119,6 +2215,92 @@ void TestUtil::ExpectRepeatedExtensionsSwapped( EXPECT_EQ("325", message.GetExtension(unittest::repeated_cord_extension, 0)); } +void TestUtil::SetOneof1(unittest::TestOneof2* message) { + message->mutable_foo_lazy_message()->set_qux_int(100); + message->set_bar_string("101"); + message->set_baz_int(102); + message->set_baz_string("103"); +} + +void TestUtil::SetOneof2(unittest::TestOneof2* message) { + message->set_foo_int(200); + message->set_bar_enum(unittest::TestOneof2::BAZ); + message->set_baz_int(202); + message->set_baz_string("203"); +} + +void TestUtil::ExpectOneofSet1(const unittest::TestOneof2& message) { + ExpectAtMostOneFieldSetInOneof(message); + + EXPECT_TRUE(message.has_foo_lazy_message ()); + EXPECT_TRUE(message.foo_lazy_message().has_qux_int()); + + EXPECT_TRUE(message.has_bar_string()); + EXPECT_TRUE(message.has_baz_int ()); + EXPECT_TRUE(message.has_baz_string()); + + ASSERT_EQ(0, message.foo_lazy_message().corge_int_size()); + + EXPECT_EQ(100 , message.foo_lazy_message().qux_int()); + EXPECT_EQ("101", message.bar_string ()); + EXPECT_EQ(102 , message.baz_int ()); + EXPECT_EQ("103", message.baz_string ()); +} + +void TestUtil::ExpectOneofSet2(const unittest::TestOneof2& message) { + ExpectAtMostOneFieldSetInOneof(message); + + EXPECT_TRUE(message.has_foo_int ()); + EXPECT_TRUE(message.has_bar_enum ()); + EXPECT_TRUE(message.has_baz_int ()); + EXPECT_TRUE(message.has_baz_string()); + + EXPECT_EQ(200 , message.foo_int ()); + EXPECT_EQ(unittest::TestOneof2::BAZ, message.bar_enum ()); + EXPECT_EQ(202 , message.baz_int ()); + EXPECT_EQ("203" , message.baz_string()); +} + +void TestUtil::ExpectOneofClear(const unittest::TestOneof2& message) { + EXPECT_FALSE(message.has_foo_int()); + EXPECT_FALSE(message.has_foo_string()); + EXPECT_FALSE(message.has_foo_bytes()); + EXPECT_FALSE(message.has_foo_enum()); + EXPECT_FALSE(message.has_foo_message()); + EXPECT_FALSE(message.has_foogroup()); + EXPECT_FALSE(message.has_foo_lazy_message()); + + EXPECT_FALSE(message.has_bar_int()); + EXPECT_FALSE(message.has_bar_string()); + EXPECT_FALSE(message.has_bar_bytes()); + EXPECT_FALSE(message.has_bar_enum()); + + EXPECT_FALSE(message.has_baz_int()); + EXPECT_FALSE(message.has_baz_string()); + + EXPECT_EQ(unittest::TestOneof2::FOO_NOT_SET, message.foo_case()); + EXPECT_EQ(unittest::TestOneof2::BAR_NOT_SET, message.bar_case()); +} + +void TestUtil::ExpectAtMostOneFieldSetInOneof( + const unittest::TestOneof2& message) { + int count = 0; + if (message.has_foo_int()) count++; + if (message.has_foo_string()) count++; + if (message.has_foo_bytes()) count++; + if (message.has_foo_enum()) count++; + if (message.has_foo_message()) count++; + if (message.has_foogroup()) count++; + if (message.has_foo_lazy_message()) count++; + EXPECT_LE(count, 1); + count = 0; + if (message.has_bar_int()) count++; + if (message.has_bar_string()) count++; + if (message.has_bar_bytes()) count++; + if (message.has_bar_enum()) count++; + EXPECT_TRUE(count == 0 || count == 1); +} + // =================================================================== TestUtil::ReflectionTester::ReflectionTester( @@ -2335,6 +2517,69 @@ void TestUtil::ReflectionTester::SetAllFieldsViaReflection(Message* message) { reflection->SetString(message, F("default_string_piece"), "424"); reflection->SetString(message, F("default_cord"), "425"); + + reflection->SetUInt32(message, F("oneof_uint32" ), 601); + sub_message = reflection->MutableMessage(message, F("oneof_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 602); + reflection->SetString(message, F("oneof_string"), "603"); + reflection->SetString(message, F("oneof_bytes" ), "604"); +} + +void TestUtil::ReflectionTester::SetOneofViaReflection(Message* message) { + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* reflection = message->GetReflection(); + Message* sub_message = reflection->MutableMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + sub_message->GetReflection()->SetInt64( + sub_message, + descriptor->file()->pool()->FindFieldByName( + "protobuf_unittest.TestOneof2.NestedMessage.qux_int"), + 100); + + reflection->SetString(message, + descriptor->FindFieldByName("bar_cord"), + "101"); + reflection->SetInt32(message, + descriptor->FindFieldByName("baz_int"), + 102); + reflection->SetString(message, + descriptor->FindFieldByName("baz_string"), + "103"); +} + +void TestUtil::ReflectionTester::ExpectOneofSetViaReflection( + const Message& message) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = message.GetReflection(); + string scratch; + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("foo_lazy_message"))); + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("baz_int"))); + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("baz_string"))); + + const Message* sub_message = &reflection->GetMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_EQ(100, sub_message->GetReflection()->GetInt64( + *sub_message, + descriptor->file()->pool()->FindFieldByName( + "protobuf_unittest.TestOneof2.NestedMessage.qux_int"))); + + EXPECT_EQ("101", reflection->GetString( + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("101", reflection->GetStringReference( + message, descriptor->FindFieldByName("bar_cord"), &scratch)); + + EXPECT_EQ(102, reflection->GetInt32( + message, descriptor->FindFieldByName("baz_int"))); + + EXPECT_EQ("103", reflection->GetString( + message, descriptor->FindFieldByName("baz_string"))); + EXPECT_EQ("103", reflection->GetStringReference( + message, descriptor->FindFieldByName("baz_string"), &scratch)); } void TestUtil::ReflectionTester::SetPackedFieldsViaReflection( @@ -2473,6 +2718,20 @@ void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( EXPECT_EQ("125", reflection->GetString(message, F("optional_cord"))); EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), &scratch)); + EXPECT_TRUE(reflection->HasField(message, F("oneof_bytes" ))); + EXPECT_EQ("604", reflection->GetString(message, F("oneof_bytes" ))); + + if (base_descriptor_->name() == "TestAllTypes") { + EXPECT_FALSE(reflection->HasField(message, F("oneof_uint32"))); + EXPECT_FALSE(reflection->HasField(message, F("oneof_string"))); + } else { + EXPECT_TRUE(reflection->HasField(message, F("oneof_uint32"))); + EXPECT_TRUE(reflection->HasField(message, F("oneof_string"))); + EXPECT_EQ(601 , reflection->GetUInt32(message, F("oneof_uint32"))); + EXPECT_EQ("603", reflection->GetString(message, F("oneof_string"))); + sub_message = &reflection->GetMessage(message, F("oneof_nested_message")); + EXPECT_EQ(602, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + } } void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( @@ -3013,6 +3272,45 @@ void TestUtil::ReflectionTester::SwapRepeatedsViaReflection(Message* message) { } } +void TestUtil::ReflectionTester:: +SetAllocatedOptionalMessageFieldsToNullViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + vector fields; + reflection->ListFields(*message, &fields); + + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + if (!field->is_optional() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + reflection->SetAllocatedMessage(message, NULL, field); + } +} + +void TestUtil::ReflectionTester:: +SetAllocatedOptionalMessageFieldsToMessageViaReflection( + Message* from_message, + Message* to_message) { + EXPECT_EQ(from_message->GetDescriptor(), to_message->GetDescriptor()); + const Reflection* from_reflection = from_message->GetReflection(); + const Reflection* to_reflection = to_message->GetReflection(); + + vector fields; + from_reflection->ListFields(*from_message, &fields); + + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + if (!field->is_optional() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + Message* sub_message = + from_reflection->ReleaseMessage(from_message, field); + to_reflection->SetAllocatedMessage(to_message, sub_message, field); + } +} + void TestUtil::ReflectionTester::ExpectMessagesReleasedViaReflection( Message* message, TestUtil::ReflectionTester::MessageReleaseState expected_release_state) { diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h index 45519573..6e2d552a 100644 --- a/src/google/protobuf/test_util.h +++ b/src/google/protobuf/test_util.h @@ -54,11 +54,15 @@ class TestUtil { static void AddRepeatedFields1(unittest::TestAllTypes* message); static void AddRepeatedFields2(unittest::TestAllTypes* message); static void SetDefaultFields(unittest::TestAllTypes* message); + static void SetOneofFields(unittest::TestAllTypes* message); static void SetAllExtensions(unittest::TestAllExtensions* message); + static void SetOneofFields(unittest::TestAllExtensions* message); static void SetAllFieldsAndExtensions(unittest::TestFieldOrderings* message); static void SetPackedFields(unittest::TestPackedTypes* message); static void SetPackedExtensions(unittest::TestPackedExtensions* message); static void SetUnpackedFields(unittest::TestUnpackedTypes* message); + static void SetOneof1(unittest::TestOneof2* message); + static void SetOneof2(unittest::TestOneof2* message); // Use the repeated versions of the set_*() accessors to modify all the // repeated fields of the messsage (which should already have been @@ -79,6 +83,10 @@ class TestUtil { const unittest::TestPackedExtensions& message); static void ExpectUnpackedFieldsSet( const unittest::TestUnpackedTypes& message); + static void ExpectUnpackedExtensionsSet( + const unittest::TestUnpackedExtensions& message); + static void ExpectOneofSet1(const unittest::TestOneof2& message); + static void ExpectOneofSet2(const unittest::TestOneof2& message); // Expect that the message is modified as would be expected from // Modify*Fields(). @@ -97,6 +105,7 @@ class TestUtil { static void ExpectPackedClear(const unittest::TestPackedTypes& message); static void ExpectPackedExtensionsClear( const unittest::TestPackedExtensions& message); + static void ExpectOneofClear(const unittest::TestOneof2& message); // Check that the passed-in serialization is the canonical serialization we // expect for a TestFieldOrderings message filled in by @@ -119,6 +128,9 @@ class TestUtil { static void ExpectRepeatedExtensionsSwapped( const unittest::TestAllExtensions& message); + static void ExpectAtMostOneFieldSetInOneof( + const unittest::TestOneof2 &message); + // Like above, but use the reflection interface. class ReflectionTester { public: @@ -143,6 +155,11 @@ class TestUtil { void ReleaseLastRepeatedsViaReflection( Message* message, bool expect_extensions_notnull); void SwapRepeatedsViaReflection(Message* message); + void SetAllocatedOptionalMessageFieldsToNullViaReflection( + Message* message); + static void SetAllocatedOptionalMessageFieldsToMessageViaReflection( + Message* from_message, + Message* to_message); enum MessageReleaseState { IS_NULL, @@ -152,6 +169,11 @@ class TestUtil { void ExpectMessagesReleasedViaReflection( Message* message, MessageReleaseState expected_release_state); + // Set and check functions for TestOneof2 messages. No need to construct + // the ReflectionTester by TestAllTypes nor TestAllExtensions. + static void SetOneofViaReflection(Message* message); + static void ExpectOneofSetViaReflection(const Message& message); + private: const FieldDescriptor* F(const string& name); diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc index 9099292a..cbf808be 100644 --- a/src/google/protobuf/test_util_lite.cc +++ b/src/google/protobuf/test_util_lite.cc @@ -153,6 +153,11 @@ void TestUtilLite::SetAllFields(unittest::TestAllTypesLite* message) { message->set_default_foreign_enum(unittest::FOREIGN_LITE_FOO ); message->set_default_import_enum (unittest_import::IMPORT_LITE_FOO); + + message->set_oneof_uint32(601); + message->mutable_oneof_nested_message()->set_bb(602); + message->set_oneof_string("603"); + message->set_oneof_bytes("604"); } // ------------------------------------------------------------------- @@ -378,6 +383,13 @@ void TestUtilLite::ExpectAllFieldsSet( EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.default_foreign_enum()); EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.default_import_enum ()); + + EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string ()); + EXPECT_TRUE(message.has_oneof_bytes ()); + + EXPECT_EQ("604", message.oneof_bytes()); } // ------------------------------------------------------------------- @@ -518,6 +530,11 @@ void TestUtilLite::ExpectClear(const unittest::TestAllTypesLite& message) { EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.default_foreign_enum()); EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.default_import_enum ()); + + EXPECT_FALSE(message.has_oneof_uint32 ()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string ()); + EXPECT_FALSE(message.has_oneof_bytes ()); } // ------------------------------------------------------------------- @@ -900,6 +917,11 @@ void TestUtilLite::SetAllExtensions(unittest::TestAllExtensionsLite* message) { message->SetExtension(unittest::default_foreign_enum_extension_lite, unittest::FOREIGN_LITE_FOO ); message->SetExtension(unittest::default_import_enum_extension_lite , unittest_import::IMPORT_LITE_FOO); + + message->SetExtension(unittest::oneof_uint32_extension_lite, 601); + message->MutableExtension(unittest::oneof_nested_message_extension_lite)->set_bb(602);; + message->SetExtension(unittest::oneof_string_extension_lite, "603"); + message->SetExtension(unittest::oneof_bytes_extension_lite, "604"); } // ------------------------------------------------------------------- @@ -1126,6 +1148,16 @@ void TestUtilLite::ExpectAllExtensionsSet( EXPECT_EQ(unittest::FOREIGN_LITE_FOO , message.GetExtension(unittest::default_foreign_enum_extension_lite)); EXPECT_EQ(unittest_import::IMPORT_LITE_FOO, message.GetExtension(unittest::default_import_enum_extension_lite )); + + EXPECT_TRUE(message.HasExtension(unittest::oneof_uint32_extension_lite)); + EXPECT_TRUE(message.GetExtension(unittest::oneof_nested_message_extension_lite).has_bb()); + EXPECT_TRUE(message.HasExtension(unittest::oneof_string_extension_lite)); + EXPECT_TRUE(message.HasExtension(unittest::oneof_bytes_extension_lite)); + + EXPECT_EQ(601, message.GetExtension(unittest::oneof_uint32_extension_lite)); + EXPECT_EQ(602, message.GetExtension(unittest::oneof_nested_message_extension_lite).bb()); + EXPECT_EQ("603", message.GetExtension(unittest::oneof_string_extension_lite)); + EXPECT_EQ("604", message.GetExtension(unittest::oneof_bytes_extension_lite)); } // ------------------------------------------------------------------- @@ -1274,6 +1306,11 @@ void TestUtilLite::ExpectExtensionsClear( EXPECT_EQ(unittest::FOREIGN_LITE_BAR , message.GetExtension(unittest::default_foreign_enum_extension_lite)); EXPECT_EQ(unittest_import::IMPORT_LITE_BAR, message.GetExtension(unittest::default_import_enum_extension_lite )); + + EXPECT_FALSE(message.HasExtension(unittest::oneof_uint32_extension_lite)); + EXPECT_FALSE(message.GetExtension(unittest::oneof_nested_message_extension_lite).has_bb()); + EXPECT_FALSE(message.HasExtension(unittest::oneof_string_extension_lite)); + EXPECT_FALSE(message.HasExtension(unittest::oneof_bytes_extension_lite)); } // ------------------------------------------------------------------- diff --git a/src/google/protobuf/testdata/bad_utf8_string b/src/google/protobuf/testdata/bad_utf8_string new file mode 100644 index 00000000..a1337ec6 --- /dev/null +++ b/src/google/protobuf/testdata/bad_utf8_string @@ -0,0 +1 @@ +rÿ \ No newline at end of file diff --git a/src/google/protobuf/testdata/golden_message b/src/google/protobuf/testdata/golden_message index 4dd62cd3..0b7e6552 100644 Binary files a/src/google/protobuf/testdata/golden_message and b/src/google/protobuf/testdata/golden_message differ diff --git a/src/google/protobuf/testdata/golden_message_oneof_implemented b/src/google/protobuf/testdata/golden_message_oneof_implemented new file mode 100644 index 00000000..b48c8985 Binary files /dev/null and b/src/google/protobuf/testdata/golden_message_oneof_implemented differ diff --git a/src/google/protobuf/testdata/text_format_unittest_data.txt b/src/google/protobuf/testdata/text_format_unittest_data.txt index bbe58826..7a874b54 100644 --- a/src/google/protobuf/testdata/text_format_unittest_data.txt +++ b/src/google/protobuf/testdata/text_format_unittest_data.txt @@ -126,3 +126,9 @@ default_foreign_enum: FOREIGN_FOO default_import_enum: IMPORT_FOO default_string_piece: "424" default_cord: "425" +oneof_uint32: 601 +oneof_nested_message { + bb: 602 +} +oneof_string: "603" +oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt b/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt new file mode 100644 index 00000000..ec95e1e8 --- /dev/null +++ b/src/google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt @@ -0,0 +1,129 @@ +optional_int32: 101 +optional_int64: 102 +optional_uint32: 103 +optional_uint64: 104 +optional_sint32: 105 +optional_sint64: 106 +optional_fixed32: 107 +optional_fixed64: 108 +optional_sfixed32: 109 +optional_sfixed64: 110 +optional_float: 111 +optional_double: 112 +optional_bool: true +optional_string: "115" +optional_bytes: "116" +OptionalGroup { + a: 117 +} +optional_nested_message { + bb: 118 +} +optional_foreign_message { + c: 119 +} +optional_import_message { + d: 120 +} +optional_nested_enum: BAZ +optional_foreign_enum: FOREIGN_BAZ +optional_import_enum: IMPORT_BAZ +optional_string_piece: "124" +optional_cord: "125" +optional_public_import_message { + e: 126 +} +optional_lazy_message { + bb: 127 +} +repeated_int32: 201 +repeated_int32: 301 +repeated_int64: 202 +repeated_int64: 302 +repeated_uint32: 203 +repeated_uint32: 303 +repeated_uint64: 204 +repeated_uint64: 304 +repeated_sint32: 205 +repeated_sint32: 305 +repeated_sint64: 206 +repeated_sint64: 306 +repeated_fixed32: 207 +repeated_fixed32: 307 +repeated_fixed64: 208 +repeated_fixed64: 308 +repeated_sfixed32: 209 +repeated_sfixed32: 309 +repeated_sfixed64: 210 +repeated_sfixed64: 310 +repeated_float: 211 +repeated_float: 311 +repeated_double: 212 +repeated_double: 312 +repeated_bool: true +repeated_bool: false +repeated_string: "215" +repeated_string: "315" +repeated_bytes: "216" +repeated_bytes: "316" +RepeatedGroup { + a: 217 +} +RepeatedGroup { + a: 317 +} +repeated_nested_message { + bb: 218 +} +repeated_nested_message { + bb: 318 +} +repeated_foreign_message { + c: 219 +} +repeated_foreign_message { + c: 319 +} +repeated_import_message { + d: 220 +} +repeated_import_message { + d: 320 +} +repeated_nested_enum: BAR +repeated_nested_enum: BAZ +repeated_foreign_enum: FOREIGN_BAR +repeated_foreign_enum: FOREIGN_BAZ +repeated_import_enum: IMPORT_BAR +repeated_import_enum: IMPORT_BAZ +repeated_string_piece: "224" +repeated_string_piece: "324" +repeated_cord: "225" +repeated_cord: "325" +repeated_lazy_message { + bb: 227 +} +repeated_lazy_message { + bb: 327 +} +default_int32: 401 +default_int64: 402 +default_uint32: 403 +default_uint64: 404 +default_sint32: 405 +default_sint64: 406 +default_fixed32: 407 +default_fixed64: 408 +default_sfixed32: 409 +default_sfixed64: 410 +default_float: 411 +default_double: 412 +default_bool: false +default_string: "415" +default_bytes: "416" +default_nested_enum: FOO +default_foreign_enum: FOREIGN_FOO +default_import_enum: IMPORT_FOO +default_string_piece: "424" +default_cord: "425" +oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt b/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt new file mode 100644 index 00000000..e1011ebf --- /dev/null +++ b/src/google/protobuf/testdata/text_format_unittest_data_pointy.txt @@ -0,0 +1,134 @@ +optional_int32: 101 +optional_int64: 102 +optional_uint32: 103 +optional_uint64: 104 +optional_sint32: 105 +optional_sint64: 106 +optional_fixed32: 107 +optional_fixed64: 108 +optional_sfixed32: 109 +optional_sfixed64: 110 +optional_float: 111 +optional_double: 112 +optional_bool: true +optional_string: "115" +optional_bytes: "116" +OptionalGroup < + a: 117 +> +optional_nested_message < + bb: 118 +> +optional_foreign_message < + c: 119 +> +optional_import_message < + d: 120 +> +optional_nested_enum: BAZ +optional_foreign_enum: FOREIGN_BAZ +optional_import_enum: IMPORT_BAZ +optional_string_piece: "124" +optional_cord: "125" +optional_public_import_message < + e: 126 +> +optional_lazy_message < + bb: 127 +> +repeated_int32: 201 +repeated_int32: 301 +repeated_int64: 202 +repeated_int64: 302 +repeated_uint32: 203 +repeated_uint32: 303 +repeated_uint64: 204 +repeated_uint64: 304 +repeated_sint32: 205 +repeated_sint32: 305 +repeated_sint64: 206 +repeated_sint64: 306 +repeated_fixed32: 207 +repeated_fixed32: 307 +repeated_fixed64: 208 +repeated_fixed64: 308 +repeated_sfixed32: 209 +repeated_sfixed32: 309 +repeated_sfixed64: 210 +repeated_sfixed64: 310 +repeated_float: 211 +repeated_float: 311 +repeated_double: 212 +repeated_double: 312 +repeated_bool: true +repeated_bool: false +repeated_string: "215" +repeated_string: "315" +repeated_bytes: "216" +repeated_bytes: "316" +RepeatedGroup < + a: 217 +> +RepeatedGroup < + a: 317 +> +repeated_nested_message < + bb: 218 +> +repeated_nested_message < + bb: 318 +> +repeated_foreign_message < + c: 219 +> +repeated_foreign_message < + c: 319 +> +repeated_import_message < + d: 220 +> +repeated_import_message < + d: 320 +> +repeated_nested_enum: BAR +repeated_nested_enum: BAZ +repeated_foreign_enum: FOREIGN_BAR +repeated_foreign_enum: FOREIGN_BAZ +repeated_import_enum: IMPORT_BAR +repeated_import_enum: IMPORT_BAZ +repeated_string_piece: "224" +repeated_string_piece: "324" +repeated_cord: "225" +repeated_cord: "325" +repeated_lazy_message < + bb: 227 +> +repeated_lazy_message < + bb: 327 +> +default_int32: 401 +default_int64: 402 +default_uint32: 403 +default_uint64: 404 +default_sint32: 405 +default_sint64: 406 +default_fixed32: 407 +default_fixed64: 408 +default_sfixed32: 409 +default_sfixed64: 410 +default_float: 411 +default_double: 412 +default_bool: false +default_string: "415" +default_bytes: "416" +default_nested_enum: FOO +default_foreign_enum: FOREIGN_FOO +default_import_enum: IMPORT_FOO +default_string_piece: "424" +default_cord: "425" +oneof_uint32: 601 +oneof_nested_message < + bb: 602 +> +oneof_string: "603" +oneof_bytes: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt index 0a217f02..8c8b1eb4 100644 --- a/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt +++ b/src/google/protobuf/testdata/text_format_unittest_extensions_data.txt @@ -126,3 +126,9 @@ [protobuf_unittest.default_import_enum_extension]: IMPORT_FOO [protobuf_unittest.default_string_piece_extension]: "424" [protobuf_unittest.default_cord_extension]: "425" +[protobuf_unittest.oneof_uint32_extension]: 601 +[protobuf_unittest.oneof_nested_message_extension] { + bb: 602 +} +[protobuf_unittest.oneof_string_extension]: "603" +[protobuf_unittest.oneof_bytes_extension]: "604" diff --git a/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt b/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt new file mode 100644 index 00000000..132f7445 --- /dev/null +++ b/src/google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt @@ -0,0 +1,134 @@ +[protobuf_unittest.optional_int32_extension]: 101 +[protobuf_unittest.optional_int64_extension]: 102 +[protobuf_unittest.optional_uint32_extension]: 103 +[protobuf_unittest.optional_uint64_extension]: 104 +[protobuf_unittest.optional_sint32_extension]: 105 +[protobuf_unittest.optional_sint64_extension]: 106 +[protobuf_unittest.optional_fixed32_extension]: 107 +[protobuf_unittest.optional_fixed64_extension]: 108 +[protobuf_unittest.optional_sfixed32_extension]: 109 +[protobuf_unittest.optional_sfixed64_extension]: 110 +[protobuf_unittest.optional_float_extension]: 111 +[protobuf_unittest.optional_double_extension]: 112 +[protobuf_unittest.optional_bool_extension]: true +[protobuf_unittest.optional_string_extension]: "115" +[protobuf_unittest.optional_bytes_extension]: "116" +[protobuf_unittest.optionalgroup_extension] < + a: 117 +> +[protobuf_unittest.optional_nested_message_extension] < + bb: 118 +> +[protobuf_unittest.optional_foreign_message_extension] < + c: 119 +> +[protobuf_unittest.optional_import_message_extension] < + d: 120 +> +[protobuf_unittest.optional_nested_enum_extension]: BAZ +[protobuf_unittest.optional_foreign_enum_extension]: FOREIGN_BAZ +[protobuf_unittest.optional_import_enum_extension]: IMPORT_BAZ +[protobuf_unittest.optional_string_piece_extension]: "124" +[protobuf_unittest.optional_cord_extension]: "125" +[protobuf_unittest.optional_public_import_message_extension] < + e: 126 +> +[protobuf_unittest.optional_lazy_message_extension] < + bb: 127 +> +[protobuf_unittest.repeated_int32_extension]: 201 +[protobuf_unittest.repeated_int32_extension]: 301 +[protobuf_unittest.repeated_int64_extension]: 202 +[protobuf_unittest.repeated_int64_extension]: 302 +[protobuf_unittest.repeated_uint32_extension]: 203 +[protobuf_unittest.repeated_uint32_extension]: 303 +[protobuf_unittest.repeated_uint64_extension]: 204 +[protobuf_unittest.repeated_uint64_extension]: 304 +[protobuf_unittest.repeated_sint32_extension]: 205 +[protobuf_unittest.repeated_sint32_extension]: 305 +[protobuf_unittest.repeated_sint64_extension]: 206 +[protobuf_unittest.repeated_sint64_extension]: 306 +[protobuf_unittest.repeated_fixed32_extension]: 207 +[protobuf_unittest.repeated_fixed32_extension]: 307 +[protobuf_unittest.repeated_fixed64_extension]: 208 +[protobuf_unittest.repeated_fixed64_extension]: 308 +[protobuf_unittest.repeated_sfixed32_extension]: 209 +[protobuf_unittest.repeated_sfixed32_extension]: 309 +[protobuf_unittest.repeated_sfixed64_extension]: 210 +[protobuf_unittest.repeated_sfixed64_extension]: 310 +[protobuf_unittest.repeated_float_extension]: 211 +[protobuf_unittest.repeated_float_extension]: 311 +[protobuf_unittest.repeated_double_extension]: 212 +[protobuf_unittest.repeated_double_extension]: 312 +[protobuf_unittest.repeated_bool_extension]: true +[protobuf_unittest.repeated_bool_extension]: false +[protobuf_unittest.repeated_string_extension]: "215" +[protobuf_unittest.repeated_string_extension]: "315" +[protobuf_unittest.repeated_bytes_extension]: "216" +[protobuf_unittest.repeated_bytes_extension]: "316" +[protobuf_unittest.repeatedgroup_extension] < + a: 217 +> +[protobuf_unittest.repeatedgroup_extension] < + a: 317 +> +[protobuf_unittest.repeated_nested_message_extension] < + bb: 218 +> +[protobuf_unittest.repeated_nested_message_extension] < + bb: 318 +> +[protobuf_unittest.repeated_foreign_message_extension] < + c: 219 +> +[protobuf_unittest.repeated_foreign_message_extension] < + c: 319 +> +[protobuf_unittest.repeated_import_message_extension] < + d: 220 +> +[protobuf_unittest.repeated_import_message_extension] < + d: 320 +> +[protobuf_unittest.repeated_nested_enum_extension]: BAR +[protobuf_unittest.repeated_nested_enum_extension]: BAZ +[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAR +[protobuf_unittest.repeated_foreign_enum_extension]: FOREIGN_BAZ +[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAR +[protobuf_unittest.repeated_import_enum_extension]: IMPORT_BAZ +[protobuf_unittest.repeated_string_piece_extension]: "224" +[protobuf_unittest.repeated_string_piece_extension]: "324" +[protobuf_unittest.repeated_cord_extension]: "225" +[protobuf_unittest.repeated_cord_extension]: "325" +[protobuf_unittest.repeated_lazy_message_extension] < + bb: 227 +> +[protobuf_unittest.repeated_lazy_message_extension] < + bb: 327 +> +[protobuf_unittest.default_int32_extension]: 401 +[protobuf_unittest.default_int64_extension]: 402 +[protobuf_unittest.default_uint32_extension]: 403 +[protobuf_unittest.default_uint64_extension]: 404 +[protobuf_unittest.default_sint32_extension]: 405 +[protobuf_unittest.default_sint64_extension]: 406 +[protobuf_unittest.default_fixed32_extension]: 407 +[protobuf_unittest.default_fixed64_extension]: 408 +[protobuf_unittest.default_sfixed32_extension]: 409 +[protobuf_unittest.default_sfixed64_extension]: 410 +[protobuf_unittest.default_float_extension]: 411 +[protobuf_unittest.default_double_extension]: 412 +[protobuf_unittest.default_bool_extension]: false +[protobuf_unittest.default_string_extension]: "415" +[protobuf_unittest.default_bytes_extension]: "416" +[protobuf_unittest.default_nested_enum_extension]: FOO +[protobuf_unittest.default_foreign_enum_extension]: FOREIGN_FOO +[protobuf_unittest.default_import_enum_extension]: IMPORT_FOO +[protobuf_unittest.default_string_piece_extension]: "424" +[protobuf_unittest.default_cord_extension]: "425" +[protobuf_unittest.oneof_uint32_extension]: 601 +[protobuf_unittest.oneof_nested_message_extension] < + bb: 602 +> +[protobuf_unittest.oneof_string_extension]: "603" +[protobuf_unittest.oneof_bytes_extension]: "604" diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc index e224781d..9a5b35e8 100644 --- a/src/google/protobuf/testing/file.cc +++ b/src/google/protobuf/testing/file.cc @@ -82,6 +82,24 @@ void File::ReadFileToStringOrDie(const string& name, string* output) { GOOGLE_CHECK(ReadFileToString(name, output)) << "Could not read: " << name; } +bool File::WriteStringToFile(const string& contents, const string& name) { + FILE* file = fopen(name.c_str(), "wb"); + if (file == NULL) { + GOOGLE_LOG(ERROR) << "fopen(" << name << ", \"wb\"): " << strerror(errno); + return false; + } + + if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) { + GOOGLE_LOG(ERROR) << "fwrite(" << name << "): " << strerror(errno); + return false; + } + + if (fclose(file) != 0) { + return false; + } + return true; +} + void File::WriteStringToFileOrDie(const string& contents, const string& name) { FILE* file = fopen(name.c_str(), "wb"); GOOGLE_CHECK(file != NULL) diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h index a6b1c764..91ecce92 100644 --- a/src/google/protobuf/testing/file.h +++ b/src/google/protobuf/testing/file.h @@ -56,6 +56,10 @@ class File { static void ReadFileToStringOrDie(const string& name, string* output); // Create a file and write a string to it. + static bool WriteStringToFile(const string& contents, + const string& name); + + // Same as above, but crash on failure. static void WriteStringToFileOrDie(const string& contents, const string& name); @@ -73,6 +77,16 @@ class File { static void DeleteRecursively(const string& name, void* dummy1, void* dummy2); + static bool GetContents( + const string& name, string* output, bool /*is_default*/) { + return ReadFileToString(name, output); + } + + static bool SetContents( + const string& name, const string& contents, bool /*is_default*/) { + return WriteStringToFile(contents, name); + } + private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(File); }; diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index b2ea7ee8..3ecb110f 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -32,6 +32,7 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include #include #include #include @@ -42,6 +43,7 @@ #include #include +#include #include #include #include @@ -49,12 +51,26 @@ #include #include #include -#include +#include #include namespace google { namespace protobuf { +namespace { + +inline bool IsHexNumber(const string& str) { + return (str.length() >= 2 && str[0] == '0' && + (str[1] == 'x' || str[1] == 'X')); +} + +inline bool IsOctNumber(const string& str) { + return (str.length() >= 2 && str[0] == '0' && + (str[1] >= '0' && str[1] < '8')); +} + +} // namespace + string Message::DebugString() const { string debug_string; @@ -177,9 +193,10 @@ TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( class TextFormat::Parser::ParserImpl { public: - // Determines if repeated values for a non-repeated field are - // permitted, e.g., the string "foo: 1 foo: 2" for a - // required/optional field named "foo". + // Determines if repeated values for non-repeated fields and + // oneofs are permitted, e.g., the string "foo: 1 foo: 2" for a + // required/optional field named "foo", or "baz: 1 qux: 2" + // where "baz" and "qux" are members of the same oneof. enum SingularOverwritePolicy { ALLOW_SINGULAR_OVERWRITES = 0, // the last value is retained FORBID_SINGULAR_OVERWRITES = 1, // an error is issued @@ -191,7 +208,11 @@ class TextFormat::Parser::ParserImpl { TextFormat::Finder* finder, ParseInfoTree* parse_info_tree, SingularOverwritePolicy singular_overwrite_policy, - bool allow_unknown_field) + bool allow_case_insensitive_field, + bool allow_unknown_field, + bool allow_unknown_enum, + bool allow_field_number, + bool allow_relaxed_whitespace) : error_collector_(error_collector), finder_(finder), parse_info_tree_(parse_info_tree), @@ -199,7 +220,10 @@ class TextFormat::Parser::ParserImpl { tokenizer_(input_stream, &tokenizer_error_collector_), root_message_type_(root_message_type), singular_overwrite_policy_(singular_overwrite_policy), + allow_case_insensitive_field_(allow_case_insensitive_field), allow_unknown_field_(allow_unknown_field), + allow_unknown_enum_(allow_unknown_enum), + allow_field_number_(allow_field_number), had_errors_(false) { // For backwards-compatibility with proto1, we need to allow the 'f' suffix // for floats. @@ -208,6 +232,11 @@ class TextFormat::Parser::ParserImpl { // '#' starts a comment. tokenizer_.set_comment_style(io::Tokenizer::SH_COMMENT_STYLE); + if (allow_relaxed_whitespace) { + tokenizer_.set_require_space_after_number(false); + tokenizer_.set_allow_multiline_strings(true); + } + // Consume the starting token. tokenizer_.Next(); } @@ -219,7 +248,7 @@ class TextFormat::Parser::ParserImpl { // GOOGLE_LOG(ERROR)). bool Parse(Message* output) { // Consume fields until we cannot do so anymore. - while(true) { + while (true) { if (LookingAtType(io::Tokenizer::TYPE_END)) { return !had_errors_; } @@ -304,6 +333,7 @@ class TextFormat::Parser::ParserImpl { return true; } + // Consumes the current field (as returned by the tokenizer) on the // passed in message. bool ConsumeField(Message* message) { @@ -346,23 +376,38 @@ class TextFormat::Parser::ParserImpl { } else { DO(ConsumeIdentifier(&field_name)); - field = descriptor->FindFieldByName(field_name); - // Group names are expected to be capitalized as they appear in the - // .proto file, which actually matches their type names, not their field - // names. - if (field == NULL) { - string lower_field_name = field_name; - LowerString(&lower_field_name); - field = descriptor->FindFieldByName(lower_field_name); - // If the case-insensitive match worked but the field is NOT a group, - if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) { + int32 field_number; + if (allow_field_number_ && safe_strto32(field_name, &field_number)) { + if (descriptor->IsExtensionNumber(field_number)) { + field = reflection->FindKnownExtensionByNumber(field_number); + } else { + field = descriptor->FindFieldByNumber(field_number); + } + } else { + field = descriptor->FindFieldByName(field_name); + // Group names are expected to be capitalized as they appear in the + // .proto file, which actually matches their type names, not their + // field names. + if (field == NULL) { + string lower_field_name = field_name; + LowerString(&lower_field_name); + field = descriptor->FindFieldByName(lower_field_name); + // If the case-insensitive match worked but the field is NOT a group, + if (field != NULL && field->type() != FieldDescriptor::TYPE_GROUP) { + field = NULL; + } + } + // Again, special-case group names as described above. + if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP + && field->message_type()->name() != field_name) { field = NULL; } - } - // Again, special-case group names as described above. - if (field != NULL && field->type() == FieldDescriptor::TYPE_GROUP - && field->message_type()->name() != field_name) { - field = NULL; + + if (field == NULL && allow_case_insensitive_field_) { + string lower_field_name = field_name; + LowerString(&lower_field_name); + field = descriptor->FindFieldByLowercaseName(lower_field_name); + } } if (field == NULL) { @@ -393,33 +438,53 @@ class TextFormat::Parser::ParserImpl { } } - // Fail if the field is not repeated and it has already been specified. - if ((singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) && - !field->is_repeated() && reflection->HasField(*message, field)) { - ReportError("Non-repeated field \"" + field_name + - "\" is specified multiple times."); - return false; + if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { + // Fail if the field is not repeated and it has already been specified. + if (!field->is_repeated() && reflection->HasField(*message, field)) { + ReportError("Non-repeated field \"" + field_name + + "\" is specified multiple times."); + return false; + } + // Fail if the field is a member of a oneof and another member has already + // been specified. + const OneofDescriptor* oneof = field->containing_oneof(); + if (oneof != NULL && reflection->HasOneof(*message, oneof)) { + const FieldDescriptor* other_field = + reflection->GetOneofFieldDescriptor(*message, oneof); + ReportError("Field \"" + field_name + "\" is specified along with " + "field \"" + other_field->name() + "\", another member " + "of oneof \"" + oneof->name() + "\"."); + return false; + } } // Perform special handling for embedded message types. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // ':' is optional here. TryConsume(":"); - DO(ConsumeFieldMessage(message, reflection, field)); } else { + // ':' is required here. DO(Consume(":")); - if (field->is_repeated() && TryConsume("[")) { - // Short repeated format, e.g. "foo: [1, 2, 3]" - while (true) { + } + + if (field->is_repeated() && TryConsume("[")) { + // Short repeated format, e.g. "foo: [1, 2, 3]" + while (true) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Perform special handling for embedded message types. + DO(ConsumeFieldMessage(message, reflection, field)); + } else { DO(ConsumeFieldValue(message, reflection, field)); - if (TryConsume("]")) { - break; - } - DO(Consume(",")); } - } else { - DO(ConsumeFieldValue(message, reflection, field)); + if (TryConsume("]")) { + break; + } + DO(Consume(",")); } + } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + DO(ConsumeFieldMessage(message, reflection, field)); + } else { + DO(ConsumeFieldValue(message, reflection, field)); } // For historical reasons, fields may optionally be separated by commas or @@ -595,9 +660,9 @@ class TextFormat::Parser::ParserImpl { } else { string value; DO(ConsumeIdentifier(&value)); - if (value == "true" || value == "t") { + if (value == "true" || value == "True" || value == "t") { SET_FIELD(Bool, true); - } else if (value == "false" || value == "f") { + } else if (value == "false" || value == "False" || value == "f") { SET_FIELD(Bool, false); } else { ReportError("Invalid value for boolean field \"" + field->name() @@ -630,9 +695,15 @@ class TextFormat::Parser::ParserImpl { } if (enum_value == NULL) { - ReportError("Unknown enumeration value of \"" + value + "\" for " - "field \"" + field->name() + "\"."); - return false; + if (!allow_unknown_enum_) { + ReportError("Unknown enumeration value of \"" + value + "\" for " + "field \"" + field->name() + "\"."); + return false; + } else { + ReportWarning("Unknown enumeration value of \"" + value + "\" for " + "field \"" + field->name() + "\"."); + return true; + } } SET_FIELD(Enum, enum_value); @@ -717,15 +788,23 @@ class TextFormat::Parser::ParserImpl { // Consumes an identifier and saves its value in the identifier parameter. // Returns false if the token is not of type IDENTFIER. bool ConsumeIdentifier(string* identifier) { - if (!LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { - ReportError("Expected identifier."); - return false; + if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) { + *identifier = tokenizer_.current().text; + tokenizer_.Next(); + return true; } - *identifier = tokenizer_.current().text; + // If allow_field_numer_ or allow_unknown_field_ is true, we should able + // to parse integer identifiers. + if ((allow_field_number_ || allow_unknown_field_) + && LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + *identifier = tokenizer_.current().text; + tokenizer_.Next(); + return true; + } - tokenizer_.Next(); - return true; + ReportError("Expected identifier."); + return false; } // Consumes a string and saves its value in the text parameter. @@ -792,6 +871,29 @@ class TextFormat::Parser::ParserImpl { return true; } + // Consumes a uint64 and saves its value in the value parameter. + // Accepts decimal numbers only, rejects hex or oct numbers. + bool ConsumeUnsignedDecimalInteger(uint64* value, uint64 max_value) { + if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { + ReportError("Expected integer."); + return false; + } + + const string& text = tokenizer_.current().text; + if (IsHexNumber(text) || IsOctNumber(text)) { + ReportError("Expect a decimal number."); + return false; + } + + if (!io::Tokenizer::ParseInteger(text, max_value, value)) { + ReportError("Integer out of range."); + return false; + } + + tokenizer_.Next(); + return true; + } + // Consumes a double and saves its value in the value parameter. // Note that since the tokenizer does not support negative numbers, // we actually may consume an additional token (for the minus sign) in this @@ -809,7 +911,7 @@ class TextFormat::Parser::ParserImpl { if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) { // We have found an integer value for the double. uint64 integer_value; - DO(ConsumeUnsignedInteger(&integer_value, kuint64max)); + DO(ConsumeUnsignedDecimalInteger(&integer_value, kuint64max)); *value = static_cast(integer_value); } else if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) { @@ -879,7 +981,7 @@ class TextFormat::Parser::ParserImpl { explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser) : parser_(parser) { } - virtual ~ParserErrorCollector() { }; + virtual ~ParserErrorCollector() { } virtual void AddError(int line, int column, const string& message) { parser_->ReportError(line, column, message); @@ -901,7 +1003,10 @@ class TextFormat::Parser::ParserImpl { io::Tokenizer tokenizer_; const Descriptor* root_message_type_; SingularOverwritePolicy singular_overwrite_policy_; - bool allow_unknown_field_; + const bool allow_case_insensitive_field_; + const bool allow_unknown_field_; + const bool allow_unknown_enum_; + const bool allow_field_number_; bool had_errors_; }; @@ -1039,7 +1144,12 @@ TextFormat::Parser::Parser() finder_(NULL), parse_info_tree_(NULL), allow_partial_(false), - allow_unknown_field_(false) { + allow_case_insensitive_field_(false), + allow_unknown_field_(false), + allow_unknown_enum_(false), + allow_field_number_(false), + allow_relaxed_whitespace_(false), + allow_singular_overwrites_(false) { } TextFormat::Parser::~Parser() {} @@ -1047,10 +1157,18 @@ TextFormat::Parser::~Parser() {} bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, Message* output) { output->Clear(); + + ParserImpl::SingularOverwritePolicy overwrites_policy = + allow_singular_overwrites_ + ? ParserImpl::ALLOW_SINGULAR_OVERWRITES + : ParserImpl::FORBID_SINGULAR_OVERWRITES; + ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, parse_info_tree_, - ParserImpl::FORBID_SINGULAR_OVERWRITES, - allow_unknown_field_); + overwrites_policy, + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_enum_, allow_field_number_, + allow_relaxed_whitespace_); return MergeUsingImpl(input, output, &parser); } @@ -1065,7 +1183,9 @@ bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, ParserImpl parser(output->GetDescriptor(), input, error_collector_, finder_, parse_info_tree_, ParserImpl::ALLOW_SINGULAR_OVERWRITES, - allow_unknown_field_); + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_enum_, allow_field_number_, + allow_relaxed_whitespace_); return MergeUsingImpl(input, output, &parser); } @@ -1083,7 +1203,7 @@ bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */, vector missing_fields; output->FindInitializationErrors(&missing_fields); parser_impl->ReportError(-1, 0, "Message missing required fields: " + - JoinStrings(missing_fields, ", ")); + Join(missing_fields, ", ")); return false; } return true; @@ -1097,7 +1217,9 @@ bool TextFormat::Parser::ParseFieldValueFromString( ParserImpl parser(output->GetDescriptor(), &input_stream, error_collector_, finder_, parse_info_tree_, ParserImpl::ALLOW_SINGULAR_OVERWRITES, - allow_unknown_field_); + allow_case_insensitive_field_, allow_unknown_field_, + allow_unknown_enum_, allow_field_number_, + allow_relaxed_whitespace_); return parser.ParseField(field, output); } @@ -1123,13 +1245,124 @@ bool TextFormat::Parser::ParseFieldValueFromString( // =========================================================================== +// The default implementation for FieldValuePrinter. The base class just +// does simple formatting. That way, deriving classes could decide to fallback +// to that behavior. +TextFormat::FieldValuePrinter::FieldValuePrinter() {} +TextFormat::FieldValuePrinter::~FieldValuePrinter() {} +string TextFormat::FieldValuePrinter::PrintBool(bool val) const { + return val ? "true" : "false"; +} +string TextFormat::FieldValuePrinter::PrintInt32(int32 val) const { + return SimpleItoa(val); +} +string TextFormat::FieldValuePrinter::PrintUInt32(uint32 val) const { + return SimpleItoa(val); +} +string TextFormat::FieldValuePrinter::PrintInt64(int64 val) const { + return SimpleItoa(val); +} +string TextFormat::FieldValuePrinter::PrintUInt64(uint64 val) const { + return SimpleItoa(val); +} +string TextFormat::FieldValuePrinter::PrintFloat(float val) const { + return SimpleFtoa(val); +} +string TextFormat::FieldValuePrinter::PrintDouble(double val) const { + return SimpleDtoa(val); +} +string TextFormat::FieldValuePrinter::PrintString(const string& val) const { + return StrCat("\"", CEscape(val), "\""); +} +string TextFormat::FieldValuePrinter::PrintBytes(const string& val) const { + return PrintString(val); +} +string TextFormat::FieldValuePrinter::PrintEnum(int32 val, + const string& name) const { + return name; +} +string TextFormat::FieldValuePrinter::PrintFieldName( + const Message& message, + const Reflection* reflection, + const FieldDescriptor* field) const { + if (field->is_extension()) { + // We special-case MessageSet elements for compatibility with proto1. + if (field->containing_type()->options().message_set_wire_format() + && field->type() == FieldDescriptor::TYPE_MESSAGE + && field->is_optional() + && field->extension_scope() == field->message_type()) { + return StrCat("[", field->message_type()->full_name(), "]"); + } else { + return StrCat("[", field->full_name(), "]"); + } + } else if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Groups must be serialized with their original capitalization. + return field->message_type()->name(); + } else { + return field->name(); + } +} +string TextFormat::FieldValuePrinter::PrintMessageStart( + const Message& message, + int field_index, + int field_count, + bool single_line_mode) const { + return single_line_mode ? " { " : " {\n"; +} +string TextFormat::FieldValuePrinter::PrintMessageEnd( + const Message& message, + int field_index, + int field_count, + bool single_line_mode) const { + return single_line_mode ? "} " : "}\n"; +} + +namespace { +// Our own specialization: for UTF8 escaped strings. +class FieldValuePrinterUtf8Escaping : public TextFormat::FieldValuePrinter { + public: + virtual string PrintString(const string& val) const { + return StrCat("\"", strings::Utf8SafeCEscape(val), "\""); + } + virtual string PrintBytes(const string& val) const { + return TextFormat::FieldValuePrinter::PrintString(val); + } +}; + +} // namespace + TextFormat::Printer::Printer() : initial_indent_level_(0), single_line_mode_(false), + use_field_number_(false), use_short_repeated_primitives_(false), - utf8_string_escaping_(false) {} + hide_unknown_fields_(false), + print_message_fields_in_index_order_(false) { + SetUseUtf8StringEscaping(false); +} -TextFormat::Printer::~Printer() {} +TextFormat::Printer::~Printer() { + STLDeleteValues(&custom_printers_); +} + +void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) { + SetDefaultFieldValuePrinter(as_utf8 + ? new FieldValuePrinterUtf8Escaping() + : new FieldValuePrinter()); +} + +void TextFormat::Printer::SetDefaultFieldValuePrinter( + const FieldValuePrinter* printer) { + default_field_value_printer_.reset(printer); +} + +bool TextFormat::Printer::RegisterFieldValuePrinter( + const FieldDescriptor* field, + const FieldValuePrinter* printer) { + return field != NULL + && printer != NULL + && custom_printers_.insert(make_pair(field, printer)).second; +} bool TextFormat::Printer::PrintToString(const Message& message, string* output) const { @@ -1138,9 +1371,7 @@ bool TextFormat::Printer::PrintToString(const Message& message, output->clear(); io::StringOutputStream output_stream(output); - bool result = Print(message, &output_stream); - - return result; + return Print(message, &output_stream); } bool TextFormat::Printer::PrintUnknownFieldsToString( @@ -1174,15 +1405,30 @@ bool TextFormat::Printer::PrintUnknownFields( return !generator.failed(); } +namespace { +// Comparison functor for sorting FieldDescriptors by field index. +struct FieldIndexSorter { + bool operator()(const FieldDescriptor* left, + const FieldDescriptor* right) const { + return left->index() < right->index(); + } +}; +} // namespace + void TextFormat::Printer::Print(const Message& message, TextGenerator& generator) const { const Reflection* reflection = message.GetReflection(); vector fields; reflection->ListFields(message, &fields); + if (print_message_fields_in_index_order_) { + sort(fields.begin(), fields.end(), FieldIndexSorter()); + } for (int i = 0; i < fields.size(); i++) { PrintField(message, reflection, fields[i], generator); } - PrintUnknownFields(reflection->GetUnknownFields(message), generator); + if (!hide_unknown_fields_) { + PrintUnknownFields(reflection->GetUnknownFields(message), generator); + } } void TextFormat::Printer::PrintFieldValueToString( @@ -1221,35 +1467,30 @@ void TextFormat::Printer::PrintField(const Message& message, } for (int j = 0; j < count; ++j) { + const int field_index = field->is_repeated() ? j : -1; + PrintFieldName(message, reflection, field, generator); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (single_line_mode_) { - generator.Print(" { "); - } else { - generator.Print(" {\n"); - generator.Indent(); - } + const FieldValuePrinter* printer = FindWithDefault( + custom_printers_, field, default_field_value_printer_.get()); + const Message& sub_message = + field->is_repeated() + ? reflection->GetRepeatedMessage(message, field, j) + : reflection->GetMessage(message, field); + generator.Print( + printer->PrintMessageStart( + sub_message, field_index, count, single_line_mode_)); + generator.Indent(); + Print(sub_message, generator); + generator.Outdent(); + generator.Print( + printer->PrintMessageEnd( + sub_message, field_index, count, single_line_mode_)); } else { generator.Print(": "); - } - - // Write the field value. - int field_index = j; - if (!field->is_repeated()) { - field_index = -1; - } - - PrintFieldValue(message, reflection, field, field_index, generator); - - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - if (single_line_mode_) { - generator.Print("} "); - } else { - generator.Outdent(); - generator.Print("}\n"); - } - } else { + // Write the field value. + PrintFieldValue(message, reflection, field, field_index, generator); if (single_line_mode_) { generator.Print(" "); } else { @@ -1280,30 +1521,20 @@ void TextFormat::Printer::PrintShortRepeatedField( } } -void TextFormat::Printer::PrintFieldName(const Message& /* message */, - const Reflection* /* reflection */, +void TextFormat::Printer::PrintFieldName(const Message& message, + const Reflection* reflection, const FieldDescriptor* field, TextGenerator& generator) const { - if (field->is_extension()) { - generator.Print("["); - // We special-case MessageSet elements for compatibility with proto1. - if (field->containing_type()->options().message_set_wire_format() - && field->type() == FieldDescriptor::TYPE_MESSAGE - && field->is_optional() - && field->extension_scope() == field->message_type()) { - generator.Print(field->message_type()->full_name()); - } else { - generator.Print(field->full_name()); - } - generator.Print("]"); - } else { - if (field->type() == FieldDescriptor::TYPE_GROUP) { - // Groups must be serialized with their original capitalization. - generator.Print(field->message_type()->name()); - } else { - generator.Print(field->name()); - } + // if use_field_number_ is true, prints field number instead + // of field name. + if (use_field_number_) { + generator.Print(SimpleItoa(field->number())); + return; } + + const FieldValuePrinter* printer = FindWithDefault( + custom_printers_, field, default_field_value_printer_.get()); + generator.Print(printer->PrintFieldName(message, reflection, field)); } void TextFormat::Printer::PrintFieldValue( @@ -1315,62 +1546,56 @@ void TextFormat::Printer::PrintFieldValue( GOOGLE_DCHECK(field->is_repeated() || (index == -1)) << "Index must be -1 for non-repeated fields"; + const FieldValuePrinter* printer + = FindWithDefault(custom_printers_, field, + default_field_value_printer_.get()); + switch (field->cpp_type()) { -#define OUTPUT_FIELD(CPPTYPE, METHOD, TO_STRING) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - generator.Print(TO_STRING(field->is_repeated() ? \ - reflection->GetRepeated##METHOD(message, field, index) : \ - reflection->Get##METHOD(message, field))); \ - break; \ - - OUTPUT_FIELD( INT32, Int32, SimpleItoa); - OUTPUT_FIELD( INT64, Int64, SimpleItoa); - OUTPUT_FIELD(UINT32, UInt32, SimpleItoa); - OUTPUT_FIELD(UINT64, UInt64, SimpleItoa); - OUTPUT_FIELD( FLOAT, Float, SimpleFtoa); - OUTPUT_FIELD(DOUBLE, Double, SimpleDtoa); +#define OUTPUT_FIELD(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + generator.Print(printer->Print##METHOD(field->is_repeated() \ + ? reflection->GetRepeated##METHOD(message, field, index) \ + : reflection->Get##METHOD(message, field))); \ + break + + OUTPUT_FIELD( INT32, Int32); + OUTPUT_FIELD( INT64, Int64); + OUTPUT_FIELD(UINT32, UInt32); + OUTPUT_FIELD(UINT64, UInt64); + OUTPUT_FIELD( FLOAT, Float); + OUTPUT_FIELD(DOUBLE, Double); + OUTPUT_FIELD( BOOL, Bool); #undef OUTPUT_FIELD - case FieldDescriptor::CPPTYPE_STRING: { - string scratch; - const string& value = field->is_repeated() ? - reflection->GetRepeatedStringReference( - message, field, index, &scratch) : - reflection->GetStringReference(message, field, &scratch); - - generator.Print("\""); - if (utf8_string_escaping_) { - generator.Print(strings::Utf8SafeCEscape(value)); - } else { - generator.Print(CEscape(value)); - } - generator.Print("\""); - - break; + case FieldDescriptor::CPPTYPE_STRING: { + string scratch; + const string& value = field->is_repeated() + ? reflection->GetRepeatedStringReference( + message, field, index, &scratch) + : reflection->GetStringReference(message, field, &scratch); + if (field->type() == FieldDescriptor::TYPE_STRING) { + generator.Print(printer->PrintString(value)); + } else { + GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_BYTES); + generator.Print(printer->PrintBytes(value)); } + break; + } - case FieldDescriptor::CPPTYPE_BOOL: - if (field->is_repeated()) { - generator.Print(reflection->GetRepeatedBool(message, field, index) - ? "true" : "false"); - } else { - generator.Print(reflection->GetBool(message, field) - ? "true" : "false"); - } - break; - - case FieldDescriptor::CPPTYPE_ENUM: - generator.Print(field->is_repeated() ? - reflection->GetRepeatedEnum(message, field, index)->name() : - reflection->GetEnum(message, field)->name()); - break; + case FieldDescriptor::CPPTYPE_ENUM: { + const EnumValueDescriptor *enum_val = field->is_repeated() + ? reflection->GetRepeatedEnum(message, field, index) + : reflection->GetEnum(message, field); + generator.Print(printer->PrintEnum(enum_val->number(), enum_val->name())); + break; + } - case FieldDescriptor::CPPTYPE_MESSAGE: - Print(field->is_repeated() ? - reflection->GetRepeatedMessage(message, field, index) : - reflection->GetMessage(message, field), - generator); - break; + case FieldDescriptor::CPPTYPE_MESSAGE: + Print(field->is_repeated() + ? reflection->GetRepeatedMessage(message, field, index) + : reflection->GetMessage(message, field), + generator); + break; } } diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h index 01f3ffb0..b4cba1db 100644 --- a/src/google/protobuf/text_format.h +++ b/src/google/protobuf/text_format.h @@ -39,11 +39,13 @@ #define GOOGLE_PROTOBUF_TEXT_FORMAT_H__ #include +#include #include #include + #include -#include #include +#include namespace google { namespace protobuf { @@ -85,6 +87,41 @@ class LIBPROTOBUF_EXPORT TextFormat { int index, string* output); + // The default printer that converts scalar values from fields into + // their string representation. + // You can derive from this FieldValuePrinter if you want to have + // fields to be printed in a different way and register it at the + // Printer. + class LIBPROTOBUF_EXPORT FieldValuePrinter { + public: + FieldValuePrinter(); + virtual ~FieldValuePrinter(); + virtual string PrintBool(bool val) const; + virtual string PrintInt32(int32 val) const; + virtual string PrintUInt32(uint32 val) const; + virtual string PrintInt64(int64 val) const; + virtual string PrintUInt64(uint64 val) const; + virtual string PrintFloat(float val) const; + virtual string PrintDouble(double val) const; + virtual string PrintString(const string& val) const; + virtual string PrintBytes(const string& val) const; + virtual string PrintEnum(int32 val, const string& name) const; + virtual string PrintFieldName(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field) const; + virtual string PrintMessageStart(const Message& message, + int field_index, + int field_count, + bool single_line_mode) const; + virtual string PrintMessageEnd(const Message& message, + int field_index, + int field_count, + bool single_line_mode) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter); + }; + // Class for those users which require more fine-grained control over how // a protobuffer message is printed out. class LIBPROTOBUF_EXPORT Printer { @@ -120,6 +157,15 @@ class LIBPROTOBUF_EXPORT TextFormat { single_line_mode_ = single_line_mode; } + bool IsInSingleLineMode() { + return single_line_mode_; + } + + // If use_field_number is true, uses field number instead of field name. + void SetUseFieldNumber(bool use_field_number) { + use_field_number_ = use_field_number; + } + // Set true to print repeated primitives in a format like: // field_name: [1, 2, 3, 4] // instead of printing each value on its own line. Short format applies @@ -132,11 +178,41 @@ class LIBPROTOBUF_EXPORT TextFormat { // Set true to output UTF-8 instead of ASCII. The only difference // is that bytes >= 0x80 in string fields will not be escaped, // because they are assumed to be part of UTF-8 multi-byte - // sequences. - void SetUseUtf8StringEscaping(bool as_utf8) { - utf8_string_escaping_ = as_utf8; + // sequences. This will change the default FieldValuePrinter. + void SetUseUtf8StringEscaping(bool as_utf8); + + // Set the default FieldValuePrinter that is used for all fields that + // don't have a field-specific printer registered. + // Takes ownership of the printer. + void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer); + + // Sets whether we want to hide unknown fields or not. + // Usually unknown fields are printed in a generic way that includes the + // tag number of the field instead of field name. However, sometimes it + // is useful to be able to print the message without unknown fields (e.g. + // for the python protobuf version to maintain consistency between its pure + // python and c++ implementations). + void SetHideUnknownFields(bool hide) { + hide_unknown_fields_ = hide; } + // If print_message_fields_in_index_order is true, print fields of a proto + // message using the order defined in source code instead of the field + // number. By default, use the field number order. + void SetPrintMessageFieldsInIndexOrder( + bool print_message_fields_in_index_order) { + print_message_fields_in_index_order_ = + print_message_fields_in_index_order; + } + + // Register a custom field-specific FieldValuePrinter for fields + // with a particular FieldDescriptor. + // Returns "true" if the registration succeeded, or "false", if there is + // already a printer for that FieldDescriptor. + // Takes ownership of the printer on successful registration. + bool RegisterFieldValuePrinter(const FieldDescriptor* field, + const FieldValuePrinter* printer); + private: // Forward declaration of an internal class used to print the text // output to the OutputStream (see text_format.cc for implementation). @@ -184,9 +260,18 @@ class LIBPROTOBUF_EXPORT TextFormat { bool single_line_mode_; + bool use_field_number_; + bool use_short_repeated_primitives_; - bool utf8_string_escaping_; + bool hide_unknown_fields_; + + bool print_message_fields_in_index_order_; + + scoped_ptr default_field_value_printer_; + typedef map CustomPrinterMap; + CustomPrinterMap custom_printers_; }; // Parses a text-format protocol message from the given input stream to @@ -314,12 +399,24 @@ class LIBPROTOBUF_EXPORT TextFormat { allow_partial_ = allow; } + // Allow field names to be matched case-insensitively. + // This is not advisable if there are fields that only differ in case, or + // if you want to enforce writing in the canonical form. + // This is 'false' by default. + void AllowCaseInsensitiveField(bool allow) { + allow_case_insensitive_field_ = allow; + } + // Like TextFormat::ParseFieldValueFromString bool ParseFieldValueFromString(const string& input, const FieldDescriptor* field, Message* output); + void AllowFieldNumber(bool allow) { + allow_field_number_ = allow; + } + private: // Forward declaration of an internal class used to parse text // representations (see text_format.cc for implementation). @@ -335,9 +432,15 @@ class LIBPROTOBUF_EXPORT TextFormat { Finder* finder_; ParseInfoTree* parse_info_tree_; bool allow_partial_; + bool allow_case_insensitive_field_; bool allow_unknown_field_; + bool allow_unknown_enum_; + bool allow_field_number_; + bool allow_relaxed_whitespace_; + bool allow_singular_overwrites_; }; + private: // Hack: ParseInfoTree declares TextFormat as a friend which should extend // the friendship to TextFormat::Parser::ParserImpl, but unfortunately some @@ -358,6 +461,7 @@ inline void TextFormat::RecordLocation(ParseInfoTree* info_tree, info_tree->RecordLocation(field, location); } + inline TextFormat::ParseInfoTree* TextFormat::CreateNested( ParseInfoTree* info_tree, const FieldDescriptor* field) { return info_tree->CreateNested(field); diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index 304fb844..b3cf7b8e 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -74,10 +74,11 @@ const string kEscapeTestStringEscaped = class TextFormatTest : public testing::Test { public: static void SetUpTestCase() { - File::ReadFileToStringOrDie( - TestSourceDir() - + "/google/protobuf/testdata/text_format_unittest_data.txt", - &static_proto_debug_string_); + GOOGLE_CHECK_OK(File::GetContents( + TestSourceDir() + + "/google/protobuf/" + "testdata/text_format_unittest_data_oneof_implemented.txt", + &static_proto_debug_string_, true)); } TextFormatTest() : proto_debug_string_(static_proto_debug_string_) {} @@ -95,11 +96,10 @@ string TextFormatTest::static_proto_debug_string_; class TextFormatExtensionsTest : public testing::Test { public: static void SetUpTestCase() { - File::ReadFileToStringOrDie( - TestSourceDir() - + "/google/protobuf/testdata/" - "text_format_unittest_extensions_data.txt", - &static_proto_debug_string_); + GOOGLE_CHECK_OK(File::GetContents(TestSourceDir() + + "/google/protobuf/testdata/" + "text_format_unittest_extensions_data.txt", + &static_proto_debug_string_, true)); } TextFormatExtensionsTest() @@ -205,16 +205,25 @@ TEST_F(TextFormatTest, StringEscape) { TEST_F(TextFormatTest, Utf8DebugString) { // Set the string value to test. proto_.set_optional_string("\350\260\267\346\255\214"); + proto_.set_optional_bytes("\350\260\267\346\255\214"); // Get the DebugString from the proto. string debug_string = proto_.DebugString(); string utf8_debug_string = proto_.Utf8DebugString(); // Hardcode a correct value to test against. - string correct_utf8_string = "optional_string: " + string correct_utf8_string = + "optional_string: " "\"\350\260\267\346\255\214\"" + "\n" + "optional_bytes: " + "\"\\350\\260\\267\\346\\255\\214\"" "\n"; - string correct_string = "optional_string: " + string correct_string = + "optional_string: " + "\"\\350\\260\\267\\346\\255\\214\"" + "\n" + "optional_bytes: " "\"\\350\\260\\267\\346\\255\\214\"" "\n"; @@ -253,6 +262,31 @@ TEST_F(TextFormatTest, PrintUnknownFields) { message.DebugString()); } +TEST_F(TextFormatTest, PrintUnknownFieldsHidden) { + // Test printing of unknown fields in a message when supressed. + + unittest::OneString message; + message.set_data("data"); + UnknownFieldSet* unknown_fields = message.mutable_unknown_fields(); + + unknown_fields->AddVarint(5, 1); + unknown_fields->AddFixed32(5, 2); + unknown_fields->AddFixed64(5, 3); + unknown_fields->AddLengthDelimited(5, "4"); + unknown_fields->AddGroup(5)->AddVarint(10, 5); + + unknown_fields->AddVarint(8, 1); + unknown_fields->AddVarint(8, 2); + unknown_fields->AddVarint(8, 3); + + TextFormat::Printer printer; + printer.SetHideUnknownFields(true); + string output; + printer.PrintToString(message, &output); + + EXPECT_EQ("data: \"data\"\n", output); +} + TEST_F(TextFormatTest, PrintUnknownMessage) { // Test heuristic printing of messages in an UnknownFieldSet. @@ -354,6 +388,146 @@ TEST_F(TextFormatTest, PrintBufferTooSmall) { EXPECT_EQ(output_stream.ByteCount(), 1); } +// A printer that appends 'u' to all unsigned int32. +class CustomUInt32FieldValuePrinter : public TextFormat::FieldValuePrinter { + public: + virtual string PrintUInt32(uint32 val) const { + return StrCat(FieldValuePrinter::PrintUInt32(val), "u"); + } +}; + +TEST_F(TextFormatTest, DefaultCustomFieldPrinter) { + protobuf_unittest::TestAllTypes message; + + message.set_optional_uint32(42); + message.add_repeated_uint32(1); + message.add_repeated_uint32(2); + message.add_repeated_uint32(3); + + TextFormat::Printer printer; + printer.SetDefaultFieldValuePrinter(new CustomUInt32FieldValuePrinter()); + // Let's see if that works well together with the repeated primitives: + printer.SetUseShortRepeatedPrimitives(true); + string text; + printer.PrintToString(message, &text); + EXPECT_EQ("optional_uint32: 42u\nrepeated_uint32: [1u, 2u, 3u]\n", text); +} + +class CustomInt32FieldValuePrinter : public TextFormat::FieldValuePrinter { + public: + virtual string PrintInt32(int32 val) const { + return StrCat("value-is(", FieldValuePrinter::PrintInt32(val), ")"); + } +}; + +TEST_F(TextFormatTest, FieldSpecificCustomPrinter) { + protobuf_unittest::TestAllTypes message; + + message.set_optional_int32(42); // This will be handled by our Printer. + message.add_repeated_int32(42); // This will be printed as number. + + TextFormat::Printer printer; + EXPECT_TRUE(printer.RegisterFieldValuePrinter( + message.GetDescriptor()->FindFieldByName("optional_int32"), + new CustomInt32FieldValuePrinter())); + string text; + printer.PrintToString(message, &text); + EXPECT_EQ("optional_int32: value-is(42)\nrepeated_int32: 42\n", text); +} + +TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) { + protobuf_unittest::TestAllTypes message; + TextFormat::Printer printer; + // NULL printer. + EXPECT_FALSE(printer.RegisterFieldValuePrinter( + message.GetDescriptor()->FindFieldByName("optional_int32"), + NULL)); + // Because registration fails, the ownership of this printer is never taken. + TextFormat::FieldValuePrinter my_field_printer; + // NULL field + EXPECT_FALSE(printer.RegisterFieldValuePrinter(NULL, &my_field_printer)); +} + +class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter { + public: + virtual string PrintInt32(int32 v) const { + return StrCat(FieldValuePrinter::PrintInt32(v), " # x", ToHex(v)); + } + + virtual string PrintMessageStart(const Message& message, + int field_index, + int field_count, + bool single_line_mode) const { + if (single_line_mode) { + return " { "; + } + return StrCat( + " { # ", message.GetDescriptor()->name(), ": ", field_index, "\n"); + } +}; + +TEST_F(TextFormatTest, CustomPrinterForComments) { + protobuf_unittest::TestAllTypes message; + message.mutable_optional_nested_message(); + message.mutable_optional_import_message()->set_d(42); + message.add_repeated_nested_message(); + message.add_repeated_nested_message(); + message.add_repeated_import_message()->set_d(43); + message.add_repeated_import_message()->set_d(44); + TextFormat::Printer printer; + CustomMessageFieldValuePrinter my_field_printer; + printer.SetDefaultFieldValuePrinter(new CustomMessageFieldValuePrinter()); + string text; + printer.PrintToString(message, &text); + EXPECT_EQ( + "optional_nested_message { # NestedMessage: -1\n" + "}\n" + "optional_import_message { # ImportMessage: -1\n" + " d: 42 # x2a\n" + "}\n" + "repeated_nested_message { # NestedMessage: 0\n" + "}\n" + "repeated_nested_message { # NestedMessage: 1\n" + "}\n" + "repeated_import_message { # ImportMessage: 0\n" + " d: 43 # x2b\n" + "}\n" + "repeated_import_message { # ImportMessage: 1\n" + " d: 44 # x2c\n" + "}\n", + text); +} + +class CustomMultilineCommentPrinter : public TextFormat::FieldValuePrinter { + public: + virtual string PrintMessageStart(const Message& message, + int field_index, + int field_count, + bool single_line_comment) const { + return StrCat(" { # 1\n", " # 2\n"); + } +}; + +TEST_F(TextFormatTest, CustomPrinterForMultilineComments) { + protobuf_unittest::TestAllTypes message; + message.mutable_optional_nested_message(); + message.mutable_optional_import_message()->set_d(42); + TextFormat::Printer printer; + CustomMessageFieldValuePrinter my_field_printer; + printer.SetDefaultFieldValuePrinter(new CustomMultilineCommentPrinter()); + string text; + printer.PrintToString(message, &text); + EXPECT_EQ( + "optional_nested_message { # 1\n" + " # 2\n" + "}\n" + "optional_import_message { # 1\n" + " # 2\n" + " d: 42\n" + "}\n", + text); +} + TEST_F(TextFormatTest, ParseBasic) { io::ArrayInputStream input_stream(proto_debug_string_.data(), proto_debug_string_.size()); @@ -449,7 +623,11 @@ TEST_F(TextFormatTest, ParseShortRepeatedForm) { " 3]\n" // Note that while the printer won't print repeated strings in short-form, // the parser will accept them. - "repeated_string: [ \"foo\", 'bar' ]\n"; + "repeated_string: [ \"foo\", 'bar' ]\n" + // Repeated message + "repeated_nested_message: [ { bb: 1 }, { bb : 2 }]\n" + // Repeated group + "RepeatedGroup [{ a: 3 },{ a: 4 }]\n"; ASSERT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); @@ -466,8 +644,17 @@ TEST_F(TextFormatTest, ParseShortRepeatedForm) { ASSERT_EQ(2, proto_.repeated_string_size()); EXPECT_EQ("foo", proto_.repeated_string(0)); EXPECT_EQ("bar", proto_.repeated_string(1)); + + ASSERT_EQ(2, proto_.repeated_nested_message_size()); + EXPECT_EQ(1, proto_.repeated_nested_message(0).bb()); + EXPECT_EQ(2, proto_.repeated_nested_message(1).bb()); + + ASSERT_EQ(2, proto_.repeatedgroup_size()); + EXPECT_EQ(3, proto_.repeatedgroup(0).a()); + EXPECT_EQ(4, proto_.repeatedgroup(1).a()); } + TEST_F(TextFormatTest, Comments) { // Test that comments are ignored. @@ -720,6 +907,27 @@ TEST_F(TextFormatTest, ParseExotic) { message.repeated_string(0)); } +TEST_F(TextFormatTest, PrintFieldsInIndexOrder) { + protobuf_unittest::TestFieldOrderings message; + // Fields are listed in index order instead of field number. + message.set_my_string("Test String"); // Field number 11 + message.set_my_int(12345); // Field number 1 + message.set_my_float(0.999); // Field number 101 + TextFormat::Printer printer; + string text; + + // By default, print in field number order. + printer.PrintToString(message, &text); + EXPECT_EQ("my_int: 12345\nmy_string: \"Test String\"\nmy_float: 0.999\n", + text); + + // Print in index order. + printer.SetPrintMessageFieldsInIndexOrder(true); + printer.PrintToString(message, &text); + EXPECT_EQ("my_string: \"Test String\"\nmy_int: 12345\nmy_float: 0.999\n", + text); +} + class TextFormatParserTest : public testing::Test { protected: void ExpectFailure(const string& input, const string& message, int line, @@ -738,7 +946,8 @@ class TextFormatParserTest : public testing::Test { TextFormat::Parser parser; MockErrorCollector error_collector; parser.RecordErrorsTo(&error_collector); - EXPECT_EQ(parser.ParseFromString(input, proto), expected_result); + EXPECT_EQ(expected_result, parser.ParseFromString(input, proto)) + << input << " -> " << proto->DebugString(); EXPECT_EQ(SimpleItoa(line) + ":" + SimpleItoa(col) + ": " + message + "\n", error_collector.text_); } @@ -927,11 +1136,14 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { EXPECT_BOOL_FIELD(bool, true, "t"); EXPECT_BOOL_FIELD(bool, false, "0"); EXPECT_BOOL_FIELD(bool, false, "f"); + EXPECT_FIELD(bool, true, "True"); + EXPECT_FIELD(bool, false, "False"); + EXPECT_INVALID(bool, "tRue"); + EXPECT_INVALID(bool, "faLse"); EXPECT_INVALID(bool, "2"); EXPECT_INVALID(bool, "-0"); EXPECT_INVALID(bool, "on"); EXPECT_INVALID(bool, "a"); - EXPECT_INVALID(bool, "True"); // float EXPECT_FIELD(float, 1, "1"); @@ -948,6 +1160,9 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { EXPECT_DOUBLE_FIELD(double, 3e5, "3e5"); EXPECT_INVALID(double, "a"); EXPECT_INVALID(double, "1,2"); + // Rejects hex and oct numbers for a double field. + EXPECT_INVALID(double, "0xf"); + EXPECT_INVALID(double, "012"); // string EXPECT_FIELD(string, "hello", "\"hello\""); @@ -1010,6 +1225,22 @@ TEST_F(TextFormatParserTest, InvalidCapitalization) { 1, 16); } +TEST_F(TextFormatParserTest, AllowIgnoreCapitalizationError) { + TextFormat::Parser parser; + protobuf_unittest::TestAllTypes proto; + + // These fields have a mismatching case. + EXPECT_FALSE(parser.ParseFromString("Optional_Double: 10.0", &proto)); + EXPECT_FALSE(parser.ParseFromString("oPtIoNaLgRoUp { a: 15 }", &proto)); + + // ... but are parsed correctly if we match case insensitive. + parser.AllowCaseInsensitiveField(true); + EXPECT_TRUE(parser.ParseFromString("Optional_Double: 10.0", &proto)); + EXPECT_EQ(10.0, proto.optional_double()); + EXPECT_TRUE(parser.ParseFromString("oPtIoNaLgRoUp { a: 15 }", &proto)); + EXPECT_EQ(15, proto.optionalgroup().a()); +} + TEST_F(TextFormatParserTest, InvalidFieldValues) { // Invalid values for a double/float field. ExpectFailure("optional_double: \"hello\"\n", "Expected double.", 1, 18); diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto index 6eb2d86f..969684fd 100644 --- a/src/google/protobuf/unittest.proto +++ b/src/google/protobuf/unittest.proto @@ -69,6 +69,7 @@ message TestAllTypes { FOO = 1; BAR = 2; BAZ = 3; + NEG = -1; // Intentionally negative. } // Singular @@ -167,6 +168,20 @@ message TestAllTypes { optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; optional string default_cord = 85 [ctype=CORD,default="123"]; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } +} + +// This proto includes a recusively nested message. +message NestedTestAllTypes { + optional NestedTestAllTypes child = 1; + optional TestAllTypes payload = 2; } message TestDeprecatedFields { @@ -294,6 +309,12 @@ extend TestAllExtensions { optional string default_string_piece_extension = 84 [ctype=STRING_PIECE, default="abc"]; optional string default_cord_extension = 85 [ctype=CORD, default="123"]; + + // For oneof test + optional uint32 oneof_uint32_extension = 111; + optional TestAllTypes.NestedMessage oneof_nested_message_extension = 112; + optional string oneof_string_extension = 113; + optional bytes oneof_bytes_extension = 114; } message TestNestedExtension { @@ -301,6 +322,9 @@ message TestNestedExtension { // Check for bug where string extensions declared in tested scope did not // compile. optional string test = 1002 [default="test"]; + // Used to test if generated extension name is correct when there are + // underscores. + optional string nested_string_extension = 1003; } } @@ -435,6 +459,7 @@ message TestNestedMessageHasBits { // Test an enum that has multiple values with the same number. enum TestEnumWithDupValue { option allow_alias = true; + FOO1 = 1; BAR1 = 2; BAZ = 3; @@ -535,6 +560,7 @@ message TestExtremeDefaultValues { default="ab\000c"]; optional string cord_with_zero = 26 [ctype=CORD, default="12\0003"]; + optional string replacement_string = 27 [default="${unknown}"]; } message SparseEnumMessage { @@ -558,6 +584,100 @@ message MoreBytes { repeated bytes data = 1; } +// Test int32, uint32, int64, uint64, and bool are all compatible +message Int32Message { + optional int32 data = 1; +} + +message Uint32Message { + optional uint32 data = 1; +} + +message Int64Message { + optional int64 data = 1; +} + +message Uint64Message { + optional uint64 data = 1; +} + +message BoolMessage { + optional bool data = 1; +} + +// Test oneofs. +message TestOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + TestAllTypes foo_message = 3; + group FooGroup = 4 { + optional int32 a = 5; + optional string b = 6; + } + } +} + +message TestOneofBackwardsCompatible { + optional int32 foo_int = 1; + optional string foo_string = 2; + optional TestAllTypes foo_message = 3; + optional group FooGroup = 4 { + optional int32 a = 5; + optional string b = 6; + } +} + +message TestOneof2 { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + string foo_cord = 3 [ctype=CORD]; + string foo_string_piece = 4 [ctype=STRING_PIECE]; + bytes foo_bytes = 5; + NestedEnum foo_enum = 6; + NestedMessage foo_message = 7; + group FooGroup = 8 { + optional int32 a = 9; + optional string b = 10; + } + NestedMessage foo_lazy_message = 11 [lazy=true]; + } + + oneof bar { + int32 bar_int = 12 [default = 5]; + string bar_string = 13 [default = "STRING"]; + string bar_cord = 14 [ctype=CORD, default = "CORD"]; + string bar_string_piece = 15 [ctype=STRING_PIECE, default = "SPIECE"]; + bytes bar_bytes = 16 [default = "BYTES"]; + NestedEnum bar_enum = 17 [default = BAR]; + } + + optional int32 baz_int = 18; + optional string baz_string = 19 [default = "BAZ"]; + + message NestedMessage { + optional int64 qux_int = 1; + repeated int32 corge_int = 2; + } + + enum NestedEnum { + FOO = 1; + BAR = 2; + BAZ = 3; + } +} + +message TestRequiredOneof { + oneof foo { + int32 foo_int = 1; + string foo_string = 2; + NestedMessage foo_message = 3; + } + message NestedMessage { + required double required_double = 1; + } +} // Test messages for packed fields @@ -618,6 +738,27 @@ extend TestPackedExtensions { repeated ForeignEnum packed_enum_extension = 103 [packed = true]; } +message TestUnpackedExtensions { + extensions 1 to max; +} + +extend TestUnpackedExtensions { + repeated int32 unpacked_int32_extension = 90 [packed = false]; + repeated int64 unpacked_int64_extension = 91 [packed = false]; + repeated uint32 unpacked_uint32_extension = 92 [packed = false]; + repeated uint64 unpacked_uint64_extension = 93 [packed = false]; + repeated sint32 unpacked_sint32_extension = 94 [packed = false]; + repeated sint64 unpacked_sint64_extension = 95 [packed = false]; + repeated fixed32 unpacked_fixed32_extension = 96 [packed = false]; + repeated fixed64 unpacked_fixed64_extension = 97 [packed = false]; + repeated sfixed32 unpacked_sfixed32_extension = 98 [packed = false]; + repeated sfixed64 unpacked_sfixed64_extension = 99 [packed = false]; + repeated float unpacked_float_extension = 100 [packed = false]; + repeated double unpacked_double_extension = 101 [packed = false]; + repeated bool unpacked_bool_extension = 102 [packed = false]; + repeated ForeignEnum unpacked_enum_extension = 103 [packed = false]; +} + // Used by ExtensionSetTest/DynamicExtensions. The test actually builds // a set of extensions to TestAllExtensions dynamically, based on the fields // of this message type. @@ -717,3 +858,4 @@ service TestService { message BarRequest {} message BarResponse {} + diff --git a/src/google/protobuf/unittest_custom_options.proto b/src/google/protobuf/unittest_custom_options.proto index e591d294..52ee6c71 100644 --- a/src/google/protobuf/unittest_custom_options.proto +++ b/src/google/protobuf/unittest_custom_options.proto @@ -218,6 +218,7 @@ message ComplexOptionType1 { optional int32 foo = 1; optional int32 foo2 = 2; optional int32 foo3 = 3; + repeated int32 foo4 = 4; extensions 100 to max; } @@ -235,6 +236,7 @@ message ComplexOptionType2 { } optional ComplexOptionType4 fred = 3; + repeated ComplexOptionType4 barney = 4; extensions 100 to max; } @@ -271,6 +273,8 @@ message VariousComplexOptions { option (.protobuf_unittest.complex_opt1).foo = 42; option (protobuf_unittest.complex_opt1).(.protobuf_unittest.quux) = 324; option (.protobuf_unittest.complex_opt1).(protobuf_unittest.corge).qux = 876; + option (protobuf_unittest.complex_opt1).foo4 = 99; + option (protobuf_unittest.complex_opt1).foo4 = 88; option (complex_opt2).baz = 987; option (complex_opt2).(grault) = 654; option (complex_opt2).bar.foo = 743; @@ -281,6 +285,8 @@ message VariousComplexOptions { option (complex_opt2).(protobuf_unittest.garply).(corge).qux = 2121; option (ComplexOptionType2.ComplexOptionType4.complex_opt4).waldo = 1971; option (complex_opt2).fred.waldo = 321; + option (complex_opt2).barney = { waldo: 101 }; + option (complex_opt2).barney = { waldo: 212 }; option (protobuf_unittest.complex_opt3).qux = 9; option (complex_opt3).complexoptiontype5.plugh = 22; option (complexopt6).xyzzy = 24; diff --git a/src/google/protobuf/unittest_lite.proto b/src/google/protobuf/unittest_lite.proto index a1764aac..ffff012f 100644 --- a/src/google/protobuf/unittest_lite.proto +++ b/src/google/protobuf/unittest_lite.proto @@ -151,6 +151,14 @@ message TestAllTypesLite { optional string default_string_piece = 84 [ctype=STRING_PIECE,default="abc"]; optional string default_cord = 85 [ctype=CORD,default="123"]; + + // For oneof test + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + } } message ForeignMessageLite { @@ -293,6 +301,12 @@ extend TestAllExtensionsLite { optional string default_string_piece_extension_lite = 84 [ctype=STRING_PIECE, default="abc"]; optional string default_cord_extension_lite = 85 [ctype=CORD, default="123"]; + + // For oneof test + optional uint32 oneof_uint32_extension_lite = 111; + optional TestAllTypesLite.NestedMessage oneof_nested_message_extension_lite = 112; + optional string oneof_string_extension_lite = 113; + optional bytes oneof_bytes_extension_lite = 114; } message TestPackedExtensionsLite { @@ -358,3 +372,13 @@ message TestParsingMergeLite { repeated TestAllTypesLite repeated_ext = 1001; } } + +// TestEmptyMessageLite is used to test unknown fields support in lite mode. +message TestEmptyMessageLite{ +} + +// Like above, but declare all field numbers as potential extensions. No +// actual extensions should ever be defined for this type. +message TestEmptyMessageWithExtensionsLite { + extensions 1 to max; +} diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto index 3497f09f..1d325592 100644 --- a/src/google/protobuf/unittest_mset.proto +++ b/src/google/protobuf/unittest_mset.proto @@ -62,6 +62,17 @@ message TestMessageSetExtension2 { optional string str = 25; } +// This message was used to generate +// //net/proto2/python/internal/testdata/message_set_message, but is commented +// out since it must not actually exist in code, to simulate an "unknown" +// extension. +// message TestMessageSetUnknownExtension { +// extend TestMessageSet { +// optional TestMessageSetUnknownExtension message_set_extension = 56141421; +// } +// optional int64 a = 1; +// } + // MessageSet wire format is equivalent to this. message RawMessageSet { repeated group Item = 1 { diff --git a/src/google/protobuf/unittest_no_generic_services.proto b/src/google/protobuf/unittest_no_generic_services.proto index cffb4122..a414220a 100644 --- a/src/google/protobuf/unittest_no_generic_services.proto +++ b/src/google/protobuf/unittest_no_generic_services.proto @@ -32,6 +32,7 @@ package google.protobuf.no_generic_services_test; + // *_generic_services are false by default. message TestMessage { diff --git a/src/google/protobuf/unittest_optimize_for.proto b/src/google/protobuf/unittest_optimize_for.proto index feecbef8..541d47fe 100644 --- a/src/google/protobuf/unittest_optimize_for.proto +++ b/src/google/protobuf/unittest_optimize_for.proto @@ -50,12 +50,17 @@ message TestOptimizedForSize { optional int32 test_extension = 1234; optional TestRequiredOptimizedForSize test_extension2 = 1235; } + + oneof foo { + int32 integer_field = 2; + string string_field = 3; + } } message TestRequiredOptimizedForSize { required int32 x = 1; } - + message TestOptionalOptimizedForSize { optional TestRequiredOptimizedForSize o = 1; } diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc index 841433d5..c0356af6 100644 --- a/src/google/protobuf/unknown_field_set.cc +++ b/src/google/protobuf/unknown_field_set.cc @@ -45,7 +45,7 @@ namespace google { namespace protobuf { UnknownFieldSet::UnknownFieldSet() - : fields_(NULL) {} + : fields_(NULL) {} UnknownFieldSet::~UnknownFieldSet() { Clear(); @@ -104,7 +104,7 @@ void UnknownFieldSet::AddVarint(int number, uint64 value) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_VARINT; + field.SetType(UnknownField::TYPE_VARINT); field.varint_ = value; fields_->push_back(field); } @@ -113,7 +113,7 @@ void UnknownFieldSet::AddFixed32(int number, uint32 value) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_FIXED32; + field.SetType(UnknownField::TYPE_FIXED32); field.fixed32_ = value; fields_->push_back(field); } @@ -122,7 +122,7 @@ void UnknownFieldSet::AddFixed64(int number, uint64 value) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_FIXED64; + field.SetType(UnknownField::TYPE_FIXED64); field.fixed64_ = value; fields_->push_back(field); } @@ -131,7 +131,7 @@ string* UnknownFieldSet::AddLengthDelimited(int number) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_LENGTH_DELIMITED; + field.SetType(UnknownField::TYPE_LENGTH_DELIMITED); field.length_delimited_.string_value_ = new string; fields_->push_back(field); return field.length_delimited_.string_value_; @@ -142,7 +142,7 @@ UnknownFieldSet* UnknownFieldSet::AddGroup(int number) { if (fields_ == NULL) fields_ = new vector; UnknownField field; field.number_ = number; - field.type_ = UnknownField::TYPE_GROUP; + field.SetType(UnknownField::TYPE_GROUP); field.group_ = new UnknownFieldSet; fields_->push_back(field); return field.group_; @@ -188,10 +188,9 @@ void UnknownFieldSet::DeleteByNumber(int number) { } bool UnknownFieldSet::MergeFromCodedStream(io::CodedInputStream* input) { - UnknownFieldSet other; if (internal::WireFormat::SkipMessage(input, &other) && - input->ConsumedEntireMessage()) { + input->ConsumedEntireMessage()) { MergeFrom(other); return true; } else { @@ -206,8 +205,8 @@ bool UnknownFieldSet::ParseFromCodedStream(io::CodedInputStream* input) { bool UnknownFieldSet::ParseFromZeroCopyStream(io::ZeroCopyInputStream* input) { io::CodedInputStream coded_input(input); - return ParseFromCodedStream(&coded_input) && - coded_input.ConsumedEntireMessage(); + return (ParseFromCodedStream(&coded_input) && + coded_input.ConsumedEntireMessage()); } bool UnknownFieldSet::ParseFromArray(const void* data, int size) { @@ -248,14 +247,14 @@ void UnknownField::DeepCopy() { void UnknownField::SerializeLengthDelimitedNoTag( io::CodedOutputStream* output) const { - GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); const string& data = *length_delimited_.string_value_; output->WriteVarint32(data.size()); - output->WriteString(data); + output->WriteRawMaybeAliased(data.data(), data.size()); } uint8* UnknownField::SerializeLengthDelimitedNoTagToArray(uint8* target) const { - GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); const string& data = *length_delimited_.string_value_; target = io::CodedOutputStream::WriteVarint32ToArray(data.size(), target); target = io::CodedOutputStream::WriteStringToArray(data, target); diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h index 825bba83..efaf78a5 100644 --- a/src/google/protobuf/unknown_field_set.h +++ b/src/google/protobuf/unknown_field_set.h @@ -42,7 +42,6 @@ #include #include #include -// TODO(jasonh): some people seem to rely on protobufs to include this for them! namespace google { namespace protobuf { @@ -53,7 +52,7 @@ namespace protobuf { } namespace internal { class WireFormat; // wire_format.h - class UnknownFieldSetFieldSkipperUsingCord; + class MessageSetFieldSkipperUsingCord; // extension_set_heavy.cc } @@ -202,9 +201,12 @@ class LIBPROTOBUF_EXPORT UnknownField { // Make a deep copy of any pointers in this UnknownField. void DeepCopy(); + // Set the wire type of this UnknownField. Should only be used when this + // UnknownField is being created. + inline void SetType(Type type); - unsigned int number_ : 29; - unsigned int type_ : 3; + uint32 number_; + uint32 type_; union { uint64 varint_; uint32 fixed32_; @@ -254,57 +256,62 @@ inline UnknownField::Type UnknownField::type() const { return static_cast(type_); } -inline uint64 UnknownField::varint () const { - assert(type_ == TYPE_VARINT); +inline uint64 UnknownField::varint() const { + assert(type() == TYPE_VARINT); return varint_; } inline uint32 UnknownField::fixed32() const { - assert(type_ == TYPE_FIXED32); + assert(type() == TYPE_FIXED32); return fixed32_; } inline uint64 UnknownField::fixed64() const { - assert(type_ == TYPE_FIXED64); + assert(type() == TYPE_FIXED64); return fixed64_; } inline const string& UnknownField::length_delimited() const { - assert(type_ == TYPE_LENGTH_DELIMITED); + assert(type() == TYPE_LENGTH_DELIMITED); return *length_delimited_.string_value_; } inline const UnknownFieldSet& UnknownField::group() const { - assert(type_ == TYPE_GROUP); + assert(type() == TYPE_GROUP); return *group_; } inline void UnknownField::set_varint(uint64 value) { - assert(type_ == TYPE_VARINT); + assert(type() == TYPE_VARINT); varint_ = value; } inline void UnknownField::set_fixed32(uint32 value) { - assert(type_ == TYPE_FIXED32); + assert(type() == TYPE_FIXED32); fixed32_ = value; } inline void UnknownField::set_fixed64(uint64 value) { - assert(type_ == TYPE_FIXED64); + assert(type() == TYPE_FIXED64); fixed64_ = value; } inline void UnknownField::set_length_delimited(const string& value) { - assert(type_ == TYPE_LENGTH_DELIMITED); + assert(type() == TYPE_LENGTH_DELIMITED); length_delimited_.string_value_->assign(value); } inline string* UnknownField::mutable_length_delimited() { - assert(type_ == TYPE_LENGTH_DELIMITED); + assert(type() == TYPE_LENGTH_DELIMITED); return length_delimited_.string_value_; } inline UnknownFieldSet* UnknownField::mutable_group() { - assert(type_ == TYPE_GROUP); + assert(type() == TYPE_GROUP); return group_; } inline int UnknownField::GetLengthDelimitedSize() const { - GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type_); + GOOGLE_DCHECK_EQ(TYPE_LENGTH_DELIMITED, type()); return length_delimited_.string_value_->size(); } +inline void UnknownField::SetType(Type type) { + type_ = type; +} + + } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc index c6b8769f..8e9bc842 100644 --- a/src/google/protobuf/unknown_field_set_unittest.cc +++ b/src/google/protobuf/unknown_field_set_unittest.cc @@ -118,7 +118,12 @@ TEST_F(UnknownFieldSetTest, AllFieldsPresent) { const FieldDescriptor* field = descriptor_->FindFieldByNumber(i); if (field != NULL) { ASSERT_LT(pos, unknown_fields_->field_count()); - EXPECT_EQ(i, unknown_fields_->field(pos++).number()); + // Do not check oneof field if it is not set. + if (field->containing_oneof() == NULL) { + EXPECT_EQ(i, unknown_fields_->field(pos++).number()); + } else if (i == unknown_fields_->field(pos).number()) { + pos++; + } if (field->is_repeated()) { // Should have a second instance. ASSERT_LT(pos, unknown_fields_->field_count()); diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc index ead763b1..91892897 100644 --- a/src/google/protobuf/wire_format.cc +++ b/src/google/protobuf/wire_format.cc @@ -39,6 +39,7 @@ #include #include +#include #include #include #include @@ -182,7 +183,8 @@ void WireFormat::SerializeUnknownFields(const UnknownFieldSet& unknown_fields, output->WriteVarint32(WireFormatLite::MakeTag(field.number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED)); output->WriteVarint32(field.length_delimited().size()); - output->WriteString(field.length_delimited()); + output->WriteRawMaybeAliased(field.length_delimited().data(), + field.length_delimited().size()); break; case UnknownField::TYPE_GROUP: output->WriteVarint32(WireFormatLite::MakeTag(field.number(), @@ -411,6 +413,37 @@ bool WireFormat::ParseAndMergePartial(io::CodedInputStream* input, } } +bool WireFormat::SkipMessageSetField(io::CodedInputStream* input, + uint32 field_number, + UnknownFieldSet* unknown_fields) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + return input->ReadString( + unknown_fields->AddLengthDelimited(field_number), length); +} + +bool WireFormat::ParseAndMergeMessageSetField(uint32 field_number, + const FieldDescriptor* field, + Message* message, + io::CodedInputStream* input) { + const Reflection* message_reflection = message->GetReflection(); + if (field == NULL) { + // We store unknown MessageSet extensions as groups. + return SkipMessageSetField( + input, field_number, message_reflection->MutableUnknownFields(message)); + } else if (field->is_repeated() || + field->type() != FieldDescriptor::TYPE_MESSAGE) { + // This shouldn't happen as we only allow optional message extensions to + // MessageSet. + GOOGLE_LOG(ERROR) << "Extensions of MessageSets must be optional messages."; + return false; + } else { + Message* sub_message = message_reflection->MutableMessage( + message, field, input->GetExtensionFactory()); + return WireFormatLite::ReadMessage(input, sub_message); + } +} + bool WireFormat::ParseAndMergeField( uint32 tag, const FieldDescriptor* field, // May be NULL for unknown @@ -562,7 +595,8 @@ bool WireFormat::ParseAndMergeField( case FieldDescriptor::TYPE_STRING: { string value; if (!WireFormatLite::ReadString(input, &value)) return false; - VerifyUTF8String(value.data(), value.length(), PARSE); + VerifyUTF8StringNamedField(value.data(), value.length(), PARSE, + field->name().c_str()); if (field->is_repeated()) { message_reflection->AddString(message, field, value); } else { @@ -626,10 +660,7 @@ bool WireFormat::ParseAndMergeMessageSetItem( // required int32 type_id = 2; // required data message = 3; - // Once we see a type_id, we'll construct a fake tag for this extension - // which is the tag it would have had under the proto2 extensions wire - // format. - uint32 fake_tag = 0; + uint32 last_type_id = 0; // Once we see a type_id, we'll look up the FieldDescriptor for the // extension. @@ -647,8 +678,7 @@ bool WireFormat::ParseAndMergeMessageSetItem( case WireFormatLite::kMessageSetTypeIdTag: { uint32 type_id; if (!input->ReadVarint32(&type_id)) return false; - fake_tag = WireFormatLite::MakeTag( - type_id, WireFormatLite::WIRETYPE_LENGTH_DELIMITED); + last_type_id = type_id; field = message_reflection->FindKnownExtensionByNumber(type_id); if (!message_data.empty()) { @@ -657,8 +687,8 @@ bool WireFormat::ParseAndMergeMessageSetItem( io::ArrayInputStream raw_input(message_data.data(), message_data.size()); io::CodedInputStream sub_input(&raw_input); - if (!ParseAndMergeField(fake_tag, field, message, - &sub_input)) { + if (!ParseAndMergeMessageSetField(last_type_id, field, message, + &sub_input)) { return false; } message_data.clear(); @@ -668,7 +698,7 @@ bool WireFormat::ParseAndMergeMessageSetItem( } case WireFormatLite::kMessageSetMessageTag: { - if (fake_tag == 0) { + if (last_type_id == 0) { // We haven't seen a type_id yet. Append this data to message_data. string temp; uint32 length; @@ -680,7 +710,8 @@ bool WireFormat::ParseAndMergeMessageSetItem( coded_output.WriteString(temp); } else { // Already saw type_id, so we can parse this directly. - if (!ParseAndMergeField(fake_tag, field, message, input)) { + if (!ParseAndMergeMessageSetField(last_type_id, field, message, + input)) { return false; } } @@ -828,7 +859,8 @@ void WireFormat::SerializeFieldWithCachedSizes( message_reflection->GetRepeatedStringReference( message, field, j, &scratch) : message_reflection->GetStringReference(message, field, &scratch); - VerifyUTF8String(value.data(), value.length(), SERIALIZE); + VerifyUTF8StringNamedField(value.data(), value.length(), SERIALIZE, + field->name().c_str()); WireFormatLite::WriteString(field->number(), value, output); break; } @@ -1038,7 +1070,8 @@ int WireFormat::MessageSetItemByteSize( void WireFormat::VerifyUTF8StringFallback(const char* data, int size, - Operation op) { + Operation op, + const char* field_name) { if (!IsStructurallyValidUTF8(data, size)) { const char* operation_str = NULL; switch (op) { @@ -1050,10 +1083,15 @@ void WireFormat::VerifyUTF8StringFallback(const char* data, break; // no default case: have the compiler warn if a case is not covered. } - GOOGLE_LOG(ERROR) << "String field contains invalid UTF-8 data when " - << operation_str - << " a protocol buffer. Use the 'bytes' type if you intend to " - "send raw bytes."; + string quoted_field_name = ""; + if (field_name != NULL) { + quoted_field_name = StringPrintf(" '%s'", field_name); + } + // no space below to avoid double space when the field name is missing. + GOOGLE_LOG(ERROR) << "String field" << quoted_field_name << " contains invalid " + << "UTF-8 data when " << operation_str << " a protocol " + << "buffer. Use the 'bytes' type if you intend to send raw " + << "bytes. "; } } diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h index 6cc90029..0c05c0d8 100644 --- a/src/google/protobuf/wire_format.h +++ b/src/google/protobuf/wire_format.h @@ -79,7 +79,7 @@ class LIBPROTOBUF_EXPORT WireFormat { static inline WireFormatLite::WireType WireTypeForField( const FieldDescriptor* field); - // Given a FieldSescriptor::Type return its WireType + // Given a FieldDescriptor::Type return its WireType static inline WireFormatLite::WireType WireTypeForFieldType( FieldDescriptor::Type type); @@ -180,7 +180,7 @@ class LIBPROTOBUF_EXPORT WireFormat { // of packed repeated fields. static uint32 MakeTag(const FieldDescriptor* field); - // Parse a single field. The input should start out positioned immidately + // Parse a single field. The input should start out positioned immediately // after the tag. static bool ParseAndMergeField( uint32 tag, @@ -228,14 +228,34 @@ class LIBPROTOBUF_EXPORT WireFormat { }; // Verifies that a string field is valid UTF8, logging an error if not. + // This function will not be called by newly generated protobuf code + // but remains present to support existing code. static void VerifyUTF8String(const char* data, int size, Operation op); + // The NamedField variant takes a field name in order to produce an + // informative error message if verification fails. + static void VerifyUTF8StringNamedField(const char* data, + int size, + Operation op, + const char* field_name); private: // Verifies that a string field is valid UTF8, logging an error if not. static void VerifyUTF8StringFallback( const char* data, int size, - Operation op); + Operation op, + const char* field_name); + + // Skip a MessageSet field. + static bool SkipMessageSetField(io::CodedInputStream* input, + uint32 field_number, + UnknownFieldSet* unknown_fields); + + // Parse a MessageSet field. + static bool ParseAndMergeMessageSetField(uint32 field_number, + const FieldDescriptor* field, + Message* message, + io::CodedInputStream* input); @@ -293,13 +313,21 @@ inline int WireFormat::TagSize(int field_number, FieldDescriptor::Type type) { inline void WireFormat::VerifyUTF8String(const char* data, int size, WireFormat::Operation op) { #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED - WireFormat::VerifyUTF8StringFallback(data, size, op); + WireFormat::VerifyUTF8StringFallback(data, size, op, NULL); #else // Avoid the compiler warning about unsued variables. (void)data; (void)size; (void)op; #endif } +inline void WireFormat::VerifyUTF8StringNamedField( + const char* data, int size, WireFormat::Operation op, + const char* field_name) { +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + WireFormat::VerifyUTF8StringFallback(data, size, op, field_name); +#endif +} + } // namespace internal } // namespace protobuf diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc index 0a3357b1..d65844dc 100644 --- a/src/google/protobuf/wire_format_lite.cc +++ b/src/google/protobuf/wire_format_lite.cc @@ -153,8 +153,65 @@ bool WireFormatLite::SkipField( } } +bool WireFormatLite::SkipField( + io::CodedInputStream* input, uint32 tag, io::CodedOutputStream* output) { + switch (WireFormatLite::GetTagWireType(tag)) { + case WireFormatLite::WIRETYPE_VARINT: { + uint64 value; + if (!input->ReadVarint64(&value)) return false; + output->WriteVarint32(tag); + output->WriteVarint64(value); + return true; + } + case WireFormatLite::WIRETYPE_FIXED64: { + uint64 value; + if (!input->ReadLittleEndian64(&value)) return false; + output->WriteVarint32(tag); + output->WriteLittleEndian64(value); + return true; + } + case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + output->WriteVarint32(tag); + output->WriteVarint32(length); + // TODO(mkilavuz): Provide API to prevent extra string copying. + string temp; + if (!input->ReadString(&temp, length)) return false; + output->WriteString(temp); + return true; + } + case WireFormatLite::WIRETYPE_START_GROUP: { + output->WriteVarint32(tag); + if (!input->IncrementRecursionDepth()) return false; + if (!SkipMessage(input, output)) return false; + input->DecrementRecursionDepth(); + // Check that the ending tag matched the starting tag. + if (!input->LastTagWas(WireFormatLite::MakeTag( + WireFormatLite::GetTagFieldNumber(tag), + WireFormatLite::WIRETYPE_END_GROUP))) { + return false; + } + return true; + } + case WireFormatLite::WIRETYPE_END_GROUP: { + return false; + } + case WireFormatLite::WIRETYPE_FIXED32: { + uint32 value; + if (!input->ReadLittleEndian32(&value)) return false; + output->WriteVarint32(tag); + output->WriteLittleEndian32(value); + return true; + } + default: { + return false; + } + } +} + bool WireFormatLite::SkipMessage(io::CodedInputStream* input) { - while(true) { + while (true) { uint32 tag = input->ReadTag(); if (tag == 0) { // End of input. This is a valid place to end, so return true. @@ -172,6 +229,27 @@ bool WireFormatLite::SkipMessage(io::CodedInputStream* input) { } } +bool WireFormatLite::SkipMessage(io::CodedInputStream* input, + io::CodedOutputStream* output) { + while (true) { + uint32 tag = input->ReadTag(); + if (tag == 0) { + // End of input. This is a valid place to end, so return true. + return true; + } + + WireFormatLite::WireType wire_type = WireFormatLite::GetTagWireType(tag); + + if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) { + output->WriteVarint32(tag); + // Must be the end of the message. + return true; + } + + if (!SkipField(input, tag, output)) return false; + } +} + bool FieldSkipper::SkipField( io::CodedInputStream* input, uint32 tag) { return WireFormatLite::SkipField(input, tag); @@ -186,6 +264,21 @@ void FieldSkipper::SkipUnknownEnum( // Nothing. } +bool CodedOutputStreamFieldSkipper::SkipField( + io::CodedInputStream* input, uint32 tag) { + return WireFormatLite::SkipField(input, tag, unknown_fields_); +} + +bool CodedOutputStreamFieldSkipper::SkipMessage(io::CodedInputStream* input) { + return WireFormatLite::SkipMessage(input, unknown_fields_); +} + +void CodedOutputStreamFieldSkipper::SkipUnknownEnum( + int field_number, int value) { + unknown_fields_->WriteVarint32(field_number); + unknown_fields_->WriteVarint64(value); +} + bool WireFormatLite::ReadPackedEnumNoInline(io::CodedInputStream* input, bool (*is_valid)(int), RepeatedField* values) { @@ -285,6 +378,15 @@ void WireFormatLite::WriteString(int field_number, const string& value, output->WriteVarint32(value.size()); output->WriteString(value); } +void WireFormatLite::WriteStringMaybeAliased( + int field_number, const string& value, + io::CodedOutputStream* output) { + // String is for UTF-8 text only + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK(value.size() <= kint32max); + output->WriteVarint32(value.size()); + output->WriteRawMaybeAliased(value.data(), value.size()); +} void WireFormatLite::WriteBytes(int field_number, const string& value, io::CodedOutputStream* output) { WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); @@ -292,6 +394,14 @@ void WireFormatLite::WriteBytes(int field_number, const string& value, output->WriteVarint32(value.size()); output->WriteString(value); } +void WireFormatLite::WriteBytesMaybeAliased( + int field_number, const string& value, + io::CodedOutputStream* output) { + WriteTag(field_number, WIRETYPE_LENGTH_DELIMITED, output); + GOOGLE_CHECK(value.size() <= kint32max); + output->WriteVarint32(value.size()); + output->WriteRawMaybeAliased(value.data(), value.size()); +} void WireFormatLite::WriteGroup(int field_number, diff --git a/src/google/protobuf/wire_format_lite.h b/src/google/protobuf/wire_format_lite.h index cb4fc918..4b6b53e7 100644 --- a/src/google/protobuf/wire_format_lite.h +++ b/src/google/protobuf/wire_format_lite.h @@ -163,11 +163,22 @@ class LIBPROTOBUF_EXPORT WireFormatLite { // records to an UnknownFieldSet. static bool SkipField(io::CodedInputStream* input, uint32 tag); + // Skips a field value with the given tag. The input should start + // positioned immediately after the tag. Skipped values are recorded to a + // CodedOutputStream. + static bool SkipField(io::CodedInputStream* input, uint32 tag, + io::CodedOutputStream* output); + // Reads and ignores a message from the input. Skipped values are simply // discarded, not recorded anywhere. See WireFormat::SkipMessage() for a // version that records to an UnknownFieldSet. static bool SkipMessage(io::CodedInputStream* input); + // Reads and ignores a message from the input. Skipped values are recorded + // to a CodedOutputStream. + static bool SkipMessage(io::CodedInputStream* input, + io::CodedOutputStream* output); + // This macro does the same thing as WireFormatLite::MakeTag(), but the // result is usable as a compile-time constant, which makes it usable // as a switch case or a template input. WireFormatLite::MakeTag() is more @@ -340,6 +351,10 @@ class LIBPROTOBUF_EXPORT WireFormatLite { static void WriteString(field_number, const string& value, output); static void WriteBytes (field_number, const string& value, output); + static void WriteStringMaybeAliased( + field_number, const string& value, output); + static void WriteBytesMaybeAliased( + field_number, const string& value, output); static void WriteGroup( field_number, const MessageLite& value, output); @@ -490,6 +505,12 @@ class LIBPROTOBUF_EXPORT WireFormatLite { google::protobuf::io::CodedInputStream* input, RepeatedField* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + // Like ReadRepeatedFixedSizePrimitive but for packed primitive fields. + template + static inline bool ReadPackedFixedSizePrimitive( + google::protobuf::io::CodedInputStream* input, + RepeatedField* value) GOOGLE_ATTRIBUTE_ALWAYS_INLINE; + static const CppType kFieldTypeToCppTypeMap[]; static const WireFormatLite::WireType kWireTypeForFieldType[]; @@ -518,6 +539,24 @@ class LIBPROTOBUF_EXPORT FieldSkipper { virtual void SkipUnknownEnum(int field_number, int value); }; +// Subclass of FieldSkipper which saves skipped fields to a CodedOutputStream. + +class LIBPROTOBUF_EXPORT CodedOutputStreamFieldSkipper : public FieldSkipper { + public: + explicit CodedOutputStreamFieldSkipper(io::CodedOutputStream* unknown_fields) + : unknown_fields_(unknown_fields) {} + virtual ~CodedOutputStreamFieldSkipper() {} + + // implements FieldSkipper ----------------------------------------- + virtual bool SkipField(io::CodedInputStream* input, uint32 tag); + virtual bool SkipMessage(io::CodedInputStream* input); + virtual void SkipUnknownEnum(int field_number, int value); + + protected: + io::CodedOutputStream* unknown_fields_; +}; + + // inline methods ==================================================== inline WireFormatLite::CppType diff --git a/src/google/protobuf/wire_format_lite_inl.h b/src/google/protobuf/wire_format_lite_inl.h index 641cc92f..ba9f9ce3 100644 --- a/src/google/protobuf/wire_format_lite_inl.h +++ b/src/google/protobuf/wire_format_lite_inl.h @@ -150,8 +150,8 @@ template <> inline bool WireFormatLite::ReadPrimitive( io::CodedInputStream* input, bool* value) { - uint32 temp; - if (!input->ReadVarint32(&temp)) return false; + uint64 temp; + if (!input->ReadVarint64(&temp)) return false; *value = temp != 0; return true; } @@ -221,10 +221,11 @@ inline const uint8* WireFormatLite::ReadPrimitiveFromArray< } template -inline bool WireFormatLite::ReadRepeatedPrimitive(int, // tag_size, unused. - uint32 tag, - io::CodedInputStream* input, - RepeatedField* values) { +inline bool WireFormatLite::ReadRepeatedPrimitive( + int, // tag_size, unused. + uint32 tag, + io::CodedInputStream* input, + RepeatedField* values) { CType value; if (!ReadPrimitive(input, &value)) return false; values->Add(value); @@ -284,7 +285,7 @@ inline bool WireFormatLite::ReadRepeatedFixedSizePrimitive( return true; } -// Specializations of ReadRepeatedPrimitive for the fixed size types, which use +// Specializations of ReadRepeatedPrimitive for the fixed size types, which use // the optimized code path. #define READ_REPEATED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ template <> \ @@ -333,6 +334,86 @@ inline bool WireFormatLite::ReadPackedPrimitive(io::CodedInputStream* input, return true; } +template +inline bool WireFormatLite::ReadPackedFixedSizePrimitive( + io::CodedInputStream* input, RepeatedField* values) { + uint32 length; + if (!input->ReadVarint32(&length)) return false; + const uint32 old_entries = values->size(); + const uint32 new_entries = length / sizeof(CType); + const uint32 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 + // to a malicious user-supplied "length" above. So we have a fast + // path that pre-allocates when the "length" is less than a bound. + // We determine the bound by calling BytesUntilTotalBytesLimit() and + // BytesUntilLimit(). These return -1 to mean "no limit set". + // There are four cases: + // TotalBytesLimit Limit + // -1 -1 Use slow path. + // -1 >= 0 Use fast path if length <= Limit. + // >= 0 -1 Use slow path. + // >= 0 >= 0 Use fast path if length <= min(both limits). + int64 bytes_limit = input->BytesUntilTotalBytesLimit(); + if (bytes_limit == -1) { + bytes_limit = input->BytesUntilLimit(); + } else { + bytes_limit = + min(bytes_limit, static_cast(input->BytesUntilLimit())); + } + if (bytes_limit >= new_bytes) { + // Fast-path that pre-allocates *values to the final size. +#if defined(PROTOBUF_LITTLE_ENDIAN) + values->Resize(old_entries + new_entries, 0); + // values->mutable_data() may change after Resize(), so do this after: + void* dest = reinterpret_cast(values->mutable_data() + old_entries); + if (!input->ReadRaw(dest, new_bytes)) { + values->Truncate(old_entries); + return false; + } +#else + values->Reserve(old_entries + new_entries); + CType value; + for (int i = 0; i < new_entries; ++i) { + if (!ReadPrimitive(input, &value)) return false; + values->AddAlreadyReserved(value); + } +#endif + } else { + // This is the slow-path case where "length" may be too large to + // safely allocate. We read as much as we can into *values + // without pre-allocating "length" bytes. + CType value; + for (int i = 0; i < new_entries; ++i) { + if (!ReadPrimitive(input, &value)) return false; + values->Add(value); + } + } + return true; +} + +// Specializations of ReadPackedPrimitive for the fixed size types, which use +// an optimized code path. +#define READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(CPPTYPE, DECLARED_TYPE) \ +template <> \ +inline bool WireFormatLite::ReadPackedPrimitive< \ + CPPTYPE, WireFormatLite::DECLARED_TYPE>( \ + io::CodedInputStream* input, \ + RepeatedField* values) { \ + return ReadPackedFixedSizePrimitive< \ + CPPTYPE, WireFormatLite::DECLARED_TYPE>(input, values); \ +} + +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint32, TYPE_FIXED32); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(uint64, TYPE_FIXED64); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int32, TYPE_SFIXED32); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(int64, TYPE_SFIXED64); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(float, TYPE_FLOAT); +READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE(double, TYPE_DOUBLE); + +#undef READ_REPEATED_PACKED_FIXED_SIZE_PRIMITIVE + template bool WireFormatLite::ReadPackedPrimitiveNoInline(io::CodedInputStream* input, RepeatedField* values) { @@ -660,15 +741,13 @@ inline uint8* WireFormatLite::WriteStringToArray(int field_number, // WriteString() to avoid code duplication. If the implementations become // different, you will need to update that usage. target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); - target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); - return io::CodedOutputStream::WriteStringToArray(value, target); + return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); } inline uint8* WireFormatLite::WriteBytesToArray(int field_number, const string& value, uint8* target) { target = WriteTagToArray(field_number, WIRETYPE_LENGTH_DELIMITED, target); - target = io::CodedOutputStream::WriteVarint32ToArray(value.size(), target); - return io::CodedOutputStream::WriteStringToArray(value, target); + return io::CodedOutputStream::WriteStringWithSizeToArray(value, target); } diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc index 9822828b..3a44aaf7 100644 --- a/src/google/protobuf/wire_format_unittest.cc +++ b/src/google/protobuf/wire_format_unittest.cc @@ -175,6 +175,43 @@ TEST(WireFormatTest, ParsePackedExtensions) { TestUtil::ExpectPackedExtensionsSet(dest); } +TEST(WireFormatTest, ParseOneof) { + unittest::TestOneof2 source, dest; + string data; + + // Serialize using the generated code. + TestUtil::SetOneof1(&source); + source.SerializeToString(&data); + + // Parse using WireFormat. + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &dest); + + // Check. + TestUtil::ExpectOneofSet1(dest); +} + +TEST(WireFormatTest, OneofOnlySetLast) { + unittest::TestOneofBackwardsCompatible source; + unittest::TestOneof oneof_dest; + string data; + + // Set two fields + source.set_foo_int(100); + source.set_foo_string("101"); + + // Serialize and parse to oneof message. + source.SerializeToString(&data); + io::ArrayInputStream raw_input(data.data(), data.size()); + io::CodedInputStream input(&raw_input); + WireFormat::ParseAndMergePartial(&input, &oneof_dest); + + // Only the last field is set. + EXPECT_FALSE(oneof_dest.has_foo_int()); + EXPECT_TRUE(oneof_dest.has_foo_string()); +} + TEST(WireFormatTest, ByteSize) { unittest::TestAllTypes message; TestUtil::SetAllFields(&message); @@ -217,6 +254,18 @@ TEST(WireFormatTest, ByteSizePackedExtensions) { EXPECT_EQ(0, WireFormat::ByteSize(message)); } +TEST(WireFormatTest, ByteSizeOneof) { + unittest::TestOneof2 message; + TestUtil::SetOneof1(&message); + + EXPECT_EQ(message.ByteSize(), + WireFormat::ByteSize(message)); + message.Clear(); + + EXPECT_EQ(0, message.ByteSize()); + EXPECT_EQ(0, WireFormat::ByteSize(message)); +} + TEST(WireFormatTest, Serialize) { unittest::TestAllTypes message; string generated_data; @@ -311,6 +360,36 @@ TEST(WireFormatTest, SerializeFieldsAndExtensions) { TestUtil::ExpectAllFieldsAndExtensionsInOrder(generated_data); } +TEST(WireFormatTest, SerializeOneof) { + unittest::TestOneof2 message; + string generated_data; + string dynamic_data; + + TestUtil::SetOneof1(&message); + int size = message.ByteSize(); + + // Serialize using the generated code. + { + io::StringOutputStream raw_output(&generated_data); + io::CodedOutputStream output(&raw_output); + message.SerializeWithCachedSizes(&output); + ASSERT_FALSE(output.HadError()); + } + + // Serialize using WireFormat. + { + io::StringOutputStream raw_output(&dynamic_data); + io::CodedOutputStream output(&raw_output); + WireFormat::SerializeWithCachedSizes(message, size, &output); + ASSERT_FALSE(output.HadError()); + } + + // Should be the same. + // Don't use EXPECT_EQ here because we're comparing raw binary data and + // we really don't want it dumped to stdout on failure. + EXPECT_TRUE(dynamic_data == generated_data); +} + TEST(WireFormatTest, ParseMultipleExtensionRanges) { // Make sure we can parse a message that contains multiple extensions ranges. unittest::TestFieldOrderings source; @@ -687,6 +766,34 @@ TEST(WireFormatTest, RepeatedScalarsDifferentTagSizes) { EXPECT_EQ(msg1.DebugString(), msg2.DebugString()); } +TEST(WireFormatTest, CompatibleTypes) { + const int64 data = 0x100000000; + unittest::Int64Message msg1; + msg1.set_data(data); + string serialized; + msg1.SerializeToString(&serialized); + + // Test int64 is compatible with bool + unittest::BoolMessage msg2; + ASSERT_TRUE(msg2.ParseFromString(serialized)); + ASSERT_EQ(static_cast(data), msg2.data()); + + // Test int64 is compatible with uint64 + unittest::Uint64Message msg3; + ASSERT_TRUE(msg3.ParseFromString(serialized)); + ASSERT_EQ(static_cast(data), msg3.data()); + + // Test int64 is compatible with int32 + unittest::Int32Message msg4; + ASSERT_TRUE(msg4.ParseFromString(serialized)); + ASSERT_EQ(static_cast(data), msg4.data()); + + // Test int64 is compatible with uint32 + unittest::Uint32Message msg5; + ASSERT_TRUE(msg5.ParseFromString(serialized)); + ASSERT_EQ(static_cast(data), msg5.data()); +} + class WireFormatInvalidInputTest : public testing::Test { protected: // Make a serialized TestAllTypes in which the field optional_nested_message @@ -852,7 +959,16 @@ bool StartsWith(const string& s, const string& prefix) { return s.substr(0, prefix.length()) == prefix; } -TEST(Utf8ValidationTest, WriteInvalidUTF8String) { +class Utf8ValidationTest : public ::testing::Test { + protected: + Utf8ValidationTest() {} + virtual ~Utf8ValidationTest() {} + virtual void SetUp() { + } + +}; + +TEST_F(Utf8ValidationTest, WriteInvalidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; vector errors; @@ -864,7 +980,7 @@ TEST(Utf8ValidationTest, WriteInvalidUTF8String) { #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED ASSERT_EQ(1, errors.size()); EXPECT_TRUE(StartsWith(errors[0], - "String field contains invalid UTF-8 data when " + "String field 'data' contains invalid UTF-8 data when " "serializing a protocol buffer. Use the " "'bytes' type if you intend to send raw bytes.")); #else @@ -872,7 +988,8 @@ TEST(Utf8ValidationTest, WriteInvalidUTF8String) { #endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED } -TEST(Utf8ValidationTest, ReadInvalidUTF8String) { + +TEST_F(Utf8ValidationTest, ReadInvalidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; WriteMessage(kInvalidUTF8String, &input, &wire_buffer); @@ -886,7 +1003,7 @@ TEST(Utf8ValidationTest, ReadInvalidUTF8String) { #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED ASSERT_EQ(1, errors.size()); EXPECT_TRUE(StartsWith(errors[0], - "String field contains invalid UTF-8 data when " + "String field 'data' contains invalid UTF-8 data when " "parsing a protocol buffer. Use the " "'bytes' type if you intend to send raw bytes.")); @@ -895,7 +1012,8 @@ TEST(Utf8ValidationTest, ReadInvalidUTF8String) { #endif // GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED } -TEST(Utf8ValidationTest, WriteValidUTF8String) { + +TEST_F(Utf8ValidationTest, WriteValidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; vector errors; @@ -907,7 +1025,7 @@ TEST(Utf8ValidationTest, WriteValidUTF8String) { ASSERT_EQ(0, errors.size()); } -TEST(Utf8ValidationTest, ReadValidUTF8String) { +TEST_F(Utf8ValidationTest, ReadValidUTF8String) { string wire_buffer; protobuf_unittest::OneString input; WriteMessage(kValidUTF8String, &input, &wire_buffer); @@ -923,7 +1041,7 @@ TEST(Utf8ValidationTest, ReadValidUTF8String) { } // Bytes: anything can pass as bytes, use invalid UTF-8 string to test -TEST(Utf8ValidationTest, WriteArbitraryBytes) { +TEST_F(Utf8ValidationTest, WriteArbitraryBytes) { string wire_buffer; protobuf_unittest::OneBytes input; vector errors; @@ -935,7 +1053,7 @@ TEST(Utf8ValidationTest, WriteArbitraryBytes) { ASSERT_EQ(0, errors.size()); } -TEST(Utf8ValidationTest, ReadArbitraryBytes) { +TEST_F(Utf8ValidationTest, ReadArbitraryBytes) { string wire_buffer; protobuf_unittest::OneBytes input; WriteMessage(kInvalidUTF8String, &input, &wire_buffer); @@ -950,7 +1068,7 @@ TEST(Utf8ValidationTest, ReadArbitraryBytes) { EXPECT_EQ(input.data(), output.data()); } -TEST(Utf8ValidationTest, ParseRepeatedString) { +TEST_F(Utf8ValidationTest, ParseRepeatedString) { protobuf_unittest::MoreBytes input; input.add_data(kValidUTF8String); input.add_data(kInvalidUTF8String); @@ -972,6 +1090,30 @@ TEST(Utf8ValidationTest, ParseRepeatedString) { EXPECT_EQ(wire_buffer, output.SerializeAsString()); } +// Test the old VerifyUTF8String() function, which may still be called by old +// generated code. +TEST_F(Utf8ValidationTest, OldVerifyUTF8String) { + string data(kInvalidUTF8String); + + vector errors; + { + ScopedMemoryLog log; + WireFormat::VerifyUTF8String(data.data(), data.size(), + WireFormat::SERIALIZE); + errors = log.GetMessages(ERROR); + } +#ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED + ASSERT_EQ(1, errors.size()); + EXPECT_TRUE(StartsWith(errors[0], + "String field contains invalid UTF-8 data when " + "serializing a protocol buffer. Use the " + "'bytes' type if you intend to send raw bytes.")); +#else + ASSERT_EQ(0, errors.size()); +#endif +} + + } // namespace } // namespace internal } // namespace protobuf -- cgit v1.2.3